Files

195 lines
8.2 KiB
JavaScript

import { test, beforeEach, afterEach } from 'node:test'
import assert from 'node:assert/strict'
import { config } from '../server/config.js'
import * as schalter from '../server/services/termine/schalter.js'
const { termineAus, termineFuerKunde, termineModus } = schalter
// Namensraum für termineTextformNoetig: fehlt der Export, scheitert nur sein Test
const termineTextformNoetig = (email) => schalter.termineTextformNoetig(email)
const TERMINE_ENV = [
'TERMINE_ENABLED',
'TERMINE_PILOT_EMAILS',
'TERMINE_FORM_MIN_SECONDS',
'TERMINE_MIN_ANTWORT_MS',
'APPWRITE_COLLECTION_TERMINE_CONFIG',
'APPWRITE_COLLECTION_TERMINE_BOOKINGS',
'APPWRITE_COLLECTION_TERMINE_CLAIMS',
'APPWRITE_COLLECTION_TERMINE_OUTBOX',
]
let original
beforeEach(() => {
original = { ...config.termine }
})
afterEach(() => {
Object.assign(config.termine, original)
})
/** Frische config.js-Instanz mit genau diesen Termine-Umgebungsvariablen (alle anderen entfernt). */
let freshCounter = 0
async function freshConfig(env = {}) {
const saved = Object.fromEntries(TERMINE_ENV.map((key) => [key, process.env[key]]))
for (const key of TERMINE_ENV) delete process.env[key]
Object.assign(process.env, env)
try {
freshCounter += 1
return (await import(`../server/config.js?termine-test=${freshCounter}`)).config
} finally {
for (const key of TERMINE_ENV) {
if (saved[key] === undefined) delete process.env[key]
else process.env[key] = saved[key]
}
}
}
test('Konfiguration: Vorgaben ohne Umgebungsvariablen', async () => {
const fresh = await freshConfig()
// avvVersion: Fassung der Bestellunterlagen (Berliner Tag des Fassungs-Commits), hier nur das Datumsmuster
assert.match(fresh.termine.avvVersion, /^\d{4}-\d{2}-\d{2}$/)
assert.deepEqual(fresh.termine, {
mode: 'off',
pilotEmails: [],
avvVersion: fresh.termine.avvVersion,
holdMinutes: 30,
zelleMin: 5,
mailsProStunde: 200,
mailsProFunktion: 40,
mailsReserve: 0.25,
mailListe: 100,
loeschDeckel: 2000,
loeschDeckelGesamt: 20000,
zellenDeckel: 5000,
formMinSekunden: 3,
minAntwortMs: 300,
})
assert.equal(fresh.collections.termineConfig, 'termineConfig')
assert.equal(fresh.collections.termineBookings, 'termineBookings')
assert.equal(fresh.collections.termineClaims, 'termineClaims')
assert.equal(fresh.collections.termineOutbox, 'termineOutbox')
})
test('Konfiguration: Umgebungsvariablen werden gelesen und bereinigt', async () => {
const fresh = await freshConfig({
TERMINE_ENABLED: ' Pilot ',
TERMINE_PILOT_EMAILS: ' Kenso.Gri@Gmail.com, ,justin@webklar.com ',
TERMINE_FORM_MIN_SECONDS: '0',
TERMINE_MIN_ANTWORT_MS: '0',
APPWRITE_COLLECTION_TERMINE_CONFIG: 'tConfig',
APPWRITE_COLLECTION_TERMINE_BOOKINGS: 'tBookings',
APPWRITE_COLLECTION_TERMINE_CLAIMS: 'tClaims',
APPWRITE_COLLECTION_TERMINE_OUTBOX: 'tOutbox',
})
assert.equal(fresh.termine.mode, 'pilot')
assert.deepEqual(fresh.termine.pilotEmails, ['kenso.gri@gmail.com', 'justin@webklar.com'])
assert.equal(fresh.termine.formMinSekunden, 0)
assert.equal(fresh.termine.minAntwortMs, 0)
assert.deepEqual(
[fresh.collections.termineConfig, fresh.collections.termineBookings, fresh.collections.termineClaims, fresh.collections.termineOutbox],
['tConfig', 'tBookings', 'tClaims', 'tOutbox'],
)
})
test('Konfiguration: leerer oder unbekannter Schalter ist off, ungueltige Sekunden fallen auf 3', async () => {
for (const value of ['', ' ', 'banane', 'true', '1', 'ON ']) {
const fresh = await freshConfig({ TERMINE_ENABLED: value })
assert.equal(fresh.termine.mode, value.trim().toLowerCase() === 'on' ? 'on' : 'off', `TERMINE_ENABLED=${JSON.stringify(value)}`)
}
for (const value of ['', 'abc', '-1', 'NaN']) {
const fresh = await freshConfig({ TERMINE_FORM_MIN_SECONDS: value })
assert.equal(fresh.termine.formMinSekunden, 3, `TERMINE_FORM_MIN_SECONDS=${JSON.stringify(value)}`)
}
assert.equal((await freshConfig({ TERMINE_FORM_MIN_SECONDS: '7' })).termine.formMinSekunden, 7)
for (const value of ['', 'abc', '-1', 'NaN']) {
const fresh = await freshConfig({ TERMINE_MIN_ANTWORT_MS: value })
assert.equal(fresh.termine.minAntwortMs, 300, `TERMINE_MIN_ANTWORT_MS=${JSON.stringify(value)}`)
}
assert.equal((await freshConfig({ TERMINE_MIN_ANTWORT_MS: '750' })).termine.minAntwortMs, 750)
})
test('termineModus: leer und unbekannt sind off, pilot und on bleiben', () => {
for (const value of [undefined, null, '', 'banane', 'PILOT', 'true']) {
config.termine.mode = value
assert.equal(termineModus(), 'off', `mode=${JSON.stringify(value)}`)
assert.equal(termineAus(), true)
}
config.termine.mode = 'pilot'
assert.equal(termineModus(), 'pilot')
assert.equal(termineAus(), false)
config.termine.mode = 'on'
assert.equal(termineModus(), 'on')
assert.equal(termineAus(), false)
})
test('termineModus: Aenderung von config.termine.mode wirkt sofort', () => {
config.termine.mode = 'off'
assert.equal(termineModus(), 'off')
config.termine.mode = 'on'
assert.equal(termineModus(), 'on')
config.termine.mode = 'off'
assert.equal(termineAus(), true)
})
test('termineFuerKunde: off sperrt alle, auch mit Stern in der Liste', () => {
config.termine.mode = 'off'
config.termine.pilotEmails = ['*', 'kenso.gri@gmail.com']
assert.equal(termineFuerKunde('kenso.gri@gmail.com'), false)
assert.equal(termineFuerKunde('jemand@example.com'), false)
})
test('termineFuerKunde: pilot erlaubt nur Adressen der Liste, Schreibweise egal', () => {
config.termine.mode = 'pilot'
config.termine.pilotEmails = ['kenso.gri@gmail.com']
assert.equal(termineFuerKunde('KENSO.gri@gmail.com '), true)
assert.equal(termineFuerKunde('kenso.gri@gmail.com'), true)
assert.equal(termineFuerKunde('jemand@example.com'), false)
assert.equal(termineFuerKunde('kenso.gri@gmail.com.evil.de'), false)
})
test('termineFuerKunde: pilot mit Stern erlaubt alle, mit leerer Liste niemanden', () => {
config.termine.mode = 'pilot'
config.termine.pilotEmails = ['*']
assert.equal(termineFuerKunde('jemand@example.com'), true)
config.termine.pilotEmails = []
assert.equal(termineFuerKunde('kenso.gri@gmail.com'), false)
})
test('termineFuerKunde: pilot ohne E-Mail-Adresse ist false', () => {
config.termine.mode = 'pilot'
config.termine.pilotEmails = ['kenso.gri@gmail.com']
for (const email of [undefined, null, '', ' ']) assert.equal(termineFuerKunde(email), false)
})
test('termineFuerKunde: on gilt fuer alle ohne E-Mail-Filter', () => {
config.termine.mode = 'on'
config.termine.pilotEmails = ['kenso.gri@gmail.com']
assert.equal(termineFuerKunde('jemand@example.com'), true)
assert.equal(termineFuerKunde(undefined), true)
})
test('termineTextformNoetig: nur im Modus on und nur außerhalb der Pilotliste; „*“ und fehlende Adresse befreien nicht', () => {
for (const mode of ['off', 'pilot', undefined, '', 'banane']) {
config.termine.mode = mode
config.termine.pilotEmails = []
assert.equal(termineTextformNoetig('jemand@example.com'), false, `mode=${JSON.stringify(mode)}`)
config.termine.pilotEmails = ['*']
assert.equal(termineTextformNoetig('jemand@example.com'), false, `mode=${JSON.stringify(mode)} mit Stern`)
}
config.termine.mode = 'on'
config.termine.pilotEmails = []
assert.equal(termineTextformNoetig('jemand@example.com'), true)
config.termine.pilotEmails = ['kenso.gri@gmail.com']
assert.equal(termineTextformNoetig('jemand@example.com'), true)
assert.equal(termineTextformNoetig('KENSO.gri@gmail.com '), false, 'Pilotadresse, Schreibweise egal')
assert.equal(termineTextformNoetig('kenso.gri@gmail.com.evil.de'), true)
config.termine.pilotEmails = ['*']
assert.equal(termineTextformNoetig('jemand@example.com'), true, 'der Stern zählt in on nicht als Pilotadresse')
assert.equal(termineTextformNoetig('*'), true)
config.termine.pilotEmails = ['*', 'kenso.gri@gmail.com']
assert.equal(termineTextformNoetig('kenso.gri@gmail.com'), false)
for (const email of [undefined, null, '', ' ']) assert.equal(termineTextformNoetig(email), true, `ohne Adresse: ${JSON.stringify(email)}`)
// wirkt sofort wie die übrigen Schalter
config.termine.mode = 'pilot'
assert.equal(termineTextformNoetig('jemand@example.com'), false)
})