story-kit: merge 109_story_add_test_coverage_for_lozengeflycontext_selectionscreen_and_chatheader_components
This commit is contained in:
136
frontend/src/components/selection/SelectionScreen.test.tsx
Normal file
136
frontend/src/components/selection/SelectionScreen.test.tsx
Normal file
@@ -0,0 +1,136 @@
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import type { KeyboardEvent } from "react";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { SelectionScreenProps } from "./SelectionScreen";
|
||||
import { SelectionScreen } from "./SelectionScreen";
|
||||
|
||||
function makeProps(
|
||||
overrides: Partial<SelectionScreenProps> = {},
|
||||
): SelectionScreenProps {
|
||||
return {
|
||||
knownProjects: [],
|
||||
onOpenProject: vi.fn(),
|
||||
onForgetProject: vi.fn(),
|
||||
pathInput: "",
|
||||
homeDir: null,
|
||||
onPathInputChange: vi.fn(),
|
||||
onPathInputKeyDown: vi.fn() as (
|
||||
event: KeyboardEvent<HTMLInputElement>,
|
||||
) => void,
|
||||
isOpening: false,
|
||||
suggestionTail: "",
|
||||
matchList: [],
|
||||
selectedMatch: -1,
|
||||
onSelectMatch: vi.fn(),
|
||||
onAcceptMatch: vi.fn(),
|
||||
onCloseSuggestions: vi.fn(),
|
||||
completionError: null,
|
||||
currentPartial: "",
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe("SelectionScreen", () => {
|
||||
it("renders the title and description", () => {
|
||||
render(<SelectionScreen {...makeProps()} />);
|
||||
expect(screen.getByText("StorkIt")).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText("Paste or complete a project path to start."),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("renders recent projects list when knownProjects is non-empty", () => {
|
||||
render(
|
||||
<SelectionScreen
|
||||
{...makeProps({ knownProjects: ["/Users/test/project"] })}
|
||||
/>,
|
||||
);
|
||||
expect(screen.getByText("Recent projects")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not render recent projects list when knownProjects is empty", () => {
|
||||
render(<SelectionScreen {...makeProps({ knownProjects: [] })} />);
|
||||
expect(screen.queryByText("Recent projects")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("calls onOpenProject when Open Project button is clicked", () => {
|
||||
const onOpenProject = vi.fn();
|
||||
render(
|
||||
<SelectionScreen
|
||||
{...makeProps({ pathInput: "/my/path", onOpenProject })}
|
||||
/>,
|
||||
);
|
||||
fireEvent.click(screen.getByText("Open Project"));
|
||||
expect(onOpenProject).toHaveBeenCalledWith("/my/path");
|
||||
});
|
||||
|
||||
it("shows Opening... text and disables buttons when isOpening is true", () => {
|
||||
render(<SelectionScreen {...makeProps({ isOpening: true })} />);
|
||||
expect(screen.getByText("Opening...")).toBeInTheDocument();
|
||||
const buttons = screen.getAllByRole("button");
|
||||
for (const button of buttons) {
|
||||
if (
|
||||
button.textContent === "Opening..." ||
|
||||
button.textContent === "New Project"
|
||||
) {
|
||||
expect(button).toBeDisabled();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("displays completion error when completionError is provided", () => {
|
||||
render(
|
||||
<SelectionScreen {...makeProps({ completionError: "Path not found" })} />,
|
||||
);
|
||||
expect(screen.getByText("Path not found")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("does not display error div when completionError is null", () => {
|
||||
const { container } = render(<SelectionScreen {...makeProps()} />);
|
||||
const errorDiv = container.querySelector('[style*="color: red"]');
|
||||
expect(errorDiv).toBeNull();
|
||||
});
|
||||
|
||||
it("New Project button calls onPathInputChange with homeDir (trailing slash appended)", () => {
|
||||
const onPathInputChange = vi.fn();
|
||||
const onCloseSuggestions = vi.fn();
|
||||
render(
|
||||
<SelectionScreen
|
||||
{...makeProps({
|
||||
homeDir: "/Users/test",
|
||||
onPathInputChange,
|
||||
onCloseSuggestions,
|
||||
})}
|
||||
/>,
|
||||
);
|
||||
fireEvent.click(screen.getByText("New Project"));
|
||||
expect(onPathInputChange).toHaveBeenCalledWith("/Users/test/");
|
||||
expect(onCloseSuggestions).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("New Project button uses homeDir as-is when it already ends with /", () => {
|
||||
const onPathInputChange = vi.fn();
|
||||
const onCloseSuggestions = vi.fn();
|
||||
render(
|
||||
<SelectionScreen
|
||||
{...makeProps({
|
||||
homeDir: "/Users/test/",
|
||||
onPathInputChange,
|
||||
onCloseSuggestions,
|
||||
})}
|
||||
/>,
|
||||
);
|
||||
fireEvent.click(screen.getByText("New Project"));
|
||||
expect(onPathInputChange).toHaveBeenCalledWith("/Users/test/");
|
||||
expect(onCloseSuggestions).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("New Project button uses empty string when homeDir is null", () => {
|
||||
const onPathInputChange = vi.fn();
|
||||
render(
|
||||
<SelectionScreen {...makeProps({ homeDir: null, onPathInputChange })} />,
|
||||
);
|
||||
fireEvent.click(screen.getByText("New Project"));
|
||||
expect(onPathInputChange).toHaveBeenCalledWith("");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user