import assert from 'node:assert/strict' import { chromium } from 'playwright' import { installCertFixture } from './mp-pl-plan-cert-fixture.mjs' // 挂载真实 Web 弹窗与附件组件,仅替换 API 边界,不写入业务数据库。 const origin = process.env.PLAN_CERT_TEST_ORIGIN || 'http://localhost:3006' const browser = await chromium.launch({ headless: true, channel: 'chrome' }) const context = await browser.newContext({ viewport: { width: 1440, height: 1000 } }) const fixture = await installCertFixture(context) const page = await context.newPage() const errors = [] page.on('pageerror', (error) => errors.push(error.message)) page.setDefaultTimeout(15000) let releaseUpload const saves = () => fixture.calls.filter((c) => c.method === 'PATCH' && c.path.endsWith('/product-certs')) try { await page.goto(`${origin}/#/m/pl/plan-cert?mpTicket=cert-fixture`) await page.getByText('YS001', { exact: true }).first().waitFor() await page.evaluate(async () => { const { createVNode, render, defineComponent, ref, h } = await import( '/node_modules/.vite/deps/vue.js' ) const { default: Dialog } = await import( '/src/components/business/pl-plan-cert-upload-dialog/index.vue' ) const host = document.createElement('div') document.body.appendChild(host) const Wrapper = defineComponent({ setup() { const visible = ref(true) return () => [ h( 'button', { id: 'reopen-web-cert', onClick: () => { visible.value = true } }, '重新打开 Web 证书' ), h(Dialog, { visible: visible.value, planId: 'plan-1', 'onUpdate:visible': (v) => { visible.value = v } }) ] } }) const vnode = createVNode(Wrapper) vnode.appContext = document.querySelector('#app').__vue_app__._context render(vnode, host) }) const dialog = page.getByRole('dialog').filter({ hasText: '上传危化品证书' }) await dialog.getByText('测试易制毒产品', { exact: true }).waitFor() assert.equal(await dialog.locator('input[type="file"]').count(), 3) // 使用最后一个产品的附件,确保保护覆盖所有嵌套循环中的上传组件。 fixture.uploadGate = new Promise((resolve) => { releaseUpload = resolve }) await dialog .locator('input[type="file"]') .last() .setInputFiles({ name: 'legal-cert.pdf', mimeType: 'application/pdf', buffer: Buffer.from('%PDF-1.4\nfixture') }) await dialog.locator('.is-uploading').waitFor() await dialog.getByRole('button', { name: '保存', exact: true }).click() // toast 表明真实处理函数已完成,不以固定等待推断没有请求。 await page .getByText(/^(附件正在上传,请稍候再保存|证书保存成功)$/) .first() .waitFor() assert.equal(saves().length, 0, '附件未上传完成时不能提交旧 URL') assert.equal( await page.getByText('附件正在上传,请稍候再保存', { exact: true }).isVisible(), true ) assert.equal(await dialog.isVisible(), true) releaseUpload() await dialog.locator('.is-uploading').waitFor({ state: 'hidden' }) await dialog.getByRole('button', { name: '保存', exact: true }).click() await dialog.waitFor({ state: 'hidden' }) assert.equal(saves().length, 1) assert.ok(JSON.stringify(saves()[0].body).includes('/fixtures/cert.pdf')) // 关闭销毁后重新打开,不遗留上传引用;正常保存仍可用。 await page.locator('#reopen-web-cert').click() await dialog.getByText('测试易制毒产品', { exact: true }).waitFor() await dialog.getByRole('button', { name: '保存', exact: true }).click() await dialog.waitFor({ state: 'hidden' }) assert.equal(saves().length, 2) assert.deepEqual(errors, []) assert.deepEqual(fixture.unknown, []) console.log('PASS: Web 附件上传中阻止保存、上传后提交新 URL、销毁重开正常保存') } finally { releaseUpload?.() await browser.close() }