c5dc3bd256
The +layout.svelte auth guard only treated /login as public, so any unauthenticated visit to /register bounced to /login?returnTo=%2Fregister. The "Register" link on the login page therefore looped back to itself, making the first-user-becomes-admin bootstrap path (handleRegister + CreateUserFirstAdminRace) unreachable in production. Extracted isPublicRoute() into web/src/lib/auth/publicRoutes.ts so the public-route set has one source of truth and is unit-testable. Test file explicitly comment-tags /register as a #376 regression guard. Closes the last gap in user-mgmt umbrella #376. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
34 lines
1.1 KiB
TypeScript
34 lines
1.1 KiB
TypeScript
import { describe, expect, test } from 'vitest';
|
|
import { isPublicRoute } from './publicRoutes';
|
|
|
|
describe('isPublicRoute', () => {
|
|
test('/login is public — login form must render to unauthenticated visitors', () => {
|
|
expect(isPublicRoute('/login')).toBe(true);
|
|
});
|
|
|
|
// Regression guard for #376: /register was previously bounced to /login
|
|
// by the layout guard, breaking bootstrap-admin self-registration on
|
|
// fresh deployments. Do NOT remove /register from the public set unless
|
|
// you have a deliberate replacement (e.g. invite-only landing page).
|
|
test('/register is public — bootstrap admin must reach the form', () => {
|
|
expect(isPublicRoute('/register')).toBe(true);
|
|
});
|
|
|
|
test('/ is gated', () => {
|
|
expect(isPublicRoute('/')).toBe(false);
|
|
});
|
|
|
|
test('/admin/users is gated', () => {
|
|
expect(isPublicRoute('/admin/users')).toBe(false);
|
|
});
|
|
|
|
test('/settings is gated', () => {
|
|
expect(isPublicRoute('/settings')).toBe(false);
|
|
});
|
|
|
|
test('paths that merely start with /login are not public', () => {
|
|
expect(isPublicRoute('/login/extra')).toBe(false);
|
|
expect(isPublicRoute('/loginx')).toBe(false);
|
|
});
|
|
});
|