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);
});
});
});