Files
kandev/apps/web/components/task/task-pr-shortcut.test.tsx
T
2026-08-26 15:54:59 +00:00

102 lines
2.8 KiB
TypeScript

import { act, cleanup, render, screen, waitFor } from "@testing-library/react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import type { TaskPR } from "@/lib/types/github";
const { mockOpenExternalLink, mockToast } = vi.hoisted(() => ({
mockOpenExternalLink: vi.fn(),
mockToast: vi.fn(),
}));
let mockPRs: TaskPR[] = [];
vi.mock("@/components/state-provider", () => ({
useAppStore: (
selector: (state: { userSettings: { keyboardShortcuts: Record<string, unknown> } }) => unknown,
) => selector({ userSettings: { keyboardShortcuts: {} } }),
}));
vi.mock("@/components/toast-provider", () => ({
useToast: () => ({ toast: mockToast }),
}));
vi.mock("@/hooks/domains/github/use-task-pr", () => ({
useTaskPR: () => ({ prs: mockPRs }),
}));
vi.mock("@/hooks/domains/gitlab/use-task-mr", () => ({
useTaskMRs: () => [],
}));
vi.mock("@/lib/desktop/external-links", () => ({
openExternalLink: mockOpenExternalLink,
}));
import { TaskPRShortcut } from "./task-pr-shortcut";
function makePR(id: string, number: number): TaskPR {
return {
id,
workspace_id: "workspace-1",
task_id: "task-1",
owner: "acme",
repo: "kandev",
pr_number: number,
pr_url: `https://github.com/acme/kandev/pull/${number}`,
pr_title: `PR ${number}`,
head_branch: `feature/${number}`,
base_branch: "main",
author_login: "alice",
state: "open",
review_state: "",
checks_state: "",
mergeable_state: "",
review_count: 0,
pending_review_count: 0,
comment_count: 0,
unresolved_review_threads: 0,
checks_total: 0,
checks_passing: 0,
additions: 0,
deletions: 0,
created_at: "2026-07-31T00:00:00Z",
merged_at: null,
closed_at: null,
last_synced_at: null,
updated_at: "2026-07-31T00:00:00Z",
};
}
function dispatchKey(type: "keydown" | "keyup", key: string, init: KeyboardEventInit = {}) {
act(() => {
window.dispatchEvent(
new KeyboardEvent(type, { key, bubbles: true, cancelable: true, ...init }),
);
});
}
describe("TaskPRShortcut", () => {
beforeEach(() => {
mockPRs = [makePR("pr-1", 1), makePR("pr-2", 2)];
mockOpenExternalLink.mockReset().mockResolvedValue(undefined);
mockToast.mockReset();
});
afterEach(() => cleanup());
it("opens the cycled review when the primary modifier is released", async () => {
render(<TaskPRShortcut taskId="task-1" />);
dispatchKey("keydown", "g", { ctrlKey: true, shiftKey: true });
dispatchKey("keydown", "g", { ctrlKey: true });
await waitFor(() =>
expect(screen.getByTestId("task-pr-picker-row-pr-2").getAttribute("data-selected")).toBe(
"true",
),
);
dispatchKey("keyup", "Control");
await waitFor(() => expect(mockOpenExternalLink).toHaveBeenCalledWith(mockPRs[1].pr_url));
});
});