Files
tickte-system/tests/unit/zeitenView.test.mjs
T
ClaudeandClaude Opus 5.5 919d96f7a0 Öffnungszeiten: Status "Leisten live – Einbau läuft" nur bei einbau angestossen
In der Einrichtung nennt der Statustext "Leisten live – Einbau läuft" nur noch, wenn der Neubau angestossen ist.
Bei einbau manuell oder leer steht "Einbau läuft (Team setzt die Skript-Zeile von Hand)"; "wartet auf die Zeiten des Kunden" geht weiter vor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:10:45 +00:00

351 lines
21 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import test from 'node:test'
import assert from 'node:assert/strict'
import { loadModule } from './load.mjs'
// Öffnungszeiten live im Funktionen-Reiter: Statustexte, Prüfung des Navigations-Selektors (Spiegel des Portals) und Rumpf der Team-Einstellungen
const {
zeitenStatusText, navSelektorFehler, NAV_SELEKTOR_MAX, NAV_SELEKTOR_FEHLER, teamBody,
ersatzPfad, zeitenTeamPfad, teamFormular, teamGeaendert, mergeTeam, teamSpeichernFehler,
ersatzKnoepfe, ersatzKopieren, ersatzMeldung, abschaltMeldung, KEINE_ZEITEN_TEXT, ZWISCHENABLAGE_FEHLT,
} = await loadModule('src/lib/zeitenView.js')
const EINBAU = 'Leisten live – Einbau läuft'
const VON_HAND = 'Einbau läuft (Team setzt die Skript-Zeile von Hand)'
const WARTET = 'wartet auf die Zeiten des Kunden'
test('zeitenStatusText: Einrichtung ohne Hindernis, Einbau angestossen – Leisten sind live, der Einbau läuft', () => {
assert.equal(zeitenStatusText({ state: 'setup', hindernis: null, einbau: 'angestossen' }), EINBAU)
assert.equal(zeitenStatusText({ state: 'setup', einbau: 'angestossen' }), EINBAU, 'ohne Feld hindernis')
assert.equal(zeitenStatusText({ state: 'setup', hindernis: '', einbau: 'angestossen' }), EINBAU)
})
test('zeitenStatusText: Einrichtung mit einbau manuell oder leer – nie "Leisten live", das Team setzt die Zeile von Hand', () => {
for (const einbau of ['manuell', '', null, undefined, 'irgendwas_neues']) {
assert.equal(zeitenStatusText({ state: 'setup', hindernis: null, einbau }), VON_HAND, JSON.stringify(einbau))
}
assert.equal(zeitenStatusText({ state: 'setup' }), VON_HAND, 'ohne Feld einbau')
assert.doesNotMatch(VON_HAND, /Leisten live/)
})
test('zeitenStatusText: Einrichtung mit hindernis "zeiten_fehlen" – wartet auf die Zeiten des Kunden (geht jedem Einbau-Text vor)', () => {
assert.equal(zeitenStatusText({ state: 'setup', hindernis: 'zeiten_fehlen' }), WARTET)
for (const einbau of ['angestossen', 'manuell', '', null]) {
assert.equal(zeitenStatusText({ state: 'setup', hindernis: 'zeiten_fehlen', einbau }), WARTET, JSON.stringify(einbau))
}
})
test('zeitenStatusText: unbekanntes Hindernis zeigt nichts Erfundenes, sondern den Einbau-Text', () => {
assert.equal(zeitenStatusText({ state: 'setup', hindernis: 'irgendwas_neues', einbau: 'angestossen' }), EINBAU)
assert.equal(zeitenStatusText({ state: 'setup', hindernis: 'irgendwas_neues', einbau: 'manuell' }), VON_HAND)
})
test('zeitenStatusText: Abo-Ende nennt die Frist (Berliner Tag des Abo-Endes plus 30 Tage)', () => {
const abo = (state, aboEndeAt) => zeitenStatusText({ state, hindernis: null, aboEndeAt })
const hinweis = (datum) => `Abo beendet – Abschaltung am ${datum}, falls der Kunde die Funktion nicht behält`
assert.equal(abo('active', '2026-10-04T10:00:00.000Z'), hinweis('03.11.2026'))
// 22:30 UTC ist in Berlin schon der nächste Tag (Sommerzeit, +2 h): 05.10. -> 04.11.
assert.equal(abo('active', '2026-10-04T22:30:00.000Z'), hinweis('04.11.2026'))
// Monats- und Jahreswechsel, Zeitumstellung am 25.10. spielt bei Kalendertagen keine Rolle
assert.equal(abo('active', '2026-10-20T12:00:00.000Z'), hinweis('19.11.2026'))
assert.equal(abo('active', '2026-12-15T12:00:00.000Z'), hinweis('14.01.2027'))
// Appwrite liefert auch +00:00
assert.equal(abo('active', '2026-10-04T10:00:00.000+00:00'), hinweis('03.11.2026'))
})
test('zeitenStatusText: Abo-Ende in der Einrichtung steht zusätzlich zum Einbau- bzw. Warte-Text', () => {
const aboEndeAt = '2026-10-04T10:00:00.000Z'
const frist = 'Abo beendet – Abschaltung am 03.11.2026, falls der Kunde die Funktion nicht behält'
assert.equal(zeitenStatusText({ state: 'setup', hindernis: null, einbau: 'angestossen', aboEndeAt }), `${EINBAU} · ${frist}`)
assert.equal(zeitenStatusText({ state: 'setup', hindernis: null, einbau: 'manuell', aboEndeAt }), `${VON_HAND} · ${frist}`)
assert.equal(zeitenStatusText({ state: 'setup', hindernis: 'zeiten_fehlen', aboEndeAt }), `${WARTET} · ${frist}`)
})
test('zeitenStatusText: Abo-Ende mit unlesbarem Datum nennt 30 Tage statt eines erfundenen Tages', () => {
const text = zeitenStatusText({ state: 'active', aboEndeAt: 'kein-datum' })
assert.equal(text, 'Abo beendet – Abschaltung nach 30 Tagen, falls der Kunde die Funktion nicht behält')
})
test('zeitenStatusText: aktiv ohne Abo-Ende, aus, bestellt, abgeschaltet, ohne Ansicht – leer', () => {
assert.equal(zeitenStatusText({ state: 'active', hindernis: null, aboEndeAt: null }), '')
assert.equal(zeitenStatusText({ state: 'active' }), '')
assert.equal(zeitenStatusText({ state: 'off' }), '')
assert.equal(zeitenStatusText({ state: 'ordered' }), '')
// abgeschaltet: Grund und Löschdatum zeigt abgeschaltetText, nichts doppelt
assert.equal(zeitenStatusText({ state: 'disabled', disabledReason: 'abo_ende', loeschungAm: '2026-11-04', aboEndeAt: '2026-10-04T10:00:00.000Z' }), '')
assert.equal(zeitenStatusText({ state: 'off', aboEndeAt: '2026-10-04T10:00:00.000Z' }), '')
assert.equal(zeitenStatusText(null), '')
assert.equal(zeitenStatusText(undefined), '')
})
test('zeitenStatusText: kein Text nennt "24 Uhr"', () => {
for (const feature of [
{ state: 'setup' },
{ state: 'setup', einbau: 'angestossen' },
{ state: 'setup', einbau: 'manuell' },
{ state: 'setup', hindernis: 'zeiten_fehlen' },
{ state: 'active', aboEndeAt: '2026-10-04T10:00:00.000Z' },
{ state: 'setup', hindernis: 'zeiten_fehlen', aboEndeAt: '2026-10-04T22:30:00.000Z' },
]) {
assert.doesNotMatch(zeitenStatusText(feature), /24 Uhr/)
}
})
test('navSelektorFehler: leer ist erlaubt (kein Selektor)', () => {
for (const wert of [undefined, null, '', ' ', '\n\t ']) {
assert.equal(navSelektorFehler(wert), null, JSON.stringify(wert))
}
})
test('navSelektorFehler: übliche Selektoren sind gültig', () => {
for (const wert of [
'header',
'#nav',
'.site-header',
'.site-header > nav',
'header#main-nav.fixed',
'nav[role="navigation"]',
"a[href='x']",
'ul.menu:first-child',
'div_wrap .a-b',
'ABC xyz 019',
' header ',
]) {
assert.equal(navSelektorFehler(wert), null, wert)
}
})
test('navSelektorFehler: erlaubt sind nur A–Z a–z 0–9, Leerzeichen und # . - _ > : [ ] = " \'', () => {
const zeichen = 'AZaz09 #.-_>:[]="\''
assert.equal(navSelektorFehler(zeichen), null)
assert.equal(navSelektorFehler('a'.repeat(NAV_SELEKTOR_MAX)), null)
})
test('navSelektorFehler: < { } ; und alle übrigen Zeichen werden abgelehnt', () => {
for (const zeichen of ['<', '{', '}', ';', '(', ')', ',', '*', '+', '~', '/', '\\', '@', '!', '|', '$', '%', '^', '&', '?', '`', 'ä', 'ß', '€', '\n', '\t']) {
assert.equal(navSelektorFehler(`a${zeichen}b`), NAV_SELEKTOR_FEHLER, JSON.stringify(zeichen))
}
assert.equal(navSelektorFehler('header { display: none }'), NAV_SELEKTOR_FEHLER)
assert.equal(navSelektorFehler('</style><script>'), NAV_SELEKTOR_FEHLER)
assert.equal(navSelektorFehler('a\nb'), NAV_SELEKTOR_FEHLER, 'Zeilenumbruch mitten im Text')
})
test('navSelektorFehler: höchstens 120 Zeichen, gezählt nach dem Trimmen', () => {
assert.equal(NAV_SELEKTOR_MAX, 120)
assert.equal(navSelektorFehler('a'.repeat(120)), null)
assert.equal(navSelektorFehler(` ${'a'.repeat(120)} `), null, 'Leerraum außen zählt nicht')
assert.equal(navSelektorFehler('a'.repeat(121)), NAV_SELEKTOR_FEHLER)
assert.equal(navSelektorFehler(`${'a'.repeat(60)} ${'b'.repeat(60)}`), NAV_SELEKTOR_FEHLER, '121 mit Leerzeichen innen')
})
test('navSelektorFehler: kein Text wird abgelehnt wie auf dem Server (Zahl, Objekt, Wahrheitswert)', () => {
for (const wert of [5, true, {}, []]) {
assert.equal(navSelektorFehler(wert), NAV_SELEKTOR_FEHLER, JSON.stringify(wert))
}
})
test('NAV_SELEKTOR_FEHLER: wörtlich wie die Meldung des Portals', () => {
assert.equal(NAV_SELEKTOR_FEHLER, 'Der Selektor darf höchstens 120 Zeichen lang sein und nur A–Z, 0–9, Leerzeichen und # . - _ > : [ ] = " \' enthalten.')
})
test('teamBody: genau die fünf Felder der Team-Route, Selektor getrimmt, leer wird null', () => {
assert.deepEqual(
teamBody({ projectId: 'p1', teamVersion: 3, navSelektor: ' header > nav ', kontaktleisteAus: true, hinweisleisteAus: false }),
{ projectId: 'p1', teamVersion: 3, navSelektor: 'header > nav', kontaktleisteAus: true, hinweisleisteAus: false }
)
for (const leer of ['', ' ', null, undefined]) {
assert.equal(teamBody({ projectId: 'p1', teamVersion: 0, navSelektor: leer, kontaktleisteAus: false, hinweisleisteAus: false }).navSelektor, null, JSON.stringify(leer))
}
})
test('teamBody: Schalter sind immer echte Wahrheitswerte, nur true gilt als an', () => {
const body = (kontaktleisteAus, hinweisleisteAus) => teamBody({ projectId: 'p1', teamVersion: 1, navSelektor: '', kontaktleisteAus, hinweisleisteAus })
assert.deepEqual(body(true, true), { projectId: 'p1', teamVersion: 1, navSelektor: null, kontaktleisteAus: true, hinweisleisteAus: true })
assert.deepEqual(body(undefined, undefined), { projectId: 'p1', teamVersion: 1, navSelektor: null, kontaktleisteAus: false, hinweisleisteAus: false })
assert.deepEqual(body('true', 1), { projectId: 'p1', teamVersion: 1, navSelektor: null, kontaktleisteAus: false, hinweisleisteAus: false })
})
test('teamBody: die Version wird unverändert durchgereicht (das Portal prüft sie), auch 0', () => {
assert.equal(teamBody({ projectId: 'p1', teamVersion: 0, navSelektor: '', kontaktleisteAus: false, hinweisleisteAus: false }).teamVersion, 0)
assert.equal(teamBody({ projectId: 'p1', teamVersion: 41, navSelektor: '', kontaktleisteAus: false, hinweisleisteAus: false }).teamVersion, 41)
})
test('teamBody: ein ungültiger Selektor wird nicht "repariert", sondern unverändert gesendet (das Formular sperrt vorher, das Portal prüft noch einmal)', () => {
assert.equal(teamBody({ projectId: 'p1', teamVersion: 1, navSelektor: 'a{b}', kontaktleisteAus: false, hinweisleisteAus: false }).navSelektor, 'a{b}')
})
// --- Panel: Pfade, Formular, Speichern, Ersatz-HTML, Abschalt-Meldung ---
test('ersatzPfad: GET .../zeiten/ersatz mit kodierten Parametern projectId und plan', () => {
assert.equal(ersatzPfad('c1', 'p1', 'haupt'), '/funktionen/c1/zeiten/ersatz?projectId=p1&plan=haupt')
assert.equal(ersatzPfad('c/1', 'p 1', 'a&b=c'), '/funktionen/c%2F1/zeiten/ersatz?projectId=p%201&plan=a%26b%3Dc')
})
test('ersatzPfad: ohne plan fehlt der Parameter (Hauptplan), ein leerer plan bleibt stehen (das Portal antwortet dann 404)', () => {
assert.equal(ersatzPfad('c1', 'p1'), '/funktionen/c1/zeiten/ersatz?projectId=p1')
assert.equal(ersatzPfad('c1', 'p1', null), '/funktionen/c1/zeiten/ersatz?projectId=p1')
assert.equal(ersatzPfad('c1', 'p1', ''), '/funktionen/c1/zeiten/ersatz?projectId=p1&plan=')
})
test('zeitenTeamPfad: PATCH .../zeiten/team', () => {
assert.equal(zeitenTeamPfad('c1'), '/funktionen/c1/zeiten/team')
assert.equal(zeitenTeamPfad('c/1'), '/funktionen/c%2F1/zeiten/team')
})
test('teamFormular: Startwerte aus feature.team, null-Selektor wird ein leeres Feld', () => {
assert.deepEqual(
teamFormular({ team: { navSelektor: 'header > nav', kontaktleisteAus: true, hinweisleisteAus: false } }),
{ navSelektor: 'header > nav', kontaktleisteAus: true, hinweisleisteAus: false }
)
assert.deepEqual(
teamFormular({ team: { navSelektor: null, kontaktleisteAus: false, hinweisleisteAus: true } }),
{ navSelektor: '', kontaktleisteAus: false, hinweisleisteAus: true }
)
})
test('teamFormular: ohne Team-Feld (ältere Antwort, keine Ansicht) alles aus und leer', () => {
const leer = { navSelektor: '', kontaktleisteAus: false, hinweisleisteAus: false }
assert.deepEqual(teamFormular({}), leer)
assert.deepEqual(teamFormular({ team: null }), leer)
assert.deepEqual(teamFormular(null), leer)
assert.deepEqual(teamFormular(undefined), leer)
// Schalter nur bei true an, Selektor nur als Text
assert.deepEqual(teamFormular({ team: { navSelektor: 5, kontaktleisteAus: 'true', hinweisleisteAus: 1 } }), leer)
})
test('teamGeaendert: nur ein echter Unterschied zum gespeicherten Stand zählt, Leerraum um den Selektor nicht', () => {
const feature = { team: { navSelektor: 'header', kontaktleisteAus: false, hinweisleisteAus: true } }
const gleich = { navSelektor: 'header', kontaktleisteAus: false, hinweisleisteAus: true }
assert.equal(teamGeaendert(gleich, feature), false)
assert.equal(teamGeaendert({ ...gleich, navSelektor: ' header ' }, feature), false)
assert.equal(teamGeaendert({ ...gleich, navSelektor: 'header nav' }, feature), true)
assert.equal(teamGeaendert({ ...gleich, kontaktleisteAus: true }, feature), true)
assert.equal(teamGeaendert({ ...gleich, hinweisleisteAus: false }, feature), true)
// gespeichert ohne Selektor: leeres oder leeres-mit-Leerraum Feld ist keine Änderung
const ohne = { team: { navSelektor: null, kontaktleisteAus: false, hinweisleisteAus: false } }
assert.equal(teamGeaendert({ navSelektor: ' ', kontaktleisteAus: false, hinweisleisteAus: false }, ohne), false)
assert.equal(teamGeaendert({ navSelektor: 'x', kontaktleisteAus: false, hinweisleisteAus: false }, ohne), true)
})
test('mergeTeam: übernimmt team und teamVersion in genau dieses Projekt, alles andere bleibt', () => {
const zeiten = { state: 'active', plaene: [{ kurz: 'a', name: 'A', haupt: true }], team: { navSelektor: null, kontaktleisteAus: false, hinweisleisteAus: false }, teamVersion: 2 }
const projects = [
{ projectId: 'p1', projectName: 'Eins', features: { news: { state: 'off' }, zeiten } },
{ projectId: 'p2', projectName: 'Zwei', features: { zeiten: { ...zeiten, teamVersion: 7 } } },
]
const neu = mergeTeam(projects, 'p1', { team: { navSelektor: 'header', kontaktleisteAus: true, hinweisleisteAus: false }, teamVersion: 3 })
assert.notEqual(neu, projects, 'neue Liste')
assert.deepEqual(neu[0].features.zeiten, { ...zeiten, team: { navSelektor: 'header', kontaktleisteAus: true, hinweisleisteAus: false }, teamVersion: 3 })
assert.deepEqual(neu[0].features.news, { state: 'off' })
assert.equal(neu[0].projectName, 'Eins')
assert.equal(neu[1], projects[1], 'anderes Projekt unverändert')
assert.equal(projects[0].features.zeiten.teamVersion, 2, 'Eingabe nicht verändert')
})
test('mergeTeam: unbrauchbare Antwort oder Projekt ohne Zeiten ändert nichts', () => {
const projects = [{ projectId: 'p1', features: { zeiten: { state: 'active', teamVersion: 1, team: {} } } }, { projectId: 'p2', features: {} }]
assert.equal(mergeTeam(projects, 'p1', null), projects)
assert.equal(mergeTeam(projects, 'p1', {}), projects)
assert.equal(mergeTeam(projects, 'p1', { team: { navSelektor: null }, teamVersion: 'x' }), projects)
assert.equal(mergeTeam(projects, 'p1', { teamVersion: 2 }), projects)
assert.deepEqual(mergeTeam(projects, 'p2', { team: {}, teamVersion: 1 }), projects, 'p2 hat keine Zeiten: nichts erfunden')
assert.deepEqual(mergeTeam(projects, 'p9', { team: {}, teamVersion: 1 }), projects)
})
test('teamSpeichernFehler: 409 ZEITEN_VERALTET – „Inzwischen geändert – bitte neu laden“, danach neu laden', () => {
const err = Object.assign(new Error('Inzwischen geändert – bitte neu laden.'), { status: 409, code: 'ZEITEN_VERALTET' })
assert.deepEqual(teamSpeichernFehler(err), { text: 'Inzwischen geändert – bitte neu laden.', neuLaden: true })
// der feste Text gilt auch, wenn der Server-Text anders lautet
const anders = Object.assign(new Error('irgendwas'), { status: 409, code: 'ZEITEN_VERALTET' })
assert.equal(teamSpeichernFehler(anders).text, 'Inzwischen geändert – bitte neu laden.')
})
test('teamSpeichernFehler: anderer 409 (z. B. nicht eingeschaltet) zeigt den Text des Portals, die Ansicht ist trotzdem veraltet', () => {
const err = Object.assign(new Error('Öffnungszeiten live ist für dieses Projekt nicht eingeschaltet.'), { status: 409 })
assert.deepEqual(teamSpeichernFehler(err), { text: 'Öffnungszeiten live ist für dieses Projekt nicht eingeschaltet.', neuLaden: true })
})
test('teamSpeichernFehler: 400 und Netzfehler zeigen ihren Text unverändert, ohne Neuladen; ohne Text eine Ersatzmeldung', () => {
assert.deepEqual(teamSpeichernFehler(Object.assign(new Error(NAV_SELEKTOR_FEHLER), { status: 400 })), { text: NAV_SELEKTOR_FEHLER, neuLaden: false })
assert.deepEqual(teamSpeichernFehler(Object.assign(new Error('Das Kundenportal ist gerade nicht erreichbar.'), { status: 0 })), { text: 'Das Kundenportal ist gerade nicht erreichbar.', neuLaden: false })
assert.deepEqual(teamSpeichernFehler(new Error('')), { text: 'Speichern fehlgeschlagen.', neuLaden: false })
assert.deepEqual(teamSpeichernFehler(null), { text: 'Speichern fehlgeschlagen.', neuLaden: false })
})
test('ersatzKnoepfe: ein Plan – „Ersatz-HTML kopieren“, der Hauptplan zuerst bleibt in der Reihenfolge des Portals', () => {
assert.deepEqual(ersatzKnoepfe({ plaene: [{ kurz: 'haupt', name: 'Öffnungszeiten', haupt: true }] }), [
{ kurz: 'haupt', label: 'Ersatz-HTML kopieren', bezeichnung: 'Öffnungszeiten (haupt)' },
])
})
test('ersatzKnoepfe: mehrere Pläne – je Plan ein Knopf mit Name und Kurzname', () => {
const knoepfe = ersatzKnoepfe({
plaene: [
{ kurz: 'laden', name: 'Laden', haupt: true },
{ kurz: 'cafe', name: 'Café', haupt: false },
{ kurz: 'lieferung', name: '', haupt: false },
{ kurz: 'abholung', name: 'abholung', haupt: false },
],
})
assert.deepEqual(knoepfe.map((k) => k.kurz), ['laden', 'cafe', 'lieferung', 'abholung'])
assert.deepEqual(knoepfe.map((k) => k.label), [
'Ersatz-HTML kopieren: Laden (laden)',
'Ersatz-HTML kopieren: Café (cafe)',
'Ersatz-HTML kopieren: lieferung',
'Ersatz-HTML kopieren: abholung',
])
})
test('ersatzKnoepfe: Pläne ohne Kurzname und Unbrauchbares werden übergangen, ohne Pläne [] (Hinweis statt Knopf)', () => {
assert.deepEqual(ersatzKnoepfe({ plaene: [{ kurz: '', name: 'x' }, null, { name: 'y' }, { kurz: 5 }] }), [])
assert.deepEqual(ersatzKnoepfe({ plaene: [] }), [])
assert.deepEqual(ersatzKnoepfe({}), [])
assert.deepEqual(ersatzKnoepfe(null), [])
assert.equal(KEINE_ZEITEN_TEXT, 'Der Kunde hat noch keine Zeiten eingetragen.')
})
test('ersatzKopieren: schreibt das HTML in die Zwischenablage', async () => {
const geschrieben = []
const clipboard = { writeText: async (text) => { geschrieben.push(text) } }
assert.equal(await ersatzKopieren('<table>&auml;</table>', clipboard), 'kopiert')
assert.deepEqual(geschrieben, ['<table>&auml;</table>'])
})
test('ersatzKopieren: ohne Zwischenablage-API oder bei Ablehnung – manuell kopieren; leeres HTML wird nie kopiert', async () => {
assert.equal(await ersatzKopieren('<p>x</p>', undefined), 'manuell')
assert.equal(await ersatzKopieren('<p>x</p>', null), 'manuell')
assert.equal(await ersatzKopieren('<p>x</p>', {}), 'manuell')
assert.equal(await ersatzKopieren('<p>x</p>', { writeText: 'kein Funktion' }), 'manuell')
assert.equal(await ersatzKopieren('<p>x</p>', { writeText: async () => { throw new Error('NotAllowedError') } }), 'manuell')
assert.equal(await ersatzKopieren('<p>x</p>', { writeText: () => { throw new Error('sofort') } }), 'manuell')
let aufgerufen = 0
const clipboard = { writeText: async () => { aufgerufen++ } }
for (const leer of ['', undefined, null, 5]) assert.equal(await ersatzKopieren(leer, clipboard), 'leer', String(leer))
assert.equal(aufgerufen, 0)
})
test('ersatzMeldung: bestätigt das Kopieren sichtbar, nennt den Plan und warnt, wenn die Zwischenablage fehlt', () => {
assert.deepEqual(ersatzMeldung('kopiert'), { ok: true, text: 'Ersatz-HTML kopiert.' })
assert.deepEqual(ersatzMeldung('kopiert', 'Café (cafe)'), { ok: true, text: 'Ersatz-HTML kopiert: Café (cafe).' })
assert.deepEqual(ersatzMeldung('manuell'), { ok: false, text: ZWISCHENABLAGE_FEHLT })
assert.match(ZWISCHENABLAGE_FEHLT, /Zwischenablage/)
assert.equal(ersatzMeldung('leer').ok, false)
assert.equal(ersatzMeldung('irgendwas').ok, false)
})
test('abschaltMeldung: angelegt, aktuell, fehler und ohne Angabe', () => {
assert.deepEqual(abschaltMeldung('angelegt'), { ok: true, text: 'Gespeichert. Ticket „Ersatz-Tabelle aktualisieren“ angelegt.' })
assert.deepEqual(abschaltMeldung('aktuell'), { ok: true, text: 'Gespeichert. Die Ersatz-Tabelle ist aktuell, kein Ticket nötig.' })
assert.deepEqual(abschaltMeldung(undefined), { ok: true, text: 'Gespeichert.' })
assert.deepEqual(abschaltMeldung('etwas-neues'), { ok: true, text: 'Gespeichert.' })
})
test('abschaltMeldung: bei „fehler“ eine sichtbare Warnung – Ticket von Hand anlegen, ein zweites Abschalten gibt es nicht', () => {
const m = abschaltMeldung('fehler')
assert.equal(m.ok, false)
assert.match(m.text, /^Gespeichert, aber/)
assert.match(m.text, /„Ersatz-Tabelle aktualisieren“/)
assert.match(m.text, /konnte nicht angelegt werden/)
assert.match(m.text, /von Hand/)
assert.doesNotMatch(m.text, /24 Uhr/)
})