Files
kandev/apps/web/components/task/task-external-link-dialog.test.tsx
T
José Almeida 4eae00964d feat: move integration links into task menus (#1644)
* feat: move integration links into task menus

* fix: address integration link review feedback

* fix: preserve archived task title when linking

* fix: address integration link review issues

* fix: remove ignored swimlane availability prop
2026-07-09 23:43:35 +01:00

127 lines
4.2 KiB
TypeScript

import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import { StateProvider } from "@/components/state-provider";
import { ToastProvider } from "@/components/toast-provider";
import { getJiraTicket } from "@/lib/api/domains/jira-api";
import { getLinearIssue } from "@/lib/api/domains/linear-api";
import { getSentryIssue } from "@/lib/api/domains/sentry-api";
import { updateTask } from "@/lib/api/domains/kanban-api";
import { TaskExternalLinkDialog } from "./task-external-link-dialog";
vi.mock("@/lib/api/domains/jira-api", () => ({
getJiraTicket: vi.fn(),
}));
vi.mock("@/lib/api/domains/linear-api", () => ({
getLinearIssue: vi.fn(),
}));
vi.mock("@/lib/api/domains/sentry-api", () => ({
getSentryIssue: vi.fn(),
}));
vi.mock("@/lib/api/domains/kanban-api", () => ({
updateTask: vi.fn(),
}));
const INPUT_TEST_ID = "task-external-link-input";
const SUBMIT_TEST_ID = "task-external-link-submit";
const ERROR_TEST_ID = "task-external-link-error";
const TASK_ID = "task-1";
const WORKSPACE_ID = "workspace-1";
const TASK_TITLE = "Fix login";
afterEach(() => {
cleanup();
vi.clearAllMocks();
});
function renderDialog(provider: "jira" | "linear" | "sentry" = "jira") {
return render(
<StateProvider>
<ToastProvider>
<TaskExternalLinkDialog
open={true}
onOpenChange={vi.fn()}
provider={provider}
task={{ id: TASK_ID, title: TASK_TITLE }}
workspaceId={WORKSPACE_ID}
/>
</ToastProvider>
</StateProvider>,
);
}
describe("TaskExternalLinkDialog", () => {
it("validates and links a Jira ticket by updating the task title", async () => {
vi.mocked(getJiraTicket).mockResolvedValue({ key: "PROJ-12" } as never);
vi.mocked(updateTask).mockResolvedValue({ id: TASK_ID, title: "PROJ-12: Fix login" } as never);
renderDialog("jira");
fireEvent.change(screen.getByTestId(INPUT_TEST_ID), {
target: { value: "PROJ-12" },
});
fireEvent.click(screen.getByTestId(SUBMIT_TEST_ID));
await waitFor(() => {
expect(getJiraTicket).toHaveBeenCalledWith("PROJ-12", { workspaceId: WORKSPACE_ID });
});
expect(updateTask).toHaveBeenCalledWith(TASK_ID, { title: "PROJ-12: Fix login" });
});
it("validates and links a Linear issue by updating the task title", async () => {
vi.mocked(getLinearIssue).mockResolvedValue({ identifier: "ENG-20" } as never);
vi.mocked(updateTask).mockResolvedValue({ id: TASK_ID, title: "ENG-20: Fix login" } as never);
renderDialog("linear");
fireEvent.change(screen.getByTestId(INPUT_TEST_ID), {
target: { value: "eng-20" },
});
fireEvent.click(screen.getByTestId(SUBMIT_TEST_ID));
await waitFor(() => {
expect(getLinearIssue).toHaveBeenCalledWith("ENG-20", { workspaceId: WORKSPACE_ID });
});
expect(updateTask).toHaveBeenCalledWith(TASK_ID, { title: "ENG-20: Fix login" });
});
it("extracts and links a Sentry issue key from a numeric issue URL", async () => {
vi.mocked(getSentryIssue).mockResolvedValue({ shortId: "API-42" } as never);
vi.mocked(updateTask).mockResolvedValue({ id: TASK_ID, title: "API-42: Fix login" } as never);
renderDialog("sentry");
fireEvent.change(screen.getByTestId(INPUT_TEST_ID), {
target: { value: "https://sentry.io/organizations/acme/issues/123456/" },
});
fireEvent.click(screen.getByTestId(SUBMIT_TEST_ID));
await waitFor(() => {
expect(getSentryIssue).toHaveBeenCalledWith("123456", { workspaceId: WORKSPACE_ID });
});
expect(updateTask).toHaveBeenCalledWith(TASK_ID, { title: "API-42: Fix login" });
});
it("shows an inline validation error for invalid input", async () => {
renderDialog("jira");
fireEvent.change(screen.getByTestId(INPUT_TEST_ID), {
target: { value: "not a key" },
});
fireEvent.click(screen.getByTestId(SUBMIT_TEST_ID));
expect((await screen.findByTestId(ERROR_TEST_ID)).textContent).toMatch(
/Paste a Jira ticket URL or key/i,
);
expect(updateTask).not.toHaveBeenCalled();
fireEvent.change(screen.getByTestId(INPUT_TEST_ID), {
target: { value: "PROJ-12" },
});
expect(screen.queryByTestId(ERROR_TEST_ID)).toBeNull();
});
});