refactor: strip WP-/RB- ticket refs from apps and libs (RD-18)
204 WP-NN/RB-NN comments named a closed ticket instead of the code they sit next to. git blame already records history and stays correct when code moves; the comment does not. This sweep removes the reference and keeps the sentence, across 95 files in apps/ and libs/ plus the behaviour-spec generator's header text. Eleven references stay: five story files justify an a11y disable per the README's rule, and one line in a11y.mdx documents that convention. Two sentences needed a rewrite, not a deletion, so the reference's meaning survives its removal. behaviour-spec.mdx is regenerated, not hand-edited. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -46,8 +46,8 @@ describe('AanvragenStore', () => {
|
||||
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
|
||||
// A failed cancel must not be silent — the row rolls back AND the store
|
||||
// surfaces the error the page renders. Before this fix it 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'));
|
||||
|
||||
@@ -14,7 +14,7 @@ type Err = Error | undefined;
|
||||
* change-detection timing, HTTP caching, or a resource `reload()`. `reload()` re-fetches
|
||||
* so a page revisit reflects auto-approval (Concept → In behandeling → Goedgekeurd is
|
||||
* computed server-side on read). Cancel goes through `runSubmit` and rolls back plus
|
||||
* surfaces `lastError` on failure (RB-20).
|
||||
* surfaces `lastError` on failure.
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AanvragenStore {
|
||||
@@ -23,7 +23,7 @@ export class AanvragenStore {
|
||||
private state = signal<RemoteData<Err, Aanvraag[]>>({ tag: 'Loading' });
|
||||
readonly aanvragen = this.state.asReadonly();
|
||||
|
||||
/** Set on a failed cancel (RB-20): the optimistic removal already rolled back by
|
||||
/** Set on a failed cancel: the optimistic removal already rolled back by
|
||||
then, this is only the message for the alert the page renders above the list. */
|
||||
private error = signal<string | null>(null);
|
||||
readonly lastError = this.error.asReadonly();
|
||||
@@ -55,7 +55,7 @@ export class AanvragenStore {
|
||||
|
||||
/** Cancel a Concept: drop it now (synchronous, guaranteed), then confirm the DELETE.
|
||||
No resync — the delete succeeded, so the optimistic removal is authoritative. On
|
||||
failure, roll back AND surface the error (RB-20) — a silent reappearance leaves the
|
||||
failure, roll back AND surface the error — a silent reappearance leaves the
|
||||
user guessing why the block came back. */
|
||||
async cancel(id: string) {
|
||||
const before = this.state();
|
||||
|
||||
@@ -44,8 +44,8 @@ describe('AdminCasesStore', () => {
|
||||
expect(s.tag === 'Success' && s.value.map((c) => c.id)).toEqual(['b']);
|
||||
});
|
||||
|
||||
// RB-20: a failed delete must not be silent — the row rolls back AND the store
|
||||
// surfaces the error the page renders. Before RB-20 this only rolled back
|
||||
// A failed delete must not be silent — the row rolls back AND the store
|
||||
// surfaces the error the page renders. Before this fix it 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 delete fails', async () => {
|
||||
const deleteAny = vi.fn().mockRejectedValue(new Error('boom'));
|
||||
|
||||
@@ -7,11 +7,11 @@ import { AanvragenAdapter, parseAanvragen } from '@registratie/infrastructure/aa
|
||||
type Err = Error | undefined;
|
||||
|
||||
/**
|
||||
* Admin view of ALL cases across owners (WP-36; `cases:manage`) — the back-office
|
||||
* Admin view of ALL cases across owners (`cases:manage`) — the back-office
|
||||
* counterpart of the user-facing `AanvragenStore`. Same shape: one root singleton
|
||||
* owns the list as a writable RemoteData signal, delete removes the row synchronously
|
||||
* (optimistic), goes through `runSubmit`, and rolls back plus surfaces `lastError` on
|
||||
* failure (RB-20). Admin delete removes any case (any owner, submitted or not — the
|
||||
* failure. Admin delete removes any case (any owner, submitted or not — the
|
||||
* server enforces the capability).
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
@@ -21,7 +21,7 @@ export class AdminCasesStore {
|
||||
private state = signal<RemoteData<Err, Aanvraag[]>>({ tag: 'Loading' });
|
||||
readonly cases = this.state.asReadonly();
|
||||
|
||||
/** Set on a failed delete (RB-20): the optimistic removal already rolled back by
|
||||
/** Set on a failed delete: the optimistic removal already rolled back by
|
||||
then, this is only the message for the alert the page renders above the list. */
|
||||
private error = signal<string | null>(null);
|
||||
readonly lastError = this.error.asReadonly();
|
||||
@@ -47,7 +47,7 @@ export class AdminCasesStore {
|
||||
}
|
||||
|
||||
/** Delete a case: drop it now (synchronous), then confirm the DELETE; roll back on error
|
||||
AND surface it (RB-20) — a silent reappearance leaves the admin guessing why. */
|
||||
AND surface it — a silent reappearance leaves the admin guessing why. */
|
||||
async delete(id: string) {
|
||||
const before = this.state();
|
||||
if (before.tag === 'Success') {
|
||||
|
||||
@@ -96,7 +96,7 @@ describe('createDraftSync', () => {
|
||||
expect(r.ok).toBe(false);
|
||||
});
|
||||
|
||||
it('recovers from a create conflict by adopting the existing Concept (WP-35)', async () => {
|
||||
it('recovers from a create conflict by adopting the existing Concept', async () => {
|
||||
// Server enforces one Concept per type: a stale/cross-tab create is rejected (409),
|
||||
// and ensureId adopts the existing Concept from the list instead of erroring.
|
||||
const create = vi.fn().mockRejectedValue({ status: 409 });
|
||||
|
||||
@@ -63,7 +63,7 @@ export function createDraftSync(deps: DraftSyncDeps) {
|
||||
if (id) return id;
|
||||
ensuring ??= adapter
|
||||
.create(deps.type)
|
||||
// WP-35: one Concept per type is server-enforced. Within a tab the resumeGate
|
||||
// One Concept per type is server-enforced. Within a tab the resumeGate
|
||||
// already prevents a second create, but a cross-tab/stale race can still hit the
|
||||
// server's guard (409) — recover by adopting the existing Concept instead of
|
||||
// erroring. Only recover when one actually exists; otherwise surface the failure.
|
||||
|
||||
@@ -3,7 +3,7 @@ import { AanvragenAdapter, parseAanvragen } from '@registratie/infrastructure/aa
|
||||
|
||||
/**
|
||||
* Read half of the Concept lookup that `createDraftSync` (`draft-sync.ts`) needs
|
||||
* before it can start writing (RB-21 / CQ-001). Free functions that take the adapter
|
||||
* before it can start writing (CQ-001). Free functions that take the adapter
|
||||
* as a parameter, not `inject()`, so they get a direct spec without Angular TestBed.
|
||||
* `createDraftSync` keeps the closure state (`id`, `resumeGate`) and the write path;
|
||||
* these two functions only read.
|
||||
|
||||
Reference in New Issue
Block a user