Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 87 additions & 1 deletion client/__tests__/AddGameModal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ vi.mock("lucide-react", () => ({
Calendar: () => <div data-testid="icon-calendar" />,
Loader2: () => <div data-testid="icon-loader" />,
Check: () => <div data-testid="icon-check" />,
ChevronDown: () => <div />,
ChevronUp: () => <div />,
X: () => <div />,
}));

Expand Down Expand Up @@ -145,7 +147,7 @@ describe("AddGameModal", () => {
// The effect runs on `open` change; simulate by typing and then looking for clear.
const input = screen.getByDisplayValue("Hollow Knight");
fireEvent.change(input, { target: { value: "" } });
expect(screen.getByDisplayValue("")).toBeInTheDocument();
expect(screen.getByLabelText("Search games")).toHaveValue("");
});

it("shows Calendar icon for search results with a release date", async () => {
Expand Down Expand Up @@ -195,6 +197,90 @@ describe("AddGameModal", () => {
});
});

it("requests at most 10 games and forwards a valid release year filter", async () => {
const searchResults = Array.from({ length: 12 }, (_, index) => ({
...makeSearchResult(`God of War ${index + 1}`, "2005-03-22"),
id: `igdb-${index + 1}`,
igdbId: 100 + index,
}));
setupFetch({ searchResults });
renderModal({ initialQuery: "God of War" });
fireEvent.click(screen.getByTestId("open-btn"));

const yearInput = await screen.findByLabelText("Release year filter");
fireEvent.change(yearInput, { target: { value: "2005" } });

await waitFor(() => {
const searchCalls = vi
.mocked(globalThis.fetch)
.mock.calls.filter(([url]) => String(url).includes("/api/igdb/search"));
expect(
searchCalls.some(([url]) => {
const params = new URL(String(url), "http://localhost").searchParams;
return params.get("limit") === "10" && params.get("year") === "2005";
})
).toBe(true);
});

await waitFor(() => {
expect(screen.getAllByTestId(/^search-result-igdb-/)).toHaveLength(10);
});
expect(screen.queryByText("God of War 11")).not.toBeInTheDocument();
});

it("does not search while a nonempty release year is incomplete", async () => {
setupFetch({ searchResults: [makeSearchResult("God of War", "2005-03-22")] });
renderModal({ initialQuery: "God of War" });
fireEvent.click(screen.getByTestId("open-btn"));

await screen.findByText("God of War");
const searchCallsBefore = vi
.mocked(globalThis.fetch)
.mock.calls.filter(([url]) => String(url).includes("/api/igdb/search")).length;

fireEvent.change(screen.getByLabelText("Release year filter"), {
target: { value: "20" },
});

await waitFor(() => {
expect(screen.queryByText("God of War")).not.toBeInTheDocument();
});
const searchCallsAfter = vi
.mocked(globalThis.fetch)
.mock.calls.filter(([url]) => String(url).includes("/api/igdb/search")).length;
expect(searchCallsAfter).toBe(searchCallsBefore);
});

it("seeds a single discovered platform and persists its IGDB pair", async () => {
setupFetch({
searchResults: [
{
...makeSearchResult("God of War", "2005-03-22"),
platforms: ["PlayStation 2"],
platformOptions: [{ id: 8, name: "PlayStation 2" }],
},
],
});
renderModal({ initialQuery: "God of War" });
fireEvent.click(screen.getByTestId("open-btn"));

expect(await screen.findByLabelText("Target platform for God of War")).toHaveTextContent(
"PlayStation 2"
);
fireEvent.click(screen.getByTestId("button-add-igdb-1"));

await waitFor(() => {
const postCall = vi
.mocked(globalThis.fetch)
.mock.calls.find(([url, init]) => String(url) === "/api/games" && init?.method === "POST");
expect(postCall).toBeDefined();
expect(JSON.parse(String(postCall?.[1]?.body))).toMatchObject({
targetPlatformId: 8,
targetPlatformName: "PlayStation 2",
});
});
});

it("shows the mobile configuration prompt when IGDB is not configured", async () => {
mockIsMobile = true;
setupFetch({ configured: false });
Expand Down
40 changes: 40 additions & 0 deletions client/__tests__/GameDetailsModal.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,46 @@ describe("GameDetailsModal", () => {
expect(screen.getByTestId("badge-platform-ps5")).toBeInTheDocument();
});

it("updates and clears the automatic download target", async () => {
(global.fetch as ReturnType<typeof vi.fn>).mockImplementation(
makeFetchMock({
"/api/igdb/platforms": [
{ id: 8, name: "PlayStation 2" },
{ id: 48, name: "PlayStation 4" },
],
})
);
renderComponent();

const targetSelect = await screen.findByLabelText("Automatic download target");
await screen.findByRole("option", { name: "PlayStation 2" });
fireEvent.change(targetSelect, { target: { value: "8" } });

await waitFor(() => {
expect(global.fetch).toHaveBeenCalledWith(
"/api/games/1/target-platform",
expect.objectContaining({
method: "PATCH",
body: JSON.stringify({
targetPlatformId: 8,
targetPlatformName: "PlayStation 2",
}),
})
);
});

fireEvent.change(targetSelect, { target: { value: "" } });
await waitFor(() => {
expect(global.fetch).toHaveBeenCalledWith(
"/api/games/1/target-platform",
expect.objectContaining({
method: "PATCH",
body: JSON.stringify({ targetPlatformId: null, targetPlatformName: null }),
})
);
});
});

it("renders screenshots in Media tab", () => {
renderComponent();
// Media tab uses forceMount so screenshots are always in the DOM (hidden until tab activated)
Expand Down
Loading