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); });