import { test, before, after } from 'node:test' import assert from 'node:assert/strict' import { startFakeAppwrite } from './helpers/fakeAppwrite.js' import { mailSink } from './support/mailSink.js' let fake let findEmployeeForPusher, buildPushTimeMail, sendPushTimeMail let renderMail, verifyPushTimeToken, setMailTransportForTests const KENSO = { $id: 'k', displayName: 'Kenso Grimm', shortcode: 'KNSO', email: 'kenso@webklar.com', $createdAt: '2026-01-01T00:00:00.000Z' } const ANDREJ = { $id: 'a', displayName: 'Andrej Stevanovski', shortcode: 'ANDJ', email: '', $createdAt: '2026-01-02T00:00:00.000Z' } const ticket = { $id: 't1', woid: '100118', customerName: 'Amin Friseur', topic: 'Website Amin Friseur', details: 'Neue Seite', status: 'Occupied' } const worksheet = { $id: 'ws9', woid: '100118', serviceType: 'GIT' } const commits = [ { id: 'abc1234def', message: 'Startseite: Hero neu\n\nlanger Text' }, { id: 'def5678abc', message: ' & Co' }, ] const input = (extra = {}) => ({ ticket, worksheet, repoFullName: 'WEBklar/amin-friseur', branch: 'main', commits, pushedAt: new Date('2026-09-30T14:46:00Z'), ...extra, }) before(async () => { fake = await startFakeAppwrite({ seed: { employees: [ANDREJ, KENSO] } }) Object.assign(process.env, { APPWRITE_ENDPOINT: fake.endpoint, APPWRITE_API_KEY: 'test-key', PUSH_TIME_SECRET: 'z'.repeat(40), }) ;({ findEmployeeForPusher, buildPushTimeMail, sendPushTimeMail } = await import('../server/services/pushTimeMail.js')) ;({ renderMail } = await import('../server/services/mailTemplates.js')) ;({ verifyPushTimeToken } = await import('../server/services/pushTimeToken.js')) ;({ setMailTransportForTests } = await import('../server/services/mailer.js')) }) after(async () => { setMailTransportForTests?.(null) await fake.close() }) test('findEmployeeForPusher: Kürzel, voller Name, ohne E-Mail, unbekannt', () => { const employees = [ANDREJ, KENSO] assert.equal(findEmployeeForPusher({ username: 'knso' }, employees)?.$id, 'k') assert.equal(findEmployeeForPusher({ full_name: ' kenso grimm ' }, employees)?.$id, 'k') assert.equal(findEmployeeForPusher({ login: 'ANDJ' }, employees), null) assert.equal(findEmployeeForPusher({ username: 'fremd' }, employees), null) assert.equal(findEmployeeForPusher({}, employees), null) }) test('buildPushTimeMail: Betreff, Links, Escaping, gültiger Token', () => { const mail = buildPushTimeMail({ employee: KENSO, ...input() }) assert.equal(mail.template, 'T15') const out = renderMail('T15', mail.values) assert.deepEqual(out.problems, []) assert.equal(out.subject, '[Zeit] #100118 Amin Friseur – 2 Commit(s)') assert.match(out.html, /Hallo Kenso,/) assert.match(out.html, /In Arbeit/) assert.match(out.html, /30\.09\.2026 16:46/) for (const m of [15, 30, 45, 60, 90, 120, 180]) { assert.match(out.html, new RegExp(`/zeit/[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\?min=${m}"`)) } assert.match(out.html, /\/zeit\/[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+"/, 'Andere Zeit ohne min') assert.match(out.html, /https:\/\/ticket\.webklar\.com\/tickets\?woid=100118/) assert.match(out.html, /abc1234 Startseite: Hero neu/) assert.doesNotMatch(out.html, /langer Text/) assert.match(out.html, /<script>x<\/script> & Co/) assert.doesNotMatch(out.html, /