import { nextTick } from 'vue' import { afterEach, describe, expect, it, vi } from 'vitest' import { printLoadingList } from './printLoadingList' afterEach(() => { vi.restoreAllMocks(); document.body.replaceChildren() }) function manifest() { document.body.innerHTML = `
柜次号CB-TEST
集装箱号CONTAINER-TEST
入仓码SKU备注
IN-FIRSTSKU & <盒>第一行备注
IN-LASTSKU-LAST最后一列完整备注
操作历史:创建计划、调整货物
` return document.getElementById('manifest')! } function interceptPrint(onPrint: (frame: HTMLIFrameElement) => void) { let frame: HTMLIFrameElement | undefined const append = document.body.append.bind(document.body) vi.spyOn(document.body, 'append').mockImplementation((...nodes) => { append(...nodes) for (const node of nodes) { if (!(node instanceof HTMLIFrameElement)) continue frame = node vi.spyOn(node.contentWindow!, 'focus').mockImplementation(() => {}) vi.spyOn(node.contentWindow!, 'print').mockImplementation(() => onPrint(node)) } }) return async () => { await nextTick() if (!frame) throw new Error('Print frame was not created') frame.dispatchEvent(new Event('load')) return frame } } describe('loading list printing', () => { it('prints the manifest summary and every cargo row and column in an isolated document', async () => { const root = manifest(), original = root.outerHTML const hostPrint = vi.spyOn(window, 'print').mockImplementation(() => {}) let snapshot: Document | undefined const load = interceptPrint(frame => { snapshot = frame.contentDocument! expect(snapshot.title).toBe('装柜清单 · LIST-TEST') expect(snapshot.querySelector('h1')?.textContent).toBe('装柜清单 · LIST-TEST') expect(snapshot.body.textContent).toContain('CB-TEST') expect(snapshot.body.textContent).toContain('CONTAINER-TEST') expect(snapshot.querySelectorAll('tbody tr')).toHaveLength(2) expect(snapshot.querySelectorAll('thead th')).toHaveLength(3) expect(snapshot.body.textContent).toContain('最后一列完整备注') expect(snapshot.body.textContent).toContain('SKU & <盒>') expect(snapshot.querySelector('td')?.getAttribute('style')).toBeNull() expect(snapshot.body.textContent).not.toMatch(/平台导航|后台页签|返回货柜概览|字段设置|操作历史/) expect(snapshot.querySelectorAll('button')).toHaveLength(0) frame.contentWindow!.dispatchEvent(new Event('afterprint')) }) const pending = printLoadingList(root) const frame = await load() await expect(pending).resolves.toBe(true) expect(snapshot).toBeDefined() expect(hostPrint).not.toHaveBeenCalled() expect(frame.isConnected).toBe(false) expect(root.outerHTML).toBe(original) }) it('keeps the print document until the dialog closes and prevents duplicate print jobs', async () => { const root = manifest(), print = vi.fn() const load = interceptPrint(print) const pending = printLoadingList(root) const frame = await load() expect(frame.isConnected).toBe(true) expect(print).toHaveBeenCalledOnce() await expect(printLoadingList(root)).resolves.toBe(false) expect(document.querySelectorAll('iframe')).toHaveLength(1) frame.contentWindow!.dispatchEvent(new Event('afterprint')) await expect(pending).resolves.toBe(true) expect(frame.isConnected).toBe(false) expect(document.querySelector('aside')?.textContent).toBe('平台导航') }) it('never falls back to printing the entire page when the manifest is missing or incomplete', async () => { const hostPrint = vi.spyOn(window, 'print').mockImplementation(() => {}) await expect(printLoadingList(null)).rejects.toThrow('清单尚未加载完成') await expect(printLoadingList(document.createElement('section'))).rejects.toThrow('清单尚未加载完成') expect(hostPrint).not.toHaveBeenCalled() expect(document.querySelector('iframe')).toBeNull() }) it('removes the isolated document after a print failure', async () => { const root = manifest(), original = root.outerHTML const load = interceptPrint(() => { throw new Error('printer unavailable') }) const pending = printLoadingList(root) const rejected = expect(pending).rejects.toThrow('printer unavailable') const frame = await load() await rejected expect(frame.isConnected).toBe(false) expect(root.outerHTML).toBe(original) }) })