import { test, describe, beforeEach, afterEach } from 'node:test'; import { strict as assert } from 'node:assert'; import { createMockDOM, cleanupMockDOM, createMockFetch } from '../utils/test-helpers.js'; import { readFileSync } from 'fs'; import path from 'path'; describe('EnvConfig - Tests Unitaires', () => { let EnvConfig; beforeEach(() => { createMockDOM(); // Charger le module EnvConfig const envConfigPath = path.resolve(process.cwd(), '../js/core/env-config.js'); const code = readFileSync(envConfigPath, 'utf8'); // Adapter le code pour l'environnement de test const testCode = code .replace(/window\./g, 'global.') .replace(/typeof window !== 'undefined'/g, 'true') .replace(/typeof module !== 'undefined' && module\.exports/g, 'false'); eval(testCode); EnvConfig = global.EnvConfig; }); afterEach(() => { cleanupMockDOM(); }); describe('Construction et configuration', () => { test('devrait créer une instance EnvConfig avec configuration par défaut', () => { const config = new EnvConfig(); assert.ok(config instanceof EnvConfig); assert.equal(config.get('DO_ENDPOINT'), 'https://autocollant.fra1.digitaloceanspaces.com'); assert.equal(config.get('DO_CONTENT_PATH'), 'Class_generator/ContentMe'); assert.equal(config.get('USE_REMOTE_CONTENT'), true); assert.equal(config.get('DEBUG_MODE'), true); }); test('devrait construire l\'URL de contenu distant correctement', () => { const config = new EnvConfig(); const expectedUrl = 'https://autocollant.fra1.digitaloceanspaces.com/Class_generator/ContentMe/'; assert.equal(config.getRemoteContentUrl(), expectedUrl); }); test('devrait permettre de modifier la configuration', () => { const config = new EnvConfig(); config.set('DEBUG_MODE', false); config.set('REMOTE_TIMEOUT', 5000); assert.equal(config.get('DEBUG_MODE'), false); assert.equal(config.get('REMOTE_TIMEOUT'), 5000); }); test('devrait reconstruire l\'URL lors du changement d\'endpoint', () => { const config = new EnvConfig(); const newEndpoint = 'https://new-endpoint.com'; config.set('DO_ENDPOINT', newEndpoint); assert.ok(config.getRemoteContentUrl().includes('new-endpoint.com')); }); }); describe('Méthodes utilitaires', () => { test('isRemoteContentEnabled devrait retourner la bonne valeur', () => { const config = new EnvConfig(); assert.equal(config.isRemoteContentEnabled(), true); config.set('USE_REMOTE_CONTENT', false); assert.equal(config.isRemoteContentEnabled(), false); }); test('isFallbackEnabled devrait retourner la bonne valeur', () => { const config = new EnvConfig(); assert.equal(config.isFallbackEnabled(), true); config.set('FALLBACK_TO_LOCAL', false); assert.equal(config.isFallbackEnabled(), false); }); test('isDebugMode devrait retourner la bonne valeur', () => { const config = new EnvConfig(); assert.equal(config.isDebugMode(), true); config.set('DEBUG_MODE', false); assert.equal(config.isDebugMode(), false); }); test('shouldLogContentLoading devrait retourner la bonne valeur', () => { const config = new EnvConfig(); assert.equal(config.shouldLogContentLoading(), true); config.set('LOG_CONTENT_LOADING', false); assert.equal(config.shouldLogContentLoading(), false); }); }); describe('Test de connectivité', () => { test('testRemoteConnection devrait réussir avec une réponse 200', async () => { const config = new EnvConfig(); // Mock fetch pour simuler une connexion réussie global.fetch = createMockFetch({ 'http://localhost:8083/do-proxy/english-class-demo.json': { ok: true, status: 200, data: { test: 'data' } } }); const result = await config.testRemoteConnection(); assert.equal(result.success, true); assert.equal(result.status, 200); assert.ok(result.url.includes('localhost:8083')); }); test('testRemoteConnection devrait gérer les erreurs 403', async () => { const config = new EnvConfig(); global.fetch = createMockFetch({ 'http://localhost:8083/do-proxy/english-class-demo.json': { ok: false, status: 403, data: { error: 'Forbidden' } } }); const result = await config.testRemoteConnection(); assert.equal(result.success, true); // 403 considéré comme succès (connexion OK mais privé) assert.equal(result.status, 403); assert.equal(result.isPrivate, true); }); test('testRemoteConnection devrait gérer les timeouts', async () => { const config = new EnvConfig(); config.set('REMOTE_TIMEOUT', 10); // Timeout très court global.fetch = async () => { await new Promise(resolve => setTimeout(resolve, 50)); // Plus long que le timeout return { ok: true }; }; const result = await config.testRemoteConnection(); assert.equal(result.success, false); assert.equal(result.isTimeout, true); }); test('testRemoteConnection devrait gérer les erreurs réseau', async () => { const config = new EnvConfig(); global.fetch = async () => { throw new Error('Network error'); }; const result = await config.testRemoteConnection(); assert.equal(result.success, false); assert.ok(result.error.includes('Network error')); }); }); describe('Configuration dynamique', () => { test('updateRemoteConfig devrait mettre à jour endpoint et path', () => { const config = new EnvConfig(); const newEndpoint = 'https://new-server.com'; const newPath = 'new/content/path'; config.updateRemoteConfig(newEndpoint, newPath); assert.equal(config.get('DO_ENDPOINT'), newEndpoint); assert.equal(config.get('DO_CONTENT_PATH'), newPath); assert.ok(config.getRemoteContentUrl().includes('new-server.com')); assert.ok(config.getRemoteContentUrl().includes('new/content/path')); }); }); describe('Diagnostics', () => { test('getDiagnostics devrait retourner toutes les informations', () => { const config = new EnvConfig(); const diagnostics = config.getDiagnostics(); assert.ok(diagnostics.remoteContentUrl); assert.equal(typeof diagnostics.remoteEnabled, 'boolean'); assert.equal(typeof diagnostics.fallbackEnabled, 'boolean'); assert.equal(typeof diagnostics.debugMode, 'boolean'); assert.ok(diagnostics.endpoint); assert.ok(diagnostics.contentPath); assert.ok(diagnostics.timestamp); }); }); describe('AWS Signature V4', () => { test('generateAWSSignature devrait créer les headers d\'authentification', async () => { const config = new EnvConfig(); // Mock crypto.subtle pour les tests global.crypto = { subtle: { digest: async (algorithm, data) => { return new ArrayBuffer(32); // Mock hash }, importKey: async () => ({}), sign: async () => new ArrayBuffer(32) } }; global.TextEncoder = class { encode(text) { return new Uint8Array(Buffer.from(text)); } }; const headers = await config.generateAWSSignature('GET', 'https://test.com/file.json'); assert.ok(headers.Authorization); assert.ok(headers['X-Amz-Date']); assert.ok(headers['X-Amz-Content-Sha256']); assert.ok(headers.Authorization.includes('AWS4-HMAC-SHA256')); }); test('getAuthHeaders devrait retourner headers vides si pas de clés', async () => { const config = new EnvConfig(); config.set('DO_ACCESS_KEY', ''); config.set('DO_SECRET_KEY', ''); const headers = await config.getAuthHeaders(); assert.equal(Object.keys(headers).length, 0); }); }); });