Skip to content
Source
Sign inSign up

AddProjectToMachineDialog.browser.test.tsx

95 lines3.2 KB

1import { EnvironmentId, ProjectId } from "@t3tools/contracts";
2import { scopeProjectRef } from "@t3tools/client-runtime/environment";
3import { describe, expect, it, vi } from "vite-plus/test";
4​
5import { act, render } from "../../test/render";
6​
7const project = vi.hoisted(() => {
8 let value: unknown = null;
9 const listeners = new Set<() => void>();
10 return {
11 // Each test starts from no project and no listeners left by an earlier test.
12 setup: (initial: unknown) => {
13 value = initial;
14 listeners.clear();
15 },
16 get: () => value,
17 set: (next: unknown) => {
18 value = next;
19 for (const listener of listeners) listener();
20 },
21 subscribe: (listener: () => void) => {
22 listeners.add(listener);
23 return () => listeners.delete(listener);
24 },
25 };
26});
27​
28vi.mock(import("../state/entities"), async (original) => {
29 const { useSyncExternalStore } = await import("react");
30 return {
31 ...(await original()),
32 readProject: (() => project.get()) as never,
33 subscribeProject: ((_ref: unknown, listener: (value: unknown) => void) =>
34 project.subscribe(() => listener(project.get()))) as never,
35 useProject: (() => useSyncExternalStore(project.subscribe, project.get)) as never,
36 };
37});
38vi.mock(import("../state/environments"), async (original) => ({
39 ...(await original()),
40 useEnvironments: (() => ({ environments: [] })) as never,
41}));
42vi.mock(import("../hooks/useHandleNewThread"), async (original) => ({
43 ...(await original()),
44 useNewThreadHandler: (() => () => undefined) as never,
45}));
46vi.mock(import("../hooks/useAddProjectTargets"), async (original) => ({
47 ...(await original()),
48 useAddProjectTargets: (() => []) as never,
49}));
50vi.mock(import("../hooks/useLogicalProjectEnvironments"), async (original) => ({
51 ...(await original()),
52 useLogicalProjectEnvironments: (() => []) as never,
53}));
54​
55import {
56 AddProjectToMachineDialogHost,
57 openAddProjectToMachine,
58} from "./AddProjectToMachineDialog";
59​
60const environmentId = EnvironmentId.make("environment-1");
61const projectRef = scopeProjectRef(environmentId, ProjectId.make("project-1"));
62const PROJECT = {
63 environmentId,
64 id: projectRef.projectId,
65 title: "Repo",
66 workspaceRoot: "/repo",
67 repositoryIdentity: null,
68};
69​
70describe("AddProjectToMachineDialog", () => {
71 it("closes when its project goes away", async () => {
72 project.setup(PROJECT);
73 await using screen = await render(<AddProjectToMachineDialogHost />);
74​
75 await act(() => openAddProjectToMachine({ projectRef, targetEnvironmentId: null }));
76 await expect.element(screen.getByText("Add to another machine")).toBeInTheDocument();
77​
78 await act(() => project.set(null));
79 await act(() => project.set(PROJECT));
80 await expect.element(screen.getByText("Add to another machine")).not.toBeInTheDocument();
81 });
82​
83 it("does not reopen for a project that vanished before the dialog showed", async () => {
84 project.setup(PROJECT);
85 await using screen = await render(<AddProjectToMachineDialogHost />);
86​
87 await act(() => {
88 openAddProjectToMachine({ projectRef, targetEnvironmentId: null });
89 project.set(null);
90 });
91 await act(() => project.set(PROJECT));
92​
93 await expect.element(screen.getByText("Add to another machine")).not.toBeInTheDocument();
94 });
95});