import {afterEach, describe, expect, test} from 'vitest'; import {DOM} from './dom.ts'; function sanitizeToHTML(input: string): string { const container = document.createElement('div'); container.append(DOM.sanitize(input)); return container.innerHTML; } describe('DOM', () => { describe('sanitize', () => { // A named form control shadows the same-named property of its own form element in a browser, so markup can // choose what `form.remove` or `form.localName` resolve to. jsdom does not implement that // (`[LegacyOverrideBuiltIns]`), so the emulation below is what makes the tests using it fail against a // sanitizer that reads those off the element rather than off `Element.prototype`. const clobberedProperties: string[] = []; function clobberFormProperty(property: string) { clobberedProperties.push(property); const inherited = Object.getOwnPropertyDescriptor(Element.prototype, property); Object.defineProperty(HTMLFormElement.prototype, property, { configurable: true, get(this: HTMLFormElement) { const named = Element.prototype.querySelectorAll.call(this, `[name="${property}"]`); if (named.length === 0) return inherited.get ? inherited.get.call(this) : inherited.value; return named.length === 1 ? named[0] : named; } }); } afterEach(() => { for (const property of clobberedProperties) delete HTMLFormElement.prototype[property]; clobberedProperties.length = 0; }); test('should not fail on empty string', () => { const input = ''; const output = sanitizeToHTML(input); expect(output).toBe(''); }); test('should remove script tags', () => { const input = ''; const output = sanitizeToHTML(input); expect(output).toBe(''); }); test('should remove script tags from nested elements', () => { const input = '
'; const output = sanitizeToHTML(input); expect(output).toBe(''); }); test('should remove potentially dangerous attributes', () => { const input = 'click me'; const output = sanitizeToHTML(input); expect(output).toBe('click me'); }); test('should remove potentially dangerous attributes from img', () => { const input = '