mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 13:35:42 +09:00
166 lines
4.9 KiB
TypeScript
166 lines
4.9 KiB
TypeScript
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
import {afterAll, beforeAll, beforeEach, describe, expect, it} from 'vitest';
|
|
import type {ApiTestHarness} from '../../test/ApiTestHarness';
|
|
import {createBuilder, createBuilderWithoutAuth} from '../../test/TestRequestBuilder';
|
|
import {createAuthHarness, createTestAccount, createUniqueEmail, createUniqueUsername} from './AuthTestUtils';
|
|
|
|
interface ValidationErrorResponse {
|
|
code: string;
|
|
message: string;
|
|
errors?: Array<{
|
|
path: string;
|
|
code: string;
|
|
message: string;
|
|
}>;
|
|
}
|
|
|
|
describe('Registration validation', () => {
|
|
let harness: ApiTestHarness;
|
|
beforeAll(async () => {
|
|
harness = await createAuthHarness();
|
|
});
|
|
beforeEach(async () => {
|
|
await harness.reset();
|
|
});
|
|
afterAll(async () => {
|
|
await harness?.shutdown();
|
|
});
|
|
it('rejects invalid email format', async () => {
|
|
const json = await createBuilderWithoutAuth<ValidationErrorResponse>(harness)
|
|
.post('/auth/register')
|
|
.header('accept-language', 'fr')
|
|
.body({
|
|
email: 'not-an-email',
|
|
username: createUniqueUsername(),
|
|
global_name: 'Test User',
|
|
password: 'a-strong-password',
|
|
date_of_birth: '2000-01-01',
|
|
consent: true,
|
|
})
|
|
.expect(400, 'INVALID_FORM_BODY')
|
|
.execute();
|
|
const emailError = json.errors?.find((e) => e.path === 'email');
|
|
expect(emailError?.code).toBe('INVALID_EMAIL_FORMAT');
|
|
expect(emailError?.message).toBe("Format d'adresse e-mail invalide.");
|
|
});
|
|
it('rejects blocked registration email TLDs as invalid email', async () => {
|
|
await createBuilderWithoutAuth(harness)
|
|
.post('/auth/register')
|
|
.body({
|
|
email: '[email protected]',
|
|
username: createUniqueUsername(),
|
|
global_name: 'Test User',
|
|
password: 'a-strong-password',
|
|
date_of_birth: '2000-01-01',
|
|
consent: true,
|
|
})
|
|
.expect(400)
|
|
.execute();
|
|
});
|
|
it('rejects weak password', async () => {
|
|
const json = await createBuilderWithoutAuth<ValidationErrorResponse>(harness)
|
|
.post('/auth/register')
|
|
.body({
|
|
email: createUniqueEmail(),
|
|
username: createUniqueUsername(),
|
|
global_name: 'Test User',
|
|
password: 'weak',
|
|
date_of_birth: '2000-01-01',
|
|
consent: true,
|
|
})
|
|
.expect(400, 'INVALID_FORM_BODY')
|
|
.execute();
|
|
const passwordError = json.errors?.find((e) => e.path === 'password');
|
|
expect(passwordError?.code).toBe('PASSWORD_LENGTH_INVALID');
|
|
expect(passwordError?.message).toBe('String length must be between 8 and 256 characters.');
|
|
});
|
|
it('includes bounds in username length validation message', async () => {
|
|
const json = await createBuilderWithoutAuth<ValidationErrorResponse>(harness)
|
|
.post('/auth/register')
|
|
.body({
|
|
email: createUniqueEmail(),
|
|
username: 'a'.repeat(33),
|
|
global_name: 'Test User',
|
|
password: 'a-strong-password',
|
|
date_of_birth: '2000-01-01',
|
|
consent: true,
|
|
})
|
|
.expect(400, 'INVALID_FORM_BODY')
|
|
.execute();
|
|
const usernameError = json.errors?.find((e) => e.path === 'username');
|
|
expect(usernameError?.code).toBe('USERNAME_LENGTH_INVALID');
|
|
expect(usernameError?.message).toBe('Username must be between 1 and 32 characters.');
|
|
});
|
|
it('rejects duplicate email', async () => {
|
|
const account = await createTestAccount(harness);
|
|
await createBuilderWithoutAuth(harness)
|
|
.post('/auth/register')
|
|
.body({
|
|
email: account.email,
|
|
username: createUniqueUsername(),
|
|
global_name: 'Test User',
|
|
password: 'a-strong-password',
|
|
date_of_birth: '2000-01-01',
|
|
consent: true,
|
|
})
|
|
.expect(400, 'INVALID_FORM_BODY')
|
|
.execute();
|
|
});
|
|
it('rejects missing date of birth', async () => {
|
|
await createBuilderWithoutAuth(harness)
|
|
.post('/auth/register')
|
|
.body({
|
|
email: createUniqueEmail(),
|
|
username: createUniqueUsername(),
|
|
global_name: 'Test User',
|
|
password: 'a-strong-password',
|
|
consent: true,
|
|
})
|
|
.expect(400)
|
|
.execute();
|
|
});
|
|
it('allows emoji in global name', async () => {
|
|
const globalName = '🌻 Sunflower';
|
|
const reg = await createBuilderWithoutAuth<{
|
|
token: string;
|
|
}>(harness)
|
|
.post('/auth/register')
|
|
.body({
|
|
email: createUniqueEmail('emoji'),
|
|
username: createUniqueUsername('emoji'),
|
|
global_name: globalName,
|
|
password: 'a-strong-password',
|
|
date_of_birth: '2000-01-01',
|
|
consent: true,
|
|
})
|
|
.execute();
|
|
const me = await createBuilder<{
|
|
global_name: string;
|
|
}>(harness, reg.token)
|
|
.get('/users/@me')
|
|
.execute();
|
|
expect(me.global_name).toBe(globalName);
|
|
});
|
|
it('derives username from global name when username is not provided', async () => {
|
|
const reg = await createBuilderWithoutAuth<{
|
|
token: string;
|
|
}>(harness)
|
|
.post('/auth/register')
|
|
.body({
|
|
email: createUniqueEmail('derived'),
|
|
global_name: 'Magic Tester',
|
|
password: 'a-strong-password',
|
|
date_of_birth: '2000-01-01',
|
|
consent: true,
|
|
})
|
|
.execute();
|
|
const me = await createBuilder<{
|
|
username: string;
|
|
}>(harness, reg.token)
|
|
.get('/users/@me')
|
|
.execute();
|
|
expect(me.username).toBe('Magic_Tester');
|
|
});
|
|
});
|