2026-07-12 18:03:44 -07:00
|
|
|
import { describe, test, expect } from 'vitest';
|
|
|
|
|
import { Footer } from './Footer';
|
|
|
|
|
|
|
|
|
|
const toHtml = (Footer as any).toHtml;
|
|
|
|
|
|
|
|
|
|
describe('Footer.toHtml text escaping (attacker-controlled `text` prop)', () => {
|
|
|
|
|
test('a tag-breakout attempt in text is neutralized (no injected element)', () => {
|
|
|
|
|
const { html } = toHtml({ text: '</footer><img src=x onerror=alert(1)>' }, '');
|
|
|
|
|
expect(html).not.toContain('<img');
|
|
|
|
|
expect(html).toContain('<img');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('ampersand is escaped for well-formed text content (consistency with escapeHtml)', () => {
|
|
|
|
|
const { html } = toHtml({ text: 'Terms & Conditions' }, '');
|
|
|
|
|
expect(html).toContain('Terms & Conditions');
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('a normal copyright text value still renders unchanged', () => {
|
|
|
|
|
const { html } = toHtml({ text: '© 2026 MySite. All rights reserved.' }, '');
|
|
|
|
|
expect(html).toContain('© 2026 MySite. All rights reserved.');
|
|
|
|
|
});
|
|
|
|
|
});
|
2026-07-14 06:47:59 -07:00
|
|
|
|
|
|
|
|
describe('Footer (F4: box-model + animation + visibility props on craft.props)', () => {
|
|
|
|
|
test('craft.props includes animation/visibility defaults so the panel controls always render', () => {
|
|
|
|
|
const craftProps = (Footer as any).craft.props;
|
|
|
|
|
expect(craftProps).toHaveProperty('animation', 'none');
|
|
|
|
|
expect(craftProps).toHaveProperty('animationDelay', '0');
|
|
|
|
|
expect(craftProps).toHaveProperty('hideOnDesktop', false);
|
|
|
|
|
expect(craftProps).toHaveProperty('hideOnTablet', false);
|
|
|
|
|
expect(craftProps).toHaveProperty('hideOnMobile', false);
|
|
|
|
|
});
|
|
|
|
|
});
|