329 lines
18 KiB
JavaScript
329 lines
18 KiB
JavaScript
import { test, after, beforeEach } from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { startAppwriteMock } from './support/appwriteMock.js'
|
|
import { startFakeStripe } from './support/fakeStripe.js'
|
|
import { useTestEnv } from './support/testEnv.js'
|
|
import { schemaKeys } from './support/schema.js'
|
|
|
|
// Buchungskalender Task 11: Funktion bestellen "auf Anfrage", Freischaltung, Ticket-Details, Team-API
|
|
const NAMEN = ['portalFeatures', 'ukEinstellungen', 'ukUnterkuenfte', 'ukPreise', 'ukAnfragen', 'ukSperren', 'ukRechnungen', 'featureConsents']
|
|
const aw = await startAppwriteMock({
|
|
schema: Object.fromEntries(NAMEN.map((n) => [n, schemaKeys(n)])),
|
|
datetimes: { ukEinstellungen: ['rechnungAuftragAt', 'anfrageAt', 'anfrageEntschiedenAt', 'icalFehlerMailAt'] },
|
|
})
|
|
const st = await startFakeStripe()
|
|
useTestEnv({ appwriteUrl: aw.url, stripeUrl: st.url })
|
|
const { config } = await import('../server/config.js')
|
|
const { startTestApp, send, rawGet, post: rawPost } = await import('./support/testApp.js')
|
|
const { customerCookie, kundenansichtCookie, seedFixtures, customers } = await import('./support/fixtures.js')
|
|
const { deleteDocument } = await import('../server/services/appwriteAdmin.js')
|
|
const { renderMail } = await import('../server/services/mailTemplates.js')
|
|
const af = await import('../server/services/unterkunft/anfrageFunktion.js')
|
|
const { freischaltbar } = await import('../server/services/unterkunft/freischaltung.js')
|
|
const { unterkunftTicketDetails } = await import('../server/services/unterkunft/ticketDetails.js')
|
|
const { featureHaken } = await import('../server/services/featureRegistry.js')
|
|
const { default: ukRoutes, resetUnterkunftRoutesForTests } = await import('../server/routes/unterkunft.js')
|
|
const { default: teamRoutes } = await import('../server/routes/team/index.js')
|
|
const { kundenansichtGuard } = await import('../server/middleware/kundenansichtGuard.js')
|
|
|
|
const app = await startTestApp({ '/': kundenansichtGuard, '/api/unterkunft': ukRoutes, '/api/team': teamRoutes })
|
|
after(() => Promise.all([app.close(), aw.close(), st.close()]))
|
|
|
|
seedFixtures(aw)
|
|
aw.seed('employees', { $id: 'e_staff2', userId: 'u_staff2', displayName: 'Andrej', email: 'andrej@webklar.com' })
|
|
const P = 'pu1'
|
|
const FEATURE = `f_${P}_unterkunft`
|
|
const cookie = customerCookie('c1')
|
|
const staff = { headers: { authorization: 'Bearer jwt-staff' } }
|
|
const person = { name: 'Kunde Eins', email: customers.c1.email }
|
|
const vorher = { ...config.unterkunft }
|
|
const GUELTIG = { art: 'ferienwohnung', einheiten: 3, portale: ['booking', 'airbnb'], nachricht: 'Hallo' }
|
|
const stelle = (b = {}, opts = { cookie }) => send('POST', `/api/unterkunft/anfrage-funktion?projectId=${P}`, { ...opts, body: { ...GUELTIG, ...b } })
|
|
const zurueck = (opts = { cookie }) => send('POST', `/api/unterkunft/anfrage-funktion/zurueckziehen?projectId=${P}`, { ...opts, body: {} })
|
|
const status = (opts = { cookie }) => send('GET', `/api/unterkunft/status?projectId=${P}`, opts)
|
|
const entscheide = (b, opts = staff) => rawPost(`/api/team/unterkunft/c1/anfrage`, { projectId: P, ...b }, opts)
|
|
const einst = () => aw.docs('ukEinstellungen').get(FEATURE) ?? null
|
|
|
|
// Mails: die Aufrufe werden festgehalten und gegen die echten Vorlagen K34/T23 gerendert (problems muss leer bleiben)
|
|
const aufrufe = { admin: [], kunde: [], probleme: [], adminFehler: false, kundeFehler: false }
|
|
af._versand.admin = async (m) => {
|
|
aufrufe.admin.push(m)
|
|
aufrufe.probleme.push(...renderMail(m.template, m.values, m.blocks ?? {}).problems.map((x) => `${m.template}: ${x}`))
|
|
if (aufrufe.adminFehler) throw new Error('SMTP')
|
|
return { sent: true }
|
|
}
|
|
af._versand.kunde = async (an, m) => {
|
|
aufrufe.kunde.push({ an, ...m })
|
|
aufrufe.probleme.push(...renderMail(m.template, m.values, m.blocks ?? {}).problems.map((x) => `${m.template}: ${x}`))
|
|
if (aufrufe.kundeFehler) throw new Error('SMTP')
|
|
}
|
|
|
|
beforeEach(async () => {
|
|
for (const c of [...NAMEN, 'websiteProjects']) for (const id of [...aw.docs(c).keys()]) await deleteDocument(config.collections[c], id)
|
|
Object.assign(config.unterkunft, vorher, { mode: 'pilot', pilotEmails: [customers.c1.email] })
|
|
resetUnterkunftRoutesForTests()
|
|
aufrufe.admin.length = 0
|
|
aufrufe.probleme.length = 0
|
|
aufrufe.kunde.length = 0
|
|
aufrufe.adminFehler = aufrufe.kundeFehler = false
|
|
aw.seed('websiteProjects', { $id: P, customerId: 'c1', projectName: 'Donau', archived: false })
|
|
aw.seed('websiteProjects', { $id: 'pfremd', customerId: 'c2', projectName: 'Fremd' })
|
|
})
|
|
|
|
test('normalisiereAnfrage: gueltig, Alias monteur, Fehler je Feld', () => {
|
|
const ok = af.normalisiereAnfrage({ ...GUELTIG, art: 'monteur', x: 1 })
|
|
assert.deepEqual(ok.anfrage, { art: 'monteurzimmer', einheiten: 3, portale: ['booking', 'airbnb'], nachricht: 'Hallo' })
|
|
const f = (a) => af.normalisiereAnfrage({ ...GUELTIG, ...a }).fehler
|
|
assert.ok(f({ art: 'villa' }).art)
|
|
assert.ok(f({ art: 'constructor' }).art)
|
|
assert.ok(f({ einheiten: 0 }).einheiten)
|
|
assert.ok(f({ einheiten: '3' }).einheiten)
|
|
assert.ok(f({ einheiten: 1000 }).einheiten)
|
|
assert.equal(f({ einheiten: 999 }), undefined)
|
|
assert.ok(f({ portale: ['ebay'] }).portale)
|
|
assert.ok(f({ portale: 'booking' }).portale)
|
|
assert.deepEqual(af.normalisiereAnfrage({ ...GUELTIG, portale: [] }).anfrage.portale, [])
|
|
assert.deepEqual(af.normalisiereAnfrage({ ...GUELTIG, portale: true }).anfrage.portale, ['andere'])
|
|
assert.ok(f({ nachricht: 'n'.repeat(1001) }).nachricht)
|
|
assert.equal(af.normalisiereAnfrage({ ...GUELTIG, nachricht: undefined }).anfrage.nachricht, '')
|
|
assert.ok(af.normalisiereAnfrage(null).fehler.art)
|
|
})
|
|
|
|
test('Anfrage stellen: gespeichert, T23 ans Team, Status-Block fuer state off', async () => {
|
|
const leer = await status()
|
|
assert.equal(leer.status, 200)
|
|
assert.equal(leer.body.state, 'off')
|
|
assert.equal(leer.body.anfrage, null)
|
|
const res = await stelle({ art: 'monteur' })
|
|
assert.equal(res.status, 200)
|
|
assert.equal(res.body.anfrage.status, 'offen')
|
|
assert.equal(res.body.anfrage.anfrage.art, 'monteur', 'das Portal liest monteur')
|
|
assert.deepEqual(res.body.anfrage.anfrage.portale, ['booking', 'airbnb'])
|
|
assert.equal(einst().anfrageStatus, 'offen')
|
|
assert.equal(JSON.parse(einst().anfrage).art, 'monteurzimmer')
|
|
assert.equal(aw.docs('portalFeatures').get(FEATURE).state, 'off')
|
|
assert.equal(aufrufe.admin.length, 1)
|
|
assert.equal(aufrufe.admin[0].template, 'T23')
|
|
assert.equal(aufrufe.admin[0].values.projekt, 'Donau')
|
|
assert.match(aufrufe.admin[0].values.nachricht, /^Art: Monteurwohnung\nEinheiten: 3\nPortale: Booking\.com, Airbnb/)
|
|
assert.equal(aufrufe.admin[0].values.woms_url, `${config.womsBaseUrl}/customers/c1?tab=funktionen`)
|
|
assert.equal(aufrufe.kunde.length, 0)
|
|
const s = (await status()).body.anfrage
|
|
assert.equal(s.status, 'offen')
|
|
assert.ok(s.at)
|
|
assert.deepEqual(Object.keys(s.anfrage).sort(), ['art', 'einheiten', 'nachricht', 'portale'])
|
|
})
|
|
|
|
test('Anfrage: doppelt 409, nur bei state off, Eingabefehler, Schalter, fremdes Projekt, Kundenansicht', async () => {
|
|
assert.equal((await stelle()).status, 200)
|
|
const doppelt = await stelle()
|
|
assert.equal(doppelt.status, 409)
|
|
assert.equal(doppelt.body.fehler, 'anfrage_laeuft')
|
|
assert.equal(aufrufe.admin.length, 1)
|
|
|
|
await deleteDocument(config.collections.ukEinstellungen, FEATURE)
|
|
aw.seed('portalFeatures', { $id: FEATURE, customerId: 'c1', projectId: P, featureKey: 'unterkunft', siteKey: 'abcdefghijklmnop', state: 'active', enabled: true })
|
|
const aktiv = await stelle()
|
|
assert.equal(aktiv.status, 409)
|
|
assert.equal(aktiv.body.fehler, 'vorhanden')
|
|
aw.seed('portalFeatures', { $id: FEATURE, customerId: 'c1', projectId: P, featureKey: 'unterkunft', siteKey: 'abcdefghijklmnop', state: 'off', enabled: false })
|
|
|
|
const schlecht = await stelle({ einheiten: 0, art: 'x' })
|
|
assert.equal(schlecht.status, 400)
|
|
assert.equal(schlecht.body.fehler, 'ungueltig')
|
|
assert.ok(schlecht.body.felder.einheiten && schlecht.body.felder.art)
|
|
assert.equal(einst(), null)
|
|
|
|
assert.equal((await send('POST', '/api/unterkunft/anfrage-funktion?projectId=pfremd', { cookie, body: GUELTIG })).status, 403)
|
|
assert.equal((await send('POST', '/api/unterkunft/anfrage-funktion', { cookie, body: GUELTIG })).status, 400)
|
|
assert.equal((await stelle({}, {})).status, 401)
|
|
assert.equal((await stelle({}, { cookie: kundenansichtCookie(), headers: { 'x-kundenansicht': 'a'.repeat(32) } })).status, 403)
|
|
config.unterkunft.mode = 'off'
|
|
const aus = await stelle()
|
|
assert.equal(aus.status, 409)
|
|
assert.equal(aus.body.fehler, 'nicht_verfuegbar')
|
|
assert.equal(einst(), null)
|
|
})
|
|
|
|
test('Anfrage: Mail-Fehler bei T23 verhindert nichts; Grenze 20 je Stunde', async () => {
|
|
aufrufe.adminFehler = true
|
|
assert.equal((await stelle()).status, 200)
|
|
assert.equal(einst().anfrageStatus, 'offen')
|
|
let letzter
|
|
for (let i = 0; i < 20; i++) letzter = await zurueck()
|
|
assert.equal(letzter.status, 429)
|
|
})
|
|
|
|
test('zurueckziehen: nur offen; danach neue Anfrage moeglich; Status-Block zeigt keine zurueckgezogene', async () => {
|
|
assert.equal((await zurueck()).status, 409)
|
|
await stelle()
|
|
const z = await zurueck()
|
|
assert.equal(z.status, 200)
|
|
assert.equal(z.body.anfrage.status, 'zurueckgezogen')
|
|
assert.equal((await status()).body.anfrage, null)
|
|
assert.equal((await zurueck()).status, 409)
|
|
assert.equal((await stelle({ einheiten: 5 })).status, 200)
|
|
assert.equal(JSON.parse(einst().anfrage).einheiten, 5)
|
|
})
|
|
|
|
test('Team: Uebersicht je Projekt und Entscheidung annehmen/ablehnen mit K34', async () => {
|
|
assert.equal((await rawGet('/api/team/unterkunft/c1', {})).status, 401)
|
|
const leer = (await rawGet('/api/team/unterkunft/c1', staff)).body.projects
|
|
assert.equal(leer.length, 1)
|
|
assert.deepEqual(leer[0], { projectId: P, name: 'Donau', state: 'off', unterkuenfte: 0, offeneAnfragen: 0, stripe: { accountId: false, status: null }, anfrage: null })
|
|
await stelle({ art: 'monteur', portale: [] })
|
|
const p = (await rawGet('/api/team/unterkunft/c1', staff)).body.projects[0]
|
|
assert.equal(p.anfrage.status, 'offen')
|
|
assert.equal(p.anfrage.art, 'monteurzimmer')
|
|
assert.equal(p.anfrage.einheiten, 3)
|
|
assert.equal(p.anfrage.portale, false)
|
|
|
|
assert.equal((await entscheide({ entscheidung: 'vielleicht' })).status, 400)
|
|
const ohneGrund = await entscheide({ entscheidung: 'ablehnen', begruendung: ' ' })
|
|
assert.equal(ohneGrund.status, 400)
|
|
assert.equal(einst().anfrageStatus, 'offen')
|
|
|
|
assert.deepEqual(await featureHaken('unterkunft').bestellpruefung({ customerId: 'c1', projectId: P }), [af.ANFRAGE_OFFEN_TEXT])
|
|
const ab = await entscheide({ entscheidung: 'ablehnen', begruendung: 'Passt nicht.' })
|
|
assert.equal(ab.status, 200)
|
|
assert.equal(ab.body.anfrage.status, 'abgelehnt')
|
|
assert.equal(aufrufe.kunde.length, 1)
|
|
assert.equal(aufrufe.kunde[0].template, 'K34')
|
|
assert.equal(aufrufe.kunde[0].an, customers.c1.email)
|
|
assert.equal(aufrufe.kunde[0].values.begruendung, 'Passt nicht.')
|
|
assert.equal(aufrufe.kunde[0].values.portal_url, `${config.publicBaseUrl}/dashboard.html#buchungen?projekt=${P}`)
|
|
assert.deepEqual(aufrufe.kunde[0].blocks, { angenommen: false, abgelehnt: true })
|
|
assert.equal((await status()).body.anfrage.begruendung, 'Passt nicht.')
|
|
assert.equal((await entscheide({ entscheidung: 'annehmen' })).status, 409, 'nicht mehr offen')
|
|
|
|
await stelle()
|
|
assert.equal(einst().anfrageBegruendung, '', 'neue Anfrage loescht die Entscheidung')
|
|
aufrufe.kundeFehler = true
|
|
const an = await entscheide({ entscheidung: 'annehmen' })
|
|
assert.equal(an.status, 200)
|
|
assert.equal(an.body.mailFehler, true)
|
|
assert.equal(an.body.anfrage.status, 'angenommen')
|
|
assert.equal(einst().anfrageEntschiedenVon, 'Andrej <andrej@webklar.com>')
|
|
assert.deepEqual(aufrufe.kunde.at(-1).blocks, { angenommen: true, abgelehnt: false })
|
|
assert.deepEqual(await af.anfrageOffenePunkte({ customerId: 'c1', projectId: P }), [])
|
|
assert.deepEqual(await featureHaken('unterkunft').bestellpruefung({ customerId: 'c1', projectId: P }), [])
|
|
assert.equal((await status()).body.anfrage.status, 'angenommen')
|
|
// fremdes Projekt des Kunden
|
|
assert.equal((await rawPost('/api/team/unterkunft/c1/anfrage', { projectId: 'pfremd', entscheidung: 'annehmen' }, staff)).status, 403)
|
|
})
|
|
|
|
test('Team: Stripe-Form wie Webshop, Entscheidung nur bei state off, Status ohne Lesefehler-500', async () => {
|
|
await stelle()
|
|
aw.seed('ukEinstellungen', { ...einst(), stripeAccountId: 'acct_1', stripeStatus: JSON.stringify({ charges_enabled: true }) })
|
|
const p = (await rawGet('/api/team/unterkunft/c1', staff)).body.projects[0]
|
|
assert.deepEqual(p.stripe, { accountId: true, status: { charges_enabled: true } })
|
|
aw.seed('portalFeatures', { ...aw.docs('portalFeatures').get(FEATURE), state: 'setup' })
|
|
assert.equal((await entscheide({ entscheidung: 'annehmen' })).status, 409)
|
|
aw.seed('portalFeatures', { ...aw.docs('portalFeatures').get(FEATURE), state: 'off' })
|
|
const echt = config.collections.ukEinstellungen
|
|
config.collections.ukEinstellungen = 'gibt_es_nicht'
|
|
try {
|
|
const s = await status()
|
|
assert.equal(s.status, 200)
|
|
assert.equal(s.body.anfrage, null)
|
|
} finally {
|
|
config.collections.ukEinstellungen = echt
|
|
}
|
|
})
|
|
|
|
test('anfrageOffenePunkte: ohne Dokumente offen, Lesefehler wird weitergereicht', async () => {
|
|
assert.equal((await af.anfrageOffenePunkte({ customerId: 'c1', projectId: P })).length, 1)
|
|
aw.seed('portalFeatures', { $id: FEATURE, customerId: 'c1', projectId: P, featureKey: 'unterkunft', siteKey: 'abcdefghijklmnop', state: 'off', enabled: false })
|
|
assert.equal((await af.anfrageOffenePunkte({ customerId: 'c1', projectId: P })).length, 1)
|
|
})
|
|
|
|
// ------------------------------------------------------------------------------------------------ Freischaltung
|
|
|
|
const EINST = {
|
|
firma: 'Donau Home', strasse: 'Weg 1', plz: '78576', ort: 'Stetten', email: 'mimi@example.com', steuernummer: '12/345/67890', ustId: '',
|
|
rechnungAuftragAt: '2026-10-01T00:00:00.000Z',
|
|
}
|
|
const PREISE = {
|
|
staffeln: JSON.stringify([{ abNaechten: 1, preisProNachtCent: 10000 }]), reinigungCent: 5000, personenInklusive: 2, aufpreisPersonNachtCent: 1500,
|
|
direktrabattProzent: 0, steuerart: 'regel', ustUebernachtung: 7, ustReinigung: 19, fristTage: 3, stornobedingungen: 'Kostenlos bis 7 Tage vor Anreise.',
|
|
}
|
|
function seedFrei({ einst = {}, aktiv = true, preise = {} } = {}) {
|
|
aw.seed('portalFeatures', { $id: FEATURE, customerId: 'c1', projectId: P, featureKey: 'unterkunft', siteKey: 'abcdefghijklmnop', state: 'setup', enabled: false })
|
|
aw.seed('ukEinstellungen', { $id: FEATURE, featureId: FEATURE, ...EINST, ...einst })
|
|
aw.seed('ukUnterkuenfte', { $id: 'u1', featureId: FEATURE, customerId: 'c1', projectId: P, name: 'Erste', maxPersonen: 4, aktiv, sort: 1 })
|
|
aw.seed('ukPreise', { $id: 'pr1', unterkunftId: 'u1', featureId: FEATURE, ...PREISE, ...preise })
|
|
}
|
|
const doc = () => aw.docs('portalFeatures').get(FEATURE)
|
|
|
|
test('freischaltbar: false ohne Daten, true mit vollstaendigen Daten, je Pflicht eine Gegenprobe', async () => {
|
|
assert.equal(await freischaltbar({ $id: FEATURE }), false)
|
|
assert.equal(await freischaltbar(null), false)
|
|
seedFrei()
|
|
assert.equal(await freischaltbar(doc()), true)
|
|
assert.equal(await featureHaken('unterkunft').freischaltbar(doc()), true)
|
|
const ust = { steuernummer: '', ustId: 'DE123456789' }
|
|
for (const [name, kaputt] of [
|
|
['Firma', { einst: { firma: '' } }], ['Strasse', { einst: { strasse: ' ' } }], ['PLZ', { einst: { plz: '' } }], ['Ort', { einst: { ort: '' } }],
|
|
['E-Mail', { einst: { email: '' } }], ['Steuer', { einst: { steuernummer: '', ustId: '' } }], ['Auftrag', { einst: { rechnungAuftragAt: null } }],
|
|
['Unterkunft inaktiv', { aktiv: false }], ['Preise leer', { preise: { staffeln: '[]' } }], ['Storno leer', { preise: { stornobedingungen: ' ' } }],
|
|
]) {
|
|
await beforeEachClear()
|
|
seedFrei(kaputt)
|
|
assert.equal(await freischaltbar(doc()), false, name)
|
|
}
|
|
await beforeEachClear()
|
|
seedFrei({ einst: ust })
|
|
assert.equal(await freischaltbar(doc()), true, 'ustId statt Steuernummer')
|
|
})
|
|
|
|
async function beforeEachClear() {
|
|
for (const c of ['portalFeatures', 'ukEinstellungen', 'ukUnterkuenfte', 'ukPreise']) for (const id of [...aw.docs(c).keys()]) await deleteDocument(config.collections[c], id)
|
|
}
|
|
|
|
test('freischaltbar: Lesefehler => false (fail-closed)', async () => {
|
|
seedFrei()
|
|
const d = doc()
|
|
const echt = config.collections.ukPreise
|
|
config.collections.ukPreise = 'gibt_es_nicht'
|
|
try {
|
|
assert.equal(await freischaltbar(d), false)
|
|
} finally {
|
|
config.collections.ukPreise = echt
|
|
}
|
|
})
|
|
|
|
test('ticketDetails: siteKey, Snippet, Schritte, Verweis, Anfrage; wirft nie', async () => {
|
|
seedFrei()
|
|
aw.seed('ukEinstellungen', { $id: FEATURE, featureId: FEATURE, ...EINST, anfrage: JSON.stringify({ art: 'pension', einheiten: 4, portale: ['airbnb'], nachricht: 'x' }), anfrageStatus: 'angenommen' })
|
|
const text = await unterkunftTicketDetails({ doc: doc(), project: { projectName: 'Donau' }, customer: { name: 'Mimi' } })
|
|
assert.match(text, /siteKey: abcdefghijklmnop/)
|
|
assert.ok(text.includes('<div data-webklar-unterkunft="abcdefghijklmnop" data-api="https://project.webklar.com"></div>'))
|
|
assert.ok(text.includes('<script src="https://project.webklar.com/embed/unterkunft.js" defer></script>'))
|
|
assert.match(text, /docs\/funktionen\/unterkunft-einbau\.md/)
|
|
assert.match(text, /Art: Pension oder Gästezimmer, Einheiten: 4, Portale: Airbnb/)
|
|
assert.match(text, /Funktion: Buchungskalender/)
|
|
assert.match(text, /CSS-Variablen/)
|
|
assert.match(text, /--wku-akzent, --wku-akzent-text, --wku-hintergrund, --wku-text, --wku-rand, --wku-radius, --wku-schrift, --wku-schrift-titel/)
|
|
assert.doesNotMatch(text, /wk-uk-/)
|
|
assert.match(text, /Verweis: /)
|
|
const notfall = await unterkunftTicketDetails(null)
|
|
assert.match(notfall, /Buchungskalender/)
|
|
const viaConfig = await config.features.unterkunft.ticket.details({ doc: doc(), project: {}, customer: null, feature: { key: 'Buchungskalender' } })
|
|
assert.ok(viaConfig.includes('abcdefghijklmnop'))
|
|
})
|
|
|
|
test('T23 und K34 (angenommen und abgelehnt) passen zu den Vorlagen: keine Platzhalter-Probleme', async () => {
|
|
assert.equal((await stelle({ nachricht: 'Hallo\nZeile 2' })).status, 200)
|
|
assert.equal((await entscheide({ entscheidung: 'ablehnen', begruendung: 'Passt nicht.' })).status, 200)
|
|
assert.equal((await stelle()).status, 200)
|
|
assert.equal((await entscheide({ entscheidung: 'annehmen' })).status, 200)
|
|
assert.deepEqual(aufrufe.admin.map((m) => m.template), ['T23', 'T23'])
|
|
assert.deepEqual(aufrufe.kunde.map((m) => m.template), ['K34', 'K34'])
|
|
assert.deepEqual(aufrufe.probleme, [])
|
|
const t22 = renderMail('T23', aufrufe.admin[0].values, {})
|
|
assert.match(t22.text, /Art: Ferienwohnung oder Ferienhaus/)
|
|
assert.match(t22.text, /Hallo/)
|
|
const k34 = renderMail('K34', aufrufe.kunde[1].values, aufrufe.kunde[1].blocks)
|
|
assert.match(k34.text, /199 €/)
|
|
})
|