const assert = require("assert"); const fs = require("fs"); const path = require("path"); const root = path.resolve(__dirname, ".."); const read = (file) => fs.readFileSync(path.join(root, file), "utf8"); const auth = read("src/utils/auth.js"); const demoStorage = read("src/utils/studentDemo.js"); const api = read("src/api/studentDemo.js"); const teacherPage = read("src/views/teacherEnd/trainingTask/index.vue"); const demoPage = read("src/views/studentDemo/index.vue"); assert(auth.includes("getStudentDemoSession") && demoStorage.includes("sessionStorage"), "demo token must use tab-local session storage"); assert(api.includes("/api/teacher/student-demo-sessions"), "teacher ticket API missing"); assert(api.includes("/api/student-demo-sessions/exchange"), "ticket exchange API missing"); assert(teacherPage.includes("学生端讲解"), "teacher entry missing"); assert(teacherPage.includes("window.open("), "teacher entry must open a new window"); assert(teacherPage.includes("STUDENT_DEMO_READY"), "teacher must wait for child readiness"); assert(demoPage.includes("STUDENT_DEMO_TICKET"), "demo page must receive ticket via postMessage"); assert(demoPage.includes("window.location.origin"), "postMessage must validate origin"); assert(!teacherPage.includes("ticket="), "ticket must not be sent in URL"); console.log("student demo mode front-end contract passed");