import { test, expect } from "@playwright/test"; import { resetData } from "./helpers"; // /channels columns are sortable client-side. Default state shows no sort // indicator (input order from listChannels). Clicking a header sorts by that // column; clicking the active header flips direction. Sort state does not // persist across navigation. test("clicking column headers sorts the channels table and indicates direction", async ({ page, }) => { await resetData("two-slow-channels"); await page.goto("/channels"); // Default: no header carries an active aria-sort. // // THE FIXED COLUMNS ONLY. The pipeline columns to the right of Report are // derived from the operations enabled in settings and are labelled with each // operation's `shortLabel` ("Download", "Transcribe", "Digest", …), so a // literal list of them here is a list of whatever the fixture's settings // happened to enable. (This loop used to name "Downloads" and "Transcripts", // which were the header labels before the per-operation strip landed; they // have matched nothing since.) for (const header of [ "Slug", "Name", "Handling", "Build", // Was "Sync" — the sync-inclusion toggle's column is the channel priority // tier now, and its sort key is the compiled order. "Tier", "Playlist", "Last sync", "Report", ]) { const th = page .getByRole("columnheader") .filter({ hasText: new RegExp(`^${header}$`) }); await expect(th).toHaveAttribute("aria-sort", "none"); } // Click Slug — sorts ascending alphabetically. await page.getByRole("button", { name: "sort by Slug" }).click(); { const slugHeader = page .getByRole("columnheader") .filter({ hasText: /^Slug/ }); await expect(slugHeader).toHaveAttribute("aria-sort", "ascending"); const rows = page.getByRole("row"); // 0 is header row; first body row should be slow-a. await expect(rows.nth(1)).toContainText("slow-a"); await expect(rows.nth(2)).toContainText("slow-b"); } // Click Slug again — direction flips to descending. await page.getByRole("button", { name: "sort by Slug" }).click(); { const slugHeader = page .getByRole("columnheader") .filter({ hasText: /^Slug/ }); await expect(slugHeader).toHaveAttribute("aria-sort", "descending"); const rows = page.getByRole("row"); await expect(rows.nth(1)).toContainText("slow-b"); await expect(rows.nth(2)).toContainText("slow-a"); } // Click Last sync — the active sort moves; Slug no longer indicated. await page.getByRole("button", { name: "sort by Last sync" }).click(); { const slugHeader = page .getByRole("columnheader") .filter({ hasText: /^Slug/ }); await expect(slugHeader).toHaveAttribute("aria-sort", "none"); const lastSyncHeader = page .getByRole("columnheader") .filter({ hasText: /^Last sync/ }); await expect(lastSyncHeader).toHaveAttribute("aria-sort", "ascending"); } // Refresh — sort state is client-only and resets. await page.reload(); { const lastSyncHeader = page .getByRole("columnheader") .filter({ hasText: /^Last sync/ }); await expect(lastSyncHeader).toHaveAttribute("aria-sort", "none"); } });