| 12345678910111213141516171819202122232425262728293031323334353637383940 |
- 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];
- test('real AI adapter appends all server-resolved words and rejects stale source before provider call',async()=>{
- const sent=[],wordList=Array.from({length:17},(_,i)=>'word'+i);
- const ctx=vm.createContext({Parse:{Config:{get:async()=>({get:()=> 'test-provider-token'})}},fetch:async(url,init)=>{sent.push(JSON.parse(init.body));return{ok:true,text:async()=>JSON.stringify({choices:[{message:{content:'article'}}]})}}});
- vm.runInContext(source,ctx);ctx.appReadingSource=async()=>({sourceVersion:'4',wordList});
- await ctx.readingAi({sourceStudyId:'fixture',sourceVersion:'4',prompt:'Write a story'},{});
- assert.equal(sent.length,1);for(const word of wordList)assert(sent[0].messages[0].content.includes(word));
- await assert.rejects(ctx.readingAi({sourceStudyId:'fixture',sourceVersion:'3',prompt:'Write a story'},{}),/已更新/);assert.equal(sent.length,1);
- });
- const lessonStudy=readFileSync(new URL('../cloud/lesson-study.js',import.meta.url),'utf8');
- function readingSourceContext(record,order,authorizeRecord=true,studentId=86){
- const calls=[];
- const ctx=vm.createContext({number:Number,recordDetailData:async()=>{if(!authorizeRecord)throw Object.assign(Error('无权查看该学员的学习记录'),{status:403});return{record,words:[{GeneralID:1,Title:'apple'},{GeneralID:2,Title:'school'}]};},orderDetailRow:async(id,current,authorize=true)=>{calls.push({id,authorize});if(authorize)throw Object.assign(Error('无权查看该业务记录'),{status:403});return order;},fail:(status,message)=>{throw Object.assign(Error(message),{status});}});
- vm.runInContext(lessonStudy,ctx);return{run:()=>ctx.appReadingSource({sourceStudyId:record.GeneralID,studentId},{id:'linked-teacher'}),calls};
- }
- test('关联老师可以用已授权的学员课堂词表生成阅读,无需读取其他老师的课程详情',async()=>{
- const {run,calls}=readingSourceContext({GeneralID:'study',userId:86,pl:104,dsid:'lesson',recordScope:'lesson',studyVersion:9},{szyh:86,pl:104,dszt:30});
- const result=await run();assert.equal(result.studentId,86);assert.equal(result.sourceVersion,'9');assert.deepEqual(Array.from(result.wordList),['apple','school']);assert.equal(calls.length,1);assert.equal(calls[0].authorize,false);
- });
- test('未通过学习记录授权的老师仍被拒绝,不继续读取课程',async()=>{
- const {run,calls}=readingSourceContext({GeneralID:'study',userId:86,dsid:'lesson',recordScope:'lesson'},{szyh:86,dszt:30},false);
- await assert.rejects(run(),e=>e.status===403);assert.equal(calls.length,0);
- });
- test('阅读词表不能使用其他学员的课程或尚未结束的课程',async()=>{
- const record={GeneralID:'study',userId:86,dsid:'lesson',recordScope:'lesson'};
- await assert.rejects(readingSourceContext(record,{szyh:85,dszt:30}).run(),/课程学员不一致/);
- await assert.rejects(readingSourceContext(record,null).run(),/课程学员不一致/);
- await assert.rejects(readingSourceContext(record,{szyh:86,dszt:10}).run(),/请先完成课程/);
- });
- test('历史非课堂记录沿用学习记录权限,不误触发预约详情权限',async()=>{
- const {run,calls}=readingSourceContext({GeneralID:'historical',userId:86,dsid:'old-lesson',updatedAt:'old-version'},null);
- assert.equal((await run()).studentId,86);assert.equal(calls.length,0);
- });
- test('阅读入口指定的学员必须与学习记录一致,不能串用关联学员词表',async()=>{
- const {run,calls}=readingSourceContext({GeneralID:'study',userId:86,dsid:'lesson',recordScope:'lesson'},{szyh:86,dszt:30},true,85);
- await assert.rejects(run(),e=>e.status===403&&e.message.includes('阅读学员与学习记录不一致'));assert.equal(calls.length,0);
- });
|