import { expect } from '@open-wc/testing'; import { toInlineStyledHtml, buildWordDocument, buildPrintDocument } from './export'; /** Renders HTML into a live, attached, styled element and returns its root. */ function styledRoot(inner: string, css = ''): HTMLElement { const host = document.createElement('div'); if (css) { const style = document.createElement('style'); style.textContent = css; host.appendChild(style); } const root = document.createElement('div'); root.innerHTML = inner; host.appendChild(root); document.body.appendChild(host); return root; } describe('export', () => { describe('toInlineStyledHtml', () => { it('folds computed colour into an inline style attribute', () => { const root = styledRoot('

hi

', '.c { color: rgb(255, 0, 0); }'); const out = toInlineStyledHtml(root); root.parentElement!.remove(); expect(out).to.match(/]*style="[^"]*color: rgb\(255, 0, 0\)/); }); it('strips classes and editor-only attributes', () => { const root = styledRoot('

t

'); const out = toInlineStyledHtml(root); root.parentElement!.remove(); expect(out).to.not.include('class='); expect(out).to.not.include('contenteditable'); expect(out).to.not.include('data-x'); }); it('keeps structural attributes like href and src', () => { const root = styledRoot('

x

'); const out = toInlineStyledHtml(root); root.parentElement!.remove(); expect(out).to.include('href="https://a.b"'); }); it('does not repeat inherited values already set on the parent', () => { const root = styledRoot( '

child

', '.wrap { color: rgb(0, 128, 0); }' ); const out = toInlineStyledHtml(root); root.parentElement!.remove(); // The wrapper carries the colour; the inheriting

should not repeat it. const pMatch = /]*)>/.exec(out); expect(pMatch![1]).to.not.include('color: rgb(0, 128, 0)'); }); it('caps images at 100% width', () => { const root = styledRoot('

x

'); const out = toInlineStyledHtml(root); root.parentElement!.remove(); expect(out).to.match(/]*max-width: 100%/); }); it('emits borders on table cells', () => { const root = styledRoot( '
a
', '.cell { border: 2px solid rgb(0, 0, 0); }' ); const out = toInlineStyledHtml(root); root.parentElement!.remove(); // Four equal sides serialize to the border-width/style/color shorthand. expect(out).to.match(/]*border-width: 2px/); expect(out).to.match(/]*border-style: solid/); }); }); describe('buildWordDocument', () => { it('wraps body in a Word-openable document with office namespaces', () => { const doc = buildWordDocument('

hi

', 'My File'); expect(doc).to.include('xmlns:w="urn:schemas-microsoft-com:office:word"'); expect(doc).to.include(''); expect(doc).to.include('My File'); expect(doc).to.include('

hi

'); }); it('escapes the title', () => { const doc = buildWordDocument('

x

', ''); expect(doc).to.include('<evil>'); }); }); describe('buildPrintDocument', () => { it('includes page CSS and the body', () => { const doc = buildPrintDocument('

hi

', { title: 'Doc' }); expect(doc).to.include('@page'); expect(doc).to.include('

hi

'); expect(doc).to.include('page-break-before: always'); }); it('renders a running header and footer when provided', () => { const doc = buildPrintDocument('

x

', { header: 'Top', footer: 'Bottom' }); expect(doc).to.include('nw-print-header'); expect(doc).to.include('Top'); expect(doc).to.include('nw-print-footer'); expect(doc).to.include('Bottom'); }); it('omits header/footer bands when not provided', () => { const doc = buildPrintDocument('

x

', { title: 'Doc' }); expect(doc).to.not.include('nw-print-header'); expect(doc).to.not.include('nw-print-footer'); }); }); });