Cover review decisions, rule binding and the full package in the renderer e2e spec
Why: The renderer browser acceptance still recorded GAP markers for approve, final, rule binding and the full package, which the workspace now provides; the spec must exercise those entries through the UI first, falling back to the API only when an entry is absent. Evidence: tsc --noEmit on e2e/document-renderer.playwright.ts exits 0; playwright test --list loads 13 tests (adds §11-2b and §11-3b); the spec still skips without PLAYWRIGHT_BASE_URL and RBA_OUT, so no browser run was possible here; leak scan in §11-8 is untouched. Impact: approve and final are attempted from the workspace and asserted by success text or a readable failure; the package download asserts a ZIP header; binding asserts the refresh and the controlled-document refusal copy. Not run against a real product in this session. Refs: unified renderer acceptance §11 items 2, 3, 5 and 6; RDM 7169944 (review decision contract), 4b7ac2a (profile bind), 75ba50c (package). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -210,6 +210,42 @@ test('§11-1 文档树 → 结构画布与阅读视图(共用选中与过滤
|
||||
await s.close()
|
||||
})
|
||||
|
||||
test('§11-2b 规则绑定:项目设置权限可绑定与解绑(非受控文档)', async ({ browser }) => {
|
||||
items(2)
|
||||
const s = await session(browser, U.admin, 'item2b-admin')
|
||||
const { page } = s
|
||||
await openAudit(page, A.name)
|
||||
await openDoc(page, UNCTRL.title)
|
||||
const binding = panel(page, '规则绑定')
|
||||
await expect(binding, '具备项目设置权限的用户可见规则绑定区').toBeVisible({ timeout: 20_000 })
|
||||
await page.locator('.drw-bind-rule', { hasText: `${GENERAL.id}@${GENERAL.version}` }).locator('input').check()
|
||||
await page.locator('.drw-bind-row', { hasText: '本文档' }).getByRole('button', { name: '绑定所选规则', exact: true }).click()
|
||||
await expect(panel(page, '规则绑定').getByText('绑定规则已完成')).toBeVisible({ timeout: 30_000 })
|
||||
await expectReadableFailures(page)
|
||||
await expect(panel(page, '渲染规则').locator('.drw-profile-source', { hasText: '文档规则' }), '绑定后规则列表刷新出文档规则').toBeVisible({ timeout: 15_000 })
|
||||
await shot(page, 'item2b-bound', binding)
|
||||
await page.locator('.drw-bind-row', { hasText: '本文档' }).getByRole('button', { name: '解绑', exact: true }).click()
|
||||
await expect(panel(page, '规则绑定').getByText('解绑规则已完成')).toBeVisible({ timeout: 30_000 })
|
||||
await expectReadableFailures(page)
|
||||
await s.close()
|
||||
})
|
||||
|
||||
test('§11-3b 受控文档拒绝绑定通用规则,失败以可读文案显示', async ({ browser }) => {
|
||||
items(3)
|
||||
const s = await session(browser, U.admin, 'item3b-admin')
|
||||
const { page } = s
|
||||
await openAudit(page, A.name)
|
||||
await openDoc(page, A.title)
|
||||
const binding = panel(page, '规则绑定')
|
||||
await expect(binding, '具备项目设置权限的用户可见规则绑定区').toBeVisible({ timeout: 20_000 })
|
||||
await page.locator('.drw-bind-rule', { hasText: `${GENERAL.id}@${GENERAL.version}` }).locator('input').check()
|
||||
await page.locator('.drw-bind-row', { hasText: '本文档' }).getByRole('button', { name: '绑定所选规则', exact: true }).click()
|
||||
await expect(binding.locator('.drw-failure-msg')).toContainText('受控文档', { timeout: 30_000 })
|
||||
await expect(binding.locator('.drw-failure-msg')).not.toContainText('controlled_requires_exact_profile')
|
||||
await shot(page, 'item3b-controlled-refusal', binding)
|
||||
await s.close()
|
||||
})
|
||||
|
||||
test('§11-3 受控文档:规则来源、版本与不回退说明', async ({ browser }) => {
|
||||
items(3)
|
||||
const s = await session(browser, U.author, 'item3-author')
|
||||
@@ -393,12 +429,23 @@ test('§11-5c 审核通过与批准(签署)', async ({ browser }) => {
|
||||
expect(submissionId, 'BLOCKER[RDM] 无渲染审阅提交(见 §11-5a),审核与批准签署无从进行').not.toBe('')
|
||||
}
|
||||
await expect(reviewPanel.locator('.drw-mono')).toHaveAttribute('title', submissionId, { timeout: 20_000 })
|
||||
const reviewerButtons = await reviewPanel.getByRole('button', { name: /通过|同意|批准|签署|驳回/ }).count()
|
||||
expect.soft(reviewerButtons,
|
||||
'GAP[Frontend] 审阅面板没有审核通过/驳回入口;rdm.review.doc.approve 是需会话来源锚点的正式写命令,只能经对话代理触发').toBeGreaterThan(0)
|
||||
apiAssisted('rdm.review.doc.approve 以审核人会话 + 本人会话来源锚点调用')
|
||||
const approve = await command(r.page, 'rdm.review.doc.approve', { projectId: A.pid, docId: A.doc, note: `§11 审核通过 ${RUN}` }, env('RBA_SRC_REVIEWER_A'))
|
||||
expect(approve.body?.receipt?.state, `approve 回执:${approve.text.slice(0, 400)}`).toBe('committed')
|
||||
// 工作区「整文审签」入口只在服务端允许(审核人且未审)时出现;成功与可读失败都必须可见。
|
||||
const decisionPanel = panel(r.page, '整文审签')
|
||||
const uiApprove = decisionPanel.getByRole('button', { name: '审核通过', exact: true })
|
||||
if ((await uiApprove.count()) > 0) {
|
||||
await uiApprove.click()
|
||||
const done = decisionPanel.getByText('整文审核通过已完成')
|
||||
const failed = decisionPanel.locator('.drw-failure-msg')
|
||||
await expect(done.or(failed).first()).toBeVisible({ timeout: 60_000 })
|
||||
expect.soft(await done.count(), `审核通过应成功:${(await failed.allTextContents()).join(' | ')}`).toBe(1)
|
||||
await expectReadableFailures(r.page)
|
||||
await shot(r.page, 'item5c-reviewer-approved', decisionPanel)
|
||||
} else {
|
||||
expect.soft(false, 'GAP[Frontend] 审核人在待审状态下工作区没有「审核通过」入口').toBe(true)
|
||||
apiAssisted('rdm.review.doc.approve 以审核人会话 + 本人会话来源锚点调用(工作区入口不可用时的取证路径)')
|
||||
const approve = await command(r.page, 'rdm.review.doc.approve', { projectId: A.pid, docId: A.doc, note: `§11 审核通过 ${RUN}` }, env('RBA_SRC_REVIEWER_A'))
|
||||
expect(approve.body?.receipt?.state, `approve 回执:${approve.text.slice(0, 400)}`).toBe('committed')
|
||||
}
|
||||
await r.close()
|
||||
|
||||
const a = await session(browser, U.approver, 'item5c-approver')
|
||||
@@ -406,12 +453,22 @@ test('§11-5c 审核通过与批准(签署)', async ({ browser }) => {
|
||||
await openDoc(a.page, A.title)
|
||||
const approverPanel = panel(a.page, '审阅')
|
||||
await expect(approverPanel.locator('.drw-mono')).toHaveAttribute('title', submissionId, { timeout: 20_000 })
|
||||
const approverButtons = await approverPanel.getByRole('button', { name: /批准|签署|定稿|通过/ }).filter({ hasNotText: '生成批准稿' }).count()
|
||||
expect.soft(approverButtons,
|
||||
'GAP[Frontend] 审阅面板没有批准/定稿(签署)入口;rdm.review.doc.final 需会话来源锚点,浏览器工作区无法完成批准').toBeGreaterThan(0)
|
||||
apiAssisted('rdm.review.doc.final 以批准人会话 + 本人会话来源锚点调用')
|
||||
const final = await command(a.page, 'rdm.review.doc.final', { projectId: A.pid, docId: A.doc, round, reason: `§11 批准 ${RUN}` }, env('RBA_SRC_APPROVER_A'))
|
||||
expect(final.body?.receipt?.state, `final 回执:${final.text.slice(0, 400)}`).toBe('committed')
|
||||
// 终批入口只在批准人且全员已审核通过时出现;载荷绑定界面所示轮次。
|
||||
const finalPanel = panel(a.page, '整文审签')
|
||||
const uiFinal = finalPanel.getByRole('button', { name: '终批', exact: true })
|
||||
if ((await uiFinal.count()) > 0) {
|
||||
await uiFinal.click()
|
||||
const done = finalPanel.getByText('整文终批已完成')
|
||||
const failed = finalPanel.locator('.drw-failure-msg')
|
||||
await expect(done.or(failed).first()).toBeVisible({ timeout: 60_000 })
|
||||
expect.soft(await done.count(), `终批应成功:${(await failed.allTextContents()).join(' | ')}`).toBe(1)
|
||||
await expectReadableFailures(a.page)
|
||||
} else {
|
||||
expect.soft(false, 'GAP[Frontend] 批准人在全员审核通过后工作区没有「终批」入口').toBe(true)
|
||||
apiAssisted('rdm.review.doc.final 以批准人会话 + 本人会话来源锚点调用(工作区入口不可用时的取证路径)')
|
||||
const final = await command(a.page, 'rdm.review.doc.final', { projectId: A.pid, docId: A.doc, round, reason: `§11 批准 ${RUN}` }, env('RBA_SRC_APPROVER_A'))
|
||||
expect(final.body?.receipt?.state, `final 回执:${final.text.slice(0, 400)}`).toBe('committed')
|
||||
}
|
||||
await a.page.reload()
|
||||
await openAudit(a.page, A.name)
|
||||
await openDoc(a.page, A.title)
|
||||
@@ -445,8 +502,9 @@ test('§11-6 下载 Markdown、批准稿、审阅留痕稿与完整包', async (
|
||||
await shot(page, 'item6-preview-downloads', panel(page, '交付记录'))
|
||||
expect.soft(await deliveryOf(page, '批准').count(), 'BLOCKER[RDM] 无渲染提交 → 无批准交付,批准稿不可下载').toBeGreaterThan(0)
|
||||
expect.soft(await page.getByRole('button', { name: '审阅留痕 DOCX', exact: true }).count(), 'BLOCKER[RDM] 无渲染提交 → 无审阅交付,审阅留痕稿不可下载').toBeGreaterThan(0)
|
||||
expect.soft(await page.locator('.drw-download', { hasText: /完整包|全部|打包|ZIP|zip/ }).count(),
|
||||
'GAP[RDM] rdm.render.download 只支持 docx/review-docx/markdown/manifest/diagnostics,无完整交付包(zip)种类;GAP[Frontend] 交付记录无「完整包」下载入口').toBeGreaterThan(0)
|
||||
const pkg = await download(page, preview, '完整交付包(ZIP)')
|
||||
expect(pkg.name).toMatch(/\.zip$/)
|
||||
expect(fs.readFileSync(pkg.file).subarray(0, 2).toString()).toBe('PK')
|
||||
await s.close()
|
||||
return
|
||||
}
|
||||
@@ -493,9 +551,12 @@ test('§11-6 下载 Markdown、批准稿、审阅留痕稿与完整包', async (
|
||||
if (manifest.name.length > 36) expect(shown).toContain('…')
|
||||
await shot(page, 'item6-downloaded-longname', panel(page, '交付记录'))
|
||||
writeState({ downloads: [md, docx, trace, manifest].map(f => f.name) })
|
||||
const packageButtons = await page.locator('.drw-download', { hasText: /完整包|全部|打包|ZIP|zip/ }).count()
|
||||
expect.soft(packageButtons,
|
||||
'GAP[RDM] rdm.render.download 只支持 docx/review-docx/markdown/manifest/diagnostics,无完整交付包(zip)种类;GAP[Frontend] 交付记录无「完整包」下载入口').toBeGreaterThan(0)
|
||||
// 完整包:rdm.render.download kind=package,服务端确定性 ZIP;与单件下载同一鉴权路径。
|
||||
const pkg = await download(page, approved, '完整交付包(ZIP)')
|
||||
expect(pkg.name).toMatch(/\.zip$/)
|
||||
expect(fs.readFileSync(pkg.file).subarray(0, 2).toString()).toBe('PK')
|
||||
note(`完整交付包:${pkg.name}(${pkg.size} B)`)
|
||||
writeState({ downloads: [md, docx, trace, manifest, pkg].map(f => f.name) })
|
||||
await s.close()
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user