import assert from 'node:assert'; import fs from 'node:fs'; import { test } from 'node:test'; // Behavioral tests for the welcome-vs-renewal classification (the exact // decision invoice.paid makes), through the exported pure classifier. const { classifySubscriptionEmail } = await import('../src/licenseLogic.js'); // Simulated invoice.paid behavior against progressively-delivered license // state — no SMTP, no Stripe, no handler spin-up required; this is the same // state machine deliverAndTrackLicenseEmail drives via updateLicense(). test('classification behavior across the real webhook order', () => { const uniq = `classify_${Date.now()}`; const license = { id: `lic_${uniq}`, key: 'DC-20F00-0000D-NB3FN-S6HXJ-A7CA0', customerId: `cus_${uniq}`, subscriptionId: `sub_${uniq}`, emailDeliveredAt: null }; // State 1: license row exists (subscription.created already processed), // no email ever delivered -> invoice.paid must send the WELCOME email. assert.equal(classifySubscriptionEmail(license).extended, false, 'pre-created license with zero delivered emails = welcome'); // State 2: welcome email delivered (deliverAndTrackLicenseEmail sets this // via updateLicense after SMTP 250). Next invoice.paid = renewal. license.emailDeliveredAt = new Date().toISOString(); assert.equal(classifySubscriptionEmail(license).extended, true, 'license with a delivered email = extended/renewal'); }); test('classification survives missing/blank email state', () => { assert.equal(classifySubscriptionEmail(null).extended, false, 'null license cannot have delivered mail -> welcome'); assert.equal(classifySubscriptionEmail({}).extended, false, 'missing field -> welcome'); assert.equal(classifySubscriptionEmail({ emailDeliveredAt: '' }).extended, false, 'blank timestamp -> welcome'); assert.equal(classifySubscriptionEmail({ emailDeliveredAt: '2026-09-22T00:00:00.000Z' }).extended, true, 'real timestamp -> extended'); }); // The server must call the classifier, not inline its own logic. test('server.js delegates classification to classifySubscriptionEmail', () => { const src = fs.readFileSync(new URL('../src/server.js', import.meta.url), 'utf8'); assert.ok(src.includes('classifySubscriptionEmail(license).extended'), 'handler must use the shared classifier'); assert.ok(!src.includes('Boolean(license.emailDeliveredAt)'), 'no inline duplicate of the logic'); });