Skip to content

Commit 19f8fe5

Browse files
committed
Add terminal page tests
1 parent cb5ae98 commit 19f8fe5

File tree

8 files changed

+490
-190
lines changed

8 files changed

+490
-190
lines changed

site/jest.config.js

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ module.exports = {
2828
testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$",
2929
testPathIgnorePatterns: ["/node_modules/", "/__tests__/fakes", "/e2e/"],
3030
moduleDirectories: ["node_modules", "<rootDir>"],
31+
moduleNameMapper: {
32+
"\\.css$": "<rootDir>/src/testHelpers/styleMock.ts"
33+
},
3134
},
3235
{
3336
displayName: "lint",

site/package.json

+3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"react-router-dom": "6.3.0",
4343
"swr": "1.2.2",
4444
"xstate": "4.31.0",
45+
"xterm": "^4.18.0",
4546
"xterm-addon-fit": "^0.5.0",
4647
"xterm-addon-web-links": "^0.5.1",
4748
"xterm-addon-webgl": "^0.11.4",
@@ -84,8 +85,10 @@
8485
"eslint-plugin-react-hooks": "4.4.0",
8586
"html-webpack-plugin": "5.5.0",
8687
"jest": "27.5.1",
88+
"jest-canvas-mock": "^2.4.0",
8789
"jest-junit": "13.1.0",
8890
"jest-runner-eslint": "1.0.0",
91+
"jest-websocket-mock": "^2.3.0",
8992
"mini-css-extract-plugin": "2.6.0",
9093
"msw": "0.39.2",
9194
"prettier": "2.6.2",

site/src/api/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,9 @@ export const getOrganizations = async (): Promise<Types.Organization[]> => {
9090
return response.data
9191
}
9292

93-
export const getWorkspace = async (organizationID: string, workspaceName: string): Promise<Types.Workspace> => {
93+
export const getWorkspace = async (organizationID: string, username = "me", workspaceName: string): Promise<Types.Workspace> => {
9494
const response = await axios.get<Types.Workspace>(
95-
`/api/v2/organizations/${organizationID}/workspaces/me/${workspaceName}`,
95+
`/api/v2/organizations/${organizationID}/workspaces/${username}/${workspaceName}`,
9696
)
9797
return response.data
9898
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
import crypto from "crypto"
2+
import "jest-canvas-mock"
3+
import { rest } from "msw"
4+
import React from "react"
5+
import { history, render } from "../../testHelpers"
6+
import { server } from "../../testHelpers/server"
7+
import { TerminalPage } from "./TerminalPage"
8+
9+
Object.defineProperty(window, "matchMedia", {
10+
writable: true,
11+
value: jest.fn().mockImplementation((query) => ({
12+
matches: false,
13+
media: query,
14+
onchange: null,
15+
addListener: jest.fn(), // deprecated
16+
removeListener: jest.fn(), // deprecated
17+
addEventListener: jest.fn(),
18+
removeEventListener: jest.fn(),
19+
dispatchEvent: jest.fn(),
20+
})),
21+
})
22+
23+
Object.defineProperty(window, "crypto", {
24+
value: {
25+
randomUUID: () => crypto.randomUUID(),
26+
},
27+
})
28+
29+
describe("TerminalPage", () => {
30+
beforeEach(() => {
31+
history.replace("/my-user/my-workspace/terminal")
32+
33+
server.use(
34+
rest.get("/api/v2/users/me/organizations", (req, res, ctx) => {
35+
return res(ctx.status(200), ctx.json([{ id: "org-id" }]))
36+
}),
37+
rest.get("/api/v2/organizations/org-id/workspaces/me/my-workspace", (req, res, ctx) => {
38+
return res(ctx.status(200), ctx.json({ id: "workspace-id" }))
39+
}),
40+
rest.get("/api/v2/workspaces/workspace-id/resources", (req, res, ctx) => {
41+
return res(ctx.status(200), ctx.json([{ agents: [{ id: "agent-id" }] }]))
42+
}),
43+
)
44+
})
45+
46+
it("shows an error if fetching organizations fails", async () => {
47+
// Given
48+
server.use(
49+
rest.get("/api/v2/users/me/organizations", async (req, res, ctx) => {
50+
return res(ctx.status(500), ctx.json({ message: "nope" }))
51+
}),
52+
)
53+
54+
// When
55+
const { container } = render(<TerminalPage renderer="dom" />)
56+
57+
await new Promise((resolve) => {
58+
let count = 0
59+
const loop = () => {
60+
count += 1
61+
const elements = container.getElementsByClassName("xterm-rows")
62+
if (elements.length < 1) {
63+
return false
64+
}
65+
const element = elements[0] as HTMLDivElement
66+
console.log(element.textContent)
67+
if (count > 50) {
68+
resolve(null)
69+
return
70+
}
71+
setTimeout(loop, 100)
72+
}
73+
loop()
74+
})
75+
76+
// await waitFor(() => {
77+
// const elements = container.getElementsByClassName("xterm-rows")
78+
// if (elements.length < 1) {
79+
// return false
80+
// }
81+
// const element = elements[0] as HTMLDivElement
82+
// console.log(element.textContent)
83+
// return false
84+
// })
85+
86+
// Then
87+
// await terminalContainsText(Language.organizationsErrorMessagePrefix)
88+
})
89+
90+
// it("shows an error if fetching workspace fails", async () => {
91+
// // Given
92+
// server.use(
93+
// rest.get("/api/v2/organizations/org-id/workspaces/me/my-workspace", (req, res, ctx) => {
94+
// return res(ctx.status(500), ctx.json({ id: "workspace-id" }))
95+
// }),
96+
// )
97+
98+
// // When
99+
// render(<TerminalPage renderer="dom" />)
100+
101+
// // Then
102+
// await terminalContainsText(Language.workspaceErrorMessagePrefix)
103+
// })
104+
105+
// it("shows an error if fetching workspace agent fails", async () => {
106+
// // Given
107+
// server.use(
108+
// rest.get("/api/v2/workspaces/workspace-id/resources", (req, res, ctx) => {
109+
// return res(ctx.status(500), ctx.json({ message: "nope" }))
110+
// }),
111+
// )
112+
113+
// // When
114+
// render(<TerminalPage renderer="dom" />)
115+
116+
// // Then
117+
// await terminalContainsText(Language.workspaceAgentErrorMessagePrefix)
118+
// })
119+
120+
// it("shows an error if the websocket fails", async () => {
121+
// // Given
122+
// server.use(
123+
// rest.get("/api/v2/workspaceagents/agent-id/pty", (req, res, ctx) => {
124+
// return res(ctx.status(500), ctx.json({}))
125+
// }),
126+
// )
127+
128+
// // When
129+
// render(<TerminalPage renderer="dom" />)
130+
131+
// // Then
132+
// await terminalContainsText(Language.websocketErrorMessagePrefix)
133+
// })
134+
135+
// it("renders data from the backend", async () => {
136+
// // Given
137+
// const server = new WS("ws://localhost/api/v2/workspaceagents/agent-id/pty")
138+
// server.on("connection", () => {
139+
// console.log("WE GOT A CONNECT")
140+
// })
141+
142+
// // When
143+
// const { container } = render(<TerminalPage renderer="dom" />)
144+
145+
// container.getElementsByClassName("xterm-rows")
146+
// // Then
147+
// await terminalContainsText(Language.websocketErrorMessagePrefix)
148+
// })
149+
150+
// it("shows an error message if SignIn fails", async () => {
151+
// // Given
152+
// server.use(
153+
// // Make login fail
154+
// rest.post("/api/v2/users/login", async (req, res, ctx) => {
155+
// return res(ctx.status(500), ctx.json({ message: "nope" }))
156+
// }),
157+
// )
158+
159+
// // When
160+
// render(<LoginPage />)
161+
// const email = screen.getByLabelText(Language.emailLabel)
162+
// const password = screen.getByLabelText(Language.passwordLabel)
163+
// await userEvent.type(email, "test@coder.com")
164+
// await userEvent.type(password, "password")
165+
// // Click sign-in
166+
// const signInButton = await screen.findByText(Language.passwordSignIn)
167+
// act(() => signInButton.click())
168+
169+
// // Then
170+
// const errorMessage = await screen.findByText(Language.authErrorMessage)
171+
// expect(errorMessage).toBeDefined()
172+
// expect(history.location.pathname).toEqual("/login")
173+
// })
174+
175+
// it("shows an error if fetching auth methods fails", async () => {
176+
// // Given
177+
// server.use(
178+
// // Make login fail
179+
// rest.get("/api/v2/users/authmethods", async (req, res, ctx) => {
180+
// return res(ctx.status(500), ctx.json({ message: "nope" }))
181+
// }),
182+
// )
183+
184+
// // When
185+
// render(<LoginPage />)
186+
187+
// // Then
188+
// const errorMessage = await screen.findByText(Language.methodsErrorMessage)
189+
// expect(errorMessage).toBeDefined()
190+
// })
191+
192+
// it("shows github authentication when enabled", async () => {
193+
// // Given
194+
// server.use(
195+
// rest.get("/api/v2/users/authmethods", async (req, res, ctx) => {
196+
// return res(
197+
// ctx.status(200),
198+
// ctx.json({
199+
// password: true,
200+
// github: true,
201+
// }),
202+
// )
203+
// }),
204+
// )
205+
206+
// // When
207+
// render(<LoginPage />)
208+
209+
// // Then
210+
// await screen.findByText(Language.passwordSignIn)
211+
// await screen.findByText(Language.githubSignIn)
212+
// })
213+
})

0 commit comments

Comments
 (0)