feat(design): the download, notification and Scheduler action lists (C1) — the rows' "…", the band's and the strip's "…" (E28 S3e3)
A download row keeps play (pause / resume / retry in the queue) and the save link; the editors, sharing, re-download, the copies and cancel / delete / remove moved into its "…" (useDownloadActions). A link inside the row keeps the browser's own right-click menu. A notification row keeps its link and its unread mark and shows its dismiss on hover; an activity notice's Find in feed and Undo are in its "…". The inbox band keeps Mark all read and puts Clear everything, now behind a confirm, in its "…". The Scheduler strip keeps Run all and Pause and puts Purge discovery in its "…". Polled lists key their menus by id (keyOf). ui/menuGroups draws a rule only between two non-empty groups. Find in feed also drops the tag, search and age filters that could hide the video it looks for.
This commit is contained in:
@@ -77,6 +77,24 @@ afterEach(() => {
|
||||
mocks.confirm.mockClear();
|
||||
});
|
||||
|
||||
/** Pick `label` from the row's menu, opened by its "…". The surface is visibility:hidden in jsdom
|
||||
* (floating-ui never positions it), so the row is matched on its text. */
|
||||
async function pick(row: string, label: string) {
|
||||
const more = screen
|
||||
.getByText(row)
|
||||
.closest<HTMLElement>("[data-nav-index]")!
|
||||
.querySelector<HTMLElement>('button[aria-label="downloads.rowMenu"]')!;
|
||||
fireEvent.click(more);
|
||||
const item = await waitFor(() => {
|
||||
const found = screen
|
||||
.getAllByRole("menuitem", { hidden: true })
|
||||
.find((b) => b.textContent === label);
|
||||
expect(found).toBeTruthy();
|
||||
return found!;
|
||||
});
|
||||
fireEvent.click(item);
|
||||
}
|
||||
|
||||
describe("DownloadCenter confirm dialogs", () => {
|
||||
it("label the confirm button with the action, not the dialog's question", async () => {
|
||||
mocks.jobs = [job(1, "running"), job(2, "done")];
|
||||
@@ -86,12 +104,15 @@ describe("DownloadCenter confirm dialogs", () => {
|
||||
</QueryClientProvider>,
|
||||
);
|
||||
|
||||
fireEvent.click(screen.getByTitle("downloads.actions.cancel"));
|
||||
// E28 C1: the destructive and rare row buttons live in the row's "…".
|
||||
await pick("Clip 1", "downloads.actions.cancel");
|
||||
await waitFor(() => expect(mocks.confirm).toHaveBeenCalledTimes(1));
|
||||
// The tab's label shares its button with a count badge.
|
||||
fireEvent.click(screen.getByRole("button", { name: /downloads\.tabs\.done/ }));
|
||||
fireEvent.click(await screen.findByTitle("downloads.actions.redownload"));
|
||||
fireEvent.click(screen.getByTitle("downloads.actions.delete"));
|
||||
await screen.findByText("Clip 2");
|
||||
await pick("Clip 2", "downloads.actions.redownload");
|
||||
await waitFor(() => expect(mocks.confirm).toHaveBeenCalledTimes(2));
|
||||
await pick("Clip 2", "downloads.actions.delete");
|
||||
await waitFor(() => expect(mocks.confirm).toHaveBeenCalledTimes(3));
|
||||
|
||||
expect(mocks.confirm.mock.calls.map(([o]) => [o.title, o.confirmLabel])).toEqual([
|
||||
|
||||
Reference in New Issue
Block a user