import { readFileSync } from 'node:fs' import { describe, expect, it } from 'vitest' import { graphSeiteLesen, graphZeitpunkt, zeigtAlsAusGraph } from './graph' import { AntwortUnbrauchbar } from './typen' /** Beispielantworten aus test/fixtures, anonymisiert. */ function fixture(name: string): unknown { return JSON.parse( readFileSync(`test/fixtures/kalender/${name}.json`, 'utf8'), ) as unknown } describe('zeigtAlsAusGraph', () => { it('übersetzt die bekannten Werte', () => { expect(zeigtAlsAusGraph('free')).toBe('FREI') expect(zeigtAlsAusGraph('busy')).toBe('GEBUCHT') expect(zeigtAlsAusGraph('tentative')).toBe('MIT_VORBEHALT') expect(zeigtAlsAusGraph('oof')).toBe('ABWESEND') expect(zeigtAlsAusGraph('workingElsewhere')).toBe('WOANDERS') }) it('nimmt Unbekanntes als unbekannt, statt es zu raten', () => { expect(zeigtAlsAusGraph('etwasNeues')).toBe('UNBEKANNT') expect(zeigtAlsAusGraph(undefined)).toBe('UNBEKANNT') }) }) describe('graphZeitpunkt', () => { it('liest eine UTC-Angabe', () => { expect( graphZeitpunkt({ dateTime: '2026-03-17T08:00:00.0000000', timeZone: 'UTC', }).toISOString(), ).toBe('2026-03-17T08:00:00.000Z') }) it('kürzt die sieben Nachkommastellen, die Date nicht versteht', () => { expect( graphZeitpunkt({ dateTime: '2026-03-17T08:00:00.1234567', timeZone: 'UTC', }).toISOString(), ).toBe('2026-03-17T08:00:00.123Z') }) it('kommt auch ohne Nachkommastellen zurecht', () => { expect( graphZeitpunkt({ dateTime: '2026-03-17T08:00:00', timeZone: 'UTC' }).toISOString(), ).toBe('2026-03-17T08:00:00.000Z') }) it('bricht bei einer anderen Zeitzone ab, statt Termine zu verschieben', () => { expect(() => graphZeitpunkt({ dateTime: '2026-03-17T09:00:00.0000000', timeZone: 'W. Europe Standard Time', }), ).toThrow(AntwortUnbrauchbar) }) it('bricht bei unlesbarer Zeitangabe ab', () => { expect(() => graphZeitpunkt({ dateTime: 'morgen früh', timeZone: 'UTC' })).toThrow( AntwortUnbrauchbar, ) }) }) describe('graphSeiteLesen', () => { it('liest die erste Seite samt Verweis auf die nächste', () => { const seite = graphSeiteLesen(fixture('graph-delta-seite1')) expect(seite.geaendert).toHaveLength(2) expect(seite.entfernt).toEqual([]) expect(seite.weiter).toContain('$skiptoken=') expect(seite.deltaVerweis).toBeNull() }) it('übernimmt Betreff, Kennung und Etag', () => { const [erster] = graphSeiteLesen(fixture('graph-delta-seite1')).geaendert expect(erster?.extId).toBe('BEISPIEL-TERMIN-1') expect(erster?.betreff).toBe('Wochenbesprechung') expect(erster?.etag).toContain('BEISPIELETAG1') expect(erster?.beginn.toISOString()).toBe('2026-03-17T08:00:00.000Z') expect(erster?.ende.toISOString()).toBe('2026-03-17T09:00:00.000Z') expect(erster?.ganztaegig).toBe(false) expect(erster?.zeigtAls).toBe('GEBUCHT') }) it('erkennt ganztägige Termine', () => { const ganztaegig = graphSeiteLesen(fixture('graph-delta-seite1')).geaendert[1] expect(ganztaegig?.ganztaegig).toBe(true) expect(ganztaegig?.zeigtAls).toBe('ABWESEND') }) it('liest die letzte Seite mit dem Delta-Verweis für die nächste Runde', () => { const seite = graphSeiteLesen(fixture('graph-delta-seite2')) expect(seite.weiter).toBeNull() expect(seite.deltaVerweis).toContain('$deltatoken=') }) it('trennt Entferntes von Geändertem', () => { const seite = graphSeiteLesen(fixture('graph-delta-seite2')) expect(seite.entfernt).toEqual(['BEISPIEL-TERMIN-9']) expect(seite.geaendert.map((t) => t.extId)).toEqual(['BEISPIEL-TERMIN-3']) }) it('erkennt einen als frei markierten Termin', () => { const [frei] = graphSeiteLesen(fixture('graph-delta-seite2')).geaendert expect(frei?.zeigtAls).toBe('FREI') }) it('bricht ab, wenn Graph eine andere Zeitzone liefert', () => { expect(() => graphSeiteLesen(fixture('graph-delta-fremde-zeitzone'))).toThrow( AntwortUnbrauchbar, ) }) it('weist eine Antwort ohne value-Liste ab', () => { expect(() => graphSeiteLesen({ irgendwas: true })).toThrow(AntwortUnbrauchbar) }) it('übergeht Einträge ohne Zeitraum, statt abzubrechen', () => { const seite = graphSeiteLesen({ value: [{ id: 'ohne-zeit', subject: 'Kein Zeitraum' }], }) expect(seite.geaendert).toEqual([]) expect(seite.entfernt).toEqual([]) }) })