fix: refresh grading status after review and ignore stale student responses
This commit is contained in:
@@ -217,6 +217,72 @@ test('score filters isolate actionable rows without hiding zero grades or changi
|
||||
expect(writes).toEqual([]);
|
||||
});
|
||||
|
||||
test('saving the last review refreshes batch status and keeps the active filter', async ({ page }) => {
|
||||
await setup(page);
|
||||
let saved = false;
|
||||
const saves: any[] = [];
|
||||
await page.route('**/api/scoring-batches', route => route.fulfill({ json: [{
|
||||
id: 71, course_version_id: 1, project_ids: [11], status: saved ? 'completed' : 'review_required',
|
||||
}] }));
|
||||
await page.route('**/api/projects/11/scores?*', route => route.fulfill({ json: {
|
||||
student_no: '9000000001', name: '学生甲', topic: '项目', totals: { overall: saved ? 0 : null }, facts: {},
|
||||
rows: [{ criterion: { criterion_id: 'stage3.plan', category: 'stage3', name: '下一阶段计划', max_score: 10 },
|
||||
score_id: 501, status: saved ? 'reviewed' : 'needs_review', final_score: saved ? 0 : null,
|
||||
teacher_score: saved ? 0 : null, teacher_comment: saved ? '已核对' : null,
|
||||
evidence: [], missing_evidence: ['计划'], evidence_gaps: [], model_comment: '需要教师核对' }],
|
||||
} }));
|
||||
await page.route('**/api/criterion-scores/501/review', route => {
|
||||
saves.push(route.request().postDataJSON()); saved = true;
|
||||
return route.fulfill({ json: { id: 501, status: 'reviewed', teacher_score: 0, final_score: 0 } });
|
||||
});
|
||||
await page.goto('/?page=scores&batch_id=71&project_id=11');
|
||||
await choose(page, '评分项筛选', '仅待教师复核(1)');
|
||||
await page.keyboard.press('Escape');
|
||||
await expect(page.locator('.ant-select-dropdown:visible')).toHaveCount(0);
|
||||
await page.getByRole('button', { name: '查看证据/复核' }).click();
|
||||
const modal = page.getByRole('dialog');
|
||||
await modal.getByRole('spinbutton', { name: '教师评分' }).fill('0');
|
||||
await modal.getByRole('textbox', { name: '教师评语' }).fill('已核对');
|
||||
await modal.getByRole('button', { name: '保存教师复核', exact: true }).click();
|
||||
await expect.poll(() => saves.length).toBe(1);
|
||||
expect(saves[0].score).toBe(0);
|
||||
await expect(page.getByText('批次 #71 · 已完成', { exact: true })).toBeVisible();
|
||||
await expect(page.getByText('仅待教师复核(0)', { exact: true })).toBeVisible();
|
||||
await expect(page.getByText('当前筛选下没有评分项', { exact: true })).toBeVisible();
|
||||
await expect(page.getByText('已评分 0 项 · 教师已复核 1 项 · 待处理 0 项', { exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
test('manual score refresh ignores late responses for a previously selected student', async ({ page }) => {
|
||||
await setup(page);
|
||||
let held = false, release: (() => void) | undefined;
|
||||
let firstReads = 0;
|
||||
await page.route('**/api/scoring-batches', route => route.fulfill({ json: [{
|
||||
id: 71, course_version_id: 1, project_ids: [11, 12], status: 'completed',
|
||||
}] }));
|
||||
await page.route('**/api/projects/*/scores?*', async route => {
|
||||
const isFirst = route.request().url().includes('/projects/11/');
|
||||
if (isFirst && ++firstReads > 1) {
|
||||
held = true;
|
||||
await new Promise<void>(resolve => { release = resolve; });
|
||||
}
|
||||
await route.fulfill({ json: {
|
||||
student_no: isFirst ? '9000000001' : '9000000002', name: isFirst ? '学生甲' : '学生乙',
|
||||
topic: isFirst ? '项目甲' : '项目乙', totals: {}, rows: [], facts: {},
|
||||
} });
|
||||
});
|
||||
await page.goto('/?page=scores&batch_id=71&project_id=11');
|
||||
await expect(page.getByText('9000000001 学生甲 · 项目甲', { exact: true })).toBeVisible();
|
||||
await page.getByRole('button', { name: '刷新评分', exact: true }).click();
|
||||
await expect.poll(() => held).toBe(true);
|
||||
await choose(page, '学生项目', /学生乙/);
|
||||
await page.keyboard.press('Escape');
|
||||
await expect(page.getByText('9000000002 学生乙 · 项目乙', { exact: true })).toBeVisible();
|
||||
const late = page.waitForResponse(response => response.url().includes('/projects/11/scores'));
|
||||
release!(); await late;
|
||||
await expect(page.getByText('9000000002 学生乙 · 项目乙', { exact: true })).toBeVisible();
|
||||
await expect(page.getByText('9000000001 学生甲 · 项目甲', { exact: true })).toHaveCount(0);
|
||||
});
|
||||
|
||||
test('a slow project list keeps the student specified in a multi-project batch link', async ({ page }) => {
|
||||
const state = await setup(page);
|
||||
await page.route('**/api/scoring-batches', route => route.fulfill({ json: [{
|
||||
|
||||
Reference in New Issue
Block a user