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('<script>alert("xss")</script>')).toBe('&lt;script&gt;alert(&quot;xss&quot;)&lt;/script&gt;');
    });

    it('échappe les attributs HTML', () => {
      expect(esc('" onmouseover="alert(1)"')).toBe('&quot; onmouseover=&quot;alert(1)&quot;');
    });

    it('échappe les ampersands', () => {
      expect(esc('a&b')).toBe('a&amp;b');
    });

    it('échappe les chevrons', () => {
      expect(esc('<img>')).toBe('&lt;img&gt;');
    });

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