workshop-data.test.js 3.6 KB

12345678910111213141516171819
  1. import test from 'node:test';
  2. import assert from 'node:assert/strict';
  3. import {loadPublicBoard,publicBoardAction} from '../src/services/workshop-data.js';
  4. import {buildModel} from '../src/core/kfs/build.js';
  5. const blank=()=>Object.fromEntries(['project','artifact','insight','source','session','opportunity'].map(k=>[k,[]]));
  6. test('公开操作只发一次,不带身份密钥;业务失败与未知写结果均不重试',async()=>{
  7. const base={url:'/api/functions',appId:'public-id',name:'ksfSetPublicOpportunityStatus',params:{requestId:'same-request'}};
  8. let calls=0;
  9. const fetchImpl=async(_url,options)=>{calls++;assert.deepEqual(Object.keys(options.headers).sort(),['Content-Type','X-Parse-Application-Id']);return{ok:true,json:async()=>({result:{ok:false,errors:[{code:'VERSION_CONFLICT',message:'请刷新'}]}})};};
  10. await assert.rejects(()=>publicBoardAction({...base,fetchImpl}),{code:'VERSION_CONFLICT',requestId:'same-request'});assert.equal(calls,1);
  11. calls=0;await assert.rejects(()=>publicBoardAction({...base,fetchImpl:async()=>{calls++;throw Error('connection closed');}}),/connection closed/);assert.equal(calls,1);
  12. });
  13. test('公开查询无需身份凭据,分页合并,不用 REST count',async()=>{const requests=[];const raw=await loadPublicBoard({appId:'public-id',fetchImpl:async(url,options)=>{
  14. requests.push({url,options});const params=JSON.parse(options.body).params;
  15. return{ok:true,json:async()=>({result:{ok:true,data:{...blank(),artifact:[{objectId:params.cursor?'a2':'a1'}],nextCursor:params.cursor?null:'next',asOf:'now'}}})};
  16. }});assert.deepEqual(raw.artifact.map(x=>x.objectId),['a1','a2']);assert.equal(requests.length,2);assert.ok(requests.every(x=>!Object.keys(x.options.headers).some(k=>/token|master|authorization/i.test(k))));});
  17. test('新版阶段/项目 Pointer 与 Agent 归属进入既有模型,显式卡住可见',()=>{const raw={...blank(),project:[{objectId:'p',title:'项目',stageCode:'S4',ownerName:'彭智康',uploadedByKey:'participant:one',progressState:'blocked'}],artifact:[{objectId:'a',title:'报告',stageCode:'S3',projectRef:{objectId:'p'},ownerName:'彭智康',uploadedByKey:'participant:one',agentName:'王刚001',agentId:'name:王刚001',uploadMethod:'session'}],session:[{objectId:'s',studentName:'彭智康',stageCode:'S4',groupId:'G1',meta:{participantKey:'participant:one'}}]};const db=buildModel(raw);assert.equal(db.artifacts[0].stageObj.code,'S3');assert.equal(db.artifacts[0].projectId,'p');assert.equal(db.artifacts[0].upload.agentName,'王刚001');assert.equal(db.projects[0].stage.code,'S4');assert.deepEqual(db.projects[0].artifactIds,['a']);assert.equal(db.memberByName['彭智康'].stuck,true);});
  18. test('同名学员不同稳定键不会合并为一个人',()=>{const raw={...blank(),session:[{objectId:'s1',studentName:'同名',groupId:'G1',meta:{participantKey:'participant:one'}},{objectId:'s2',studentName:'同名',groupId:'G2',meta:{participantKey:'participant:two'}}]};const db=buildModel(raw);assert.equal(db.members.length,2);assert.ok(db.memberByName['同名(G1)']);assert.ok(db.memberByName['同名(G2)']);});
  19. test('同组同名学员仍分开,并将项目归给正确参与人',()=>{const raw={...blank(),session:[{objectId:'s1',studentName:'同名',groupId:'G1',meta:{participantKey:'participant:00000001'}},{objectId:'s2',studentName:'同名',groupId:'G1',meta:{participantKey:'participant:00000002'}}],project:[{objectId:'p',ownerName:'同名',uploadedByKey:'participant:00000002'}]};const db=buildModel(raw);assert.equal(db.members.length,2);assert.deepEqual(db.memberByName['同名(G1 · 00000002)'].projectIds,['p']);assert.equal(db.memberByName['同名(G1 · 00000001)'].projectIds.length,0);});