import { expect, test } from './fixtures' import { TeachingContractMock } from './teaching-contract-mock' test.describe('教学运行页 P1 安全边界', () => { test('observe/readOnly 强制本人学员进入只读观察', async ({ page }) => { const contract = new TeachingContractMock('studentLeader') await contract.install(page) await page.goto('/teaching/confrontation/runs/run-confrontation?observe=1') await expect(page.getByText('只读观察', { exact: true })).toBeVisible() await expect(page.getByRole('button', { name: /提交岗位动作|完成当前岗位动作|提交团队结果/ })).toHaveCount(0) await page.goto('/teaching/confrontation/runs/run-confrontation?readOnly=1') await expect(page.getByText('只读观察', { exact: true })).toBeVisible() await expect(page.getByRole('button', { name: /提交岗位动作|完成当前岗位动作|提交团队结果/ })).toHaveCount(0) expect(contract.requests.filter((item) => ['PUT', 'POST', 'DELETE'].includes(item.method))).toHaveLength(0) }) test('正式考核提交后清空执行投影并卸载 Three 场景', async ({ page }) => { const contract = new TeachingContractMock('studentLeader') await contract.install(page) await page.goto('/teaching/exams/runs/run-exam') await expect(page.locator('.runtime-scene-window canvas')).toBeVisible() await page.getByRole('button', { name: '完成当前步骤', exact: true }).click() await expect(page.getByRole('heading', { name: /第 2 步/ })).toBeVisible() await page.getByRole('button', { name: '完成当前步骤', exact: true }).click() await page.getByRole('button', { name: '提交正式考核', exact: true }).click() const dialog = page.locator('.el-dialog:visible').last() await dialog.getByRole('button', { name: '确认提交', exact: true }).click() await expect(page.getByText('正式考核执行场景已关闭', { exact: true })).toBeVisible() await expect(page.locator('.runtime-scene-window canvas')).toHaveCount(0) await expect(page.getByRole('button', { name: /过程记录/ })).toHaveCount(0) await expect(page.locator('.runtime-event-card')).toHaveCount(0) }) test('共享对抗缺少岗位声明时只允许成员 ID 最小的本人', async ({ page }) => { const contract = new TeachingContractMock('studentOperator') const task = contract.assignments.get('assignment-confrontation') as Record const definition = task.definitionSnapshot as { steps: Array>; modeConfig: Record } definition.steps.forEach((step) => { delete step.allowedPositions delete step.requiredPositions delete step.positionCodes delete step.positionCode delete step.positionActions delete step.submitPositions }) delete definition.modeConfig.submitPositions const runtime = contract.runs.get('run-confrontation') as Record const members = runtime.members as Array> const leader = members.find((member) => member.userId === '4')! const operator = members.find((member) => member.userId === '5')! leader.id = '9' operator.id = '2' runtime.member = leader await contract.install(page) await page.goto('/teaching/confrontation/runs/run-confrontation') await expect(page.getByRole('button', { name: '提交岗位动作', exact: true })).toBeEnabled() contract.setIdentity('studentLeader') await page.reload() await expect(page.getByRole('button', { name: '提交岗位动作', exact: true })).toBeDisabled() await expect(page.getByText(/此动作需由.*运行成员 ID 最小/)).toBeVisible() }) })