import type { AxiosInstance } from 'axios'; import type { AgrarmonitorService } from './agrarmonitor.service'; import { LieferantennummernService, type LieferantennummerLaufErgebnis, } from './lieferantennummern.service'; import type { ListenLieferant } from './lieferantennummern.parser'; // Der echte Connector lädt jsdom (ESM), das Jest nicht verarbeiten kann – hier wird er nicht gebraucht. jest.mock('agrarmonitor-connector', () => ({})); interface UpdateBody { kundeID: number; formData: Record; } function detail(nummer: string): string { return ( '
' + '' + `` + '' + '' + '' + '
' ); } function kandidat(kundeId: number, firma: string): ListenLieferant { return { kundeId, lieferantennummer: '', firma, name: '', aktiv: true }; } function neuerLauf(gesamt: number): LieferantennummerLaufErgebnis { return { modus: 'alle', gestartetAm: '', beendetAm: null, gesamt, vergeben: 0, uebersprungen: 0, zuPruefen: 0, fehler: 0, abgebrochen: false, eintraege: [], }; } /** * Simuliert Agrarmonitor: speichert Nummern aus updateKunde.php pro Kunde, * vorhanden.php meldet für die Ids in `dubletten` ähnliche Kontakte. */ function fakeHttp(opts: { nummern: Record; dubletten?: number[]; speichernIgnorieren?: number[]; }) { const aufrufe: string[] = []; const updates: UpdateBody[] = []; const http = { get: jest.fn((url: string) => { aufrufe.push(`GET ${url}`); const m = /\/kunden\/detail\/(\d+)/.exec(url); if (m) { return Promise.resolve({ data: detail(opts.nummern[Number(m[1])] ?? ''), }); } return Promise.resolve({ data: '' }); }), post: jest.fn((url: string, body: string | UpdateBody) => { aufrufe.push(`POST ${url}`); if (typeof body === 'string') { const id = Number(new URLSearchParams(body).get('customerID')); return Promise.resolve({ data: opts.dubletten?.includes(id) ? '
Ähnlich
' : '', }); } updates.push(body); if (!opts.speichernIgnorieren?.includes(body.kundeID)) { opts.nummern[body.kundeID] = String(body.formData.lieferantennummer); } return Promise.resolve({ data: '/kunden/detail/' + body.kundeID }); }), }; return { http: http as unknown as AxiosInstance, aufrufe, updates }; } function service() { const agrarmonitor = { clearClient: jest.fn() }; return new LieferantennummernService( agrarmonitor as unknown as AgrarmonitorService, ); } describe('LieferantennummernService.vergeben', () => { it('vergibt fortlaufend, überspringt Vorhandene und verbraucht bei Dubletten keine Nummer', async () => { const { http, updates, aufrufe } = fakeHttp({ nummern: { 2: '15550010' }, dubletten: [3], }); const lauf = neuerLauf(4); await service().vergeben( http, [kandidat(1, 'A'), kandidat(2, 'B'), kandidat(3, 'C'), kandidat(4, 'D')], 15550706, lauf, ); expect(lauf.eintraege.map((e) => [e.kundeId, e.status, e.nummer])).toEqual([ [1, 'vergeben', '15550706'], [2, 'uebersprungen', undefined], [3, 'pruefen', undefined], [4, 'vergeben', '15550707'], ]); expect(lauf).toMatchObject({ vergeben: 2, uebersprungen: 1, zuPruefen: 1, fehler: 0, abgebrochen: false, }); expect(updates[0].kundeID).toBe(1); expect(updates[0].formData).toMatchObject({ kundennummer: '21207', lieferantennummer: '15550706', ist_kunde: '', ist_lieferant: '1', }); expect(aufrufe[aufrufe.length - 1]).toContain('itemsperpage=25'); expect(lauf.beendetAm).not.toBeNull(); }); it('bricht ab, wenn die Nummer nach dem Speichern nicht übernommen wurde', async () => { const { http, updates, aufrufe } = fakeHttp({ nummern: {}, speichernIgnorieren: [1], }); const lauf = neuerLauf(2); await service().vergeben( http, [kandidat(1, 'A'), kandidat(2, 'B')], 15550706, lauf, ); expect(updates).toHaveLength(1); expect(lauf).toMatchObject({ vergeben: 0, fehler: 1, abgebrochen: true }); expect(lauf.eintraege[0].hinweis).toContain('15550706'); expect(aufrufe[aufrufe.length - 1]).toContain('itemsperpage=25'); }); });