Skip to content

Commit bfb9aa4

Browse files
fix(site): only attempt to watch when dev containers enabled (#18892)
1 parent ca6b5e3 commit bfb9aa4

File tree

2 files changed

+71
-19
lines changed

2 files changed

+71
-19
lines changed

site/src/modules/resources/useAgentContainers.test.tsx

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,19 @@ import type { WorkspaceAgentListContainersResponse } from "api/typesGenerated";
44
import * as GlobalSnackbar from "components/GlobalSnackbar/utils";
55
import { http, HttpResponse } from "msw";
66
import type { FC, PropsWithChildren } from "react";
7-
import { QueryClient, QueryClientProvider } from "react-query";
7+
import { act } from "react";
8+
import { QueryClientProvider } from "react-query";
89
import {
910
MockWorkspaceAgent,
1011
MockWorkspaceAgentDevcontainer,
1112
} from "testHelpers/entities";
13+
import { createTestQueryClient } from "testHelpers/renderHelpers";
1214
import { server } from "testHelpers/server";
1315
import type { OneWayWebSocket } from "utils/OneWayWebSocket";
1416
import { useAgentContainers } from "./useAgentContainers";
1517

1618
const createWrapper = (): FC<PropsWithChildren> => {
17-
const queryClient = new QueryClient({
18-
defaultOptions: {
19-
queries: {
20-
retry: false,
21-
},
22-
},
23-
});
19+
const queryClient = createTestQueryClient();
2420
return ({ children }) => (
2521
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
2622
);
@@ -111,22 +107,29 @@ describe("useAgentContainers", () => {
111107
),
112108
);
113109

114-
const { unmount } = renderHook(
110+
const { result, unmount } = renderHook(
115111
() => useAgentContainers(MockWorkspaceAgent),
116112
{
117113
wrapper: createWrapper(),
118114
},
119115
);
120116

121-
// Simulate message event with parsing error
117+
// Wait for initial query to complete
118+
await waitFor(() => {
119+
expect(result.current).toEqual([MockWorkspaceAgentDevcontainer]);
120+
});
121+
122+
// Now simulate message event with parsing error
122123
const messageHandler = mockSocket.addEventListener.mock.calls.find(
123124
(call) => call[0] === "message",
124125
)?.[1];
125126

126127
if (messageHandler) {
127-
messageHandler({
128-
parseError: new Error("Parse error"),
129-
parsedMessage: null,
128+
act(() => {
129+
messageHandler({
130+
parseError: new Error("Parse error"),
131+
parsedMessage: null,
132+
});
130133
});
131134
}
132135

@@ -166,20 +169,27 @@ describe("useAgentContainers", () => {
166169
),
167170
);
168171

169-
const { unmount } = renderHook(
172+
const { result, unmount } = renderHook(
170173
() => useAgentContainers(MockWorkspaceAgent),
171174
{
172175
wrapper: createWrapper(),
173176
},
174177
);
175178

176-
// Simulate error event
179+
// Wait for initial query to complete
180+
await waitFor(() => {
181+
expect(result.current).toEqual([MockWorkspaceAgentDevcontainer]);
182+
});
183+
184+
// Now simulate error event
177185
const errorHandler = mockSocket.addEventListener.mock.calls.find(
178186
(call) => call[0] === "error",
179187
)?.[1];
180188

181189
if (errorHandler) {
182-
errorHandler(new Error("WebSocket error"));
190+
act(() => {
191+
errorHandler(new Error("WebSocket error"));
192+
});
183193
}
184194

185195
await waitFor(() => {
@@ -211,4 +221,36 @@ describe("useAgentContainers", () => {
211221

212222
watchAgentContainersSpy.mockRestore();
213223
});
224+
225+
it("does not establish WebSocket connection when dev container feature is not enabled", async () => {
226+
const watchAgentContainersSpy = jest.spyOn(API, "watchAgentContainers");
227+
228+
server.use(
229+
http.get(
230+
`/api/v2/workspaceagents/${MockWorkspaceAgent.id}/containers`,
231+
() => {
232+
return HttpResponse.json(
233+
{ message: "Dev Container feature not enabled." },
234+
{ status: 403 },
235+
);
236+
},
237+
),
238+
);
239+
240+
const { result } = renderHook(
241+
() => useAgentContainers(MockWorkspaceAgent),
242+
{
243+
wrapper: createWrapper(),
244+
},
245+
);
246+
247+
// Wait for the query to complete and error to be processed
248+
await waitFor(() => {
249+
expect(result.current).toBeUndefined();
250+
});
251+
252+
expect(watchAgentContainersSpy).not.toHaveBeenCalled();
253+
254+
watchAgentContainersSpy.mockRestore();
255+
});
214256
});

site/src/modules/resources/useAgentContainers.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ export function useAgentContainers(
1414
): readonly WorkspaceAgentDevcontainer[] | undefined {
1515
const queryClient = useQueryClient();
1616

17-
const { data: devcontainers } = useQuery({
17+
const {
18+
data: devcontainers,
19+
error: queryError,
20+
isLoading: queryIsLoading,
21+
} = useQuery({
1822
queryKey: ["agents", agent.id, "containers"],
1923
queryFn: () => API.getAgentContainers(agent.id),
2024
enabled: agent.status === "connected",
@@ -31,7 +35,7 @@ export function useAgentContainers(
3135
);
3236

3337
useEffect(() => {
34-
if (agent.status !== "connected") {
38+
if (agent.status !== "connected" || queryIsLoading || queryError) {
3539
return;
3640
}
3741

@@ -57,7 +61,13 @@ export function useAgentContainers(
5761
});
5862

5963
return () => socket.close();
60-
}, [agent.id, agent.status, updateDevcontainersCache]);
64+
}, [
65+
agent.id,
66+
agent.status,
67+
queryIsLoading,
68+
queryError,
69+
updateDevcontainersCache,
70+
]);
6171

6272
return devcontainers;
6373
}

0 commit comments

Comments
 (0)