Continuous Integration / config (pull_request) Successful in 11s
Continuous Integration / changes (pull_request) Successful in 21s
Continuous Integration / backend-build (pull_request) Skipped
Continuous Integration / backend-test (pull_request) Skipped
Continuous Integration / vulnerability-scan (pull_request) Skipped
Continuous Integration / frontend-prepare (pull_request) Successful in 1m37s
Continuous Integration / frontend-build (pull_request) Successful in 2m12s
Continuous Integration / frontend-test (pull_request) Successful in 4m42s
Continuous Integration / frontend-lint (pull_request) Successful in 2m2s
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped
Continuous Integration / publish-test (pull_request) Successful in 6m51s
Continuous Integration / deploy-test (pull_request) Skipped
Groups auth, setup, invitation, profile, users, cms, availability and system code (services/hooks, components, schemas, mocks, pages) under src/features/<name> instead of splitting by technical layer (api/, components/, lib/schemas/, mocks/, pages/). Renames the old connection-oriented `api` layer to `services` per feature, and splits the monolithic api/types.ts into per-feature types.ts files (with ProblemDetails/ApiResult merged into lib/api-client.ts as shared infra). Layout-agnostic code (ui primitives, app shell, i18n, test utils, lib) stays at the top level. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
123 lines
3.9 KiB
TypeScript
123 lines
3.9 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
passwordSchema,
|
|
setupFormSchema,
|
|
loginFormSchema,
|
|
invitationCompleteFormSchema,
|
|
} from '@/features/auth/schemas/auth';
|
|
|
|
describe('passwordSchema', () => {
|
|
it('accepts a valid password', () => {
|
|
expect(passwordSchema.safeParse('Password1!').success).toBe(true);
|
|
});
|
|
|
|
it('rejects a password that is too short', () => {
|
|
expect(passwordSchema.safeParse('Pass1!').success).toBe(false);
|
|
});
|
|
|
|
it('rejects a password without an uppercase letter', () => {
|
|
expect(passwordSchema.safeParse('password1!').success).toBe(false);
|
|
});
|
|
|
|
it('rejects a password without a digit', () => {
|
|
expect(passwordSchema.safeParse('Password!').success).toBe(false);
|
|
});
|
|
|
|
it('rejects a password without a special character', () => {
|
|
expect(passwordSchema.safeParse('Password1').success).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('setupFormSchema', () => {
|
|
const valid = {
|
|
name: 'Admin',
|
|
email: 'admin@example.com',
|
|
password: 'Password1!',
|
|
confirmPassword: 'Password1!',
|
|
language: 'nl' as const,
|
|
};
|
|
|
|
it('accepts valid setup data', () => {
|
|
expect(setupFormSchema.safeParse(valid).success).toBe(true);
|
|
});
|
|
|
|
it('rejects when passwords do not match', () => {
|
|
const result = setupFormSchema.safeParse({ ...valid, confirmPassword: 'Different1!' });
|
|
expect(result.success).toBe(false);
|
|
});
|
|
|
|
it('rejects empty name', () => {
|
|
expect(setupFormSchema.safeParse({ ...valid, name: '' }).success).toBe(false);
|
|
});
|
|
|
|
it('rejects name exceeding 255 characters', () => {
|
|
expect(setupFormSchema.safeParse({ ...valid, name: 'a'.repeat(256) }).success).toBe(false);
|
|
});
|
|
|
|
it('rejects invalid email format', () => {
|
|
expect(setupFormSchema.safeParse({ ...valid, email: 'not-an-email' }).success).toBe(false);
|
|
});
|
|
|
|
it('rejects empty email', () => {
|
|
expect(setupFormSchema.safeParse({ ...valid, email: '' }).success).toBe(false);
|
|
});
|
|
|
|
it('rejects invalid language', () => {
|
|
expect(setupFormSchema.safeParse({ ...valid, language: 'fr' }).success).toBe(false);
|
|
});
|
|
|
|
it('accepts "en" as language', () => {
|
|
expect(setupFormSchema.safeParse({ ...valid, language: 'en' }).success).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe('loginFormSchema', () => {
|
|
it('accepts valid login credentials', () => {
|
|
expect(loginFormSchema.safeParse({ email: 'user@example.com', password: 'anypass' }).success).toBe(true);
|
|
});
|
|
|
|
it('rejects empty email', () => {
|
|
expect(loginFormSchema.safeParse({ email: '', password: 'pass' }).success).toBe(false);
|
|
});
|
|
|
|
it('rejects invalid email format', () => {
|
|
expect(loginFormSchema.safeParse({ email: 'not-email', password: 'pass' }).success).toBe(false);
|
|
});
|
|
|
|
it('rejects empty password', () => {
|
|
expect(loginFormSchema.safeParse({ email: 'user@example.com', password: '' }).success).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('invitationCompleteFormSchema', () => {
|
|
const valid = {
|
|
name: 'New User',
|
|
password: 'Password1!',
|
|
confirmPassword: 'Password1!',
|
|
};
|
|
|
|
it('accepts valid invitation completion data', () => {
|
|
expect(invitationCompleteFormSchema.safeParse(valid).success).toBe(true);
|
|
});
|
|
|
|
it('rejects when passwords do not match', () => {
|
|
expect(
|
|
invitationCompleteFormSchema.safeParse({ ...valid, confirmPassword: 'Different1!' }).success,
|
|
).toBe(false);
|
|
});
|
|
|
|
it('rejects empty name', () => {
|
|
expect(invitationCompleteFormSchema.safeParse({ ...valid, name: '' }).success).toBe(false);
|
|
});
|
|
|
|
it('rejects weak password', () => {
|
|
expect(
|
|
invitationCompleteFormSchema.safeParse({
|
|
...valid,
|
|
password: 'weak',
|
|
confirmPassword: 'weak',
|
|
}).success,
|
|
).toBe(false);
|
|
});
|
|
});
|