Files
Webklar-Kundenbereich/test/pushTimeMail.test.js
T

118 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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: '<script>x</script> & 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, /&lt;script&gt;x&lt;\/script&gt; &amp; Co/)
assert.doesNotMatch(out.html, /<script>/)
const token = mail.values.link_andere.split('/zeit/')[1]
assert.deepEqual(verifyPushTimeToken(token), { worksheetId: 'ws9', employeeId: 'k' })
})
test('buildPushTimeMail: 12 Commits → 10 Zeilen + Rest', () => {
const many = Array.from({ length: 12 }, (_, i) => ({ id: `${String(i).padStart(7, '0')}ffff`, message: `Commit ${i}` }))
const { values } = buildPushTimeMail({ employee: KENSO, ...input({ commits: many }) })
const lines = values.commits.split('\n')
assert.equal(lines.length, 11)
assert.equal(lines.at(-1), '… und 2 weitere')
assert.equal(values.anzahl_commits, 12)
})
test('buildPushTimeMail: lange Beschreibung gekürzt, ohne Kunde', () => {
const { values } = buildPushTimeMail({
employee: KENSO,
...input({ ticket: { ...ticket, customerName: '', details: 'x'.repeat(400), status: 'Weird' } }),
})
assert.equal(values.ticket_beschreibung.length, 301)
assert.ok(values.ticket_beschreibung.endsWith('…'))
assert.equal(values.kunde, 'ohne Kunde')
assert.equal(values.ticket_status, 'Weird')
})
test('sendPushTimeMail: an den Pusher, ohne BCC', async () => {
const sink = mailSink()
setMailTransportForTests(sink)
const r = await sendPushTimeMail({ ...input(), pusher: { username: 'knso' } })
assert.deepEqual(r, { sent: true })
assert.equal(sink.sent.length, 1)
assert.deepEqual(sink.sent[0].to.map((t) => t.address), ['kenso@webklar.com'])
assert.equal(sink.sent[0].from.name, 'WEBklar Kundenportal')
assert.equal(sink.sent[0].bcc, undefined)
})
test('sendPushTimeMail: unbekannter Pusher → keine Mail', async () => {
const sink = mailSink()
setMailTransportForTests(sink)
const r = await sendPushTimeMail({ ...input(), pusher: { username: 'fremd' } })
assert.equal(r.sent, false)
assert.equal(sink.sent.length, 0)
})
test('sendPushTimeMail: Versandfehler wird geschluckt', async () => {
setMailTransportForTests({ sendMail: async () => { throw new Error('SMTP kaputt') } })
const r = await sendPushTimeMail({ ...input(), pusher: { username: 'knso' } })
assert.equal(r.sent, false)
})