print-layout.spec.ts 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { describe, expect, it, vi } from 'vitest'
  2. import {
  3. buildExportHtmlDocument,
  4. buildFileViewerRenderedHtmlDocument,
  5. resolveFileViewerPrintStyle,
  6. waitForFileViewerNextPaint,
  7. } from '../packages/core/src'
  8. import {
  9. buildPrintPageStyle,
  10. formatCssPixels,
  11. } from '../packages/core/src/printLayout'
  12. describe('print layout helpers', () => {
  13. it('builds a fixed-size print page from CSS pixels', () => {
  14. const css = buildPrintPageStyle({
  15. selector: '.viewer-export-content .pdf-export-page',
  16. width: 816,
  17. height: 1056
  18. })
  19. expect(formatCssPixels(816)).toBe('816px')
  20. expect(css).toContain('@page { size: 8.5in 11in; margin: 0; }')
  21. expect(css).toContain('.viewer-export-content .pdf-export-page')
  22. expect(css).toContain('width: 816px!important')
  23. expect(css).toContain('height:1056px!important')
  24. expect(css).toContain('overflow:hidden!important')
  25. })
  26. it('can keep converted Word pages flowing when content exceeds one page', () => {
  27. const css = buildPrintPageStyle({
  28. selector: '.viewer-export-content .msdoc-page',
  29. width: 794,
  30. height: 1123,
  31. heightMode: 'min'
  32. })
  33. expect(css).toContain('height:auto!important')
  34. expect(css).toContain('min-height:1123px!important')
  35. expect(css).toContain('overflow:visible!important')
  36. })
  37. it('keeps exported print markup isolated from the viewer shell', () => {
  38. const html = buildExportHtmlDocument({
  39. contentHtml: '<section class="pdf-export-page">page</section>',
  40. includeDocumentStyles: false,
  41. printStyle: '@page { size: 8.5in 11in; margin: 0; }',
  42. title: 'a<b>"demo".pdf',
  43. watermarkInlineStyle: 'opacity:0.1'
  44. })
  45. expect(html).toContain('<title>a&lt;b&gt;&quot;demo&quot;.pdf</title>')
  46. expect(html).toContain('<main class="viewer-export-shell">')
  47. expect(html).toContain('<div class="viewer-export-content"><section class="pdf-export-page">page</section></div>')
  48. expect(html).toContain('viewer-export-watermark')
  49. expect(html.trim()).toContain('<style data-viewer-print-style>@page { size: 8.5in 11in; margin: 0; }</style>')
  50. })
  51. it('builds rendered HTML through a core export adapter', async () => {
  52. const html = await buildFileViewerRenderedHtmlDocument({
  53. source: {} as HTMLElement,
  54. mode: 'print',
  55. title: 'adapter.docx',
  56. adapter: {
  57. includeDocumentStyles: false,
  58. printStyle: options => `/* ${options.mode}:${options.title} */`,
  59. toHtml: options => `<article data-mode="${options.mode}">${options.title}</article>`
  60. },
  61. watermarkInlineStyle: 'opacity:0.2'
  62. })
  63. await expect(resolveFileViewerPrintStyle(null, { mode: 'print', title: 'x' })).resolves.toBe('')
  64. expect(html).toContain('<article data-mode="print">adapter.docx</article>')
  65. expect(html).toContain('<style data-viewer-print-style>/* print:adapter.docx */</style>')
  66. expect(html).toContain('viewer-export-watermark')
  67. })
  68. it('falls back to a timer when requestAnimationFrame is unavailable', async () => {
  69. const schedule = vi.fn((callback: () => void) => {
  70. callback()
  71. return 1
  72. })
  73. await expect(waitForFileViewerNextPaint({
  74. setTimeout: schedule as unknown as Window['setTimeout']
  75. })).resolves.toBeUndefined()
  76. expect(schedule).toHaveBeenCalledTimes(1)
  77. })
  78. })