Skip to content

Commit fed5e00

Browse files
committed
fix(site): fix validation server error on change password form
1 parent 23f61c6 commit fed5e00

File tree

3 files changed

+35
-3
lines changed

3 files changed

+35
-3
lines changed

site/src/pages/ResetPasswordPage/ChangePasswordPage.stories.tsx

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export const WrongConfirmationPassword: Story = {
5151
},
5252
};
5353

54-
export const ServerError: Story = {
54+
export const GeneralServerError: Story = {
5555
play: async ({ canvasElement }) => {
5656
const serverError =
5757
"New password should be different from the old password";
@@ -71,3 +71,28 @@ export const ServerError: Story = {
7171
await canvas.findByText(serverError);
7272
},
7373
};
74+
75+
export const ValidationServerError: Story = {
76+
play: async ({ canvasElement }) => {
77+
const error = mockApiError({
78+
message: "Invalid password.",
79+
validations: [
80+
{
81+
field: "password",
82+
detail:
83+
"insecure password, try including more special characters, using uppercase letters, using numbers or using a longer password",
84+
},
85+
],
86+
});
87+
spyOn(API, "changePasswordWithOTP").mockRejectedValueOnce(error);
88+
const canvas = within(canvasElement);
89+
const user = userEvent.setup();
90+
const newPasswordInput = await canvas.findByLabelText("Password *");
91+
await user.type(newPasswordInput, "password");
92+
const confirmPasswordInput =
93+
await canvas.findByLabelText("Confirm password *");
94+
await user.type(confirmPasswordInput, "password");
95+
await user.click(canvas.getByRole("button", { name: /reset password/i }));
96+
await canvas.findByText(error.response.data.message);
97+
},
98+
};

site/src/pages/ResetPasswordPage/ChangePasswordPage.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { Interpolation, Theme } from "@emotion/react";
22
import LoadingButton from "@mui/lab/LoadingButton";
33
import Button from "@mui/material/Button";
44
import TextField from "@mui/material/TextField";
5+
import { isApiError, isApiValidationError } from "api/errors";
56
import { changePasswordWithOTP } from "api/queries/users";
67
import { ErrorAlert } from "components/Alert/ErrorAlert";
78
import { CustomLogo } from "components/CustomLogo/CustomLogo";
@@ -64,7 +65,7 @@ const ChangePasswordPage: FC<ChangePasswordChangeProps> = ({ redirect }) => {
6465
}
6566
},
6667
});
67-
const getFieldHelpers = getFormHelpers(form);
68+
const getFieldHelpers = getFormHelpers(form, changePasswordMutation.error);
6869

6970
return (
7071
<>
@@ -86,7 +87,8 @@ const ChangePasswordPage: FC<ChangePasswordChangeProps> = ({ redirect }) => {
8687
>
8788
Choose a new password
8889
</h1>
89-
{changePasswordMutation.error ? (
90+
{changePasswordMutation.error &&
91+
!isApiValidationError(changePasswordMutation.error) ? (
9092
<ErrorAlert
9193
error={changePasswordMutation.error}
9294
css={{ marginBottom: 24 }}

site/src/theme/mui.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,11 @@ export const components = {
375375
sx: {
376376
marginLeft: 0,
377377
marginTop: 1,
378+
"&::first-letter": {
379+
// Server errors are returned in all lowercase. To display them as
380+
// field errors in the UI, we capitalize the first letter.
381+
textTransform: "uppercase",
382+
},
378383
},
379384
},
380385
},

0 commit comments

Comments
 (0)