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

84 lines
4.6 KiB
JavaScript

import { test, beforeEach } from 'node:test'
import assert from 'node:assert/strict'
import { zaehle, zaehleAlle, darfG08, darfK21NichtZugeordnet, resetTermineLimitsForTests } from '../server/services/termine/limits.js'
// Grenzen im Speicher: festes Fenster ab dem ersten Ereignis, alle-oder-keine bei mehreren Regeln, Obergrenze der Schluessel.
const T0 = new Date('2026-10-05T08:00:00.000Z')
const STUNDE = 60 * 60 * 1000
const TAG = 24 * STUNDE
const plus = (ms) => new Date(T0.getTime() + ms)
beforeEach(() => resetTermineLimitsForTests())
test('zaehle: erlaubt bis max, danach false; das Fenster beginnt mit dem ersten Ereignis und endet nach fensterMs', () => {
assert.deepEqual([1, 2, 3].map(() => zaehle('a', 3, STUNDE, T0)), [true, true, true])
assert.equal(zaehle('a', 3, STUNDE, plus(10 * 60000)), false)
assert.equal(zaehle('a', 3, STUNDE, plus(STUNDE - 1)), false, 'bis zur letzten Millisekunde des Fensters')
assert.equal(zaehle('b', 3, STUNDE, T0), true, 'andere Schluessel zaehlen getrennt')
// die abgelehnten Anfragen haben nichts gezaehlt: das neue Fenster (ab plus(STUNDE)) erlaubt wieder drei
assert.deepEqual([1, 2, 3, 4].map((i) => zaehle('a', 3, STUNDE, plus(STUNDE + i))), [true, true, true, false])
})
test('zaehle: max 0 erlaubt nie, ungueltige Angaben werfen TypeError', () => {
assert.equal(zaehle('a', 0, STUNDE, T0), false)
assert.throws(() => zaehle('a', 1.5, STUNDE, T0), TypeError)
assert.throws(() => zaehle('a', -1, STUNDE, T0), TypeError)
assert.throws(() => zaehle('a', 1, 0, T0), TypeError)
assert.throws(() => zaehle('', 1, STUNDE, T0), TypeError)
assert.throws(() => zaehle('a', 1, STUNDE, undefined), TypeError)
assert.throws(() => zaehle('a', 1, STUNDE, Date.now()), TypeError)
assert.throws(() => zaehleAlle([], T0), TypeError)
})
test('zaehleAlle: alle oder keine - scheitert eine Regel, zaehlt keine', () => {
const regeln = [
{ schluessel: 'adresse', max: 3, fensterMs: TAG },
{ schluessel: 'funktion', max: 1, fensterMs: STUNDE },
]
assert.equal(zaehleAlle(regeln, T0), true)
assert.equal(zaehleAlle(regeln, plus(1000)), false, 'die Funktionsgrenze ist erreicht')
// der Adress-Zaehler wurde dabei nicht verbraucht: nach der Stunde sind noch zwei Ereignisse an diese Adresse frei
const nurAdresse = [{ schluessel: 'adresse', max: 3, fensterMs: TAG }]
assert.equal(zaehleAlle(nurAdresse, plus(2 * STUNDE)), true)
assert.equal(zaehleAlle(nurAdresse, plus(2 * STUNDE)), true)
assert.equal(zaehleAlle(nurAdresse, plus(2 * STUNDE)), false)
})
test('darfG08: 3 je Adresse und Tag (auch ueber Funktionen), 20 je Funktion und Stunde', () => {
assert.deepEqual([1, 2, 3, 4].map(() => darfG08('f1', 'max@example.com', T0)), [true, true, true, false])
assert.equal(darfG08('f2', 'max@example.com', plus(TAG - 1)), false, 'die Adresse zaehlt fuer alle Funktionen zusammen')
assert.equal(darfG08('f1', 'max@example.com', plus(TAG)), true, 'am naechsten Tag wieder')
resetTermineLimitsForTests()
const erlaubt = Array.from({ length: 22 }, (_, i) => darfG08('f1', `gast${i}@example.com`, T0))
assert.equal(erlaubt.filter(Boolean).length, 20)
assert.equal(darfG08('f2', 'neu@example.com', T0), true, 'andere Funktion hat ihr eigenes Kontingent')
assert.equal(darfG08('f1', 'spaet@example.com', plus(STUNDE)), true, 'nach einer Stunde wieder')
})
test('darfK21NichtZugeordnet: 30 je Funktion und Stunde', () => {
assert.equal(Array.from({ length: 32 }, () => darfK21NichtZugeordnet('f1', T0)).filter(Boolean).length, 30)
assert.equal(darfK21NichtZugeordnet('f2', T0), true)
assert.equal(darfK21NichtZugeordnet('f1', plus(STUNDE)), true)
})
test('Obergrenze: ueber 10 000 Schluessel faellt der aelteste Zaehler weg, die neueren bleiben', () => {
assert.equal(zaehle('aeltester', 1, TAG, T0), true)
assert.equal(zaehle('aeltester', 1, TAG, T0), false)
for (let i = 0; i < 9998; i += 1) zaehle(`k${i}`, 1, TAG, plus(1000))
assert.equal(zaehle('aeltester', 1, TAG, T0), false, 'bei 9 999 Schluesseln noch da')
assert.equal(zaehle('k9997', 1, TAG, plus(2000)), false)
zaehle('neu1', 1, TAG, plus(3000)) // 10 000
zaehle('neu2', 1, TAG, plus(3000)) // 10 001: der aelteste faellt weg
assert.equal(zaehle('aeltester', 1, TAG, plus(4000)), true, 'der aelteste Zaehler wurde verdraengt')
assert.equal(zaehle('neu2', 1, TAG, plus(4000)), false, 'der neueste bleibt')
assert.equal(zaehle('k9997', 1, TAG, plus(4000)), false, 'die juengeren bleiben')
})
test('resetTermineLimitsForTests leert alles', () => {
zaehle('a', 1, TAG, T0)
assert.equal(zaehle('a', 1, TAG, T0), false)
resetTermineLimitsForTests()
assert.equal(zaehle('a', 1, TAG, T0), true)
})