// @vitest-environment jsdom
import { act, type ReactNode } from "react";
import { createRoot } from "react-dom/client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { PROJECT_COLORS } from "@paperclipai/shared";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { projectsApi } from "../api/projects";
import { getLastProjectId } from "../lib/recent-projects";
import { NewProjectForm } from "./NewProjectDialog";
vi.mock("../api/projects", () => ({ projectsApi: { create: vi.fn() } }));
vi.mock("./ProjectRepositoryInput", () => ({
ProjectRepositoryInput: () => null,
repositoryOptionsKey: (companyId: string) => ["repositories", companyId],
}));
vi.mock("@/features/connections/ConnectionSetupFlow", () => ({ ConnectionSetupFlow: () => null }));
vi.mock("./ui/dialog", () => ({
Dialog: ({ children }: { children: ReactNode }) => <>{children}>,
DialogContent: ({ children }: { children: ReactNode }) =>
{children}
,
DialogTitle: ({ children }: { children: ReactNode }) => {children}
,
}));
let root: ReturnType;
let container: HTMLDivElement;
beforeEach(() => {
localStorage.clear();
vi.mocked(projectsApi.create).mockReset();
container = document.createElement("div");
document.body.appendChild(container);
root = createRoot(container);
});
afterEach(() => {
act(() => root.unmount());
container.remove();
vi.restoreAllMocks();
});
async function settle() {
await act(async () => { await new Promise((resolve) => setTimeout(resolve, 10)); });
}
describe("new project colors", () => {
it("previews a palette color, keeps it through a retry, and remembers the created project", async () => {
vi.mocked(projectsApi.create)
.mockRejectedValueOnce(new Error("Try again"))
.mockResolvedValueOnce({ id: "project-created" } as Awaited>);
const onClose = vi.fn();
act(() => root.render(
));
const previewColor = container.querySelector('span[style]')!.style.backgroundColor;
const input = container.querySelector('input[aria-label="Project name"]')!;
act(() => {
Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")!.set!.call(input, "Colorful project");
input.dispatchEvent(new Event("input", { bubbles: true }));
});
act(() => container.querySelector("form")!.dispatchEvent(new Event("submit", { bubbles: true, cancelable: true })));
await settle();
expect(container.querySelector('[role="alert"]')?.textContent).toBe("Try again");
const firstColor = vi.mocked(projectsApi.create).mock.calls[0][1].color;
expect(PROJECT_COLORS).toContain(firstColor);
const expected = document.createElement("span");
expected.style.backgroundColor = String(firstColor);
expect(previewColor).toBe(expected.style.backgroundColor);
act(() => container.querySelector("form")!.dispatchEvent(new Event("submit", { bubbles: true, cancelable: true })));
await settle();
expect(vi.mocked(projectsApi.create).mock.calls[1][1]).toEqual({ name: "Colorful project", color: firstColor, status: "planned", repositoryIds: [] });
expect(getLastProjectId("company-1")).toBe("project-created");
expect(onClose).toHaveBeenCalledOnce();
});
});