All checks were successful
Build & Deploy to Staging / Build & Deploy to Staging (push) Successful in 13m46s
49 lines
1.4 KiB
TypeScript
49 lines
1.4 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { escapeHtml } from '../utils/html.js';
|
|
|
|
describe('escapeHtml', () => {
|
|
it('escapes ampersands', () => {
|
|
expect(escapeHtml('foo & bar')).toBe('foo & bar');
|
|
});
|
|
|
|
it('escapes less-than', () => {
|
|
expect(escapeHtml('a < b')).toBe('a < b');
|
|
});
|
|
|
|
it('escapes greater-than', () => {
|
|
expect(escapeHtml('a > b')).toBe('a > b');
|
|
});
|
|
|
|
it('escapes double quotes', () => {
|
|
expect(escapeHtml('say "hello"')).toBe('say "hello"');
|
|
});
|
|
|
|
it('escapes single quotes', () => {
|
|
expect(escapeHtml("it's")).toBe('it's');
|
|
});
|
|
|
|
it('returns empty string unchanged', () => {
|
|
expect(escapeHtml('')).toBe('');
|
|
});
|
|
|
|
it('passes through strings with no special chars', () => {
|
|
expect(escapeHtml('hello world 123')).toBe('hello world 123');
|
|
});
|
|
|
|
it('escapes multiple special chars combined', () => {
|
|
expect(escapeHtml('<div class="x">&</div>')).toBe('<div class="x">&</div>');
|
|
});
|
|
|
|
it('escapes XSS payload', () => {
|
|
expect(escapeHtml('<script>alert("xss")</script>')).toBe('<script>alert("xss")</script>');
|
|
});
|
|
|
|
it('double-escapes existing entities', () => {
|
|
expect(escapeHtml('&')).toBe('&amp;');
|
|
expect(escapeHtml('<')).toBe('&lt;');
|
|
});
|
|
|
|
it('escapes single quotes in attributes', () => {
|
|
expect(escapeHtml("data-x='val'")).toBe('data-x='val'');
|
|
});
|
|
});
|