Fix desktop quiz submission and keep runs enabled until cancelled
This commit is contained in:
+11
-4
@@ -48,7 +48,7 @@ test('quiz observer scopes exact endpoints and origins', () => {
|
||||
// The userscript must click choices, submit, confirm, read the answer card and retry.
|
||||
function simulator({feedback=true,exhaust=false,threshold=100}={}) {
|
||||
const h=harness(); let view='idle', dialog=false, attempt=0, submissions=0;
|
||||
let answers={}, selected={}, lastCard=[];
|
||||
let answers={}, selected={}, lastCard=[],scorePercent=0;
|
||||
const definitions=[q('q1'),q('q2'),q('q3','multi')];
|
||||
const expected={q1:['A'],q2:['B'],q3:['A','B']};
|
||||
const clicks=[];
|
||||
@@ -66,11 +66,14 @@ function simulator({feedback=true,exhaust=false,threshold=100}={}) {
|
||||
});
|
||||
const start=button('开始测验',begin);
|
||||
const submit=button('交卷',()=>{dialog=true;});
|
||||
const hiddenFooter=button('交卷',()=>{throw new Error('Must not click hidden mobile footer');});
|
||||
hiddenFooter.getClientRects=()=>[];
|
||||
const confirm=button('确定交卷',()=>{
|
||||
dialog=false; ++submissions; answers=structuredClone(selected);
|
||||
const body={answers:definitions.map(d=>d.type==='multi'?{questionId:d.id,selectedOptionKeys:answers[d.id]}:{questionId:d.id,selectedOptionKey:answers[d.id][0]})};
|
||||
lastCard=body.answers.map(a=>({...a,correct:JSON.stringify([...(answers[a.questionId]||[])].sort())===JSON.stringify(expected[a.questionId])}));
|
||||
const score=lastCard.filter(a=>a.correct).length/definitions.length*100;
|
||||
scorePercent=score;
|
||||
const examId=String(900+attempt);
|
||||
h.api.receive({kind:'answers',examId,body},{bizCode:0,data:{}},200);
|
||||
h.api.receive({kind:'submit',examId},{bizCode:0,data:{scorePercent:score,passed:score>=threshold,canRetry:!exhaust,attemptsExhausted:exhaust}},200);
|
||||
@@ -86,12 +89,12 @@ function simulator({feedback=true,exhaust=false,threshold=100}={}) {
|
||||
})):[]}));
|
||||
const root=element({
|
||||
querySelector(s){
|
||||
if(s==='.quiz-result'&&['pass','fail'].includes(view)) return element({querySelector:s=>s==='.quiz-result__status.is-pass'&&view==='pass'?{}:s==='.quiz-result__score strong'?{textContent:view==='pass'?'100%':'33%'}:null});
|
||||
if(s==='.quiz-result'&&['pass','fail'].includes(view)) return element({querySelector:s=>s==='.quiz-result__status.is-pass'&&view==='pass'?{}:s==='.quiz-result__score strong'?{textContent:scorePercent+'%'}:null});
|
||||
if(s==='.quiz-result__exhausted'&&view==='fail'&&exhaust)return {};
|
||||
if(s==='button.quiz-footer__submit'&&view==='form') return submit;
|
||||
if(s==='button.quiz-footer__submit'&&view==='form') return hiddenFooter;
|
||||
return null;
|
||||
},
|
||||
querySelectorAll(s){if(s==='article.quiz-question')return view==='form'?nodes:[];if(s==='button')return view==='idle'?[start]:view==='fail'?[retry]:[];return [];}
|
||||
querySelectorAll(s){if(s==='article.quiz-question')return view==='form'?nodes:[];if(s==='button')return view==='idle'?[start]:view==='fail'?[retry]:view==='form'?[hiddenFooter,submit]:[];return [];}
|
||||
});
|
||||
h.selectors.set('.course-quiz',root);
|
||||
const original=h.context.document.querySelectorAll;
|
||||
@@ -124,4 +127,8 @@ test('foreign exam submission cannot teach this attempt', () => {
|
||||
s.h.api.receive({kind:'submit',examId:'123456'},{bizCode:0,data:{scorePercent:100,passed:true}},200);
|
||||
assert.equal(Object.keys(s.h.api.state.bank).length,0);
|
||||
});
|
||||
test('unlimited retakes are not stopped by the old 256-round cap',()=>{
|
||||
const s=simulator();s.h.api.tickQuiz(ID);s.h.api.state.quiz.round=300;s.run();
|
||||
assert.equal(s.view,'pass');assert.equal(s.submissions,3);assert.ok(s.h.api.state.armed);
|
||||
});
|
||||
console.log(`${passed} quiz tests passed.`);
|
||||
|
||||
Reference in New Issue
Block a user