You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
dianshang-qianduan/tests/ai-training-evaluation.stat...

63 lines
4.5 KiB
JavaScript

const assert = require("assert");
const fs = require("fs");
const path = require("path");
const root = path.resolve(__dirname, "..");
const api = fs.readFileSync(path.join(root, "src/api/aiTrainingEvaluation.js"), "utf8");
const component = fs.readFileSync(path.join(root, "src/views/components/TrainingAiEvaluation.vue"), "utf8");
const sidebar = fs.readFileSync(path.join(root, "src/views/components/TrainingAiSidebar.vue"), "utf8");
const page = fs.readFileSync(path.join(root, "src/views/training/GenericTrainingPage.vue"), "utf8");
const { normalizeEvaluationReports } = require(path.join(root, "src/views/components/trainingAiEvaluationReport.cjs"));
assert(/`\/api\/student\/training-tasks\/\$\{taskKey\}\/ai-evaluation`/.test(api), "evaluation API should use the student task endpoint");
assert(/\/help/.test(api) && /\/assessment/.test(api), "evaluation API should expose help and assessment operations");
assert(/TrainingAiSidebar/.test(page) && /:has-saved-answer="hasSavedAnswer"/.test(page), "generic training page should pass persisted answer state to the AI sidebar");
assert(/form\.value/.test(page) && /workRows\.value/.test(page) && /processRows\.value/.test(page), "hasAnyAnswer should inspect all supported answer shapes");
assert(/onMounted\(/.test(component) && /watch\(\s*\(\)\s*=>\s*props\.taskKey/.test(component), "AI evaluation should load on mount and task changes");
assert(/AI助学/.test(component) && /AI助评/.test(component), "AI evaluation should offer separate help and assessment controls");
assert(/PROCESSING/.test(component) && /SUCCEEDED/.test(component), "AI evaluation should surface backend statuses");
assert(/!props\.hasAnyAnswer/.test(component), "AI actions should disable when no answer is available");
assert(/proxy\?\.\$modal\?\.confirm/.test(component), "assessment should request confirmation through the modal proxy");
assert(!/v-html/.test(component), "AI reports must be rendered as interpolated text, never v-html");
assert(/scoreCriteria/.test(component), "assessment should display score criteria");
assert(/normalizeEvaluationReports/.test(component), "the component should use the executable report normalizer");
const normalizedFlatPayload = normalizeEvaluationReports({
helpStatus: "succeeded",
helpReportJson: JSON.stringify({ summary: "Add supporting data", suggestions: ["Cite the source"] }),
assessmentStatus: "succeeded",
assessmentScore: 92,
assessmentReportJson: JSON.stringify({
summary: "Clear analysis",
criteria: [
{ criterion: "Evidence", weight: 40, detail: "Uses relevant data" },
"Structure",
],
}),
});
assert.strictEqual(normalizedFlatPayload.help.status, "SUCCEEDED", "flat help status should be normalized");
assert.match(normalizedFlatPayload.helpReport, /Add supporting data/, "flat help JSON should be formatted for text display");
assert.strictEqual(normalizedFlatPayload.assessment.status, "SUCCEEDED", "flat assessment status should be normalized");
assert.strictEqual(normalizedFlatPayload.score, 92, "assessmentScore should take precedence for the displayed score");
assert.deepStrictEqual(normalizedFlatPayload.scoreCriteria, [
{ name: "Evidence", score: 40, description: "Uses relevant data" },
{ name: "Structure", score: "", description: "" },
], "assessment criteria should be mapped from the flat assessment JSON");
const malformedPayload = normalizeEvaluationReports({
helpReportJson: "{not valid JSON",
assessmentReportJson: "{also not valid JSON",
});
assert.strictEqual(malformedPayload.helpReport, "{not valid JSON", "malformed help JSON should remain safe text");
assert.strictEqual(malformedPayload.assessmentReport, "{also not valid JSON", "malformed assessment JSON should remain safe text");
assert.strictEqual(malformedPayload.score, null, "malformed assessment JSON should not produce a score");
assert.deepStrictEqual(malformedPayload.scoreCriteria, [], "malformed assessment JSON should not produce criteria");
assert(/retry/.test(component) || /重试/.test(component), "failed AI operations should expose a retry action");
assert(/hasSavedAnswer/.test(page) && /:has-saved-answer="hasSavedAnswer"/.test(page), "generic training page should distinguish persisted answers before enabling AI assessment");
assert(/hasSavedAnswer/.test(sidebar), "AI sidebar should accept persisted-answer state");
assert(/!props\.hasSavedAnswer/.test(sidebar), "AI assessment should be disabled until a saved answer exists");
assert(/catch \(error\)/.test(sidebar), "AI sidebar should handle assessment failures without an unhandled rejection");