open-design/apps/web/tests/components/PreviewModal.test.tsx
meshackm 461a312002
fix: fix link handling in example preview iframe sandbox (#701)
* fix: fix link handling in example preview iframe sandbox

* fix: added missing single quote

* fix(srcdoc): security/correctness issues
- Use location.hash = href for hash-link navigation so hashchange
  events, CSS :target, history/back and named anchors work correctly
- Always pass 'noopener,noreferrer' to window.open() for _blank links
- Guard e.target with instanceof Element before calling .closest() to
  avoid TypeError on text node click targets

* fix(srcdoc): security/correctness issues
- Added a protocol allowlist
- Re-navigation to same hash
- Consistency with rest of shim IIFE using var instead of let and const

* fix(srcdoc): scroll to top on bare hash links (#)

Intercept href="#" clicks and scroll to top of page in the iframe sandbox to mimic native browser behaviour.

* test(web): update PreviewModal sandbox test assertions to include popup flags
2026-05-09 21:24:25 +08:00

69 lines
2.1 KiB
TypeScript

import { renderToStaticMarkup } from 'react-dom/server';
import { describe, expect, it } from 'vitest';
import { PreviewModal } from '../../src/components/PreviewModal';
describe('PreviewModal sandbox isolation', () => {
it('renders generated previews without same-origin sandbox access', () => {
const markup = renderToStaticMarkup(
<PreviewModal
title="Unsafe preview"
views={[
{
id: 'preview',
label: 'Preview',
html: '<script>window.parent.document.body.innerHTML="owned"</script>',
},
]}
exportTitleFor={() => 'unsafe-preview'}
onClose={() => {}}
/>,
);
expect(markup).toContain('sandbox="allow-scripts allow-popups allow-popups-to-escape-sandbox"');
expect(markup).not.toContain('allow-same-origin');
expect(markup).toContain('srcDoc=');
});
it('keeps deck srcdoc handling for deck preview views', () => {
const markup = renderToStaticMarkup(
<PreviewModal
title="Deck preview"
views={[
{
id: 'deck',
label: 'Deck',
html: '<section class="slide">one</section><section class="slide">two</section>',
deck: true,
},
]}
exportTitleFor={() => 'deck-preview'}
onClose={() => {}}
/>,
);
expect(markup).toContain('sandbox="allow-scripts allow-popups allow-popups-to-escape-sandbox"');
expect(markup).not.toContain('allow-same-origin');
expect(markup).toContain('od:slide');
});
it('includes popup flags in the sandbox attribute', () => {
const markup = renderToStaticMarkup(
<PreviewModal
title="Popup preview"
views={[
{
id: 'popup',
label: 'Popup',
html: '<button onclick="window.open(\'https://example.com\')">Open Popup</button>',
},
]}
exportTitleFor={() => 'popup-preview'}
onClose={() => {}}
/>,
);
expect(markup).toContain('allow-popups');
expect(markup).toContain('allow-popups-to-escape-sandbox');
});
});