diff --git a/apps/next/src/app/(auth)/forgot-password/page.tsx b/apps/next/src/app/(auth)/forgot-password/page.tsx
index ec9c61f..fe56805 100644
--- a/apps/next/src/app/(auth)/forgot-password/page.tsx
+++ b/apps/next/src/app/(auth)/forgot-password/page.tsx
@@ -100,12 +100,14 @@ const ForgotPassword = () => {
await signIn('password', formData).then(() => {
setEmail(values.email);
setFlow('reset-verification');
+ // Only clear the form once the request succeeded; a failed request
+ // keeps the typed email so the user can retry without re-entering it.
+ forgotPasswordForm.reset();
});
} catch (error) {
console.error('Error resetting password: ', error);
toast.error('Error resetting password.');
} finally {
- forgotPasswordForm.reset();
setLoading(false);
}
};
@@ -121,12 +123,14 @@ const ForgotPassword = () => {
setLoading(true);
try {
await signIn('password', formData);
+ // Only clear on success (navigation follows); a failed submit keeps the
+ // entered password so the user can correct and retry.
+ resetVerificationForm.reset();
router.push('/');
} catch (error) {
console.error('Error resetting password: ', error);
toast.error('Error resetting password.');
} finally {
- resetVerificationForm.reset();
setLoading(false);
}
};
@@ -230,7 +234,7 @@ const ForgotPassword = () => {
Please enter the one-time password sent to your
- phone.
+ email.
@@ -265,7 +269,7 @@ const ForgotPassword = () => {
render={({ field }) => (
- Confirm Passsword
+ Confirm Password
{
formData.append('flow', flow);
setLoading(true);
try {
- await signIn('password', formData).then(() => router.push('/dashboard'));
+ await signIn('password', formData).then(() => {
+ signInForm.reset();
+ router.push('/dashboard');
+ });
} catch (error) {
console.error('Error signing in:', error);
toast.error('Error signing in.');
} finally {
- signInForm.reset();
setLoading(false);
}
};
@@ -153,6 +155,7 @@ const SignIn = () => {
if (values.confirmPassword !== values.password)
throw new ConvexError('Passwords do not match.');
await signIn('password', formData).then(() => {
+ signUpForm.reset();
setEmail(values.email);
setFlow('email-verification');
});
@@ -160,7 +163,6 @@ const SignIn = () => {
console.error('Error signing up:', error);
toast.error('Error signing up.');
} finally {
- signUpForm.reset();
setLoading(false);
}
};
@@ -174,12 +176,14 @@ const SignIn = () => {
formData.append('email', email);
setLoading(true);
try {
- await signIn('password', formData).then(() => router.push('/dashboard'));
+ await signIn('password', formData).then(() => {
+ verifyEmailForm.reset();
+ router.push('/dashboard');
+ });
} catch (error) {
console.error('Error verifying email:', error);
toast.error('Error verifying email.');
} finally {
- verifyEmailForm.reset();
setLoading(false);
}
};
@@ -232,7 +236,7 @@ const SignIn = () => {
/>
Verify Email
@@ -423,7 +427,7 @@ const SignIn = () => {
render={({ field }) => (
- Confirm Passsword
+ Confirm Password
({
+ mockSignIn: vi.fn(),
+ mockToastError: vi.fn(),
+}));
+
+vi.mock('@convex-dev/auth/react', () => ({
+ useAuthActions: () => ({ signIn: mockSignIn }),
+}));
+
+vi.mock('next/navigation', () => ({
+ useRouter: () => ({ push: vi.fn(), replace: vi.fn() }),
+}));
+
+vi.mock('sonner', () => ({
+ toast: {
+ error: mockToastError,
+ success: vi.fn(),
+ },
+}));
+
+describe('sign-in input retention', () => {
+ it('keeps the typed email and password after a failed sign-in', async () => {
+ mockSignIn.mockRejectedValue(new Error('Invalid credentials'));
+
+ render();
+
+ const emailInput = screen.getByPlaceholderText('you@example.com');
+ const passwordInput = screen.getByPlaceholderText('Your password');
+
+ fireEvent.change(emailInput, {
+ target: { value: 'person@example.com' },
+ });
+ fireEvent.change(passwordInput, { target: { value: 'Sup3rSecret!' } });
+
+ fireEvent.click(screen.getByRole('button', { name: 'Sign In' }));
+
+ await waitFor(() => expect(mockToastError).toHaveBeenCalled());
+
+ await waitFor(() => {
+ expect(emailInput).toHaveValue('person@example.com');
+ expect(passwordInput).toHaveValue('Sup3rSecret!');
+ });
+ });
+});