Files
Classeo/frontend/tests/unit/lib/api/config.test.ts
Mathias STRASSER fdc26eb334 test: Ajouter les tests unitaires manquants (backend et frontend)
Couverture des processors (RefreshToken, RequestPasswordReset,
ResetPassword, SwitchRole, UpdateUserRoles), des query handlers
(HasGradesInPeriod, HasStudentsInClass), des messaging handlers
(SendActivationConfirmation, SendPasswordResetEmail), et côté
frontend des modules auth, roles, monitoring, types et E2E tokens.
2026-02-15 19:29:09 +01:00

169 lines
4.6 KiB
TypeScript

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
/**
* Unit tests for the API config module (config.ts).
*
* Tests getApiBaseUrl() and getCurrentTenant() which depend on:
* - $app/environment (browser flag)
* - $env/dynamic/public (environment variables)
* - window.location (hostname, protocol)
*/
// Mutable env object so we can change values per-test
const mockEnv: Record<string, string | undefined> = {};
// Mock $app/environment - default to browser=true
let mockBrowser = true;
vi.mock('$app/environment', () => ({
get browser() {
return mockBrowser;
}
}));
// Mock $env/dynamic/public
vi.mock('$env/dynamic/public', () => ({
env: new Proxy(mockEnv, {
get(target, prop: string) {
return target[prop];
}
})
}));
describe('API config', () => {
let configModule: typeof import('$lib/api/config');
beforeEach(async () => {
// Reset env between tests
Object.keys(mockEnv).forEach((key) => delete mockEnv[key]);
mockBrowser = true;
// Reset modules to get a fresh import
vi.resetModules();
configModule = await import('$lib/api/config');
});
afterEach(() => {
vi.restoreAllMocks();
});
// ==========================================================================
// getApiBaseUrl
// ==========================================================================
describe('getApiBaseUrl', () => {
it('should return protocol://hostname:port/api when in browser with PUBLIC_API_PORT', () => {
mockBrowser = true;
mockEnv['PUBLIC_API_PORT'] = '18000';
// jsdom provides window.location - set it for the test
// Default jsdom location is http://localhost, so we work with that
const result = configModule.getApiBaseUrl();
expect(result).toBe(`${window.location.protocol}//${window.location.hostname}:18000/api`);
});
it('should return /api when in browser without PUBLIC_API_PORT', () => {
mockBrowser = true;
// PUBLIC_API_PORT is not set (undefined)
const result = configModule.getApiBaseUrl();
expect(result).toBe('/api');
});
it('should return PUBLIC_API_URL when in SSR and PUBLIC_API_URL is set', () => {
mockBrowser = false;
mockEnv['PUBLIC_API_URL'] = 'https://api.classeo.fr/api';
const result = configModule.getApiBaseUrl();
expect(result).toBe('https://api.classeo.fr/api');
});
it('should return http://php:8000/api as SSR fallback', () => {
mockBrowser = false;
// PUBLIC_API_URL is not set
const result = configModule.getApiBaseUrl();
expect(result).toBe('http://php:8000/api');
});
});
// ==========================================================================
// getCurrentTenant
// ==========================================================================
describe('getCurrentTenant', () => {
it('should return null when not in browser', () => {
mockBrowser = false;
const result = configModule.getCurrentTenant();
expect(result).toBeNull();
});
it('should extract subdomain correctly from hostname', () => {
mockBrowser = true;
mockEnv['PUBLIC_BASE_DOMAIN'] = 'classeo.local';
// Override window.location.hostname for this test
// jsdom default is "localhost" which won't match "classeo.local"
// We need to use Object.defineProperty since location is readonly
const originalHostname = window.location.hostname;
Object.defineProperty(window, 'location', {
value: { ...window.location, hostname: 'ecole-alpha.classeo.local' },
writable: true
});
const result = configModule.getCurrentTenant();
expect(result).toBe('ecole-alpha');
// Restore
Object.defineProperty(window, 'location', {
value: { ...window.location, hostname: originalHostname },
writable: true
});
});
it('should return null for www subdomain', () => {
mockBrowser = true;
mockEnv['PUBLIC_BASE_DOMAIN'] = 'classeo.fr';
Object.defineProperty(window, 'location', {
value: { ...window.location, hostname: 'www.classeo.fr' },
writable: true
});
const result = configModule.getCurrentTenant();
expect(result).toBeNull();
// Restore
Object.defineProperty(window, 'location', {
value: { ...window.location, hostname: 'localhost' },
writable: true
});
});
it('should return null when hostname does not match base domain', () => {
mockBrowser = true;
mockEnv['PUBLIC_BASE_DOMAIN'] = 'classeo.fr';
Object.defineProperty(window, 'location', {
value: { ...window.location, hostname: 'other-domain.com' },
writable: true
});
const result = configModule.getCurrentTenant();
expect(result).toBeNull();
// Restore
Object.defineProperty(window, 'location', {
value: { ...window.location, hostname: 'localhost' },
writable: true
});
});
});
});