|
@@ -0,0 +1,22 @@
|
|
|
|
|
+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('../cloud/lesson-study.js',import.meta.url),'utf8');
|
|
|
|
|
+test('待确认批次从词库批量补中文释义,保留词序与掌握状态',async()=>{
|
|
|
|
|
+ const calls=[];const context={DEFAULT_COMPANY_ID:'co',assertLessonTenant:()=>{},orderDetailRow:async()=>({szyh:20}),parseArray:v=>Array.isArray(v)?v:JSON.parse(v||'[]'),fail:(_s,m)=>{throw Error(m);},Psql:{oneOrNone:async()=>null,query:async(sql,args)=>{calls.push({sql,args});if(sql.includes('LessonStudyBatch'))return[{batchId:'b',status:'draft',words:[{GeneralID:12,Title:'crop',check:1},{GeneralID:13,Title:'gather',check:2}]},{batchId:'recovered',status:'confirmed',provenance:'user-confirmed-recovery',words:[{GeneralID:14,Title:'church',check:0},{GeneralID:15,Title:'other',jssy:'旧词义',check:0}]}];if(sql.includes('VocabularyWord'))return[{generalId:13,sy:'聚集'},{generalId:12,sy:'庄稼'},{generalId:14,sy:'教堂'}];return[];}}};
|
|
|
|
|
+ vm.createContext(context);vm.runInContext(source,context);const result=await context.appLessonStudy({orderId:'1'},{});
|
|
|
|
|
+ assert.deepEqual(Array.from(result.batches[0].words,w=>[w.Title,w.sy,w.check]),[['crop','庄稼',1],['gather','聚集',2]]);
|
|
|
|
|
+ assert.equal(result.batches[1].words[0].sy,'教堂');assert.equal(result.batches[1].words[1].jssy,'旧词义');assert.equal(result.batches[1].words[1].sy,undefined);
|
|
|
|
|
+ assert.equal(calls.filter(c=>c.sql.includes('VocabularyWord')).length,1);
|
|
|
|
|
+});
|
|
|
|
|
+test('真实 SQL 可按单词编号关联词库并恢复含掌握状态的释义',async()=>{
|
|
|
|
|
+ const {PGlite}=await import('@electric-sql/pglite');const db=new PGlite();try{
|
|
|
|
|
+ await db.exec(`CREATE TABLE "LessonStudyBatch"(company text,"orderId" text,"batchId" text,status text,provenance text,"bindingId" text,words jsonb,"updatedAt" timestamptz);
|
|
|
|
|
+ CREATE TABLE "CourseBinding"(company text,"objectId" text,kcid text);CREATE TABLE "Node"(company text,"nodeId" numeric,"nodeName" text);
|
|
|
|
|
+ CREATE TABLE "DailyStudyRecord"(company text,id numeric,dsid text,"recordScope" text,xxqs text);
|
|
|
|
|
+ CREATE TABLE "CommonModel"(company text,"modelId" numeric,"itemId" numeric,"generalId" numeric);
|
|
|
|
|
+ CREATE TABLE "VocabularyWord"(company text,id numeric,sy text);
|
|
|
|
|
+ INSERT INTO "LessonStudyBatch" VALUES('co','1','recovery','confirmed','user-confirmed-recovery',null,'[{"GeneralID":12,"Title":"crop","check":2}]',now());
|
|
|
|
|
+ INSERT INTO "CommonModel" VALUES('co',52,7,12);INSERT INTO "VocabularyWord" VALUES('co',7,'庄稼');`);
|
|
|
|
|
+ const query=async(s,p=[])=>(await db.query(s,p)).rows,context={DEFAULT_COMPANY_ID:'co',assertLessonTenant:()=>{},orderDetailRow:async()=>({szyh:20}),parseArray:v=>Array.isArray(v)?v:JSON.parse(v||'[]'),Psql:{query,oneOrNone:async(s,p)=>(await query(s,p))[0]||null}};
|
|
|
|
|
+ vm.createContext(context);vm.runInContext(source,context);const result=await context.appLessonStudy({orderId:'1'},{});assert.equal(result.batches[0].words[0].sy,'庄稼');assert.equal(result.batches[0].words[0].check,2);
|
|
|
|
|
+ }finally{await db.close();}
|
|
|
|
|
+});
|