import { describe, it, expect } from 'vitest'; import { esc } from '@presentation/helpers/format'; describe('Sécurité — Hardening', () => { describe('esc() — sanitisation XSS', () => { it('échappe les balises HTML', () => { expect(esc('')).toBe('<script>alert("xss")</script>'); }); it('échappe les attributs HTML', () => { expect(esc('" onmouseover="alert(1)"')).toBe('" onmouseover="alert(1)"'); }); it('échappe les ampersands', () => { expect(esc('a&b')).toBe('a&b'); }); it('échappe les chevrons', () => { expect(esc('')).toBe('<img>'); }); it('gère les nombres', () => { expect(esc(42)).toBe('42'); }); it('gère les chaînes vides', () => { expect(esc('')).toBe(''); }); it('préserve le texte sans caractères spéciaux', () => { expect(esc('Enclos normal')).toBe('Enclos normal'); }); it('gère les caractères accentués', () => { expect(esc('Dragodinde Émeraude')).toBe('Dragodinde Émeraude'); }); }); describe('Validation URL ntfy — HTTPS requis', () => { it('URL HTTPS est valide', () => { const url = 'https://ntfy.example.com/topic'; const parsed = new URL(url); expect(parsed.protocol).toBe('https:'); }); it('URL HTTP est rejetée', () => { const url = 'http://ntfy.example.com/topic'; const parsed = new URL(url); expect(parsed.protocol).not.toBe('https:'); }); it('URL invalide lève une erreur', () => { expect(() => new URL('not-a-url')).toThrow(); }); }); describe('Validation backup — format métadonnées', () => { it('backup valide contient app, version, exportedAt, data', () => { const backup = { app: 'obsidienne', version: '1.1.6', exportedAt: new Date().toISOString(), data: { enclos: [] }, }; expect(backup.app).toBe('obsidienne'); expect(typeof backup.version).toBe('string'); expect(typeof backup.exportedAt).toBe('string'); expect(backup.data).toBeDefined(); }); it('data: null est détecté comme invalide', () => { const backup = { app: 'obsidienne', data: null }; // typeof null === 'object' mais data === null doit être rejeté expect(backup.data === null).toBe(true); expect(!!(backup.data && typeof backup.data === 'object' && backup.data !== null)).toBe(false); }); }); });