Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
fix: updates for PR review
  • Loading branch information
jaaydenh committed Aug 8, 2025
commit 7c250df72771306f90d10cb41875be290b22cef6
Original file line number Diff line number Diff line change
Expand Up @@ -79,33 +79,28 @@ function createMockWebSocket(

addEventListener: <E extends keyof WebSocketEventMap>(
eventType: E,
callback: WebSocketEventMap[E],
cb: (event: WebSocketEventMap[E]) => void,
) => {
if (closed) {
return;
}

const subscribers = store[eventType];
const cb = callback as unknown as CallbackStore[E][0];
if (!subscribers.includes(cb)) {
subscribers.push(cb);
}
},

removeEventListener: <E extends keyof WebSocketEventMap>(
eventType: E,
callback: WebSocketEventMap[E],
cb: (event: WebSocketEventMap[E]) => void,
) => {
if (closed) {
return;
}

const subscribers = store[eventType];
const cb = callback as unknown as CallbackStore[E][0];
if (subscribers.includes(cb)) {
const updated = store[eventType].filter((c) => c !== cb);
store[eventType] = updated as unknown as CallbackStore[E];
}
const updated = store[eventType].filter((c) => c !== cb);
store[eventType] = updated as unknown as CallbackStore[E];
},

close: () => {
Expand Down Expand Up @@ -189,25 +184,25 @@ const mockDynamicParametersResponseWithError: DynamicParametersResponse = {
],
};

const renderCreateWorkspacePageExperimental = (
route = `/templates/${MockTemplate.name}/workspace`,
) => {
return renderWithAuth(<CreateWorkspacePageExperimental />, {
route,
path: "/templates/:template/workspace",
extraRoutes: [
{
path: "/:username/:workspace",
element: <div>Workspace Page</div>,
},
],
});
};

describe("CreateWorkspacePageExperimental", () => {
let mockWebSocket: WebSocket;
let publisher: MockPublisher;

const renderCreateWorkspacePageExperimental = (
route = `/templates/${MockTemplate.name}/workspace`,
) => {
return renderWithAuth(<CreateWorkspacePageExperimental />, {
route,
path: "/templates/:template/workspace",
extraRoutes: [
{
path: "/:username/:workspace",
element: <div>Workspace Page</div>,
},
],
});
};

beforeEach(() => {
jest.clearAllMocks();

Expand All @@ -234,14 +229,12 @@ describe("CreateWorkspacePageExperimental", () => {
callbacks.onClose();
});

setTimeout(() => {
publisher.publishOpen(new Event("open"));
publisher.publishMessage(
new MessageEvent("message", {
data: JSON.stringify(mockDynamicParametersResponse),
}),
);
}, 10);
publisher.publishOpen(new Event("open"));
publisher.publishMessage(
new MessageEvent("message", {
data: JSON.stringify(mockDynamicParametersResponse),
}),
);

return mockWebSocket;
});
Expand Down Expand Up @@ -269,7 +262,7 @@ describe("CreateWorkspacePageExperimental", () => {
);

await waitFor(() => {
expect(screen.getByText("Instance Type")).toBeInTheDocument();
expect(screen.getByText(/instance type/i)).toBeInTheDocument();
expect(screen.getByText("CPU Count")).toBeInTheDocument();
expect(screen.getByText("Enable Monitoring")).toBeInTheDocument();
expect(screen.getByText("Tags")).toBeInTheDocument();
Expand All @@ -280,9 +273,7 @@ describe("CreateWorkspacePageExperimental", () => {
renderCreateWorkspacePageExperimental();
await waitForLoaderToBeRemoved();

await waitFor(() => {
expect(screen.getByText("Instance Type")).toBeInTheDocument();
});
expect(screen.getByText(/instance type/i)).toBeInTheDocument();

expect(mockWebSocket.send).toBeDefined();

Expand Down Expand Up @@ -381,18 +372,16 @@ describe("CreateWorkspacePageExperimental", () => {
callbacks.onMessage(JSON.parse(event.data));
});

setTimeout(() => {
publisher.publishOpen(new Event("open"));
publisher.publishMessage(
new MessageEvent("message", {
data: JSON.stringify({
id: 0,
parameters: [mockDropdownParameter],
diagnostics: [],
}),
publisher.publishOpen(new Event("open"));
publisher.publishMessage(
new MessageEvent("message", {
data: JSON.stringify({
id: 0,
parameters: [mockDropdownParameter],
diagnostics: [],
}),
);
}, 0);
}),
);

return mockWebSocket;
});
Expand All @@ -411,20 +400,18 @@ describe("CreateWorkspacePageExperimental", () => {
diagnostics: [],
};

setTimeout(() => {
await waitFor(() => {
publisher.publishMessage(
new MessageEvent("message", { data: JSON.stringify(response1) }),
);

publisher.publishMessage(
new MessageEvent("message", { data: JSON.stringify(response2) }),
);
}, 0);

await waitFor(() => {
expect(screen.queryByText("CPU Count")).toBeInTheDocument();
expect(screen.queryByText("Instance Type")).not.toBeInTheDocument();
});

expect(screen.queryByText("CPU Count")).toBeInTheDocument();
expect(screen.queryByText("Instance Type")).not.toBeInTheDocument();
});
});

Expand All @@ -433,28 +420,18 @@ describe("CreateWorkspacePageExperimental", () => {
renderCreateWorkspacePageExperimental();
await waitForLoaderToBeRemoved();

await waitFor(() => {
expect(screen.getByText("Instance Type")).toBeInTheDocument();
expect(
screen.getByRole("combobox", { name: /instance type/i }),
).toBeInTheDocument();
});
expect(screen.getByText(/instance type/i)).toBeInTheDocument();

const select = screen.getByRole("combobox", { name: /instance type/i });

await waitFor(async () => {
await userEvent.click(select);
});

expect(
screen.getByRole("option", { name: /t3\.micro/i }),
).toBeInTheDocument();
expect(
screen.getByRole("option", { name: /t3\.small/i }),
).toBeInTheDocument();
expect(
screen.getByRole("option", { name: /t3\.medium/i }),
).toBeInTheDocument();
// Each option appears in both the trigger and the dropdown
expect(screen.getAllByText(/t3\.micro/i)).toHaveLength(2);
expect(screen.getAllByText(/t3\.small/i)).toHaveLength(2);
expect(screen.getAllByText(/t3\.medium/i)).toHaveLength(2);
});

it("renders number parameter with slider", async () => {
Expand Down Expand Up @@ -539,13 +516,11 @@ describe("CreateWorkspacePageExperimental", () => {
callbacks.onMessage(JSON.parse(event.data));
});

setTimeout(() => {
publisher.publishMessage(
new MessageEvent("message", {
data: JSON.stringify(mockDynamicParametersResponseWithError),
}),
);
}, 10);
publisher.publishMessage(
new MessageEvent("message", {
data: JSON.stringify(mockDynamicParametersResponseWithError),
}),
);

return mockWebSocket;
});
Expand Down Expand Up @@ -603,28 +578,24 @@ describe("CreateWorkspacePageExperimental", () => {
callbacks.onMessage(JSON.parse(event.data));
});

setTimeout(() => {
publisher.publishOpen(new Event("open"));
publisher.publishOpen(new Event("open"));

publisher.publishMessage(
new MessageEvent("message", {
data: JSON.stringify(mockResponseInitial),
}),
);
}, 10);
publisher.publishMessage(
new MessageEvent("message", {
data: JSON.stringify(mockResponseInitial),
}),
);

const originalSend = socket.send;
socket.send = jest.fn((data) => {
originalSend.call(socket, data);

if (typeof data === "string" && data.includes('"200"')) {
setTimeout(() => {
publisher.publishMessage(
new MessageEvent("message", {
data: JSON.stringify(mockResponseWithError),
}),
);
}, 10);
publisher.publishMessage(
new MessageEvent("message", {
data: JSON.stringify(mockResponseWithError),
}),
);
}
});

Expand Down Expand Up @@ -746,9 +717,7 @@ describe("CreateWorkspacePageExperimental", () => {

await waitForLoaderToBeRemoved();

await waitFor(() => {
expect(screen.getByText("Instance Type")).toBeInTheDocument();
});
expect(screen.getByText(/instance type/i)).toBeInTheDocument();

await waitFor(() => {
expect(screen.getByText("Create workspace")).toBeInTheDocument();
Expand All @@ -764,9 +733,7 @@ describe("CreateWorkspacePageExperimental", () => {
renderCreateWorkspacePageExperimental();
await waitForLoaderToBeRemoved();

await waitFor(() => {
expect(screen.getByText("Instance Type")).toBeInTheDocument();
});
expect(screen.getByText(/instance type/i)).toBeInTheDocument();

const nameInput = screen.getByRole("textbox", {
name: /workspace name/i,
Expand Down Expand Up @@ -813,10 +780,8 @@ describe("CreateWorkspacePageExperimental", () => {
);
await waitForLoaderToBeRemoved();

await waitFor(() => {
expect(screen.getByText("Instance Type")).toBeInTheDocument();
expect(screen.getByText("CPU Count")).toBeInTheDocument();
});
expect(screen.getByText(/instance type/i)).toBeInTheDocument();
expect(screen.getByText("CPU Count")).toBeInTheDocument();
});

it("uses custom template version when specified", async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,16 +274,19 @@ const CreateWorkspacePageExperimental: FC = () => {
return [...latestResponse.parameters].sort((a, b) => a.order - b.order);
}, [latestResponse?.parameters]);

const shouldShowLoader =
!templateQuery.data ||
isLoadingFormData ||
isLoadingExternalAuth ||
autoCreateReady ||
(!latestResponse && !wsError);
Comment on lines +277 to +282
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this expression still hurts my head, but thank you for moving it to a variable!


return (
<>
<Helmet>
<title>{pageTitle(title)}</title>
</Helmet>
{(!latestResponse && !wsError) ||
!templateQuery.data ||
isLoadingFormData ||
isLoadingExternalAuth ||
autoCreateReady ? (
{shouldShowLoader ? (
<Loader />
) : (
<CreateWorkspacePageViewExperimental
Expand Down