Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frontend/src/features/auth/AuthScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ function throttleMinutes(err: unknown): number | null | undefined {
return seconds === null ? null : Math.max(1, Math.ceil(seconds / 60));
}

function LoginForm({ onRegister }: { onRegister: () => void }) {
function LoginForm({ notice = '', onRegister }: { notice?: string; onRegister: () => void }) {
const navigate = useNavigate();
const [params, setParams] = useSearchParams();
const lang = useUIStore((s) => s.lang);
Expand Down
26 changes: 26 additions & 0 deletions frontend/src/features/auth/__tests__/signup.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// user straight back to the login screen. Registration was broken for everyone,
// not in an edge case.

import { AxiosError, AxiosHeaders, type AxiosResponse } from 'axios';
import { describe, expect, it, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
Expand Down Expand Up @@ -48,6 +49,7 @@ vi.mock('../../../hooks/useAuthStore', () => {
});

import { AuthScreen } from '../AuthScreen';
import { authCopy } from '../authStrings';

function renderSignup() {
return render(
Expand Down Expand Up @@ -209,4 +211,28 @@ describe('signing up', () => {
await waitFor(() => expect(navigate).toHaveBeenCalled());
expect(setupMFA).not.toHaveBeenCalled();
});

it('lands on the sign-in form with the reason when enrolment meets an expired token (#893)', async () => {
// The sign-up path is the one that hands its reason UP to AuthScreen, which
// passes it to the sign-in form as `notice` (#872). A merge dropped that prop
// and the sign-in form crashed on render for everyone.
login.mockResolvedValue({ status: 'mfa_enrollment_required', mfa_token: 'enrol-token' });
const response = {
status: 401,
statusText: '',
data: { code: 'TOKEN_EXPIRED' },
headers: {},
config: { headers: new AxiosHeaders() },
} as AxiosResponse;
setupMFA.mockReset();
setupMFA.mockRejectedValueOnce(
new AxiosError('refused', '401', response.config, null, response),
);

renderSignup();
await fillAndSubmit();

expect(await screen.findByTestId('login-password')).toBeInTheDocument();
expect(screen.getByTestId('auth-error')).toHaveTextContent(authCopy('fr').mfaExpired);
});
});
Loading