import {test} from 'node:test'; import assert from 'node:assert/strict'; import {readFileSync} from 'node:fs'; import vm from 'node:vm'; const source=readFileSync(new URL('../deploy-admin-functions.mjs',import.meta.url),'utf8').match(/const appGatewayCode = String.raw`([\s\S]*?)\n`;/)[1]; function context({category='primary_writing',learned=0,student=20,status=30,authorized=true,words='[]'}={}) { let legacyCalls=0; const ctx=vm.createContext({Parse:{},Psql:{query:async()=>[{company:'co',generalId:100,__addon:{userId:20,dsid:200,xxqs:words,learned}}]}}); vm.runInContext(source,ctx); ctx.authorizeLearningRecordAccess=async()=>{if(!authorized)throw Error('无权查看');}; ctx.orderDetailRow=async()=>({szyh:student,dszt:status,courseCategoryKey:category}); ctx.legacyStudyRecordWords=async()=>{legacyCalls++;return[];}; return {run:()=>ctx.recordDetailData({id:100},{}),legacyCalls:()=>legacyCalls}; } for(const category of ['primary_writing','middle_writing','high_writing'])test(category+' empty confirmed source is an intentional notes review',async()=>{ const c=context({category}),result=await c.run();assert.equal(result.words.length,0);assert.equal(result.addon[0].reviewContentMode,'notes');assert.equal(c.legacyCalls(),0); }); for(const options of [{category:'word'},{learned:1},{student:21},{status:10}])test('missing words are not converted into notes: '+JSON.stringify(options),async()=>{ const c=context(options),result=await c.run();assert.equal(result.addon[0].reviewContentMode,undefined);assert.equal(c.legacyCalls(),1); }); test('notes review still requires source record authorization',async()=>{const c=context({authorized:false});await assert.rejects(c.run(),/无权查看/);assert.equal(c.legacyCalls(),0);});