Projektarten: Mail T16 Repo zuordnen
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
08958dee77
commit
b8a530958f
3 files changed
+261
No files matched your search
@@ -0,0 +1,121 @@
|
||||
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 shouldSendAssignMail, dueReminder, sendRepoAssignMail
|
||||
let renderMail, setMailTransportForTests, getDocument
|
||||
|
||||
const NOW = new Date('2026-09-30T15:00:00Z')
|
||||
const hoursAgo = (h) => new Date(NOW.getTime() - h * 3600_000).toISOString()
|
||||
|
||||
const KENSO = { $id: 'k', displayName: 'Kenso Grimm', shortcode: 'KNSO', email: 'kenso@webklar.com', $createdAt: '2026-01-01T00:00:00.000Z' }
|
||||
const projectDoc = (extra = {}) => ({
|
||||
$id: 'p1',
|
||||
repoFullName: 'WEBklar/amin-friseur',
|
||||
giteaRepoUrl: 'https://git.webklar.com/WEBklar/amin-friseur',
|
||||
...extra,
|
||||
})
|
||||
|
||||
before(async () => {
|
||||
fake = await startFakeAppwrite({
|
||||
seed: {
|
||||
employees: [KENSO],
|
||||
websiteProjects: [projectDoc(), projectDoc({ $id: 'p2' }), projectDoc({ $id: 'p3' })],
|
||||
},
|
||||
})
|
||||
Object.assign(process.env, { APPWRITE_ENDPOINT: fake.endpoint, APPWRITE_API_KEY: 'test-key' })
|
||||
;({ shouldSendAssignMail, dueReminder, sendRepoAssignMail } = await import('../server/services/repoAssignMail.js'))
|
||||
;({ renderMail } = await import('../server/services/mailTemplates.js'))
|
||||
;({ setMailTransportForTests } = await import('../server/services/mailer.js'))
|
||||
;({ getDocument } = await import('../server/services/appwriteAdmin.js'))
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
setMailTransportForTests?.(null)
|
||||
await fake.close()
|
||||
})
|
||||
|
||||
const doc = (id) => getDocument(process.env.APPWRITE_COLLECTION_WEBSITE_PROJECTS || 'websiteProjects', id)
|
||||
|
||||
test('shouldSendAssignMail: nur neu angelegt, < 24 h, ohne Art, < 3 Versuche', () => {
|
||||
const repo = { created_at: hoursAgo(1) }
|
||||
assert.equal(shouldSendAssignMail({}, repo, { now: NOW, createdNow: true }), true)
|
||||
assert.equal(shouldSendAssignMail({}, repo, { now: NOW, createdNow: false }), false)
|
||||
assert.equal(shouldSendAssignMail({}, { created_at: hoursAgo(25) }, { now: NOW, createdNow: true }), false)
|
||||
assert.equal(shouldSendAssignMail({ kind: 'website' }, repo, { now: NOW, createdNow: true }), false)
|
||||
assert.equal(shouldSendAssignMail({ assignMailAttempts: 3 }, repo, { now: NOW, createdNow: true }), false)
|
||||
assert.equal(shouldSendAssignMail({ assignMailAttempts: 2 }, repo, { now: NOW, createdNow: true }), true)
|
||||
assert.equal(shouldSendAssignMail({ assignMailSentAt: hoursAgo(1) }, repo, { now: NOW, createdNow: true }), false)
|
||||
assert.equal(shouldSendAssignMail({}, {}, { now: NOW, createdNow: true }), false, 'ohne created_at keine Mail')
|
||||
})
|
||||
|
||||
test('dueReminder: genau nach 24 h, ohne Art, ohne frühere Erinnerung', () => {
|
||||
const base = { assignMailSentAt: hoursAgo(25) }
|
||||
assert.equal(dueReminder(base, { now: NOW }), true)
|
||||
assert.equal(dueReminder({ assignMailSentAt: hoursAgo(23) }, { now: NOW }), false)
|
||||
assert.equal(dueReminder({}, { now: NOW }), false)
|
||||
assert.equal(dueReminder({ ...base, kind: 'app' }, { now: NOW }), false)
|
||||
assert.equal(dueReminder({ ...base, assignReminderSentAt: hoursAgo(1) }, { now: NOW }), false)
|
||||
})
|
||||
|
||||
test('T16: rendert ohne Probleme, Betreff mit und ohne Erinnerung', () => {
|
||||
const values = {
|
||||
betreff_vorsatz: '', vorname: 'Kenso', repo: 'WEBklar/x', repo_link: 'https://git.webklar.com/WEBklar/x',
|
||||
angelegt_von: 'Kenso Grimm', angelegt_am: '30.09.2026 17:00', zuordnen_link: 'https://ticket.webklar.com/projects/zuordnen/p1',
|
||||
}
|
||||
const plain = renderMail('T16', values)
|
||||
assert.deepEqual(plain.problems, [])
|
||||
assert.equal(plain.subject, 'Neues Repo zuordnen: WEBklar/x')
|
||||
assert.doesNotMatch(plain.html, /einzige Erinnerung/)
|
||||
const rem = renderMail('T16', { ...values, betreff_vorsatz: 'Erinnerung: ' }, { erinnerung: true })
|
||||
assert.equal(rem.subject, 'Erinnerung: Neues Repo zuordnen: WEBklar/x')
|
||||
assert.match(rem.html, /einzige Erinnerung/)
|
||||
})
|
||||
|
||||
test('sendRepoAssignMail: Mail mit exaktem Link, setzt assignMailSentAt + Versuche', async () => {
|
||||
const sink = mailSink()
|
||||
setMailTransportForTests(sink)
|
||||
const r = await sendRepoAssignMail(projectDoc({ $id: 'p1', $createdAt: '2026-09-30T14:46:00Z' }), { giteaLogin: '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].subject, 'Neues Repo zuordnen: WEBklar/amin-friseur')
|
||||
assert.match(sink.sent[0].html, /href="https:\/\/ticket\.webklar\.com\/projects\/zuordnen\/p1"/)
|
||||
assert.match(sink.sent[0].html, /30\.09\.2026 16:46/)
|
||||
const d = await doc('p1')
|
||||
assert.ok(d.assignMailSentAt)
|
||||
assert.equal(d.assignMailAttempts, 1)
|
||||
})
|
||||
|
||||
test('sendRepoAssignMail: Erinnerung setzt assignReminderSentAt', async () => {
|
||||
const sink = mailSink()
|
||||
setMailTransportForTests(sink)
|
||||
const r = await sendRepoAssignMail(projectDoc({ $id: 'p1', assignMailAttempts: 1 }), { giteaLogin: 'knso', reminder: true })
|
||||
assert.deepEqual(r, { sent: true })
|
||||
assert.match(sink.sent[0].subject, /^Erinnerung: Neues Repo zuordnen/)
|
||||
const d = await doc('p1')
|
||||
assert.ok(d.assignReminderSentAt)
|
||||
assert.equal(d.assignMailAttempts, 2)
|
||||
})
|
||||
|
||||
test('sendRepoAssignMail: unbekannter Login → no_employee, kein Zähler', async () => {
|
||||
const sink = mailSink()
|
||||
setMailTransportForTests(sink)
|
||||
const r = await sendRepoAssignMail(projectDoc({ $id: 'p2' }), { giteaLogin: 'fremd' })
|
||||
assert.deepEqual(r, { sent: false, reason: 'no_employee' })
|
||||
assert.equal(sink.sent.length, 0)
|
||||
const d = await doc('p2')
|
||||
assert.equal(d.assignMailAttempts, undefined)
|
||||
assert.equal(d.assignMailSentAt, undefined)
|
||||
})
|
||||
|
||||
test('sendRepoAssignMail: SMTP-Fehler zählt Versuch, setzt kein SentAt, wirft nie', async () => {
|
||||
setMailTransportForTests({ sendMail: async () => { throw new Error('SMTP kaputt') } })
|
||||
const r = await sendRepoAssignMail(projectDoc({ $id: 'p3', assignMailAttempts: 1 }), { giteaLogin: 'knso' })
|
||||
assert.equal(r.sent, false)
|
||||
const d = await doc('p3')
|
||||
assert.equal(d.assignMailAttempts, 2)
|
||||
assert.equal(d.assignMailSentAt, undefined)
|
||||
})
|
||||
Reference in new issue
Block a user