commit 98d701bb98444d3c6c075bf2b5dbf82e4708e62b
parent 640e730bc934f5d22883b1fbb9b1708d98c5dfb6
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Mon, 18 May 2026 19:56:43 -0400
defer search after filter/regex changes
Diffstat:
2 files changed, 75 insertions(+), 0 deletions(-)
diff --git a/common/components/TranscriptSearch.tsx b/common/components/TranscriptSearch.tsx
Binary files differ.
diff --git a/editor/e2e/export-search.spec.ts b/editor/e2e/export-search.spec.ts
@@ -548,3 +548,78 @@ test.describe("export footer", () => {
expect(svgHtml).not.toMatch(/<svg[^>]*\sheight=/);
});
});
+
+test.describe("export TranscriptSearch — deferred search submit", () => {
+ test.beforeEach(async ({ page }) => {
+ await installFixtureRoutes(page);
+ await page.goto(EXPORT_BASE);
+ await waitForHydration(page);
+ });
+
+ test("toggling a filter does not auto-commit; results stay until Search is clicked", async ({
+ page,
+ }) => {
+ await search(page, "platypus");
+ // The deleted video is present by default.
+ const deletedVideo = page.getByRole("button", {
+ name: /Deleted platypus chronicles.*Test Channel/,
+ });
+ await expect(deletedVideo).toBeVisible();
+
+ // Toggle "Deleted" off — URL should NOT change to include nd=1 yet.
+ await page.getByRole("checkbox", { name: "Deleted" }).uncheck();
+ await expect(page).not.toHaveURL(/[?&]nd=1/);
+ // And the deleted video is STILL in the rendered results.
+ await expect(deletedVideo).toBeVisible();
+
+ // Dirty hint appears, Search button gets primary styling.
+ await expect(
+ page.getByText("Press Enter or click Search to apply"),
+ ).toBeVisible();
+
+ // Clicking the Search button commits the filter change.
+ await page.getByRole("button", { name: "Search" }).click();
+ await expect(page).toHaveURL(/[?&]nd=1/);
+ await expect(deletedVideo).toHaveCount(0);
+ // Dirty hint goes away.
+ await expect(
+ page.getByText("Press Enter or click Search to apply"),
+ ).toHaveCount(0);
+ });
+
+ test("toggling Regex does not auto-commit and the placeholder previews regex mode", async ({
+ page,
+ }) => {
+ const regex = page.getByRole("checkbox", { name: "Regex" });
+ await regex.check();
+ // The URL still has no re=1.
+ await expect(page).not.toHaveURL(/[?&]re=1/);
+ // The input placeholder reflects the *draft* regex mode.
+ await expect(page.getByPlaceholder(/Regex pattern/)).toBeVisible();
+ // Dirty hint visible.
+ await expect(
+ page.getByText("Press Enter or click Search to apply"),
+ ).toBeVisible();
+
+ // Pressing Enter commits the draft.
+ await page.getByPlaceholder(/Regex pattern/).press("Enter");
+ await expect(page).toHaveURL(/[?&]re=1/);
+ });
+
+ test("Search button is the primary CTA when filters are dirty and muted otherwise", async ({
+ page,
+ }) => {
+ const searchBtn = page.getByRole("button", { name: "Search" });
+ await expect(searchBtn).toBeVisible();
+ // Pristine: outline/muted styling — no blue background.
+ await expect(searchBtn).not.toHaveClass(/bg-blue-600/);
+
+ await page.getByRole("checkbox", { name: "Deleted" }).uncheck();
+ // Dirty: primary blue styling.
+ await expect(searchBtn).toHaveClass(/bg-blue-600/);
+
+ // Submit, returns to pristine.
+ await searchBtn.click();
+ await expect(searchBtn).not.toHaveClass(/bg-blue-600/);
+ });
+});