// 不连接业务后端:在真正的 HTTP 非安全上下文中打开、导出并重新打开测试 DOCX。
|
// node tests/superdoc-http.smoke.mjs
|
import assert from 'node:assert/strict'
|
import { mkdtemp, writeFile, readFile, rm } from 'node:fs/promises'
|
import { tmpdir } from 'node:os'
|
import path from 'node:path'
|
import { createServer } from 'node:http'
|
import { fileURLToPath } from 'node:url'
|
import { build } from 'vite'
|
import { chromium } from 'playwright'
|
import JSZip from 'jszip'
|
import superdocHttpWorker from '../vite/plugins/superdoc-http-worker.js'
|
|
const project = fileURLToPath(new URL('../', import.meta.url))
|
const temporary = await mkdtemp(path.join(tmpdir(), 'lims-superdoc-http-'))
|
const fixture = path.join(project, 'tests/.superdoc-http-smoke.html')
|
let browser
|
let server
|
try {
|
await writeFile(fixture, `<!doctype html><html><body><div id="editor"></div><script type="module">
|
import { loadSuperDoc } from '../src/utils/loadSuperDoc.js';
|
import workerUrl from 'virtual:superdoc-http-worker-url';
|
(async () => {
|
window.before = { secure: isSecureContext, uuid: typeof crypto.randomUUID };
|
const { SuperDoc } = await loadSuperDoc();
|
window.openDocument = (blob) => new Promise((resolve, reject) => {
|
window.editor?.destroy();
|
window.editor = new SuperDoc({ selector: '#editor',
|
document: new File([blob], 'http-test.docx'), workerUrls: { document: workerUrl },
|
documentMode: 'editing', telemetry: { enabled: false },
|
onReady: () => resolve(true), onException: event => reject(new Error(event.error?.message || String(event.error))),
|
onContentError: event => reject(new Error(String(event.error))) });
|
});
|
try { await openDocument(await (await fetch('/fixture.docx')).blob()); window.result = 'ready'; }
|
catch (error) { window.result = error.message; }
|
})().catch(error => { window.result = error.message });
|
</script></body></html>`)
|
const outDir = path.join(temporary, 'dist')
|
await build({ configFile: false, root: project, logLevel: 'warn', plugins: [superdocHttpWorker()],
|
build: { outDir, emptyOutDir: true, rollupOptions: { input: fixture } } })
|
const zip = new JSZip()
|
zip.file('[Content_Types].xml', '<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types"><Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/><Default Extension="xml" ContentType="application/xml"/><Override PartName="/word/document.xml" ContentType="application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"/></Types>')
|
zip.file('_rels/.rels', '<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/></Relationships>')
|
zip.file('word/document.xml', '<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"><w:body><w:p><w:r><w:t>HTTP report smoke test</w:t></w:r></w:p><w:sectPr><w:pgSz w:w="11906" w:h="16838"/><w:pgMar w:top="1440" w:right="1440" w:bottom="1440" w:left="1440"/></w:sectPr></w:body></w:document>')
|
const docx = await zip.generateAsync({ type: 'nodebuffer' })
|
server = createServer(async (req, res) => {
|
try {
|
const url = new URL(req.url, 'http://lims-http.test')
|
if (url.pathname === '/fixture.docx') { res.end(docx); return }
|
const relative = decodeURIComponent(url.pathname).replace(/^\/+/, '') || 'tests/.superdoc-http-smoke.html'
|
const filename = path.resolve(outDir, relative)
|
if (!filename.startsWith(outDir + path.sep)) { res.writeHead(403).end(); return }
|
res.setHeader('Content-Type', filename.endsWith('.js') ? 'text/javascript' : filename.endsWith('.css') ? 'text/css' : 'text/html')
|
res.end(await readFile(filename))
|
} catch { res.writeHead(404).end() }
|
})
|
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve))
|
browser = await chromium.launch({ executablePath: process.env.CHROME_PATH || 'C:/Program Files/Google/Chrome/Application/chrome.exe',
|
headless: true, args: ['--no-proxy-server', '--host-resolver-rules=MAP lims-http.test 127.0.0.1'] })
|
const page = await browser.newPage()
|
const errors = []
|
page.on('pageerror', error => errors.push(error.message))
|
await page.goto(`http://lims-http.test:${server.address().port}/`)
|
await page.waitForFunction(() => window.result, null, { timeout: 120000 })
|
const before = await page.evaluate(() => window.before)
|
assert.equal(before.secure, false)
|
assert.equal(before.uuid, 'undefined')
|
assert.equal(await page.evaluate(() => window.result), 'ready')
|
const exported = await page.evaluate(async () => {
|
const blob = await editor.export({ exportType: ['docx'], triggerDownload: false })
|
const size = blob.size
|
await openDocument(blob)
|
return size
|
})
|
assert.ok(exported > 0)
|
assert.deepEqual(errors, [])
|
console.log(JSON.stringify({ result: 'PASS', before, opened: true, exportedBytes: exported, reopened: true, browserErrors: errors }, null, 2))
|
} finally {
|
await browser?.close()
|
if (server) await new Promise(resolve => server.close(resolve))
|
await rm(fixture, { force: true })
|
assert.ok(path.resolve(temporary).startsWith(path.resolve(tmpdir()) + path.sep + 'lims-superdoc-http-'))
|
await rm(temporary, { recursive: true, force: true })
|
}
|