import assert from 'node:assert'; import fs from 'node:fs'; import { test } from 'node:test'; // Render-only tests: no SMTP, no store. email.js imports only nodemailer. const { renderLicenseEmail } = await import('../src/email.js'); const base = { code: 'DC-20F00-0000D-NB3FN-S6HXJ-A7CA0', durationDays: 30, planCode: 'premium_30d', expiresAt: '2026-10-21T23:33:00.000Z' }; test('first purchase renders WELCOME email with walkthrough', () => { const mail = renderLicenseEmail({ ...base, extended: false }); assert.equal(mail.subject, 'Your DashCaddy Premium license key', 'first purchase subject must NOT say "extended"'); assert.ok(!/extended/i.test(mail.subject), 'subject must contain no extended wording'); assert.ok(mail.html.includes('Welcome to DashCaddy Premium'), 'welcome headline'); assert.ok(mail.html.includes('What your subscription unlocks'), 'unlocks panel'); assert.ok(mail.html.includes('Auto-Login SSO'), 'feature: SSO'); assert.ok(mail.html.includes('Recipes'), 'feature: Recipes'); assert.ok(mail.html.includes('Swarm orchestration'), 'feature: Swarm'); assert.ok(mail.html.includes('Automatic renewals'), 'feature: auto-renewal value prop'); assert.ok(mail.html.includes('Getting started takes about a minute'), 'getting-started steps'); assert.ok(mail.html.includes('Admin'), 'activation path shown'); assert.ok(mail.text.includes('YOUR SUBSCRIPTION INCLUDES:'), 'plain text unlocks block'); assert.ok(mail.text.includes('GETTING STARTED:'), 'plain text steps block'); assert.equal((mail.text.match(/To activate:/g) || []).length, 0, 'welcome email replaces the bare activation line with the 3-step block'); assert.ok(mail.text.includes('Paste your license key and click Activate'), 'activation still covered, inside the getting-started steps'); assert.equal((mail.html.match(/data:image/g) || []).length, 2, 'two embedded logos (DashCaddy header + samiahmed7777 footer)'); }); test('renewal email keeps the extended copy and has NO welcome content', () => { const mail = renderLicenseEmail({ ...base, extended: true }); assert.equal(mail.subject, 'Your DashCaddy Premium license has been extended (30 days added)'); assert.ok(mail.html.includes('License extended'), 'extended headline'); assert.ok(!mail.html.includes('Welcome to DashCaddy Premium'), 'no welcome headline'); assert.ok(!mail.html.includes('What your subscription unlocks'), 'no unlocks panel'); assert.ok(!mail.html.includes('Getting started takes about a minute'), 'no getting-started steps'); assert.ok(!mail.text.includes('YOUR SUBSCRIPTION INCLUDES:'), 'plain text: no unlocks block'); assert.ok(!mail.text.includes('GETTING STARTED:'), 'plain text: no steps block'); assert.equal((mail.text.match(/To activate:/g) || []).length, 1, 'renewal keeps its single activation line'); }); test('render matches production send path (sendLicenseEmail wraps renderLicenseEmail)', async () => { const src = fs.readFileSync(new URL('../src/email.js', import.meta.url), 'utf8'); assert.ok(src.includes('renderLicenseEmail({ code, durationDays, planCode, expiresAt, extended })'), 'sendLicenseEmail must delegate to renderLicenseEmail — one shared code path'); assert.ok(src.includes('export async function sendLicenseEmail'), 'send path still exported'); });