From 6ae13b12f12ee54e93e3af64002f1fcf7c5efd79 Mon Sep 17 00:00:00 2001 From: Abhineet Jain Date: Tue, 26 Jul 2022 23:00:48 +0000 Subject: [PATCH 1/5] fix: show errors on SSH Key page --- .../SSHKeysPage/SSHKeysPage.test.tsx | 2 +- .../SSHKeysPage/SSHKeysPage.tsx | 48 ++++++++++++------- site/src/xServices/auth/authXService.ts | 8 +--- 3 files changed, 34 insertions(+), 24 deletions(-) diff --git a/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.test.tsx b/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.test.tsx index 01c1ac82dada7..b44136a415793 100644 --- a/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.test.tsx +++ b/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.test.tsx @@ -85,7 +85,7 @@ describe("SSH keys Page", () => { fireEvent.click(confirmButton) // Check if the error message is displayed - await screen.findByText(authXServiceLanguage.errorRegenerateSSHKey) + await screen.findByText(SSHKeysPageLanguage.errorRegenerateSSHKey) // Check if the API was called correctly expect(API.regenerateUserSSHKey).toBeCalledTimes(1) diff --git a/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.tsx b/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.tsx index 14beb82fe6379..ce15d0fcbbe52 100644 --- a/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.tsx +++ b/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.tsx @@ -2,6 +2,7 @@ import Box from "@material-ui/core/Box" import Button from "@material-ui/core/Button" import CircularProgress from "@material-ui/core/CircularProgress" import { useActor } from "@xstate/react" +import { ErrorSummary } from "components/ErrorSummary/ErrorSummary" import React, { useContext, useEffect } from "react" import { CodeExample } from "../../../components/CodeExample/CodeExample" import { ConfirmDialog } from "../../../components/ConfirmDialog/ConfirmDialog" @@ -19,12 +20,13 @@ export const Language = { "You will need to replace the public SSH key on services you use it with, and you'll need to rebuild existing workspaces.", confirmLabel: "Confirm", cancelLabel: "Cancel", + errorRegenerateSSHKey: "Error on regenerate the SSH Key", } export const SSHKeysPage: React.FC = () => { const xServices = useContext(XServiceContext) const [authState, authSend] = useActor(xServices.authXService) - const { sshKey } = authState.context + const { sshKey, getSSHKeyError, regenerateSSHKeyError } = authState.context useEffect(() => { authSend({ type: "GET_SSH_KEY" }) @@ -33,27 +35,39 @@ export const SSHKeysPage: React.FC = () => { return ( <>
- {!sshKey && ( + {authState.matches("signedIn.ssh.gettingSSHKey") && ( )} - {sshKey && ( - - -
- -
-
- )} + + {/* Regenerating the key is not an option if getSSHKey fails. + Only one of the error messages will exist at a single time */} + {getSSHKeyError && } + {regenerateSSHKeyError && ( + + )} + {authState.matches("signedIn.ssh.loaded") && sshKey && ( + <> + +
+ +
+ + )} +
{ displaySuccess(Language.successRegenerateSSHKey) }, - notifySSHKeyRegenerationError: () => { - displayError(Language.errorRegenerateSSHKey) - }, }, }, ) From c37b4ece6d679fa8daae315b52f8d899c756db4e Mon Sep 17 00:00:00 2001 From: Abhineet Jain Date: Tue, 26 Jul 2022 23:53:01 +0000 Subject: [PATCH 2/5] handle all auth api errors --- .../SignInForm/SignInForm.stories.tsx | 79 ++++++++++++++++--- site/src/components/SignInForm/SignInForm.tsx | 48 ++++++++--- site/src/pages/LoginPage/LoginPage.tsx | 10 ++- site/src/xServices/auth/authXService.ts | 3 +- 4 files changed, 114 insertions(+), 26 deletions(-) diff --git a/site/src/components/SignInForm/SignInForm.stories.tsx b/site/src/components/SignInForm/SignInForm.stories.tsx index 7e6b24f79ed2a..96cc39cde5c30 100644 --- a/site/src/components/SignInForm/SignInForm.stories.tsx +++ b/site/src/components/SignInForm/SignInForm.stories.tsx @@ -15,7 +15,7 @@ const Template: Story = (args: SignInFormProps) => { return Promise.resolve() }, @@ -34,29 +34,82 @@ Loading.args = { export const WithLoginError = Template.bind({}) WithLoginError.args = { ...SignedOut.args, - authError: { - response: { - data: { - message: "Email or password was invalid", - validations: [ - { - field: "password", - detail: "Password is invalid.", - }, - ], + loginErrors: { + authError: { + response: { + data: { + message: "Email or password was invalid", + validations: [ + { + field: "password", + detail: "Password is invalid.", + }, + ], + }, }, + isAxiosError: true, }, - isAxiosError: true, }, initialTouched: { password: true, }, } +export const WithGetUserError = Template.bind({}) +WithGetUserError.args = { + ...SignedOut.args, + loginErrors: { + getUserError: { + response: { + data: { + message: "Unable to fetch user details", + detail: "Resource not found or you do not have access to this resource.", + }, + }, + isAxiosError: true, + }, + }, +} + +export const WithCheckPermissionsError = Template.bind({}) +WithCheckPermissionsError.args = { + ...SignedOut.args, + loginErrors: { + checkPermissionsError: { + response: { + data: { + message: "Unable to fetch user permissions", + detail: "Resource not found or you do not have access to this resource.", + }, + }, + isAxiosError: true, + }, + }, +} + export const WithAuthMethodsError = Template.bind({}) WithAuthMethodsError.args = { ...SignedOut.args, - methodsError: new Error("Failed to fetch auth methods"), + loginErrors: { + getMethodsError: new Error("Failed to fetch auth methods"), + }, +} + +export const WithGetUserAndAuthMethodsErrors = Template.bind({}) +WithGetUserAndAuthMethodsErrors.args = { + ...SignedOut.args, + loginErrors: { + getUserError: { + response: { + data: { + message: "Unable to fetch user details", + detail: "Resource not found or you do not have access to this resource.", + }, + }, + isAxiosError: true, + }, + getMethodsError: new Error("Failed to fetch auth methods"), + }, } export const WithGithub = Template.bind({}) diff --git a/site/src/components/SignInForm/SignInForm.tsx b/site/src/components/SignInForm/SignInForm.tsx index bfa28ca8bd3cb..3bdfee507fc6a 100644 --- a/site/src/components/SignInForm/SignInForm.tsx +++ b/site/src/components/SignInForm/SignInForm.tsx @@ -29,7 +29,9 @@ export const Language = { emailInvalid: "Please enter a valid email address.", emailRequired: "Please enter an email address.", authErrorMessage: "Incorrect email or password.", - methodsErrorMessage: "Unable to fetch auth methods.", + getUserErrorMessage: "Unable to fetch user details.", + checkPermissionsErrorMessage: "Unable to fetch user permissions.", + getMethodsErrorMessage: "Unable to fetch auth methods.", passwordSignIn: "Sign In", githubSignIn: "GitHub", } @@ -65,11 +67,17 @@ const useStyles = makeStyles((theme) => ({ }, })) +type LoginErrors = { + authError?: Error | unknown + getUserError?: Error | unknown + checkPermissionsError?: Error | unknown + getMethodsError?: Error | unknown +} + export interface SignInFormProps { isLoading: boolean redirectTo: string - authError?: Error | unknown - methodsError?: Error | unknown + loginErrors: LoginErrors authMethods?: AuthMethods onSubmit: ({ email, password }: { email: string; password: string }) => Promise // initialTouched is only used for testing the error state of the form. @@ -80,8 +88,7 @@ export const SignInForm: FC = ({ authMethods, redirectTo, isLoading, - authError, - methodsError, + loginErrors, onSubmit, initialTouched, }) => { @@ -101,18 +108,39 @@ export const SignInForm: FC = ({ onSubmit, initialTouched, }) - const getFieldHelpers = getFormHelpersWithError(form, authError) + const getFieldHelpers = getFormHelpersWithError( + form, + loginErrors.authError, + ) return ( <>
- {authError && ( - + {loginErrors.authError && ( + + )} + {loginErrors.getUserError && ( + + )} + {loginErrors.checkPermissionsError && ( + )} - {methodsError && ( - + {loginErrors.getMethodsError && ( + )} { authSend({ type: "SIGN_IN", email, password }) } + const { authError, getUserError, checkPermissionsError, getMethodsError } = authState.context + if (authState.matches("signedIn")) { return } else { @@ -54,8 +56,12 @@ export const LoginPage: React.FC = () => { authMethods={authState.context.methods} redirectTo={redirectTo} isLoading={isLoading} - authError={authState.context.authError} - methodsError={authState.context.getMethodsError as Error} + loginErrors={{ + authError, + getUserError, + checkPermissionsError, + getMethodsError, + }} onSubmit={onSubmit} /> diff --git a/site/src/xServices/auth/authXService.ts b/site/src/xServices/auth/authXService.ts index c68e23cce1be0..cf0a9432ea33a 100644 --- a/site/src/xServices/auth/authXService.ts +++ b/site/src/xServices/auth/authXService.ts @@ -213,12 +213,13 @@ export const authMachine = tags: "loading", }, gettingUser: { + entry: "clearGetUserError", invoke: { src: "getMe", id: "getMe", onDone: [ { - actions: ["assignMe", "clearGetUserError"], + actions: ["assignMe"], target: "gettingPermissions", }, ], From 865c1c50d33f1e7ad9edefd51b1d7dca45c78687 Mon Sep 17 00:00:00 2001 From: Abhineet Jain Date: Thu, 28 Jul 2022 09:06:07 +0000 Subject: [PATCH 3/5] add stories, refactor code --- site/src/components/SignInForm/SignInForm.tsx | 57 +++++++---------- site/src/pages/LoginPage/LoginPage.test.tsx | 4 +- .../SSHKeysPage/SSHKeysPage.test.tsx | 7 +- .../SSHKeysPage/SSHKeysPage.tsx | 57 +++++------------ .../SSHKeysPage/SSHKeysPageView.stories.tsx | 62 ++++++++++++++++++ .../SSHKeysPage/SSHKeysPageView.tsx | 64 +++++++++++++++++++ 6 files changed, 170 insertions(+), 81 deletions(-) create mode 100644 site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPageView.stories.tsx create mode 100644 site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPageView.tsx diff --git a/site/src/components/SignInForm/SignInForm.tsx b/site/src/components/SignInForm/SignInForm.tsx index 3bdfee507fc6a..94f6c5a3fdc39 100644 --- a/site/src/components/SignInForm/SignInForm.tsx +++ b/site/src/components/SignInForm/SignInForm.tsx @@ -23,15 +23,24 @@ interface BuiltInAuthFormValues { password: string } +export enum LoginErrors { + AUTH_ERROR = "authError", + GET_USER_ERROR = "getUserError", + CHECK_PERMISSIONS_ERROR = "checkPermissionsError", + GET_METHODS_ERROR = "getMethodsError", +} + export const Language = { emailLabel: "Email", passwordLabel: "Password", emailInvalid: "Please enter a valid email address.", emailRequired: "Please enter an email address.", - authErrorMessage: "Incorrect email or password.", - getUserErrorMessage: "Unable to fetch user details.", - checkPermissionsErrorMessage: "Unable to fetch user permissions.", - getMethodsErrorMessage: "Unable to fetch auth methods.", + errorMessages: { + [LoginErrors.AUTH_ERROR]: "Incorrect email or password.", + [LoginErrors.GET_USER_ERROR]: "Unable to fetch user details.", + [LoginErrors.CHECK_PERMISSIONS_ERROR]: "Unable to fetch user permissions.", + [LoginErrors.GET_METHODS_ERROR]: "Unable to fetch auth methods.", + }, passwordSignIn: "Sign In", githubSignIn: "GitHub", } @@ -67,17 +76,10 @@ const useStyles = makeStyles((theme) => ({ }, })) -type LoginErrors = { - authError?: Error | unknown - getUserError?: Error | unknown - checkPermissionsError?: Error | unknown - getMethodsError?: Error | unknown -} - export interface SignInFormProps { isLoading: boolean redirectTo: string - loginErrors: LoginErrors + loginErrors: Record authMethods?: AuthMethods onSubmit: ({ email, password }: { email: string; password: string }) => Promise // initialTouched is only used for testing the error state of the form. @@ -118,29 +120,14 @@ export const SignInForm: FC = ({ - {loginErrors.authError && ( - - )} - {loginErrors.getUserError && ( - - )} - {loginErrors.checkPermissionsError && ( - - )} - {loginErrors.getMethodsError && ( - + {Object.keys(loginErrors).map((errorKey: string) => + loginErrors[errorKey as LoginErrors] ? ( + + ) : null, )} { server.use( // Make login fail rest.post("/api/v2/users/login", async (req, res, ctx) => { - return res(ctx.status(500), ctx.json({ message: Language.authErrorMessage })) + return res(ctx.status(500), ctx.json({ message: Language.errorMessages.authError })) }), ) @@ -45,7 +45,7 @@ describe("LoginPage", () => { act(() => signInButton.click()) // Then - const errorMessage = await screen.findByText(Language.authErrorMessage) + const errorMessage = await screen.findByText(Language.errorMessages.authError) expect(errorMessage).toBeDefined() expect(history.location.pathname).toEqual("/login") }) diff --git a/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.test.tsx b/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.test.tsx index b44136a415793..0fbde8225a9e0 100644 --- a/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.test.tsx +++ b/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.test.tsx @@ -4,6 +4,7 @@ import { GlobalSnackbar } from "../../../components/GlobalSnackbar/GlobalSnackba import { MockGitSSHKey, renderWithAuth } from "../../../testHelpers/renderHelpers" import { Language as authXServiceLanguage } from "../../../xServices/auth/authXService" import { Language as SSHKeysPageLanguage, SSHKeysPage } from "./SSHKeysPage" +import { Language as SSHKeysPageViewLanguage } from "./SSHKeysPageView" describe("SSH keys Page", () => { it("shows the SSH key", async () => { @@ -26,7 +27,7 @@ describe("SSH keys Page", () => { // Click on the "Regenerate" button to display the confirm dialog const regenerateButton = screen.getByRole("button", { - name: SSHKeysPageLanguage.regenerateLabel, + name: SSHKeysPageViewLanguage.regenerateLabel, }) fireEvent.click(regenerateButton) const confirmDialog = screen.getByRole("dialog") @@ -72,7 +73,7 @@ describe("SSH keys Page", () => { // Click on the "Regenerate" button to display the confirm dialog const regenerateButton = screen.getByRole("button", { - name: SSHKeysPageLanguage.regenerateLabel, + name: SSHKeysPageViewLanguage.regenerateLabel, }) fireEvent.click(regenerateButton) const confirmDialog = screen.getByRole("dialog") @@ -85,7 +86,7 @@ describe("SSH keys Page", () => { fireEvent.click(confirmButton) // Check if the error message is displayed - await screen.findByText(SSHKeysPageLanguage.errorRegenerateSSHKey) + await screen.findByText(SSHKeysPageViewLanguage.errorRegenerateSSHKey) // Check if the API was called correctly expect(API.regenerateUserSSHKey).toBeCalledTimes(1) diff --git a/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.tsx b/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.tsx index ce15d0fcbbe52..fcb008a6c0655 100644 --- a/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.tsx +++ b/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPage.tsx @@ -1,26 +1,19 @@ -import Box from "@material-ui/core/Box" -import Button from "@material-ui/core/Button" -import CircularProgress from "@material-ui/core/CircularProgress" import { useActor } from "@xstate/react" -import { ErrorSummary } from "components/ErrorSummary/ErrorSummary" import React, { useContext, useEffect } from "react" -import { CodeExample } from "../../../components/CodeExample/CodeExample" import { ConfirmDialog } from "../../../components/ConfirmDialog/ConfirmDialog" import { Section } from "../../../components/Section/Section" -import { Stack } from "../../../components/Stack/Stack" import { XServiceContext } from "../../../xServices/StateContext" +import { SSHKeysPageView } from "./SSHKeysPageView" export const Language = { title: "SSH keys", description: "Coder automatically inserts a private key into every workspace; you can add the corresponding public key to any services (such as Git) that you need access to from your workspace.", - regenerateLabel: "Regenerate", regenerateDialogTitle: "Regenerate SSH key?", regenerateDialogMessage: "You will need to replace the public SSH key on services you use it with, and you'll need to rebuild existing workspaces.", confirmLabel: "Confirm", cancelLabel: "Cancel", - errorRegenerateSSHKey: "Error on regenerate the SSH Key", } export const SSHKeysPage: React.FC = () => { @@ -32,42 +25,24 @@ export const SSHKeysPage: React.FC = () => { authSend({ type: "GET_SSH_KEY" }) }, [authSend]) + const isLoading = authState.matches("signedIn.ssh.gettingSSHKey") + const hasLoaded = authState.matches("signedIn.ssh.loaded") + + const onRegenerateClick = () => { + authSend({ type: "REGENERATE_SSH_KEY" }) + } + return ( <>
- {authState.matches("signedIn.ssh.gettingSSHKey") && ( - - - - )} - - - {/* Regenerating the key is not an option if getSSHKey fails. - Only one of the error messages will exist at a single time */} - {getSSHKeyError && } - {regenerateSSHKeyError && ( - - )} - {authState.matches("signedIn.ssh.loaded") && sshKey && ( - <> - -
- -
- - )} -
+
= (args: SSHKeysPageViewProps) => ( + +) + +export const Example = Template.bind({}) +Example.args = { + isLoading: false, + hasLoaded: true, + sshKey: { + user_id: "test-user-id", + created_at: "2022-07-28T07:45:50.795918897Z", + updated_at: "2022-07-28T07:45:50.795919142Z", + public_key: "SSH-Key", + }, + onRegenerateClick: () => { + return Promise.resolve() + }, +} + +export const Loading = Template.bind({}) +Loading.args = { + ...Example.args, + isLoading: true, +} + +export const WithGetSSHKeyError = Template.bind({}) +WithGetSSHKeyError.args = { + ...Example.args, + hasLoaded: false, + getSSHKeyError: { + response: { + data: { + message: "Failed to get SSH key", + }, + }, + isAxiosError: true, + }, +} + +export const WithRegenerateSSHKeyError = Template.bind({}) +WithRegenerateSSHKeyError.args = { + ...Example.args, + regenerateSSHKeyError: { + response: { + data: { + message: "Failed to regenerate SSH key", + }, + }, + isAxiosError: true, + }, +} diff --git a/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPageView.tsx b/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPageView.tsx new file mode 100644 index 0000000000000..9aa135bcf6956 --- /dev/null +++ b/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPageView.tsx @@ -0,0 +1,64 @@ +import Box from "@material-ui/core/Box" +import Button from "@material-ui/core/Button" +import CircularProgress from "@material-ui/core/CircularProgress" +import { GitSSHKey } from "api/typesGenerated" +import { CodeExample } from "components/CodeExample/CodeExample" +import { ErrorSummary } from "components/ErrorSummary/ErrorSummary" +import { Stack } from "components/Stack/Stack" +import { FC } from "react" + +export const Language = { + errorRegenerateSSHKey: "Error on regenerating the SSH Key", + regenerateLabel: "Regenerate", +} + +export interface SSHKeysPageViewProps { + isLoading: boolean + hasLoaded: boolean + getSSHKeyError?: Error | unknown + regenerateSSHKeyError?: Error | unknown + sshKey?: GitSSHKey + onRegenerateClick: () => void +} + +export const SSHKeysPageView: FC = ({ + isLoading, + hasLoaded, + getSSHKeyError, + regenerateSSHKeyError, + sshKey, + onRegenerateClick, +}) => { + if (isLoading) { + return ( + + + + ) + } + + return ( + + {/* Regenerating the key is not an option if getSSHKey fails. + Only one of the error messages will exist at a single time */} + {getSSHKeyError && } + {regenerateSSHKeyError && ( + + )} + {hasLoaded && sshKey && ( + <> + +
+ +
+ + )} +
+ ) +} From 3ce260ac8b06920c7d22eeed163c72cb351c2cb3 Mon Sep 17 00:00:00 2001 From: Abhineet Jain Date: Thu, 28 Jul 2022 21:01:29 +0000 Subject: [PATCH 4/5] remove getUserError --- .../SignInForm/SignInForm.stories.tsx | 41 ++----------------- site/src/components/SignInForm/SignInForm.tsx | 4 +- site/src/pages/LoginPage/LoginPage.tsx | 3 +- 3 files changed, 6 insertions(+), 42 deletions(-) diff --git a/site/src/components/SignInForm/SignInForm.stories.tsx b/site/src/components/SignInForm/SignInForm.stories.tsx index 96cc39cde5c30..b32449af64f55 100644 --- a/site/src/components/SignInForm/SignInForm.stories.tsx +++ b/site/src/components/SignInForm/SignInForm.stories.tsx @@ -1,5 +1,5 @@ import { Story } from "@storybook/react" -import { SignInForm, SignInFormProps } from "./SignInForm" +import { LoginErrors, SignInForm, SignInFormProps } from "./SignInForm" export default { title: "components/SignInForm", @@ -35,7 +35,7 @@ export const WithLoginError = Template.bind({}) WithLoginError.args = { ...SignedOut.args, loginErrors: { - authError: { + [LoginErrors.AUTH_ERROR]: { response: { data: { message: "Email or password was invalid", @@ -55,27 +55,11 @@ WithLoginError.args = { }, } -export const WithGetUserError = Template.bind({}) -WithGetUserError.args = { - ...SignedOut.args, - loginErrors: { - getUserError: { - response: { - data: { - message: "Unable to fetch user details", - detail: "Resource not found or you do not have access to this resource.", - }, - }, - isAxiosError: true, - }, - }, -} - export const WithCheckPermissionsError = Template.bind({}) WithCheckPermissionsError.args = { ...SignedOut.args, loginErrors: { - checkPermissionsError: { + [LoginErrors.CHECK_PERMISSIONS_ERROR]: { response: { data: { message: "Unable to fetch user permissions", @@ -91,24 +75,7 @@ export const WithAuthMethodsError = Template.bind({}) WithAuthMethodsError.args = { ...SignedOut.args, loginErrors: { - getMethodsError: new Error("Failed to fetch auth methods"), - }, -} - -export const WithGetUserAndAuthMethodsErrors = Template.bind({}) -WithGetUserAndAuthMethodsErrors.args = { - ...SignedOut.args, - loginErrors: { - getUserError: { - response: { - data: { - message: "Unable to fetch user details", - detail: "Resource not found or you do not have access to this resource.", - }, - }, - isAxiosError: true, - }, - getMethodsError: new Error("Failed to fetch auth methods"), + [LoginErrors.GET_METHODS_ERROR]: new Error("Failed to fetch auth methods"), }, } diff --git a/site/src/components/SignInForm/SignInForm.tsx b/site/src/components/SignInForm/SignInForm.tsx index 94f6c5a3fdc39..a4d75dad63dd7 100644 --- a/site/src/components/SignInForm/SignInForm.tsx +++ b/site/src/components/SignInForm/SignInForm.tsx @@ -25,7 +25,6 @@ interface BuiltInAuthFormValues { export enum LoginErrors { AUTH_ERROR = "authError", - GET_USER_ERROR = "getUserError", CHECK_PERMISSIONS_ERROR = "checkPermissionsError", GET_METHODS_ERROR = "getMethodsError", } @@ -37,7 +36,6 @@ export const Language = { emailRequired: "Please enter an email address.", errorMessages: { [LoginErrors.AUTH_ERROR]: "Incorrect email or password.", - [LoginErrors.GET_USER_ERROR]: "Unable to fetch user details.", [LoginErrors.CHECK_PERMISSIONS_ERROR]: "Unable to fetch user permissions.", [LoginErrors.GET_METHODS_ERROR]: "Unable to fetch auth methods.", }, @@ -79,7 +77,7 @@ const useStyles = makeStyles((theme) => ({ export interface SignInFormProps { isLoading: boolean redirectTo: string - loginErrors: Record + loginErrors: Partial> authMethods?: AuthMethods onSubmit: ({ email, password }: { email: string; password: string }) => Promise // initialTouched is only used for testing the error state of the form. diff --git a/site/src/pages/LoginPage/LoginPage.tsx b/site/src/pages/LoginPage/LoginPage.tsx index 924605db9f3bd..305012425130d 100644 --- a/site/src/pages/LoginPage/LoginPage.tsx +++ b/site/src/pages/LoginPage/LoginPage.tsx @@ -40,7 +40,7 @@ export const LoginPage: React.FC = () => { authSend({ type: "SIGN_IN", email, password }) } - const { authError, getUserError, checkPermissionsError, getMethodsError } = authState.context + const { authError, checkPermissionsError, getMethodsError } = authState.context if (authState.matches("signedIn")) { return @@ -58,7 +58,6 @@ export const LoginPage: React.FC = () => { isLoading={isLoading} loginErrors={{ authError, - getUserError, checkPermissionsError, getMethodsError, }} From 3dbd3f34c9b48e7ceee466bdd25352f057609f13 Mon Sep 17 00:00:00 2001 From: Abhineet Jain Date: Thu, 28 Jul 2022 21:06:31 +0000 Subject: [PATCH 5/5] use makeMockApiError helper --- .../SignInForm/SignInForm.stories.tsx | 35 +++++++------------ .../SSHKeysPage/SSHKeysPageView.stories.tsx | 23 ++++-------- 2 files changed, 20 insertions(+), 38 deletions(-) diff --git a/site/src/components/SignInForm/SignInForm.stories.tsx b/site/src/components/SignInForm/SignInForm.stories.tsx index b32449af64f55..1937dfd066a5b 100644 --- a/site/src/components/SignInForm/SignInForm.stories.tsx +++ b/site/src/components/SignInForm/SignInForm.stories.tsx @@ -1,4 +1,5 @@ import { Story } from "@storybook/react" +import { makeMockApiError } from "testHelpers/entities" import { LoginErrors, SignInForm, SignInFormProps } from "./SignInForm" export default { @@ -35,20 +36,15 @@ export const WithLoginError = Template.bind({}) WithLoginError.args = { ...SignedOut.args, loginErrors: { - [LoginErrors.AUTH_ERROR]: { - response: { - data: { - message: "Email or password was invalid", - validations: [ - { - field: "password", - detail: "Password is invalid.", - }, - ], + [LoginErrors.AUTH_ERROR]: makeMockApiError({ + message: "Email or password was invalid", + validations: [ + { + field: "password", + detail: "Password is invalid.", }, - }, - isAxiosError: true, - }, + ], + }), }, initialTouched: { password: true, @@ -59,15 +55,10 @@ export const WithCheckPermissionsError = Template.bind({}) WithCheckPermissionsError.args = { ...SignedOut.args, loginErrors: { - [LoginErrors.CHECK_PERMISSIONS_ERROR]: { - response: { - data: { - message: "Unable to fetch user permissions", - detail: "Resource not found or you do not have access to this resource.", - }, - }, - isAxiosError: true, - }, + [LoginErrors.CHECK_PERMISSIONS_ERROR]: makeMockApiError({ + message: "Unable to fetch user permissions", + detail: "Resource not found or you do not have access to this resource.", + }), }, } diff --git a/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPageView.stories.tsx b/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPageView.stories.tsx index 7641580bb4d48..4342dba6b8237 100644 --- a/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPageView.stories.tsx +++ b/site/src/pages/UserSettingsPage/SSHKeysPage/SSHKeysPageView.stories.tsx @@ -1,4 +1,5 @@ import { Story } from "@storybook/react" +import { makeMockApiError } from "testHelpers/entities" import { SSHKeysPageView, SSHKeysPageViewProps } from "./SSHKeysPageView" export default { @@ -38,25 +39,15 @@ export const WithGetSSHKeyError = Template.bind({}) WithGetSSHKeyError.args = { ...Example.args, hasLoaded: false, - getSSHKeyError: { - response: { - data: { - message: "Failed to get SSH key", - }, - }, - isAxiosError: true, - }, + getSSHKeyError: makeMockApiError({ + message: "Failed to get SSH key", + }), } export const WithRegenerateSSHKeyError = Template.bind({}) WithRegenerateSSHKeyError.args = { ...Example.args, - regenerateSSHKeyError: { - response: { - data: { - message: "Failed to regenerate SSH key", - }, - }, - isAxiosError: true, - }, + regenerateSSHKeyError: makeMockApiError({ + message: "Failed to regenerate SSH key", + }), }