refactor(search): local search ignores domain filter
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 3m11s

Der Domain-Filter im Header-Dropdown wirkt ab jetzt ausschliesslich auf
die Web-Suche (SearXNG). Die Suche in gespeicherten Rezepten liefert
immer alle Treffer, unabhaengig von der Quelldomain -- wer ein Rezept
gespeichert hat, will es finden, selbst wenn er die Domain aus dem
Filter ausgeschlossen hat.

- SearchStore: filterParam -> webFilterParam, nur noch an Web-Calls
- /api/recipes/search: domains-Query-Param wird nicht mehr gelesen
- searchLocal(): domains-Parameter + SQL-Branch entfernt
- Tests entsprechend angepasst

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-21 21:59:48 +02:00
parent 0373dc32da
commit d9490c8073
7 changed files with 25 additions and 40 deletions

View File

@@ -202,7 +202,7 @@ describe('SearchStore', () => {
expect(round).toEqual(snap);
});
it('filterParam option: gets appended to both local and web requests', async () => {
it('webFilterParam option: only appended to web requests, never to local', async () => {
vi.useFakeTimers();
const fetchImpl = mockFetch([
{ body: { hits: [] } },
@@ -211,13 +211,15 @@ describe('SearchStore', () => {
const store = new SearchStore({
fetchImpl,
debounceMs: 10,
filterParam: () => '&domains=chefkoch.de'
webFilterParam: () => '&domains=chefkoch.de'
});
store.query = 'curry';
store.runDebounced();
await vi.advanceTimersByTimeAsync(15);
await vi.waitFor(() => expect(fetchImpl).toHaveBeenCalledTimes(2));
expect(fetchImpl.mock.calls[0][0]).toMatch(/&domains=chefkoch\.de/);
expect(fetchImpl.mock.calls[0][0]).not.toMatch(/domains=/);
expect(fetchImpl.mock.calls[0][0]).toMatch(/\/api\/recipes\/search\?/);
expect(fetchImpl.mock.calls[1][0]).toMatch(/\/api\/recipes\/search\/web\?/);
expect(fetchImpl.mock.calls[1][0]).toMatch(/&domains=chefkoch\.de/);
});
@@ -243,22 +245,25 @@ describe('SearchStore', () => {
const fetchImpl = mockFetch([
{ body: { hits: [] } },
{ body: { hits: [] } },
{ body: { hits: [{ id: 1, title: 'filtered', description: null, image_path: null, source_domain: null, avg_stars: null, last_cooked_at: null }] } }
{ body: { hits: [] } },
{ body: { hits: [{ url: 'https://chefkoch.de/x', title: 'filtered', domain: 'chefkoch.de', snippet: null, thumbnail: null }] } }
]);
const store = new SearchStore({
fetchImpl,
debounceMs: 10,
filterDebounceMs: 5,
filterParam: () => filter
webFilterParam: () => filter
});
store.query = 'broth';
store.runDebounced();
await vi.advanceTimersByTimeAsync(15);
await vi.waitFor(() => expect(fetchImpl).toHaveBeenCalledTimes(2));
filter = '&domains=chefkoch.de';
store.reSearch();
await vi.advanceTimersByTimeAsync(10);
await vi.waitFor(() => expect(store.hits).toHaveLength(1));
await vi.waitFor(() => expect(store.webHits).toHaveLength(1));
const last = fetchImpl.mock.calls.at(-1)?.[0] as string;
expect(last).toMatch(/\/api\/recipes\/search\/web\?/);
expect(last).toMatch(/&domains=chefkoch\.de/);
});
});