Funktionen: Preis entfernt, Abrechnung und Abo-Fehlertext als reine Logik
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
dce7c3e53a
commit
8f75276c54
4 files changed
+119
-6
No files matched your search
@@ -144,3 +144,10 @@ test('Fehlercode und Feldmeldungen des Portals bleiben am Fehler (409 ZEITEN_VER
|
||||
assert.equal(ohne.code, undefined)
|
||||
assert.equal(ohne.fehler, undefined)
|
||||
})
|
||||
|
||||
test('Der Grund einer Abo-Sperre bleibt am Fehler (409 abo_fehlt mit grund)', async () => {
|
||||
const { api } = client({ responses: [reply(409, { error: 'x', code: 'abo_fehlt', grund: 'kein_abo' }), reply(409, { error: 'y', code: 'abo_fehlt', grund: 5 })] })
|
||||
const a = await fails(api('/funktionen/c1/news', { method: 'POST', body: {} }))
|
||||
assert.deepEqual([a.status, a.code, a.grund], [409, 'abo_fehlt', 'kein_abo'])
|
||||
assert.equal((await fails(api('/funktionen/c1/news', { method: 'POST', body: {} }))).grund, undefined)
|
||||
})
|
||||
@@ -28,6 +28,12 @@ const {
|
||||
textformAnsicht,
|
||||
textformBereit,
|
||||
featureBody,
|
||||
ABRECHNUNG_OPTIONEN,
|
||||
ABRECHNUNG_HINWEIS,
|
||||
fragtAbrechnung,
|
||||
abrechnungBereit,
|
||||
aboFehltText,
|
||||
featureFehlerText,
|
||||
speicherStatus,
|
||||
K16_WARNUNG,
|
||||
K16_WARNUNG_OHNE_UNTERLAGEN,
|
||||
@@ -59,7 +65,7 @@ test('FUNKTIONEN: News, Terminplaner, Webshop und Öffnungszeiten live (in diese
|
||||
label: 'Terminplaner',
|
||||
bestaetigen: {
|
||||
activate: 'Terminplaner ohne Zahlung aktivieren?',
|
||||
disable: 'Terminplaner abschalten? Auf der Website sind dann keine Buchungen mehr möglich. Damit beginnt die Löschung: Nach 30 Tagen werden alle Termine und Einstellungen gelöscht. Wieder einschalten ist nach diesen 30 Tagen nur mit einer neuen Bestellung (149 €) möglich.',
|
||||
disable: 'Terminplaner abschalten? Auf der Website sind dann keine Buchungen mehr möglich. Damit beginnt die Löschung: Nach 30 Tagen werden alle Termine und Einstellungen gelöscht. Wieder einschalten ist nach diesen 30 Tagen nur mit einer neuen Einrichtung möglich.',
|
||||
abnahme: 'Terminplaner freischalten? Der Kunde bekommt die Mail „bereit“ und Gäste können buchen.',
|
||||
ticket: 'Fehlendes Einrichtungs-Ticket neu anlegen?',
|
||||
},
|
||||
@@ -106,12 +112,13 @@ test('FUNKTIONEN: Schlüssel sind eindeutig und jede Funktion hat Aktivieren und
|
||||
for (const text of Object.values(zeiten)) assert.doesNotMatch(text, /24 Uhr/, 'nie "24 Uhr"')
|
||||
})
|
||||
|
||||
test('W1: der Abschalten-Dialog des Terminplaners nennt Buchungsstopp, Löschung nach 30 Tagen und die neue Bestellung (149 €)', () => {
|
||||
test('W1: der Abschalten-Dialog des Terminplaners nennt Buchungsstopp, Löschung nach 30 Tagen und die neue Einrichtung, aber keinen Preis', () => {
|
||||
const text = FUNKTIONEN.find((f) => f.key === 'termine').bestaetigen.disable
|
||||
assert.match(text, /^Terminplaner abschalten\?/)
|
||||
assert.match(text, /keine Buchungen mehr möglich/, 'Buchungen stehen')
|
||||
assert.match(text, /Nach 30 Tagen werden alle Termine und Einstellungen gelöscht/, 'Löschung nach 30 Tagen')
|
||||
assert.match(text, /nur mit einer neuen Bestellung \(149 €\)/, 'danach nur mit neuer Bestellung, mit Preis')
|
||||
assert.match(text, /nur mit einer neuen Einrichtung möglich/, 'danach nur mit neuer Einrichtung')
|
||||
assert.doesNotMatch(text, /€|Euro|Bestellung/, 'kein Preis')
|
||||
// News bleibt unverändert: dort wird nichts gelöscht
|
||||
assert.equal(FUNKTIONEN.find((f) => f.key === 'news').bestaetigen.disable, 'News abschalten? Die Website zeigt dann keine Beiträge mehr.')
|
||||
})
|
||||
@@ -837,3 +844,55 @@ test('Buchungskalender: textformNoetig, Label, Vorlage und Links aus dem Feld un
|
||||
assert.equal(schlecht.vorlage, '')
|
||||
assert.equal(textformBereit({ confirmed: true, date: '2026-10-07', channel: 'email', today: '2026-10-07' }, ukFeld()), true)
|
||||
})
|
||||
|
||||
// Kein Preis, Abrechnung beim Aktivieren (aus dem Abo / im Projekt enthalten) und Fehlertext bei fehlendem Abo
|
||||
test('Kein Text der Funktionen nennt einen Preis', () => {
|
||||
for (const f of FUNKTIONEN) for (const t of Object.values(f.bestaetigen)) assert.doesNotMatch(t, /€|\bEuro\b/, f.key)
|
||||
})
|
||||
|
||||
test('ABRECHNUNG_OPTIONEN und fragtAbrechnung: nur Aktivieren, nicht nach Team-Sperre', () => {
|
||||
assert.deepEqual(ABRECHNUNG_OPTIONEN, [{ value: 'abo', label: 'Aus dem Abo' }, { value: 'projekt', label: 'Im Projekt enthalten' }])
|
||||
for (const key of ['news', 'termine', 'shop', 'zeiten', 'unterkunft']) {
|
||||
assert.equal(fragtAbrechnung(key, 'activate', { state: 'off' }), true, key)
|
||||
assert.equal(fragtAbrechnung(key, 'activate', undefined), true, key)
|
||||
assert.equal(fragtAbrechnung(key, 'activate', { state: 'disabled', disabledReason: 'abo_ende' }), true, key)
|
||||
assert.equal(fragtAbrechnung(key, 'activate', { state: 'disabled', disabledReason: 'team' }), false, key)
|
||||
for (const action of ['disable', 'abnahme', 'ticket']) assert.equal(fragtAbrechnung(key, action, { state: 'setup' }), false, `${key} ${action}`)
|
||||
}
|
||||
assert.equal(fragtAbrechnung('analyse', 'activate', { state: 'off' }), false)
|
||||
})
|
||||
|
||||
test('ABRECHNUNG_HINWEIS: erklärt beide Wege ohne Preis', () => {
|
||||
assert.equal(
|
||||
ABRECHNUNG_HINWEIS,
|
||||
'Aus dem Abo: Die Einrichtungszeit geht aufs Stundenkonto des Kunden. Im Projekt enthalten: Sie zählt nicht aufs Stundenkonto und läuft über die Projektkosten.'
|
||||
)
|
||||
assert.doesNotMatch(ABRECHNUNG_HINWEIS, /€|\bEuro\b/)
|
||||
})
|
||||
|
||||
test('abrechnungBereit: ohne Frage immer bereit, mit Frage nur mit abo oder projekt', () => {
|
||||
const b = (o) => abrechnungBereit({ key: 'news', action: 'activate', feature: { state: 'off' }, abrechnung: '', ...o })
|
||||
assert.equal(b({}), false); assert.equal(b({ abrechnung: 'gratis' }), false); assert.equal(b({ abrechnung: undefined }), false)
|
||||
assert.equal(b({ abrechnung: 'abo' }), true); assert.equal(b({ abrechnung: 'projekt' }), true)
|
||||
assert.equal(b({ action: 'disable' }), true)
|
||||
assert.equal(b({ feature: { state: 'disabled', disabledReason: 'team' } }), true)
|
||||
})
|
||||
|
||||
test('featureBody trägt abrechnung nur beim Aktivieren und nur mit gültigem Wert', () => {
|
||||
assert.deepEqual(featureBody({ projectId: 'p1', action: 'activate', note: '', abrechnung: 'projekt' }), { projectId: 'p1', action: 'activate', note: '', abrechnung: 'projekt' })
|
||||
assert.deepEqual(featureBody({ projectId: 'p1', action: 'activate', note: '', abrechnung: 'gratis' }), { projectId: 'p1', action: 'activate', note: '' })
|
||||
assert.deepEqual(featureBody({ projectId: 'p1', action: 'disable', note: 'x', abrechnung: 'abo' }), { projectId: 'p1', action: 'disable', note: 'x' })
|
||||
assert.deepEqual(featureBody({ projectId: 'p1', action: 'activate', note: '', textformDate: '2026-10-06', textformChannel: 'chat', abrechnung: 'abo' }), { projectId: 'p1', action: 'activate', note: '', textformDate: '2026-10-06', textformChannel: 'chat', abrechnung: 'abo' })
|
||||
})
|
||||
|
||||
test('aboFehltText und featureFehlerText: jeder Grund, unbekannter Grund, andere Fehler', () => {
|
||||
const fehler = (grund, code = 'abo_fehlt') => Object.assign(new Error('Text des Portals'), { status: 409, code, grund })
|
||||
assert.equal(featureFehlerText(fehler('kein_abo'), 'news'), 'News: Der Kunde hat kein laufendes Abo. Die Funktion läuft nur mit passendem Abo.')
|
||||
assert.equal(featureFehlerText(fehler('falsches_abo'), 'termine'), 'Terminplaner: Das Hosting-Abo des Kunden enthält diese Funktion nicht. Sie ist im Wartungs-Abo enthalten.')
|
||||
assert.equal(featureFehlerText(fehler('gekuendigt'), 'shop'), 'Webshop: Das Abo des Kunden ist gekündigt. Eingeschaltet wird nicht, solange die Kündigung vorgemerkt ist.')
|
||||
assert.equal(featureFehlerText(fehler('nicht_aktiv'), 'zeiten'), 'Öffnungszeiten live: Das Abo des Kunden läuft nicht (Status nicht aktiv). Bitte zuerst das Abo klären.')
|
||||
assert.equal(featureFehlerText(fehler('unbekannt'), 'unterkunft'), 'Buchungskalender: Das passende Abo fehlt.')
|
||||
assert.equal(featureFehlerText(fehler(undefined), 'news'), 'News: Das passende Abo fehlt.')
|
||||
assert.equal(featureFehlerText(fehler('kein_abo', 'andere'), 'news'), 'Text des Portals')
|
||||
assert.equal(featureFehlerText(null, 'news'), 'Speichern fehlgeschlagen.')
|
||||
})
|
||||
Reference in new issue
Block a user