const { test } = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const vm = require('node:vm'); const ts = require('typescript'); const React = require('react'); const { renderToStaticMarkup } = require('react-dom/server'); test('course detail opens a pinned lecture without a platform connection', () => { const source = fs.readFileSync(require.resolve('../src/renderer/src/features/curriculum/CurriculumDetailPanel.tsx'), 'utf8'); const exports = {}; const output = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, jsx: ts.JsxEmit.ReactJSX, esModuleInterop: true } }).outputText; vm.runInNewContext(output, { exports, require: name => name === '../../i18n' ? { t: value => value, useLocaleRender() {} } : require(name) }); const props = { week: { week: 1, title: '제어', topics: ['속도'], detail: { overview: '개요', topicDetails: ['설명'], deliverable: '확인', learningSteps: [{ lectureVersionId: 'pinned-v1' }] } }, selected: true, activeLearningStep: '속도' }; const html = renderToStaticMarkup(React.createElement(exports.default, { ...props, onOpenLecture() {} })); assert.match(html, /슬라이드·퀴즈 열기/); assert.doesNotMatch(renderToStaticMarkup(React.createElement(exports.default, props)), /슬라이드·퀴즈 열기/); }); test('quiz sends answers only and maintains a stable request ID for retry', () => { const source = fs.readFileSync(require.resolve('../src/renderer/src/features/curriculum/LectureViewerModal.tsx'), 'utf8'); assert.match(source, /\/quiz/); assert.match(source, /questionId: q.id/); assert.match(source, /optionIndex: answers\[q.id\]/); assert.match(source, /requestId.current \?\?= crypto.randomUUID/); assert.match(source, /signal: controller.current.signal/); assert.doesNotMatch(source, /score:.*answers/); }); test('lecture controls have English translations', () => { const en = require('../src/renderer/src/i18n/en.json'); for (const key of ['슬라이드·퀴즈 열기', '강의 닫기', '슬라이드', '퀴즈', '답안 제출', '다시 풀기']) assert.ok(en[key], key); });