55 lines
2.9 KiB
JavaScript
55 lines
2.9 KiB
JavaScript
import { db, adminUserId, load } from './setup.mjs';
|
|
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
|
|
const { evaluatePromotion, runAutoPromotions } = await load('../services/promotionWorker.js');
|
|
const { createIntuneDeployment, loadDeploymentRaw } = await load('../models/psadtModel.js');
|
|
|
|
const owner = adminUserId();
|
|
const hoursAgo = (h) => new Date(Date.now() - h * 3_600_000).toISOString();
|
|
|
|
// --- pure eligibility -----------------------------------------------------
|
|
|
|
test('evaluatePromotion is due once the soak window elapses', () => {
|
|
const d = { autoPromoteAfterHours: 1, autoPromoteRing: 'Broad', soakStartedAt: hoursAgo(2), promotedAt: '' };
|
|
assert.equal(evaluatePromotion(d).due, true);
|
|
});
|
|
|
|
test('evaluatePromotion is not due while soaking, disabled, or already promoted', () => {
|
|
assert.equal(evaluatePromotion({ autoPromoteAfterHours: 4, autoPromoteRing: 'Broad', soakStartedAt: hoursAgo(1), promotedAt: '' }).due, false);
|
|
assert.equal(evaluatePromotion({ autoPromoteAfterHours: 0, autoPromoteRing: 'Broad', soakStartedAt: hoursAgo(5) }).due, false);
|
|
assert.equal(evaluatePromotion({ autoPromoteAfterHours: 1, autoPromoteRing: 'Broad', soakStartedAt: hoursAgo(5), promotedAt: hoursAgo(1) }).due, false);
|
|
assert.equal(evaluatePromotion({ autoPromoteAfterHours: 1, autoPromoteRing: '', soakStartedAt: hoursAgo(5) }).due, false);
|
|
});
|
|
|
|
// --- worker run -----------------------------------------------------------
|
|
|
|
test('runAutoPromotions promotes an eligible deployment and skips a soaking one', async () => {
|
|
const eligible = createIntuneDeployment({
|
|
name: 'Promote Me', visibility: 'shared', autoPromoteAfterHours: 1, autoPromoteRing: 'Broad', autoPromoteIntent: 'required',
|
|
assignments: [{ ring: 'Broad', intent: 'available', groupId: 'g1', groupMode: 'group' }]
|
|
}, owner);
|
|
const soaking = createIntuneDeployment({
|
|
name: 'Still Soaking', visibility: 'shared', autoPromoteAfterHours: 8, autoPromoteRing: 'Broad', autoPromoteIntent: 'required',
|
|
assignments: [{ ring: 'Broad', intent: 'available', groupId: 'g2', groupMode: 'group' }]
|
|
}, owner);
|
|
|
|
// Start the soak clock: eligible elapsed, soaking just started.
|
|
db.prepare('UPDATE intune_deployments SET soak_started_at = ? WHERE id = ?').run(hoursAgo(3), eligible.id);
|
|
db.prepare('UPDATE intune_deployments SET soak_started_at = ? WHERE id = ?').run(hoursAgo(1), soaking.id);
|
|
|
|
let pushed = 0;
|
|
const summary = await runAutoPromotions({ pusher: async () => { pushed += 1; } });
|
|
|
|
assert.ok(summary.promoted >= 1);
|
|
const promoted = loadDeploymentRaw(eligible.id);
|
|
assert.equal(promoted.assignments.find((a) => a.ring === 'Broad').intent, 'required');
|
|
assert.ok(promoted.promotedAt);
|
|
|
|
const stillSoaking = loadDeploymentRaw(soaking.id);
|
|
assert.equal(stillSoaking.assignments.find((a) => a.ring === 'Broad').intent, 'available');
|
|
assert.equal(stillSoaking.promotedAt, '');
|
|
// Neither deployment has a Graph connection, so nothing was pushed.
|
|
assert.equal(pushed, 0);
|
|
});
|