Skip to content

Commit

Permalink
chore(DIA-942): add tests for auth2 (#11192)
Browse files Browse the repository at this point in the history
* added tests for sign-up password step

* added tests for login password step

* added tests for forgot password step
  • Loading branch information
iskounen authored Nov 26, 2024
1 parent 5510c64 commit b1fd23e
Show file tree
Hide file tree
Showing 9 changed files with 292 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,14 @@ const ForgotPasswordStepForm: React.FC = () => {

{!!requestedPasswordReset ? (
<Text color="blue100" mt={1} variant="sm">
Password reset link set—check your email. Please note, you must wait 5 minutes to
Password reset link sent—check your email. Please note, you must wait 5 minutes to
receive another link.
</Text>
) : (
<>
<Spacer y={2} />
<Input
accessibilityHint="Enter your email address"
autoCapitalize="none"
autoComplete="email"
autoCorrect={false}
Expand Down
3 changes: 3 additions & 0 deletions src/app/Scenes/Onboarding/Auth2/scenes/LoginPasswordStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ const LoginPasswordStepForm: React.FC = () => {
<Text variant="sm-display">Welcome back to Artsy</Text>

<Input
accessibilityHint="Enter your password"
autoCapitalize="none"
autoComplete="password"
importantForAutofill="yes"
Expand Down Expand Up @@ -162,6 +163,7 @@ const LoginPasswordStepForm: React.FC = () => {
onPress={handleSubmit}
disabled={!isValid || !values.password}
loading={isSubmitting}
accessibilityHint="Continue to the next screen"
>
Continue
</Button>
Expand All @@ -181,6 +183,7 @@ const LoginPasswordStepForm: React.FC = () => {
})
resetForm()
}}
accessibilityHint="Go to the sign-up screen"
>
Sign up.
</LinkText>
Expand Down
3 changes: 3 additions & 0 deletions src/app/Scenes/Onboarding/Auth2/scenes/SignUpPasswordStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ const SignUpPasswordStepForm: React.FC = () => {
<Text variant="sm-display">Welcome to Artsy</Text>

<Input
accessibilityHint="Enter your password"
autoCapitalize="none"
autoComplete="password"
autoCorrect={false}
Expand Down Expand Up @@ -118,6 +119,7 @@ const SignUpPasswordStepForm: React.FC = () => {
onPress={handleSubmit}
loading={isSubmitting}
disabled={!isValid || !values.password}
accessibilityHint="Continue to the next screen"
>
Continue
</Button>
Expand All @@ -137,6 +139,7 @@ const SignUpPasswordStepForm: React.FC = () => {
})
resetForm()
}}
accessibilityHint="Go to the login screen"
>
Login.
</LinkText>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { fireEvent, screen, waitFor } from "@testing-library/react-native"
import {
useAuthNavigation,
useAuthScreen,
} from "app/Scenes/Onboarding/Auth2/hooks/useAuthNavigation"
import { ForgotPasswordStep } from "app/Scenes/Onboarding/Auth2/scenes/ForgotPasswordStep"
import { GlobalStore } from "app/store/GlobalStore"
import { renderWithWrappers } from "app/utils/tests/renderWithWrappers"

jest.mock("app/Scenes/Onboarding/Auth2/hooks/useAuthNavigation", () => ({
useAuthNavigation: jest.fn(),
useAuthScreen: jest.fn().mockReturnValue({
params: { email: "[email protected]" },
}),
}))

describe("ForgotPasswordStep", () => {
const mockUseAuthNavigation = useAuthNavigation as jest.Mock
const mockUseAuthScreen = useAuthScreen as jest.Mock

it("disables the 'send reset link' button when the email address is invalid", async () => {
renderWithWrappers(<ForgotPasswordStep />)
expect(screen.getByDisplayValue("[email protected]")).toBeOnTheScreen()
expect(screen.getByText("Send Reset Link")).toBeEnabled()
fireEvent.changeText(screen.getByA11yHint("Enter your email address"), "invalid-email")
await waitFor(() => expect(screen.getByText("Send Reset Link")).toBeDisabled())
})

describe("when a reset link is successfully requested", () => {
beforeEach(() => {
jest.spyOn(GlobalStore.actions.auth, "forgotPassword").mockResolvedValue(true)
mockUseAuthNavigation.mockReturnValue({
/**
* When the user successfully requests a password reset, we add a requestedPasswordReset param
* to the screen so that a confirmation message can be displayed on the next render. This
* simulates that by updating the useAuthScreen mock to return the new params.
*/
setParams: jest.fn().mockImplementation((params) => {
mockUseAuthScreen.mockReturnValue({
params: { ...mockUseAuthScreen().params, ...params },
})
}),
navigate: jest.fn(),
})
})

afterEach(() => {
/**
* Restore the useAuthScreen mock to its default state after each test so that subsequent
* tests don't start on the confirmation screen.
*/
mockUseAuthScreen.mockReturnValue({
params: { email: "[email protected]" },
})
})

it("shows a confirmation message", async () => {
renderWithWrappers(<ForgotPasswordStep />)
fireEvent.press(screen.getByText("Send Reset Link"))
await waitFor(() => expect(screen.queryByA11yHint("Enter your email address")).toBeNull())
expect(
screen.getByText(
"Password reset link sent—check your email. Please note, you must wait 5 minutes to receive another link."
)
).toBeOnTheScreen()
})

it("sends a reset link when the 'send again' button is pressed", async () => {
renderWithWrappers(<ForgotPasswordStep />)
fireEvent.press(screen.getByText("Send Reset Link"))
await waitFor(() => expect(screen.queryByA11yHint("Enter your email address")).toBeNull())
fireEvent.press(screen.getByText("Send Again"))
await waitFor(() => expect(GlobalStore.actions.auth.forgotPassword).toHaveBeenCalledTimes(2))
})

it("returns to the login screen when the 'return to login' button is pressed", async () => {
renderWithWrappers(<ForgotPasswordStep />)
fireEvent.press(screen.getByText("Send Reset Link"))
await waitFor(() => expect(screen.queryByA11yHint("Enter your email address")).toBeNull())
fireEvent.press(screen.getByText("Return to Login"))
await waitFor(() =>
expect(mockUseAuthNavigation().navigate).toHaveBeenCalledWith({
name: "LoginWelcomeStep",
})
)
})
})

it("displays an error message if the reset link could not be sent", async () => {
jest.spyOn(GlobalStore.actions.auth, "forgotPassword").mockResolvedValue(false)
renderWithWrappers(<ForgotPasswordStep />)
fireEvent.press(screen.getByText("Send Reset Link"))
await screen.findByText(
"Couldn't send reset password link. Please try again, or contact [email protected]"
)
})
})

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { fireEvent, screen, waitFor } from "@testing-library/react-native"
import {
useAuthNavigation,
useAuthScreen,
} from "app/Scenes/Onboarding/Auth2/hooks/useAuthNavigation"
import { LoginPasswordStep } from "app/Scenes/Onboarding/Auth2/scenes/LoginPasswordStep"
import { GlobalStore } from "app/store/GlobalStore"
import { renderWithWrappers } from "app/utils/tests/renderWithWrappers"
import { Alert } from "react-native"

jest.mock("app/Scenes/Onboarding/Auth2/hooks/useAuthNavigation")

describe("LoginPasswordStep", () => {
const mockUseAuthNavigation = useAuthNavigation as jest.Mock
const mockUseAuthScreen = useAuthScreen as jest.Mock

beforeEach(() => {
jest.clearAllMocks()
mockUseAuthNavigation.mockReturnValue({
navigate: jest.fn(),
})
mockUseAuthScreen.mockReturnValue({
name: "SignUpPasswordStep",
params: { email: "[email protected]" },
})
})

/**
* GlobalStore.actions.auth.signIn is responsible for taking the user to the home screen when
* login succeeds, so this test will only assert that it was called.
*/
it("calls the global login function", async () => {
jest.spyOn(GlobalStore.actions.auth, "signIn").mockResolvedValue("success")
renderWithWrappers(<LoginPasswordStep />)
fireEvent.changeText(screen.getByA11yHint("Enter your password"), "Password1")
fireEvent.press(screen.getByA11yHint("Continue to the next screen"))
await waitFor(() => expect(GlobalStore.actions.auth.signIn).toHaveBeenCalled())
})

it("shows an error when login fails", async () => {
jest.spyOn(GlobalStore.actions.auth, "signIn").mockResolvedValue("failure")
renderWithWrappers(<LoginPasswordStep />)
fireEvent.changeText(screen.getByA11yHint("Enter your password"), "Password2")
fireEvent.press(screen.getByA11yHint("Continue to the next screen"))
await screen.findByText("Incorrect email or password")
})

it("navigates to the standard OTP step with required", async () => {
jest.spyOn(GlobalStore.actions.auth, "signIn").mockResolvedValue("otp_missing")
renderWithWrappers(<LoginPasswordStep />)
fireEvent.changeText(screen.getByA11yHint("Enter your password"), "Password1")
fireEvent.press(screen.getByA11yHint("Continue to the next screen"))
await waitFor(() =>
expect(mockUseAuthNavigation().navigate).toHaveBeenCalledWith({
name: "LoginOTPStep",
params: { email: "[email protected]", password: "Password1", otpMode: "standard" }, // pragma: allowlist secret
})
)
})

it("navigates to the on-demand OTP step when required", async () => {
jest.spyOn(GlobalStore.actions.auth, "signIn").mockResolvedValue("on_demand_otp_missing")
renderWithWrappers(<LoginPasswordStep />)
fireEvent.changeText(screen.getByA11yHint("Enter your password"), "Password1")
fireEvent.press(screen.getByA11yHint("Continue to the next screen"))
await waitFor(() =>
expect(mockUseAuthNavigation().navigate).toHaveBeenCalledWith({
name: "LoginOTPStep",
params: { email: "[email protected]", password: "Password1", otpMode: "on_demand" }, // pragma: allowlist secret
})
)
})

it("shows an error when auth is blocked", async () => {
jest.spyOn(GlobalStore.actions.auth, "signIn").mockResolvedValue("auth_blocked")
jest.spyOn(Alert, "alert")
renderWithWrappers(<LoginPasswordStep />)
fireEvent.changeText(screen.getByA11yHint("Enter your password"), "Password1")
fireEvent.press(screen.getByA11yHint("Continue to the next screen"))
await waitFor(() =>
expect(Alert.alert).toHaveBeenCalledWith(
"Sign in attempt blocked",
"Please try signing in from a different internet connection or contact [email protected] for help.",
expect.any(Array)
)
)
})

describe("when showLoginLink param is true", () => {
beforeEach(() => {
mockUseAuthScreen.mockReturnValue({
name: "SignUpPasswordStep",
params: {
email: "[email protected]",
showSignUpLink: true,
},
})
})

it("navigates to the sign-up screen when the login link is pressed", () => {
renderWithWrappers(<LoginPasswordStep />)
fireEvent.press(screen.getByA11yHint("Go to the sign-up screen"))
expect(mockUseAuthNavigation().navigate).toHaveBeenCalledWith({
name: "SignUpPasswordStep",
params: { email: "[email protected]", showLoginLink: true },
})
})
})
})

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { fireEvent, screen, waitFor } from "@testing-library/react-native"
import {
useAuthNavigation,
useAuthScreen,
} from "app/Scenes/Onboarding/Auth2/hooks/useAuthNavigation"
import { SignUpPasswordStep } from "app/Scenes/Onboarding/Auth2/scenes/SignUpPasswordStep"
import { renderWithWrappers } from "app/utils/tests/renderWithWrappers"

jest.mock("app/Scenes/Onboarding/Auth2/hooks/useAuthNavigation", () => ({
useAuthNavigation: jest.fn().mockReturnValue({
navigate: jest.fn(),
goBack: jest.fn(),
}),
useAuthScreen: jest.fn().mockReturnValue({
name: "SignUpPasswordStep",
params: {
email: "[email protected]",
},
}),
}))

describe("SignUpPasswordStep", () => {
const mockUseAuthNavigation = useAuthNavigation as jest.Mock
const mockUseAuthScreen = useAuthScreen as jest.Mock

beforeEach(() => {
jest.clearAllMocks()
})

it("navigates to the next step when a valid password is entered", async () => {
renderWithWrappers(<SignUpPasswordStep />)

fireEvent.changeText(screen.getByA11yHint("Enter your password"), "Password1")
fireEvent.press(screen.getByA11yHint("Continue to the next screen"))

await waitFor(() => {
expect(mockUseAuthNavigation().navigate).toHaveBeenCalledWith({
name: "SignUpNameStep",
params: {
email: "[email protected]",
password: "Password1", // pragma: allowlist secret
},
})
})
})

it("navigates back when back button is pressed", () => {
renderWithWrappers(<SignUpPasswordStep />)
fireEvent.press(screen.getByA11yHint("Go back to the previous screen"))
expect(mockUseAuthNavigation().goBack).toHaveBeenCalled()
})

describe("when showLoginLink param is true", () => {
beforeEach(() => {
mockUseAuthScreen.mockReturnValue({
name: "SignUpPasswordStep",
params: {
email: "[email protected]",
showLoginLink: true,
},
})
})

it("displays a login link", () => {
renderWithWrappers(<SignUpPasswordStep />)
expect(screen.getByA11yHint("Go to the login screen")).toBeDefined()
})

it("navigates to the login screen when the login link is pressed", () => {
renderWithWrappers(<SignUpPasswordStep />)
fireEvent.press(screen.getByA11yHint("Go to the login screen"))
expect(mockUseAuthNavigation().navigate).toHaveBeenCalledWith({
name: "LoginPasswordStep",
params: { email: "[email protected]", showSignUpLink: true },
})
})
})
})

0 comments on commit b1fd23e

Please sign in to comment.