Files
ClaudeandClaude Opus 5.5 00ea4baf65 Chat: Kunde bekommt Mail, wenn das Team schreibt (K17)
Neue Vorlage K17 im Stil von K16 mit Nachricht, Absender und Link
auf den Portal-Chat. Hoechstens eine Mail je Kunde im Zeitfenster
CHAT_NOTIFY_THROTTLE_MIN (15 Min.), ohne BCC ans Team, nicht ohne
E-Mail-Adresse oder Portalzugang. Das Admin-Panel zeigt unter dem
Kundennamen, ob der Hinweis rausging.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 19:00:33 +00:00

55 lines
3.0 KiB
JavaScript

import { test, before, beforeEach } from 'node:test'
import assert from 'node:assert/strict'
import { mailSink } from './support/mailSink.js'
// K17: Hinweis an den Kunden, wenn das Team im Portal-Chat schreibt
let sendCustomerChatNotice, resetChatNoticeThrottleForTests, setMailTransportForTests
let sink
const customer = (extra = {}) => ({ $id: 'c1', name: 'Emma Schatz', email: 'emma@example.com', portalAccessEnabled: true, ...extra })
before(async () => {
Object.assign(process.env, { APPWRITE_ENDPOINT: 'http://127.0.0.1:9/v1', SMTP_HOST: '', CHAT_NOTIFY_EMAILS: 'team@webklar.invalid', PORTAL_PUBLIC_URL: 'https://project.webklar.com' })
;({ sendCustomerChatNotice, resetChatNoticeThrottleForTests, setMailTransportForTests } = await import('../server/services/mailer.js'))
})
beforeEach(() => {
sink = mailSink()
setMailTransportForTests(sink)
resetChatNoticeThrottleForTests()
})
test('Kunde bekommt K17 mit Nachricht und Portal-Link, ohne BCC ans Team', async () => {
const result = await sendCustomerChatNotice(customer(), { sender: 'Kenso Grimm', text: 'Hallo <Emma>\nZeile 2' })
assert.deepEqual(result, { sent: true, to: 'emma@example.com' })
assert.equal(sink.sent.length, 1)
const mail = sink.sent[0]
assert.deepEqual(mail.to.map((t) => t.address), ['emma@example.com'])
assert.ok(!mail.bcc, "keine Kopie ans Team")
assert.equal(mail.subject, 'Neue Nachricht von WEBklar')
assert.match(mail.html, /Hallo Emma Schatz,<br>Kenso Grimm hat Dir/)
assert.match(mail.html, /Hallo &lt;Emma&gt;<br>Zeile 2/)
assert.match(mail.html, /href="https:\/\/project\.webklar\.com\/dashboard\.html#chat"/)
assert.match(mail.text, /Hallo <Emma>\nZeile 2/)
})
test('höchstens eine Mail je Kunde im Zeitfenster, andere Kunden unabhängig', async () => {
assert.equal((await sendCustomerChatNotice(customer(), { sender: 'A', text: 'eins' })).sent, true)
assert.deepEqual(await sendCustomerChatNotice(customer(), { sender: 'A', text: 'zwei' }), { sent: false, reason: 'throttled', to: 'emma@example.com' })
assert.equal((await sendCustomerChatNotice(customer({ $id: 'c2', email: 'b@example.com' }), { sender: 'A', text: 'x' })).sent, true)
assert.equal(sink.sent.length, 2)
})
test('ohne E-Mail oder Portalzugang keine Mail', async () => {
assert.deepEqual(await sendCustomerChatNotice(customer({ email: '' }), { text: 'x' }), { sent: false, reason: 'keine E-Mail-Adresse' })
assert.deepEqual(await sendCustomerChatNotice(customer({ portalAccessEnabled: false }), { text: 'x' }), { sent: false, reason: 'kein Portalzugang' })
assert.equal(sink.sent.length, 0)
})
test('Versandfehler: Nachricht bleibt, nächster Versuch ist nicht gesperrt', async () => {
setMailTransportForTests({ sendMail: async () => { throw new Error('SMTP weg') } })
assert.deepEqual(await sendCustomerChatNotice(customer(), { text: 'x' }), { sent: false, reason: 'SMTP weg', to: 'emma@example.com' })
setMailTransportForTests(sink)
assert.equal((await sendCustomerChatNotice(customer(), { text: 'y' })).sent, true)
})