Files
kandev/apps/web/components/task/task-switcher-click.test.ts
T
José Almeida 5105ac224c feat: cmd+click and shift+click multi-select for kanban and sidebar (#1518)
* feat: add anchored range selection to multi-select reducer

* feat: cmd+click and shift+click multi-select on kanban board

* feat: add cmd/shift multi-select to sidebar task list

* test: e2e coverage for cmd/shift multi-select

* fix: harden multi-select selection lifecycle from review feedback

* test: scope multi-select e2e helpers to active containers

* fix: add sidebar multi-select hook tests and tighten bulk-action lifecycle

* fix: prune hidden sidebar selections and order bulk moves by view

* test: cover visible-order bulk move and anchor realignment

* fix: harden sidebar bulk-move scope and keyboard selection parity

* fix: order kanban bulk moves by board position

* test: cover multi-select helpers and fix stale-id sort fallback

* fix: order kanban card context-menu moves by board position

* feat: sidebar multi-select shows only bulk-valid actions with bulk pin and delete

* fix: harden multi-select bulk ordering, selection clearing, and a11y

* fix: gate kanban card move-to-step for mixed-workflow selections

* fix: unpin fully pinned sidebar selections

* refactor: keep sidebar task components under limits

* test: restore sidebar selection console spy safely
2026-07-06 17:16:14 +01:00

92 lines
2.9 KiB
TypeScript

import { describe, it, expect, vi } from "vitest";
import { dispatchSidebarRowClick } from "./task-switcher";
function fakeEvent(mods: Partial<MouseEvent> = {}) {
return {
metaKey: false,
ctrlKey: false,
shiftKey: false,
preventDefault: vi.fn(),
...mods,
} as unknown as React.MouseEvent;
}
function fakeKeyEvent(mods: Partial<KeyboardEvent> = {}) {
return {
metaKey: false,
ctrlKey: false,
shiftKey: false,
preventDefault: vi.fn(),
...mods,
} as unknown as React.KeyboardEvent;
}
function handlers() {
return {
onSelectTask: vi.fn(),
onToggleSelectTask: vi.fn(),
onSelectTaskRange: vi.fn(),
};
}
describe("dispatchSidebarRowClick", () => {
it("cmd/meta-click toggles and prevents default", () => {
const h = handlers();
const e = fakeEvent({ metaKey: true });
dispatchSidebarRowClick(e, "t1", false, h);
expect(e.preventDefault).toHaveBeenCalled();
expect(h.onToggleSelectTask).toHaveBeenCalledWith("t1");
expect(h.onSelectTask).not.toHaveBeenCalled();
});
it("shift-click range-selects and prevents default", () => {
const h = handlers();
const e = fakeEvent({ shiftKey: true });
dispatchSidebarRowClick(e, "t1", false, h);
expect(e.preventDefault).toHaveBeenCalled();
expect(h.onSelectTaskRange).toHaveBeenCalledWith("t1");
});
it("plain click toggles while a selection is active", () => {
const h = handlers();
dispatchSidebarRowClick(fakeEvent(), "t1", true, h);
expect(h.onToggleSelectTask).toHaveBeenCalledWith("t1");
expect(h.onSelectTask).not.toHaveBeenCalled();
});
it("plain click navigates when nothing is selected", () => {
const h = handlers();
dispatchSidebarRowClick(fakeEvent(), "t1", false, h);
expect(h.onSelectTask).toHaveBeenCalledWith("t1");
expect(h.onToggleSelectTask).not.toHaveBeenCalled();
});
// Keyboard activation (Enter/Space) routes through the same dispatcher.
it("cmd/meta keypress toggles", () => {
const h = handlers();
const e = fakeKeyEvent({ metaKey: true });
dispatchSidebarRowClick(e, "t1", false, h);
expect(e.preventDefault).toHaveBeenCalled();
expect(h.onToggleSelectTask).toHaveBeenCalledWith("t1");
});
it("shift keypress range-selects", () => {
const h = handlers();
dispatchSidebarRowClick(fakeKeyEvent({ shiftKey: true }), "t1", false, h);
expect(h.onSelectTaskRange).toHaveBeenCalledWith("t1");
});
it("plain keypress toggles while a selection is active", () => {
const h = handlers();
dispatchSidebarRowClick(fakeKeyEvent(), "t1", true, h);
expect(h.onToggleSelectTask).toHaveBeenCalledWith("t1");
expect(h.onSelectTask).not.toHaveBeenCalled();
});
it("plain keypress navigates when nothing is selected", () => {
const h = handlers();
dispatchSidebarRowClick(fakeKeyEvent(), "t1", false, h);
expect(h.onSelectTask).toHaveBeenCalledWith("t1");
});
});