|
- import assert from 'node:assert/strict'
- import test from 'node:test'
- import { readFileSync } from 'node:fs'
- import { createRequire } from 'node:module'
-
- const requireWeb = createRequire(new URL('../../unreal_tran_web/package.json', import.meta.url))
- const ts = requireWeb('typescript')
- const source = new URL('../../unreal_tran_web/src/features/', import.meta.url)
- const compile = path => ts.transpileModule(readFileSync(new URL(path, source), 'utf8'), {
- compilerOptions: { target: ts.ScriptTarget.ES2022, module: ts.ModuleKind.ESNext },
- }).outputText
- const url = text => `data:text/javascript;base64,${Buffer.from(text).toString('base64')}`
- const documentUrl = url(compile('training/trainingDocument.ts'))
- const bridgeUrl = url(compile('training-legacy/bridge.ts').replace(/from ['"]\.\.\/training\/trainingDocument['"]/, `from '${documentUrl}'`))
- const { trainingProjectMetadata } = await import(url(compile('training-legacy/trainingProjectMetadata.ts')))
- const { toFormalContent, toLegacyProject } = await import(bridgeUrl)
- const { saveTrainingWithCover } = await import(url(compile('training-legacy/trainingCoverPersistence.ts')))
- const current = () => ({ id: '161', type: 'TRAINING', name: 'Original name', description: 'Project purpose from creation',
- categoryCode: 'RESOURCE-TEST', trainingMode: 'VIRTUAL', content: {}, assets: [], coverUri: '', version: 3 })
-
- test('edited project name and task settings survive actual formal/legacy save roundtrip', async () => {
- const original = current()
- const legacy = { name: ' Fox inspection training ', trainingMode: 'virtual',
- task: { description: 'Inspect the visible fox', category: 'Task subject', duration: 12, level: 'L2' },
- runtime: { startMode: 'exam' }, steps: [] }
- const metadata = trainingProjectMetadata(legacy, original)
- const { content } = toFormalContent(legacy, metadata.trainingMode, original.content)
- let received
- const result = await saveTrainingWithCover(original, { ...original, ...metadata, content, dependencies: [] },
- async () => { throw new Error('No viewport in metadata unit test') }, {
- upload: async () => { throw new Error('unexpected upload') },
- update: async body => { received = structuredClone(body); return { ...body, version: 4 } },
- }, () => {})
- const reopened = toLegacyProject(result.project)
- assert.equal(received.name, 'Fox inspection training')
- assert.equal(reopened.name, 'Fox inspection training')
- assert.equal(received.description, original.description, 'project purpose is independent of task instructions')
- assert.equal(received.categoryCode, original.categoryCode, 'task category must not replace the project category')
- assert.equal(reopened.task.description, 'Inspect the visible fox')
- assert.equal(reopened.task.category, 'Task subject')
- assert.equal(reopened.runtime.startMode, 'exam', 'demo/practice/exam is runtime mode, not training channel')
- assert.equal(reopened.task.duration, 12)
- assert.equal(received.content.name, undefined, 'project name belongs only to the envelope')
- assert.equal(original.name, 'Original name')
- })
-
- test('supported document training modes agree across envelope, normalized content and reopened editor', () => {
- for (const mode of ['virtual', 'physical', 'confrontation']) {
- const previous = current()
- const legacy = { name: 'Edited', trainingMode: mode, steps: [], task: {} }
- const metadata = trainingProjectMetadata(legacy, previous)
- const { content } = toFormalContent(legacy, metadata.trainingMode, previous.content)
- const reopened = toLegacyProject({ ...previous, ...metadata, content })
- assert.equal(metadata.trainingMode, mode.toUpperCase())
- assert.equal(content.trainingMode, metadata.trainingMode)
- assert.ok(content.enabledChannels.includes(metadata.trainingMode))
- assert.equal(reopened.trainingMode, mode)
- }
- })
-
- test('missing envelope fields retain existing values while invalid supplied mode fails explicitly', () => {
- const previous = current()
- assert.deepEqual(trainingProjectMetadata({ task: { description: 'Default task prose' } }, previous), {
- name: previous.name, description: previous.description, categoryCode: previous.categoryCode, trainingMode: previous.trainingMode,
- })
- assert.throws(() => trainingProjectMetadata({ trainingMode: 'exam' }, previous), /训练形态无效/)
- })
-
- test('server mode rejection propagates without treating metadata as successfully saved', async () => {
- const previous = current()
- const metadata = trainingProjectMetadata({ name: 'Changed', trainingMode: 'physical' }, previous)
- const denied = new Error('模式修改不允许')
- await assert.rejects(saveTrainingWithCover(previous, { ...previous, ...metadata },
- async () => { throw new Error('No viewport') }, {
- upload: async () => { throw new Error('unexpected upload') },
- update: async () => { throw denied },
- }, () => {}), error => error === denied)
- assert.equal(previous.name, 'Original name')
- assert.equal(previous.trainingMode, 'VIRTUAL')
- })
|