diff --git a/frontend/src/components/DataTable.fixedLayout.dom.test.tsx b/frontend/src/components/DataTable.fixedLayout.dom.test.tsx
new file mode 100644
index 00000000..cb89d0a9
--- /dev/null
+++ b/frontend/src/components/DataTable.fixedLayout.dom.test.tsx
@@ -0,0 +1,46 @@
+// @vitest-environment jsdom
+//
+// The R14 zoom-fit foundation: DataTable's opt-in `fixedLayout` renders a
and puts the
+// table into `table-layout: fixed`, so columns with a width keep it and the rest (fluid text columns)
+// split the remainder + truncate instead of pushing the table wider than its container. Off by
+// default so existing content-sized tables are untouched.
+import { describe, it, expect, afterEach, vi } from "vitest";
+import { render, cleanup } from "@testing-library/react";
+import DataTable, { type Column } from "./DataTable";
+
+vi.mock("react-i18next", async (importOriginal) => {
+ const actual = await importOriginal();
+ return { ...actual, useTranslation: () => ({ t: (key: string) => key }) };
+});
+
+afterEach(cleanup);
+
+type Row = { a: string; b: string };
+const columns: Column[] = [
+ { key: "a", header: "A", width: "5rem", render: (r) => r.a },
+ { key: "b", header: "B", render: (r) => r.b }, // fluid — no width
+];
+const rows: Row[] = [{ a: "1", b: "hello" }];
+
+describe("DataTable fixedLayout", () => {
+ it("renders a width-bearing colgroup and table-fixed only when fixedLayout is set", () => {
+ const { container } = render(
+ r.a} fixedLayout />,
+ );
+ const table = container.querySelector("table");
+ expect(table?.className).toContain("table-fixed");
+
+ const cols = container.querySelectorAll("colgroup col");
+ expect(cols).toHaveLength(2);
+ expect((cols[0] as HTMLElement).style.width).toBe("5rem"); // fixed column keeps its width
+ expect((cols[1] as HTMLElement).style.width).toBe(""); // fluid column: no width, splits remainder
+ });
+
+ it("omits the colgroup and stays auto-layout by default", () => {
+ const { container } = render(
+ r.a} />,
+ );
+ expect(container.querySelector("colgroup")).toBeNull();
+ expect(container.querySelector("table")?.className).not.toContain("table-fixed");
+ });
+});
diff --git a/frontend/src/components/channelColumns.dom.test.tsx b/frontend/src/components/channelColumns.dom.test.tsx
new file mode 100644
index 00000000..f9272f59
--- /dev/null
+++ b/frontend/src/components/channelColumns.dom.test.tsx
@@ -0,0 +1,56 @@
+// @vitest-environment jsdom
+//
+// applySyncFilter is the sync-status pre-filter the top chips drive (R14 retired the Sync column and
+// folded its status into a Stored charm). It replaced a column `filter.test`, so it carries the exact
+// "fully" | "needsFull" | "" vocab + predicate — asserted here so a regression can't silently change
+// which channels the top chips show.
+import { describe, it, expect } from "vitest";
+import { applySyncFilter } from "./channelColumns";
+import { type ManagedChannel } from "../lib/api";
+
+const ch = (over: Partial): ManagedChannel => ({
+ id: "c",
+ title: null,
+ handle: null,
+ thumbnail_url: null,
+ subscriber_count: null,
+ video_count: null,
+ description: null,
+ stored_videos: 0,
+ last_video_at: null,
+ total_duration_seconds: 0,
+ count_normal: 0,
+ count_short: 0,
+ count_live: 0,
+ priority: 0,
+ hidden: false,
+ deep_requested: false,
+ deep_in_queue: false,
+ tag_ids: [],
+ details_synced: false,
+ recent_synced: false,
+ backfill_done: false,
+ ...over,
+});
+
+const rows = [
+ ch({ id: "fully", recent_synced: true, backfill_done: true }),
+ ch({ id: "recentOnly", recent_synced: true, backfill_done: false }),
+ ch({ id: "none", recent_synced: false, backfill_done: false }),
+];
+
+describe("applySyncFilter", () => {
+ it("returns every row for the empty/all value (and unknown values)", () => {
+ expect(applySyncFilter(rows, "").map((r) => r.id)).toEqual(["fully", "recentOnly", "none"]);
+ expect(applySyncFilter(rows, undefined)).toHaveLength(3);
+ expect(applySyncFilter(rows, "bogus")).toHaveLength(3);
+ });
+
+ it("'fully' keeps only channels with recent uploads AND full history in", () => {
+ expect(applySyncFilter(rows, "fully").map((r) => r.id)).toEqual(["fully"]);
+ });
+
+ it("'needsFull' keeps every channel whose back-catalogue is not done", () => {
+ expect(applySyncFilter(rows, "needsFull").map((r) => r.id)).toEqual(["recentOnly", "none"]);
+ });
+});