fix(documents): sync filter display state with URL on navigation
Three root causes prevented filters from reflecting the URL after SvelteKit client-side navigation: 1. +page.server.ts now resolves sender/receiver display names in parallel with the document search (UUID validation + silent 404 drop), so initialSenderName / initialReceiverName land in server data ready for the UI to use. 2. +page.svelte passes initialSenderName, initialReceiverName, and navKey (incremented via untrack on every navigation) down to SearchFilterBar. The untrack() prevents the effect from re-running due to its own navKey write. 3. SearchFilterBar forwards navKey as resetKey to each PersonTypeahead, which already had a void resetKey guard added in the previous commit. Together these ensure that after navigating to /documents?senderId=<uuid> the typeahead shows the person's display name, and clicking × reset clears it. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -167,3 +167,72 @@ describe('documents page load — network error fallback', () => {
|
||||
expect(result.items).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── person name resolution ───────────────────────────────────────────────────
|
||||
|
||||
describe('documents page load — person name resolution', () => {
|
||||
function makeSearchMock() {
|
||||
const mockGet = vi.fn().mockResolvedValue({
|
||||
response: { ok: true, status: 200 },
|
||||
data: { items: [], totalElements: 0, pageNumber: 0, pageSize: 50, totalPages: 0 }
|
||||
});
|
||||
vi.mocked(createApiClient).mockReturnValue({ GET: mockGet } as ReturnType<
|
||||
typeof createApiClient
|
||||
>);
|
||||
}
|
||||
|
||||
it('returns initialSenderName from person lookup when senderId is a valid UUID', async () => {
|
||||
makeSearchMock();
|
||||
const mockFetch = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
json: vi.fn().mockResolvedValue({ displayName: 'Max Mustermann' })
|
||||
});
|
||||
|
||||
const result = await load({
|
||||
url: makeUrl({ senderId: '11111111-1111-1111-1111-111111111111' }),
|
||||
fetch: mockFetch as unknown as typeof fetch
|
||||
});
|
||||
|
||||
expect(result.initialSenderName).toBe('Max Mustermann');
|
||||
});
|
||||
|
||||
it('returns initialReceiverName from person lookup when receiverId is a valid UUID', async () => {
|
||||
makeSearchMock();
|
||||
const mockFetch = vi.fn().mockResolvedValue({
|
||||
ok: true,
|
||||
json: vi.fn().mockResolvedValue({ displayName: 'Anna Musterfrau' })
|
||||
});
|
||||
|
||||
const result = await load({
|
||||
url: makeUrl({ receiverId: '22222222-2222-2222-2222-222222222222' }),
|
||||
fetch: mockFetch as unknown as typeof fetch
|
||||
});
|
||||
|
||||
expect(result.initialReceiverName).toBe('Anna Musterfrau');
|
||||
});
|
||||
|
||||
it('returns empty string when senderId is not a valid UUID', async () => {
|
||||
makeSearchMock();
|
||||
const mockFetch = vi.fn();
|
||||
|
||||
const result = await load({
|
||||
url: makeUrl({ senderId: 'not-a-uuid' }),
|
||||
fetch: mockFetch as unknown as typeof fetch
|
||||
});
|
||||
|
||||
expect(result.initialSenderName).toBe('');
|
||||
expect(mockFetch).not.toHaveBeenCalledWith(expect.stringContaining('/api/persons/'));
|
||||
});
|
||||
|
||||
it('returns empty string when person fetch returns 404', async () => {
|
||||
makeSearchMock();
|
||||
const mockFetch = vi.fn().mockResolvedValue({ ok: false, status: 404 });
|
||||
|
||||
const result = await load({
|
||||
url: makeUrl({ senderId: '11111111-1111-1111-1111-111111111111' }),
|
||||
fetch: mockFetch as unknown as typeof fetch
|
||||
});
|
||||
|
||||
expect(result.initialSenderName).toBe('');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user