Files
tickte-system/tests/unit/rechnungDialogState.test.mjs
ClaudeandClaude Sonnet 5.5 dec7bea7d2 Kontrolle: Rechnungsdialog übernimmt das Zahlungsziel der gewählten AB
Bei Anzahlung, Schlussrechnung und Aufwand wird 'Zahlungsziel in Tagen' mit
auftrag.zahlungszielTage vorbelegt (sonst 14); eine Eingabe des Nutzers bleibt.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-07 15:17:08 +00:00

133 lines
6.6 KiB
JavaScript
Raw Permalink 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'
const { anfangszustand, reduce } = await loadModule('src/lib/rechnungDialogState.js')
test('anfangszustand: nichts gewählt, eine leere Position, Zahlungsziel 14', () => {
assert.deepEqual(anfangszustand({ projektId: 'p1' }), {
projektId: 'p1', art: '', auftragId: '',
items: [{ uid: 1, description: '', quantity: '1', price: '' }], zusatz: [],
abgewaehlt: [], weitereTickets: [], anzahlung: {}, zeilentexte: {},
zeitraum: '', zeitraumGeaendert: false, days: '14', tageGeaendert: false, memo: '',
})
assert.equal(anfangszustand().projektId, null)
assert.equal(anfangszustand({ projektId: '' }).projektId, '')
})
test('projekt: setzt alles zurück, behält aber Zahlungsziel und Notiz', () => {
let s = anfangszustand({ projektId: 'p1' })
s = reduce(s, { type: 'tage', wert: '30' })
s = reduce(s, { type: 'notiz', wert: 'Danke' })
s = reduce(s, { type: 'art', art: 'aufwand' })
s = reduce(s, { type: 'blatt', id: 'b1' })
s = reduce(s, { type: 'zeilentext', schluessel: '2026-10-06', text: 'Neu', original: 'Alt' })
s = reduce(s, { type: 'projekt', projektId: 'p2' })
assert.equal(s.projektId, 'p2')
assert.equal(s.art, '')
assert.deepEqual(s.abgewaehlt, [])
assert.deepEqual(s.zeilentexte, {})
assert.equal(s.days, '30')
assert.equal(s.memo, 'Danke')
assert.equal(reduce(s, { type: 'projekt', projektId: null }).projektId, null)
})
test('art: Positionen für Festbetrag und Zusatzpositionen bleiben getrennt und erhalten', () => {
let s = anfangszustand({ projektId: 'p1' })
s = reduce(s, { type: 'position', liste: 'items', uid: 1, feld: 'description', wert: 'Pauschale' })
s = reduce(s, { type: 'position+', liste: 'zusatz' })
s = reduce(s, { type: 'position', liste: 'zusatz', uid: 2, feld: 'price', wert: '12,00' })
s = reduce(s, { type: 'art', art: 'aufwand' })
assert.equal(s.art, 'aufwand')
assert.equal(s.items[0].description, 'Pauschale')
assert.deepEqual(s.zusatz, [{ uid: 2, description: '', quantity: '1', price: '12,00' }])
// eine unbekannte Liste oder ein unbekanntes Feld ändert nichts
assert.equal(reduce(s, { type: 'position', liste: 'x', uid: 1, feld: 'description', wert: 'y' }), s)
assert.equal(reduce(s, { type: 'position', liste: 'items', uid: 1, feld: 'uid', wert: 9 }), s)
})
test('position+ und position-: Positionen mindestens 1, Zusatzpositionen mindestens 0, höchstens 20', () => {
let s = anfangszustand({ projektId: 'p1' })
assert.equal(reduce(s, { type: 'position-', liste: 'items', uid: 1 }), s)
s = reduce(s, { type: 'position+', liste: 'zusatz' })
assert.equal(s.zusatz[0].uid, 2)
s = reduce(s, { type: 'position-', liste: 'zusatz', uid: 2 })
assert.deepEqual(s.zusatz, [])
for (let i = 0; i < 25; i += 1) s = reduce(s, { type: 'position+', liste: 'zusatz' })
assert.equal(s.zusatz.length, 20)
})
test('blatt: Abwählen und Wiederanwählen', () => {
let s = anfangszustand({ projektId: 'p1' })
s = reduce(s, { type: 'blatt', id: 'b2' })
assert.deepEqual(s.abgewaehlt, ['b2'])
s = reduce(s, { type: 'blatt', id: 'b2' })
assert.deepEqual(s.abgewaehlt, [])
})
test('ticket+ und ticket-: ein Ticket nur einmal, beim Entfernen verschwindet die Abwahl seiner Blätter', () => {
const ticket = { ticketId: 't2', woid: '100140', titel: 'Kontaktformular' }
let s = anfangszustand({ projektId: 'p1' })
s = reduce(s, { type: 'ticket+', ticket })
s = reduce(s, { type: 'ticket+', ticket })
assert.deepEqual(s.weitereTickets, [ticket])
s = reduce(s, { type: 'blatt', id: 'w1' })
s = reduce(s, { type: 'blatt', id: 'b9' })
s = reduce(s, { type: 'ticket-', ticketId: 't2', blattIds: ['w1'] })
assert.deepEqual(s.weitereTickets, [])
assert.deepEqual(s.abgewaehlt, ['b9'])
})
test('zeitraum-vorschlag gilt nur, solange der Nutzer das Feld nicht selbst geändert hat', () => {
let s = anfangszustand({ projektId: 'p1' })
s = reduce(s, { type: 'zeitraum-vorschlag', text: '01.10.–20.10.2026' })
assert.deepEqual([s.zeitraum, s.zeitraumGeaendert], ['01.10.–20.10.2026', false])
assert.equal(reduce(s, { type: 'zeitraum-vorschlag', text: '01.10.–20.10.2026' }), s) // gleicher Text: kein neuer Zustand
s = reduce(s, { type: 'zeitraum', text: 'Oktober 2026' })
assert.deepEqual([s.zeitraum, s.zeitraumGeaendert], ['Oktober 2026', true])
assert.equal(reduce(s, { type: 'zeitraum-vorschlag', text: '02.10.–21.10.2026' }).zeitraum, 'Oktober 2026')
// ein Wechsel der Art verwirft einen Vorschlag, nicht aber die Eingabe des Nutzers
const vorschlag = reduce(anfangszustand({ projektId: 'p1' }), { type: 'zeitraum-vorschlag', text: '01.10.–20.10.2026' })
assert.equal(reduce(vorschlag, { type: 'art', art: 'festbetrag' }).zeitraum, '')
assert.equal(reduce(s, { type: 'art', art: 'festbetrag' }).zeitraum, 'Oktober 2026')
})
test('zeilentext: ein unveränderter oder leerer Text entfernt den Eintrag', () => {
let s = anfangszustand({ projektId: 'p1' })
const setze = (text) => reduce(s, { type: 'zeilentext', schluessel: '2026-10-06', text, original: 'Alt' })
s = setze('Neu')
assert.deepEqual(s.zeilentexte, { '2026-10-06': 'Neu' })
s = setze('Alt')
assert.deepEqual(s.zeilentexte, {})
s = setze('Neu')
s = setze(' ')
assert.deepEqual(s.zeilentexte, {})
})
test('anzahlung und auftrag: Eingaben ergänzen sich, eine andere AB setzt sie zurück', () => {
let s = anfangszustand({ projektId: 'p1' })
s = reduce(s, { type: 'anzahlung', patch: { modus: 'betrag' } })
s = reduce(s, { type: 'anzahlung', patch: { wert: '400,00' } })
assert.deepEqual(s.anzahlung, { modus: 'betrag', wert: '400,00' })
s = reduce(s, { type: 'auftrag', auftragId: 'a2' })
assert.deepEqual([s.auftragId, s.anzahlung], ['a2', {}])
assert.equal(reduce(s, { type: 'gibtsnicht' }), s)
})
test('tage-vorschlag: übernimmt das Zahlungsziel der AB, solange der Nutzer es nicht selbst geändert hat', () => {
let s = anfangszustand({ projektId: 'p1' })
s = reduce(s, { type: 'tage-vorschlag', wert: '30' })
assert.equal(s.days, '30')
assert.equal(s.tageGeaendert, false)
assert.equal(reduce(s, { type: 'tage-vorschlag', wert: '30' }), s) // derselbe Wert: nichts zu tun
s = reduce(s, { type: 'tage-vorschlag', wert: '14' }) // andere AB gewählt: der Vorschlag folgt
assert.equal(s.days, '14')
// eine Eingabe des Nutzers wird nie überschrieben, auch nicht nach einem Projektwechsel
s = reduce(s, { type: 'tage', wert: '7' })
assert.equal(s.tageGeaendert, true)
assert.equal(reduce(s, { type: 'tage-vorschlag', wert: '30' }), s)
s = reduce(s, { type: 'projekt', projektId: 'p2' })
assert.equal(s.days, '7')
assert.equal(reduce(s, { type: 'tage-vorschlag', wert: '30' }).days, '7')
})