refactor: rename Application → Aanvraag across the wire (Step 1/8)

The wire said Application, the domain said Aanvraag — one aggregate with
two names at every hop. Rename the backend DTOs and the /applications
route to /aanvragen, regenerate the typed client, and rename the frontend
adapter/store to match.

Renamed: ApplicationSummaryDto/DetailDto, CreateApplicationRequest,
SubmitApplicationRequest/Response → Aanvraag* equivalents;
ApplicationsAdapter/Store → AanvragenAdapter/Store;
applications.adapter.ts/applications.store.ts → aanvragen.*.

Left untouched: the admin Case/Zaak vocabulary (/admin/cases,
AdminCasesStore) — a separate read model, not part of this rename; the
internal BigRegister.Domain.Applications namespace and the Applications
EF table (renaming those needs a new EF migration, out of scope here).

Part of the dashboard-readability refactor (see the approved plan).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
eho
2026-09-04 14:33:16 +02:00
co-authored by Claude Opus 5
parent faad772f85
commit 194cccfd02
36 changed files with 400 additions and 412 deletions
@@ -0,0 +1,77 @@
import { TestBed } from '@angular/core/testing';
import { describe, it, expect, vi } from 'vitest';
import { SUBMIT_FAILED } from '@shared/application/submit';
import { AanvragenAdapter } from '@registratie/infrastructure/aanvragen.adapter';
import { AanvragenStore } from './aanvragen.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<AanvragenAdapter>): AanvragenStore {
TestBed.configureTestingModule({
providers: [{ provide: AanvragenAdapter, 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(AanvragenStore);
}
describe('AanvragenStore', () => {
it('loads and parses the list', async () => {
const store = setup({ list: () => Promise.resolve([summary('a'), summary('b')]) });
await store.load();
const s = store.aanvragen();
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.aanvragen();
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.aanvragen();
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();
});
});