Skip to content

Commit e388f8a

Browse files
committed
Add tests
1 parent 8957339 commit e388f8a

File tree

5 files changed

+107
-7
lines changed

5 files changed

+107
-7
lines changed

site/jest.setup.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
import "@testing-library/jest-dom"
2+
import crypto from "crypto"
23
import { server } from "./src/testHelpers/server"
34

5+
// Polyfill the getRandomValues that is used on utils/random.ts
6+
Object.defineProperty(global.self, "crypto", {
7+
value: {
8+
getRandomValues: function (buffer: Buffer) {
9+
return crypto.randomFillSync(buffer)
10+
},
11+
},
12+
})
13+
414
// Establish API mocking before all tests through MSW.
515
beforeAll(() =>
616
server.listen({

site/src/components/ResetPasswordDialog/ResetPasswordDialog.tsx

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,17 @@ export interface ResetPasswordDialogProps {
1313
onConfirm: () => void
1414
user?: TypesGen.User
1515
newPassword?: string
16+
loading: boolean
17+
}
18+
19+
export const Language = {
20+
title: "Reset password",
21+
message: (username?: string): JSX.Element => (
22+
<>
23+
You will need to send <strong>{username}</strong> the following password:
24+
</>
25+
),
26+
confirmText: "Reset password",
1627
}
1728

1829
export const ResetPasswordDialog: React.FC<ResetPasswordDialogProps> = ({
@@ -21,25 +32,29 @@ export const ResetPasswordDialog: React.FC<ResetPasswordDialogProps> = ({
2132
onConfirm,
2233
user,
2334
newPassword,
35+
loading,
2436
}) => {
2537
const styles = useStyles()
2638

2739
return (
2840
<Dialog open={open} onClose={onClose}>
29-
<DialogTitle title="Reset password" />
41+
<DialogTitle title={Language.title} />
3042

3143
<DialogContent>
32-
<DialogContentText variant="subtitle2">
33-
You will need to send <strong>{user?.username}</strong> the following password:
34-
</DialogContentText>
44+
<DialogContentText variant="subtitle2">{Language.message(user?.username)}</DialogContentText>
3545

3646
<DialogContentText component="div">
3747
<CodeBlock lines={[newPassword ?? ""]} className={styles.codeBlock} />
3848
</DialogContentText>
3949
</DialogContent>
4050

4151
<DialogActions>
42-
<DialogActionButtons onCancel={onClose} confirmText="Reset password" onConfirm={onConfirm} />
52+
<DialogActionButtons
53+
onCancel={onClose}
54+
confirmText={Language.confirmText}
55+
onConfirm={onConfirm}
56+
confirmLoading={loading}
57+
/>
4358
</DialogActions>
4459
</Dialog>
4560
)

site/src/pages/UsersPage/UsersPage.test.tsx

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { fireEvent, screen, waitFor, within } from "@testing-library/react"
22
import React from "react"
33
import * as API from "../../api"
44
import { GlobalSnackbar } from "../../components/GlobalSnackbar/GlobalSnackbar"
5+
import { Language as ResetPasswordDialogLanguage } from "../../components/ResetPasswordDialog/ResetPasswordDialog"
56
import { Language as UsersTableLanguage } from "../../components/UsersTable/UsersTable"
67
import { MockUser, MockUser2, render } from "../../testHelpers"
78
import { Language as usersXServiceLanguage } from "../../xServices/users/usersXService"
@@ -34,6 +35,33 @@ const suspendUser = async (setupActionSpies: () => void) => {
3435
fireEvent.click(confirmButton)
3536
}
3637

38+
const resetUserPassword = async (setupActionSpies: () => void) => {
39+
// Get the first user in the table
40+
const users = await screen.findAllByText(/.*@coder.com/)
41+
const firstUserRow = users[0].closest("tr")
42+
if (!firstUserRow) {
43+
throw new Error("Error on get the first user row")
44+
}
45+
46+
// Click on the "more" button to display the "Suspend" option
47+
const moreButton = within(firstUserRow).getByLabelText("more")
48+
fireEvent.click(moreButton)
49+
const menu = screen.getByRole("menu")
50+
const resetPasswordButton = within(menu).getByText(UsersTableLanguage.resetPasswordMenuItem)
51+
fireEvent.click(resetPasswordButton)
52+
53+
// Check if the confirm message is displayed
54+
const confirmDialog = screen.getByRole("dialog")
55+
expect(confirmDialog).toHaveTextContent(`You will need to send ${MockUser.username} the following password:`)
56+
57+
// Setup spies to check the actions after
58+
setupActionSpies()
59+
60+
// Click on the "Confirm" button
61+
const confirmButton = within(confirmDialog).getByRole("button", { name: ResetPasswordDialogLanguage.confirmText })
62+
fireEvent.click(confirmButton)
63+
}
64+
3765
describe("Users Page", () => {
3866
it("shows users", async () => {
3967
render(<UsersPage />)
@@ -81,7 +109,7 @@ describe("Users Page", () => {
81109
jest.spyOn(API, "suspendUser").mockRejectedValueOnce({})
82110
})
83111

84-
// Check if the success message is displayed
112+
// Check if the error message is displayed
85113
await screen.findByText(usersXServiceLanguage.suspendUserError)
86114

87115
// Check if the API was called correctly
@@ -90,4 +118,50 @@ describe("Users Page", () => {
90118
})
91119
})
92120
})
121+
122+
describe("reset user password", () => {
123+
describe("when it is success", () => {
124+
it("shows a success message", async () => {
125+
render(
126+
<>
127+
<UsersPage />
128+
<GlobalSnackbar />
129+
</>,
130+
)
131+
132+
await resetUserPassword(() => {
133+
jest.spyOn(API, "updateUserPassword").mockResolvedValueOnce(undefined)
134+
})
135+
136+
// Check if the success message is displayed
137+
await screen.findByText(usersXServiceLanguage.resetUserPasswordSuccess)
138+
139+
// Check if the API was called correctly
140+
expect(API.updateUserPassword).toBeCalledTimes(1)
141+
expect(API.updateUserPassword).toBeCalledWith(expect.any(String), MockUser.id)
142+
})
143+
})
144+
145+
describe("when it fails", () => {
146+
it("shows an error message", async () => {
147+
render(
148+
<>
149+
<UsersPage />
150+
<GlobalSnackbar />
151+
</>,
152+
)
153+
154+
await resetUserPassword(() => {
155+
jest.spyOn(API, "updateUserPassword").mockRejectedValueOnce({})
156+
})
157+
158+
// Check if the error message is displayed
159+
await screen.findByText(usersXServiceLanguage.resetUserPasswordError)
160+
161+
// Check if the API was called correctly
162+
expect(API.updateUserPassword).toBeCalledTimes(1)
163+
expect(API.updateUserPassword).toBeCalledWith(expect.any(String), MockUser.id)
164+
})
165+
})
166+
})
93167
})

site/src/pages/UsersPage/UsersPage.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export const UsersPage: React.FC = () => {
6868
/>
6969

7070
<ResetPasswordDialog
71+
loading={usersState.matches("resettingUserPassword")}
7172
user={userToResetPassword}
7273
newPassword={newUserPassword}
7374
open={usersState.matches("confirmUserPasswordReset")}

site/src/xServices/users/usersXService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ export const usersMachine = createMachine(
255255
displaySuccess(Language.resetUserPasswordSuccess)
256256
},
257257
displayResetPasswordErrorMessage: () => {
258-
displaySuccess(Language.resetUserPasswordError)
258+
displayError(Language.resetUserPasswordError)
259259
},
260260
generateRandomPassword: assign({
261261
newUserPassword: (_) => generateRandomString(12),

0 commit comments

Comments
 (0)