升级学生档案管理
This commit is contained in:
+136
-17
@@ -1,25 +1,39 @@
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const vm = require("vm");
|
||||
|
||||
const staticDir = path.resolve(__dirname, "../app/static");
|
||||
|
||||
function domNode(id, extras = {}) {
|
||||
let value = "";
|
||||
return {
|
||||
id,
|
||||
textContent: "",
|
||||
innerHTML: "",
|
||||
hidden: false,
|
||||
disabled: false,
|
||||
dataset: {},
|
||||
classList: { toggle() {} },
|
||||
get value() {
|
||||
return value;
|
||||
},
|
||||
set value(nextValue) {
|
||||
value = String(nextValue ?? "");
|
||||
},
|
||||
setAttribute(name, nextValue) {
|
||||
this[name] = nextValue;
|
||||
},
|
||||
addEventListener() {},
|
||||
focus() {},
|
||||
...extras,
|
||||
};
|
||||
}
|
||||
|
||||
const elements = new Map();
|
||||
|
||||
function element(id) {
|
||||
if (!elements.has(id)) {
|
||||
elements.set(id, {
|
||||
id,
|
||||
textContent: "",
|
||||
innerHTML: "",
|
||||
hidden: false,
|
||||
disabled: false,
|
||||
value: "",
|
||||
dataset: {},
|
||||
classList: { toggle() {} },
|
||||
setAttribute(name, value) {
|
||||
this[name] = value;
|
||||
},
|
||||
addEventListener() {},
|
||||
focus() {},
|
||||
});
|
||||
elements.set(id, domNode(id));
|
||||
}
|
||||
return elements.get(id);
|
||||
}
|
||||
@@ -52,6 +66,9 @@ const context = {
|
||||
Number,
|
||||
String,
|
||||
};
|
||||
context.window = { location: { href: "" } };
|
||||
context.confirm = () => true;
|
||||
context.alert = () => {};
|
||||
|
||||
function assertEqual(name, actual, expected) {
|
||||
if (actual !== expected) {
|
||||
@@ -64,7 +81,7 @@ function value(expression) {
|
||||
}
|
||||
|
||||
vm.createContext(context);
|
||||
vm.runInContext(fs.readFileSync("app/static/app.js", "utf8"), context);
|
||||
vm.runInContext(fs.readFileSync(path.join(staticDir, "app.js"), "utf8"), context);
|
||||
|
||||
vm.runInContext(
|
||||
`
|
||||
@@ -102,4 +119,106 @@ assertEqual("纠错后排序仍使用显示记录", value("currentRecordOrder.jo
|
||||
vm.runInContext("updateCorrectionToolbar('测试提交按钮')", context);
|
||||
assertEqual("提交审核按钮文案", value("submitCorrectionsBtn.textContent"), "提交审核 1 条");
|
||||
|
||||
console.log("smoke test passed");
|
||||
const adminElements = new Map();
|
||||
function adminElement(id) {
|
||||
if (!adminElements.has(id)) {
|
||||
adminElements.set(id, domNode(id, {
|
||||
scrollIntoView() {},
|
||||
}));
|
||||
}
|
||||
return adminElements.get(id);
|
||||
}
|
||||
|
||||
const adminFetchUrls = [];
|
||||
const adminContext = {
|
||||
console,
|
||||
navigator: {},
|
||||
Date,
|
||||
JSON,
|
||||
Map,
|
||||
Number,
|
||||
String,
|
||||
URLSearchParams,
|
||||
window: { location: { href: "" } },
|
||||
confirm: () => true,
|
||||
alert: () => {},
|
||||
document: {
|
||||
querySelector(selector) {
|
||||
return adminElement(selector.replace(/^#/, ""));
|
||||
},
|
||||
querySelectorAll() {
|
||||
return [];
|
||||
},
|
||||
addEventListener() {},
|
||||
createElement(tag) {
|
||||
return adminElement(`created-${tag}-${adminElements.size}`);
|
||||
},
|
||||
body: { appendChild() {} },
|
||||
execCommand() {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
fetch: async (url) => {
|
||||
adminFetchUrls.push(String(url));
|
||||
if (String(url).startsWith("/api/students")) {
|
||||
return {
|
||||
ok: true,
|
||||
json: async () => ({
|
||||
summary: { total: 1, debt: 0, warning: 0, normal: 1 },
|
||||
count: 1,
|
||||
students: [
|
||||
{
|
||||
student_id: "XS001",
|
||||
student: "甲",
|
||||
primary_entry_year: 2020,
|
||||
account_status: "正常",
|
||||
remaining: 12,
|
||||
remaining_duration: "12小时",
|
||||
payments: [{ date: "2026-06-01", hours: 12, duration: "12小时" }],
|
||||
note: "备注",
|
||||
},
|
||||
],
|
||||
}),
|
||||
};
|
||||
}
|
||||
return {
|
||||
ok: true,
|
||||
json: async () => ({
|
||||
ok: true,
|
||||
students_count: 1,
|
||||
active_teachers_count: 0,
|
||||
records_count: 0,
|
||||
course_summaries_count: 0,
|
||||
current_month_hours: 0,
|
||||
current_month_duration: "0小时",
|
||||
overview: {},
|
||||
students: { summary: {}, low_remaining: [] },
|
||||
teachers: {},
|
||||
course_summaries: {},
|
||||
tasks: {},
|
||||
teaching: {},
|
||||
period: {},
|
||||
}),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
vm.createContext(adminContext);
|
||||
vm.runInContext(fs.readFileSync(path.join(staticDir, "admin.js"), "utf8"), adminContext);
|
||||
vm.runInContext("loadStudents()", adminContext);
|
||||
setTimeout(() => {
|
||||
if (!adminFetchUrls.some((url) => url.startsWith("/api/students"))) {
|
||||
throw new Error(`学生档案列表未调用 /api/students:${adminFetchUrls.join(",")}`);
|
||||
}
|
||||
const rowsHtml = adminElements.get("studentRows").innerHTML;
|
||||
if (!rowsHtml.includes("XS001") || !rowsHtml.includes("2020")) {
|
||||
throw new Error("学生档案列表未渲染学生ID和入学年份");
|
||||
}
|
||||
vm.runInContext('openEditStudentEditor("XS001")', adminContext);
|
||||
const payload = vm.runInContext("buildStudentPayload()", adminContext);
|
||||
if (Object.prototype.hasOwnProperty.call(payload, "remaining")) {
|
||||
throw new Error("学生档案保存 payload 不应包含 remaining");
|
||||
}
|
||||
assertEqual("学生档案剩余课时只读展示", adminElements.get("editRemaining").value, "12小时");
|
||||
console.log("smoke test passed");
|
||||
}, 0);
|
||||
|
||||
Reference in New Issue
Block a user