Advance when learning is complete and the platform exam is passed

This commit is contained in:
2026-10-06 02:38:21 +08:00
parent 606d264917
commit d80c490f48
5 changed files with 63 additions and 38 deletions
+32 -10
View File
@@ -7,23 +7,45 @@ async function test(name,fn){await fn();passed++;console.log(`PASS ${name}`);}
function mount(h){const nodes=new Map();const panel={querySelector(s){if(!nodes.has(s))nodes.set(s,{textContent:'',value:'all',checked:true});return nodes.get(s);}};
h.context.document.body={append(){}};h.context.document.createElement=()=>({style:{},attachShadow:()=>panel});h.api.mount();return nodes;}
(async()=>{
await test('a platform pass below 100 never counts as a completed course',()=>{
const d=detail();d.course.status='COMPLETED';d.course.examScorePercent=60;d.resources.forEach(r=>r.completed=true);
assert.equal(core.courseDone(d.course),false);assert.equal(core.videoPlan(d).kind,'quiz');
d.course.examScorePercent=100;assert.equal(core.courseDone(d.course),true);
await test('100 percent learning with a 75 percent passing exam is complete',()=>{
const d=detail();d.course.status='COMPLETED';d.course.progressPercent=100;d.course.examScorePercent=75;d.resources.forEach(r=>r.completed=true);
assert.equal(core.courseDone(d.course),true);assert.equal(core.videoPlan(d).kind,'finish');
d.course.examPassed=false;assert.equal(core.courseDone(d.course),false);assert.equal(core.videoPlan(d).kind,'quiz');
});
await test('a course below 100 starts its quiz before playing or switching video',async()=>{
await test('an unpassed exam starts its quiz before playing or switching video',async()=>{
const h=harness();let starts=0;const c=h.api.details.get(ID).course;c.examPassed=false;c.examScorePercent=0;
const button={textContent:'开始测验',disabled:false,getClientRects:()=>[{}],click(){starts++;}};
h.selectors.set('.course-quiz',{querySelector:()=>null,querySelectorAll:s=>s==='button'?[button]:[]});
h.api.begin();await h.api.tickCourse(ID);assert.equal(starts,1);assert.equal(h.video.playCount,0);assert.equal(h.buttons[1].clicks,0);assert.equal(h.video.paused,true);
});
await test('a low passing score with a missing retake entry stays armed and does not advance',async()=>{
const h=harness();const c=h.api.details.get(ID).course;c.examScorePercent=80;
const result={getClientRects:()=>[{}],querySelector:s=>s==='.quiz-result__status.is-pass'?{}:s==='.quiz-result__score strong'?{textContent:'80%'}:null};
await test('a low passing score needs no retake entry and allows return to the list',async()=>{
const h=harness();const d=h.api.details.get(ID);const c=d.course;c.examScorePercent=75;c.progressPercent=100;d.resources.forEach(r=>r.completed=true);
let backs=0;h.selectors.set('.van-nav-bar__left',{click(){backs++;}});
const result={getClientRects:()=>[{}],querySelector:s=>s==='.quiz-result__status.is-pass'?{}:s==='.quiz-result__score strong'?{textContent:'75%'}:null};
h.selectors.set('.course-quiz',{querySelector:s=>s==='.quiz-result'?result:null,querySelectorAll:()=>[]});
h.api.begin();await h.api.tickCourse(ID);assert.equal(h.api.state.armed,true);assert.equal(h.api.state.running,false);
assert.match(h.api.state.status,/100%/);assert.equal(h.video.playCount,0);assert.equal(h.buttons[1].clicks,0);
h.api.begin();h.api.tickQuiz(ID);await h.api.tickCourse(ID);assert.equal(h.api.state.armed,true);assert.equal(h.api.state.running,true);
assert.equal(backs,1);assert.equal(h.video.playCount,0);assert.equal(h.buttons[1].clicks,0);
});
await test('learning progress and exam score cannot substitute for each other',()=>{
const c={...detail().course,progressPercent:75,examScorePercent:100};assert.equal(core.courseDone(c),false);
c.progressPercent=100;c.examPassed=false;assert.equal(core.courseDone(c),false);
c.examPassed=true;c.examScorePercent=60;assert.equal(core.courseDone(c),true);
c.progressPercent=99;c.status='COMPLETED';assert.equal(core.courseDone(c),false);
});
await test('a passed 75 percent exam with unfinished learning continues its videos',async()=>{
const h=harness();const c=h.api.details.get(ID).course;c.progressPercent=75;c.examScorePercent=75;
h.api.begin();await h.api.tickCourse(ID);h.advance(1000);await h.api.tickCourse(ID);
assert.equal(h.video.playCount,1);assert.equal(core.courseDone(c),false);
});
await test('100 percent learning and a 75 percent pass advance from the result to the next course',async()=>{
const h=harness(),d=h.api.details.get(ID);d.course.progressPercent=100;d.course.examScorePercent=75;d.course.status='COMPLETED';
d.resources.forEach(r=>r.completed=true);
h.selectors.set('.van-nav-bar__left',{click(){h.context.location.hash='#/my-course';}});
const clicks=[0,0];const names=['课程一','课程二'];
h.selectors.set('article.course-row',names.map((name,index)=>({getClientRects:()=>[{}],querySelector:()=>({textContent:name}),click(){clicks[index]++;}})));
h.api.begin();await h.api.tickCourse(ID);h.advance(1000);
h.api.receive({id:'packages',tail:''},{bizCode:0,data:[{courses:[d.course,{id:'123',courseName:'课程二',progressPercent:0,examRequired:true,examPassed:false,status:'NOT_STARTED'}]}]},200);
await h.api.tick();assert.deepEqual(clicks,[0,1]);assert.equal(h.api.state.running,true);assert.equal(h.api.state.armed,true);
});
await test('temporary waits retain the started button state and retry automatically',async()=>{
const h=harness();const ui=mount(h);ui.get('[data-start]').onclick();h.api.park('网络等待');