|
|
@@ -0,0 +1,52 @@
|
|
|
+import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
+import { render, type RenderResult } from 'vitest-browser-react'
|
|
|
+import { userEvent, type Locator } from 'vitest/browser'
|
|
|
+import { ForgotPasswordForm } from './forgot-password-form'
|
|
|
+
|
|
|
+const navigateMock = vi.fn()
|
|
|
+
|
|
|
+vi.mock('@tanstack/react-router', async (orig) => {
|
|
|
+ const actual = await orig<typeof import('@tanstack/react-router')>()
|
|
|
+ return { ...actual, useNavigate: () => navigateMock }
|
|
|
+})
|
|
|
+
|
|
|
+vi.mock('@/lib/utils', async (orig) => ({
|
|
|
+ ...(await orig()),
|
|
|
+ sleep: vi.fn(() => Promise.resolve()),
|
|
|
+}))
|
|
|
+
|
|
|
+describe('ForgotPasswordForm', () => {
|
|
|
+ let screen: RenderResult
|
|
|
+ let emailInput: Locator
|
|
|
+ let continueButton: Locator
|
|
|
+
|
|
|
+ beforeEach(async () => {
|
|
|
+ vi.clearAllMocks()
|
|
|
+
|
|
|
+ screen = await render(<ForgotPasswordForm />)
|
|
|
+ emailInput = screen.getByRole('textbox', { name: /^Email$/i })
|
|
|
+ continueButton = screen.getByRole('button', { name: /^Continue$/i })
|
|
|
+ })
|
|
|
+
|
|
|
+ it('renders email field and continue button', async () => {
|
|
|
+ expect(emailInput).toBeInTheDocument()
|
|
|
+ expect(continueButton).toBeInTheDocument()
|
|
|
+ })
|
|
|
+
|
|
|
+ it('shows validation when submitting empty form', async () => {
|
|
|
+ await userEvent.click(continueButton)
|
|
|
+ expect(screen.getByText(/^Please enter your email\.$/i)).toBeInTheDocument()
|
|
|
+ })
|
|
|
+
|
|
|
+ it('resets the form and navigates to /otp on success', async () => {
|
|
|
+ await userEvent.fill(emailInput, 'a@b.com')
|
|
|
+ await userEvent.click(continueButton)
|
|
|
+
|
|
|
+ await vi.waitFor(() =>
|
|
|
+ expect(navigateMock).toHaveBeenCalledWith({ to: '/otp' })
|
|
|
+ )
|
|
|
+
|
|
|
+ // Form should reset on success
|
|
|
+ expect(emailInput).toHaveValue('')
|
|
|
+ })
|
|
|
+})
|