145 lines
4.9 KiB
TypeScript
145 lines
4.9 KiB
TypeScript
import { cleanup, fireEvent, render, screen, waitFor } from "@testing-library/react";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import { useState } from "react";
|
|
import { TooltipProvider } from "@kandev/ui/tooltip";
|
|
import { TaskCreateAdvancedSettings } from "./task-create-dialog-advanced-settings";
|
|
|
|
afterEach(() => {
|
|
cleanup();
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
const ADVANCED_SETTINGS_TRIGGER_TEST_ID = "task-create-advanced-settings-trigger";
|
|
const DEPENDENCY_TRIGGER_TEST_ID = "task-create-dependencies-trigger";
|
|
|
|
vi.mock("react-i18next", () => ({
|
|
useTranslation: () => ({
|
|
t: (key: string) =>
|
|
({
|
|
"task:advancedSettings": "Advanced settings",
|
|
"task:dependsOn": "Depends on",
|
|
"task:dependencyInfoLabel": "About task dependencies",
|
|
"task:dependencyInfo": "This task waits until every selected task completes successfully.",
|
|
})[key] ?? key,
|
|
}),
|
|
}));
|
|
|
|
vi.mock("@/components/task-create-dialog-dependencies", () => ({
|
|
TaskCreateDependencies: ({
|
|
value,
|
|
onChange,
|
|
}: {
|
|
value: string[];
|
|
onChange: (next: string[]) => void;
|
|
}) => (
|
|
<button
|
|
type="button"
|
|
data-testid={DEPENDENCY_TRIGGER_TEST_ID}
|
|
onClick={() => onChange([...value, "task-2"])}
|
|
>
|
|
{value.length === 0 ? "No dependency" : `${value.length} dependencies`}
|
|
</button>
|
|
),
|
|
}));
|
|
|
|
function renderAdvancedSettings(
|
|
overrides: Partial<React.ComponentProps<typeof TaskCreateAdvancedSettings>> = {},
|
|
) {
|
|
return render(
|
|
<TooltipProvider>
|
|
<TaskCreateAdvancedSettings
|
|
isCreateMode
|
|
isTaskStarted={false}
|
|
blockedBy={[]}
|
|
onBlockedByChange={() => {}}
|
|
{...overrides}
|
|
/>
|
|
</TooltipProvider>,
|
|
);
|
|
}
|
|
|
|
describe("TaskCreateAdvancedSettings", () => {
|
|
it("starts collapsed and keeps the dependency selector hidden", () => {
|
|
renderAdvancedSettings();
|
|
|
|
const trigger = screen.getByTestId(ADVANCED_SETTINGS_TRIGGER_TEST_ID);
|
|
expect(trigger.getAttribute("aria-expanded")).toBe("false");
|
|
expect(trigger.className).toContain("min-h-12");
|
|
expect(screen.queryByTestId(DEPENDENCY_TRIGGER_TEST_ID)).toBeNull();
|
|
});
|
|
|
|
it("reveals the dependency selector when expanded", () => {
|
|
renderAdvancedSettings();
|
|
|
|
const trigger = screen.getByTestId(ADVANCED_SETTINGS_TRIGGER_TEST_ID);
|
|
fireEvent.click(trigger);
|
|
|
|
expect(trigger.getAttribute("aria-expanded")).toBe("true");
|
|
expect(screen.getByTestId(DEPENDENCY_TRIGGER_TEST_ID).getAttribute("hidden")).toBeNull();
|
|
});
|
|
|
|
it("labels the dependency setting and provides contextual help", async () => {
|
|
renderAdvancedSettings();
|
|
|
|
fireEvent.click(screen.getByTestId(ADVANCED_SETTINGS_TRIGGER_TEST_ID));
|
|
|
|
expect(screen.getByTestId("task-create-dependency-setting-label").textContent).toContain(
|
|
"Depends on",
|
|
);
|
|
const grid = screen.getByTestId("task-create-advanced-settings-grid");
|
|
const row = screen.getByTestId("task-create-dependency-setting-row");
|
|
const selectorContainer = screen.getByTestId("task-create-dependency-selector-container");
|
|
expect(grid.className).toContain("md:grid-cols-2");
|
|
expect(row.className).toContain("items-center");
|
|
expect(row.className).toContain("gap-3");
|
|
expect(row.className).not.toContain("flex-col");
|
|
expect(row.parentElement).toBe(grid);
|
|
expect(selectorContainer.parentElement).toBe(row);
|
|
const info = screen.getByTestId("task-create-dependency-setting-info");
|
|
expect(info.getAttribute("aria-label")).toBe("About task dependencies");
|
|
|
|
fireEvent.focus(info);
|
|
await waitFor(() => {
|
|
expect(screen.getByRole("tooltip").textContent).toContain(
|
|
"This task waits until every selected task completes successfully.",
|
|
);
|
|
});
|
|
});
|
|
|
|
it("preserves selected dependencies across collapse and reopen", () => {
|
|
function Harness() {
|
|
const [blockedBy, setBlockedBy] = useState<string[]>(["task-1"]);
|
|
return (
|
|
<TooltipProvider>
|
|
<TaskCreateAdvancedSettings
|
|
isCreateMode
|
|
isTaskStarted={false}
|
|
blockedBy={blockedBy}
|
|
onBlockedByChange={setBlockedBy}
|
|
/>
|
|
</TooltipProvider>
|
|
);
|
|
}
|
|
|
|
render(<Harness />);
|
|
const trigger = screen.getByTestId(ADVANCED_SETTINGS_TRIGGER_TEST_ID);
|
|
fireEvent.click(trigger);
|
|
fireEvent.click(screen.getByTestId(DEPENDENCY_TRIGGER_TEST_ID));
|
|
expect(screen.getByTestId(DEPENDENCY_TRIGGER_TEST_ID).textContent).toContain("2 dependencies");
|
|
|
|
fireEvent.click(trigger);
|
|
expect(screen.queryByTestId(DEPENDENCY_TRIGGER_TEST_ID)).toBeNull();
|
|
fireEvent.click(trigger);
|
|
expect(screen.getByTestId(DEPENDENCY_TRIGGER_TEST_ID).textContent).toContain("2 dependencies");
|
|
});
|
|
|
|
it.each([
|
|
["edit mode", { isCreateMode: false, isTaskStarted: false }],
|
|
["started task", { isCreateMode: true, isTaskStarted: true }],
|
|
])("does not render for a %s", (_name, props) => {
|
|
renderAdvancedSettings(props);
|
|
|
|
expect(screen.queryByTestId(ADVANCED_SETTINGS_TRIGGER_TEST_ID)).toBeNull();
|
|
});
|
|
});
|