From bbe2d80323758fee31d99f7dc6818e7de40e2836 Mon Sep 17 00:00:00 2001 From: Prom3theu5 Date: Wed, 23 Sep 2026 09:34:54 +0100 Subject: [PATCH] fix: ensure tags.all not tags.some --- crates/keryx-render/assets/dashboard.js | 4 +++- crates/keryx-render/src/lib.rs | 2 +- tests/dashboard/tags.spec.mjs | 28 ++++++++++++++++++------ website/src/content/docs/docs/tagging.md | 2 +- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/crates/keryx-render/assets/dashboard.js b/crates/keryx-render/assets/dashboard.js index 19fad4b..ab9294c 100644 --- a/crates/keryx-render/assets/dashboard.js +++ b/crates/keryx-render/assets/dashboard.js @@ -66,7 +66,9 @@ function matchesTags(row) { var tags = rowTags(row); if (untagged) return tags.length === 0; - return !selectedTags.size || tags.some(function (tag) { return selectedTags.has(tag.id); }); + return Array.from(selectedTags).every(function (id) { + return tags.some(function (tag) { return tag.id === id; }); + }); } function renderTagFilters(query) { if (!managementEnabled) return; diff --git a/crates/keryx-render/src/lib.rs b/crates/keryx-render/src/lib.rs index da807e8..59cd9a6 100644 --- a/crates/keryx-render/src/lib.rs +++ b/crates/keryx-render/src/lib.rs @@ -495,7 +495,7 @@ pub fn render_dashboard( "#, tag_filter = if management_enabled { - r#"
Tags: all

Match any selected tag

"# + r#"
Tags: all

Match all selected tags

"# } else { "" }, diff --git a/tests/dashboard/tags.spec.mjs b/tests/dashboard/tags.spec.mjs index 7bc3fcd..ed3a2eb 100644 --- a/tests/dashboard/tags.spec.mjs +++ b/tests/dashboard/tags.spec.mjs @@ -40,20 +40,34 @@ test.beforeEach(async ({ request }) => { for (const draft of body.drafts) await request.delete(`/api/drafts/${draft.draftId}?purge=true`); }); -test('ANY filters combine with repository, search and availability; URL and snapshots retain state', async ({ page, request }) => { - const { a, b, c, planning, review } = await seed(request); - await controlledRefresh(page); - await page.goto(`/?tag=${planning.id}&tag=${review.id}&draft=${a}&sort=tag`); +test('selecting a second tag narrows results to drafts with both tags', async ({ page, request }) => { + const { a, b, planning, review } = await seed(request); + await page.goto('/'); + await page.locator('#tag-filter-summary').click(); + await page.locator(`[data-tag-choice="${planning.id}"]`).check(); + await expect(visibleRows(page)).toHaveCount(2); + await page.locator(`[data-tag-choice="${review.id}"]`).check(); + await expect(visibleRows(page)).toHaveCount(1); + await expect(visibleRows(page)).toHaveAttribute('data-draft-id', b); + await expect(page.locator(`.draft-row[data-draft-id="${a}"]`)).toBeHidden(); + await page.locator(`[data-tag-choice="${review.id}"]`).uncheck(); await expect(visibleRows(page)).toHaveCount(2); +}); + +test('tag filters combine with repository, search and availability; URL and snapshots retain state', async ({ page, request }) => { + const { b, c, planning, review } = await seed(request); + await controlledRefresh(page); + await page.goto(`/?tag=${planning.id}&tag=${review.id}&draft=${b}&sort=tag`); + await expect(visibleRows(page)).toHaveCount(1); await expect(page.locator('#tag-selections .tag-chip')).toHaveCount(3); - await page.locator('#repo-filter').selectOption('test/one'); + await page.locator('#repo-filter').selectOption('test/two'); await expect(visibleRows(page)).toHaveCount(1); await page.locator('#draft-search').fill('planning'); await expect(visibleRows(page)).toHaveCount(1); await refresh(page); await expect(page.locator('#draft-search')).toHaveValue('planning'); - await expect(page.locator('#repo-filter')).toHaveValue('test/one'); - await expect(page.locator('#detail-id')).toHaveText(a); + await expect(page.locator('#repo-filter')).toHaveValue('test/two'); + await expect(page.locator('#detail-id')).toHaveText(b); await page.reload(); await expect(visibleRows(page)).toHaveCount(1); await page.locator('#tag-filter-summary').click(); diff --git a/website/src/content/docs/docs/tagging.md b/website/src/content/docs/docs/tagging.md index e5a3148..1b764da 100644 --- a/website/src/content/docs/docs/tagging.md +++ b/website/src/content/docs/docs/tagging.md @@ -27,7 +27,7 @@ Names accept ASCII letters, digits, spaces and hyphens, with a maximum of **32 c Open **Tags** in the toolbar and tick one or more tags. The list filters immediately while the dropdown stays open. Search within the dropdown to find a tag; longer lists scroll. -- Multiple selected tags match **any** of them. Selecting `planning` and `needs-review` shows drafts carrying either label, including drafts with both. +- Multiple selected tags match **all** of them. Selecting `planning` and `needs-review` shows drafts carrying both labels. - Repository, availability and text search narrow that result further. Text search also matches tag names. - **Untagged only** shows drafts with no tags and clears selected tag filters. Selecting a tag leaves Untagged mode. - Remove a selected filter chip to clear that filter, or choose **Clear all** to clear the tag filters.