import { TestBed } from '@angular/core/testing'; import { describe, it, expect, vi } from 'vitest'; import { SUBMIT_FAILED } from '@shared/application/submit'; import { ApplicationsAdapter } from '@registratie/infrastructure/applications.adapter'; import { ApplicationsStore } from './applications.store'; const summary = (id: string) => ({ id, type: 'registratie', status: { tag: 'Concept', stepIndex: 0, stepCount: 3 }, documentIds: [], createdAt: '2026-07-23T10:00:00Z', updatedAt: '2026-07-23T10:00:00Z', }); function setup(adapter: Partial): ApplicationsStore { TestBed.configureTestingModule({ providers: [{ provide: ApplicationsAdapter, useValue: adapter }], }); // The store's own constructor kicks off `load()` (dashboard revisit refresh) — // give every test a `list` so that initial call has something to resolve. return TestBed.inject(ApplicationsStore); } describe('ApplicationsStore', () => { it('loads and parses the list', async () => { const store = setup({ list: () => Promise.resolve([summary('a'), summary('b')]) }); await store.load(); const s = store.applications(); expect(s.tag).toBe('Success'); expect(s.tag === 'Success' && s.value.map((a) => a.id)).toEqual(['a', 'b']); }); it('cancels optimistically and confirms via the DELETE endpoint', async () => { const cancel = vi.fn().mockResolvedValue(undefined); const store = setup({ list: () => Promise.resolve([summary('a'), summary('b')]), cancel, }); await store.load(); await store.cancel('a'); expect(cancel).toHaveBeenCalledWith('a'); const s = store.applications(); expect(s.tag === 'Success' && s.value.map((a) => a.id)).toEqual(['b']); expect(store.lastError()).toBeNull(); }); // RB-20: a failed cancel must not be silent — the row rolls back AND the store // surfaces the error the page renders. Before RB-20 this only rolled back // (bare `catch { this.state.set(before) }`), so `lastError()` stayed null forever. it('rolls back the removal and surfaces the error when the cancel fails', async () => { const cancel = vi.fn().mockRejectedValue(new Error('boom')); const store = setup({ list: () => Promise.resolve([summary('a')]), cancel }); await store.load(); await store.cancel('a'); const s = store.applications(); expect(s.tag === 'Success' && s.value.map((a) => a.id)).toEqual(['a']); // reappears expect(store.lastError()).toBe(SUBMIT_FAILED); }); it('clears a stale error on the next cancel attempt', async () => { const cancel = vi .fn() .mockRejectedValueOnce(new Error('boom')) .mockResolvedValueOnce(undefined); const store = setup({ list: () => Promise.resolve([summary('a'), summary('b')]), cancel }); await store.load(); await store.cancel('a'); expect(store.lastError()).toBe(SUBMIT_FAILED); await store.cancel('b'); expect(store.lastError()).toBeNull(); }); });