import { describe, expect, it } from 'vitest';
import { HtmlSanitizer, sanitizeHtml } from './html-sanitizer';

describe('HtmlSanitizer', () => {
  describe('basic sanitization', () => {
    it('should remove script tags', () => {
      const sanitizer = new HtmlSanitizer();
      const maliciousHtml = '<div>Hello <script>alert("xss")</script> World</div>';
      const result = sanitizer.sanitize(maliciousHtml);

      expect(result).toBe('<div>Hello  World</div>');
      expect(result).not.toContain('<script>');
    });

    it('should remove dangerous event handlers', () => {
      const sanitizer = new HtmlSanitizer();
      const maliciousHtml = '<div onclick="alert(\'xss\')">Click me</div>';
      const result = sanitizer.sanitize(maliciousHtml);

      expect(result).toBe('<div>Click me</div>');
      expect(result).not.toContain('onclick');
    });

    it('should preserve safe HTML', () => {
      const sanitizer = new HtmlSanitizer();
      const safeHtml = '<div class="container"><p><strong>Bold text</strong> and <em>italic text</em></p></div>';
      const result = sanitizer.sanitize(safeHtml);

      expect(result).toBe(safeHtml);
    });
  });

  describe('configuration options', () => {
    it('should respect allowed tags configuration', () => {
      const sanitizer = new HtmlSanitizer({
        allowedTags: ['p', 'strong'],
      });

      const html = '<div><p><strong>Bold</strong> <em>Italic</em></p></div>';
      const result = sanitizer.sanitize(html);

      expect(result).toContain('<p>');
      expect(result).toContain('<strong>');
      expect(result).not.toContain('<div>');
      expect(result).not.toContain('<em>');
    });

    it('should strip all tags when configured', () => {
      const sanitizer = new HtmlSanitizer({
        stripAllTags: true,
      });

      const html = '<div><p><strong>Bold text</strong></p></div>';
      const result = sanitizer.sanitize(html);

      expect(result).toBe('Bold text');
      expect(result).not.toContain('<');
      expect(result).not.toContain('>');
    });
  });

  describe('static factory methods', () => {
    it('should create strict sanitizer', () => {
      const sanitizer = HtmlSanitizer.createStrict();
      const html = '<div><p><a href="http://example.com">Link</a></p></div>';
      const result = sanitizer.sanitize(html);

      // Should only allow minimal tags
      expect(result).not.toContain('<div>');
      expect(result).not.toContain('<p>');
      expect(result).not.toContain('<a>');
    });

    it('should create text-only sanitizer', () => {
      const sanitizer = HtmlSanitizer.createTextOnly();
      const html = '<div><p><strong>Bold text</strong></p></div>';
      const result = sanitizer.sanitize(html);

      expect(result).toBe('Bold text');
    });
  });

  describe('default sanitizer function', () => {
    it('should sanitize using default settings', () => {
      const maliciousHtml = '<div>Safe content <script>alert("xss")</script></div>';
      const result = sanitizeHtml(maliciousHtml);

      expect(result).toBe('<div>Safe content </div>');
      expect(result).not.toContain('<script>');
    });
  });

  describe('edge cases', () => {
    it('should handle empty strings', () => {
      const sanitizer = new HtmlSanitizer();
      expect(sanitizer.sanitize('')).toBe('');
    });

    it('should handle strings without HTML', () => {
      const sanitizer = new HtmlSanitizer();
      const text = 'Just plain text';
      expect(sanitizer.sanitize(text)).toBe(text);
    });

    it('should handle malformed HTML', () => {
      const sanitizer = new HtmlSanitizer();
      const malformedHtml = '<div><p>Unclosed paragraph<div>Another div</div>';
      const result = sanitizer.sanitize(malformedHtml);

      // Should still produce valid HTML
      expect(result).toContain('<div>');
      expect(result).toContain('<p>');
    });
  });
});
