Add comprehensive tests for profile-redirect and auth features

19 new tests across 5 test files covering the protected layout redirect,
account page load, registration action (documenting the redirect bug),
and login/register component rendering. Includes shared test utilities.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
NeilClack
2026-02-24 08:58:01 -06:00
co-authored by Claude Opus 4.6
parent b8d1ba11e7
commit 10fd06887f
6 changed files with 370 additions and 0 deletions
@@ -0,0 +1,46 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { isHttpError } from '@sveltejs/kit';
import { createLocals, mockUser, mockUserWithProfile } from '$lib/test-utils';
vi.mock('$lib/db', () => ({
prisma: {
user: {
findUnique: vi.fn()
}
}
}));
import { prisma } from '$lib/db';
import { load } from './+page.server';
const findUnique = prisma.user.findUnique as ReturnType<typeof vi.fn>;
describe('(protected)/account page server load', () => {
beforeEach(() => {
findUnique.mockReset();
});
it('throws 403 when locals.user is undefined', async () => {
findUnique.mockResolvedValue(null);
const err = await Promise.resolve(load({ locals: createLocals() } as any)).catch((e: unknown) => e);
expect(isHttpError(err, 403)).toBe(true);
});
it('throws 403 when user is not found in the database', async () => {
findUnique.mockResolvedValue(null);
const locals = createLocals(mockUser() as any);
const err = await Promise.resolve(load({ locals } as any)).catch((e: unknown) => e);
expect(isHttpError(err, 403)).toBe(true);
});
it('returns user with profile when found', async () => {
const user = mockUserWithProfile();
findUnique.mockResolvedValue(user);
const locals = createLocals(mockUser() as any);
const result = (await load({ locals } as any)) as any;
expect(result.user).toEqual(user);
});
});
@@ -0,0 +1,67 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { isHttpError, isRedirect } from '@sveltejs/kit';
import { createLocals, mockUser, mockUserWithProfile } from '$lib/test-utils';
// Mock the database module — must be at the top level for vi.mock hoisting.
vi.mock('$lib/db', () => ({
prisma: {
user: {
findUnique: vi.fn()
}
}
}));
// Import *after* the mock so we get the mocked version.
import { prisma } from '$lib/db';
import { load } from './+layout.server';
const findUnique = prisma.user.findUnique as ReturnType<typeof vi.fn>;
describe('(protected) layout server load', () => {
beforeEach(() => {
findUnique.mockReset();
});
it('throws 403 when locals.user is undefined', async () => {
findUnique.mockResolvedValue(null);
const err = await Promise.resolve(load({ locals: createLocals() } as any)).catch((e: unknown) => e);
expect(isHttpError(err, 403)).toBe(true);
});
it('throws 403 when user is not found in the database', async () => {
findUnique.mockResolvedValue(null);
const locals = createLocals(mockUser() as any);
const err = await Promise.resolve(load({ locals } as any)).catch((e: unknown) => e);
expect(isHttpError(err, 403)).toBe(true);
});
it('redirects to /account/setup when user has no profile', async () => {
findUnique.mockResolvedValue({ id: 'user-1', roleId: null, profile: null });
const locals = createLocals(mockUser() as any);
const err = await Promise.resolve(load({ locals } as any)).catch((e: unknown) => e);
expect(isRedirect(err)).toBe(true);
if (isRedirect(err)) {
expect(err.status).toBe(303);
expect(err.location).toBe('/account/setup');
}
});
it('returns userRoleId when user has a profile', async () => {
findUnique.mockResolvedValue(mockUserWithProfile({ roleId: 2 }));
const locals = createLocals(mockUser() as any);
const result = await load({ locals } as any);
expect(result).toEqual({ userRoleId: 2 });
});
it('returns userRoleId as null when user has no role', async () => {
findUnique.mockResolvedValue(mockUserWithProfile({ roleId: null }));
const locals = createLocals(mockUser() as any);
const result = await load({ locals } as any);
expect(result).toEqual({ userRoleId: null });
});
});