forked from wangziqi/gongxue-base
feat: improve student practice experience
This commit is contained in:
@@ -1065,6 +1065,20 @@ async function testCatalogAndLearning() {
|
||||
});
|
||||
assert.equal(answer.item?.isCorrect, false, 'wrong answer should be judged false');
|
||||
|
||||
const selfJudgedObjective = await request('/api/learning/answers', {
|
||||
userId: false,
|
||||
headers: { authorization: `Bearer ${freeLogin.session.token}` },
|
||||
method: 'POST',
|
||||
body: {
|
||||
questionId: ids.question,
|
||||
selectedOptions: ['0'],
|
||||
selfJudgedCorrect: true,
|
||||
practiceSessionId: freeSession.item.id,
|
||||
},
|
||||
expectStatus: 400,
|
||||
});
|
||||
assert.equal(selfJudgedObjective.code, 'SELF_JUDGMENT_NOT_ALLOWED', 'objective questions must not accept self judgment');
|
||||
|
||||
const staffSequentialSession = await request('/api/learning/practice-sessions', {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
method: 'POST',
|
||||
@@ -1128,6 +1142,19 @@ async function testCatalogAndLearning() {
|
||||
practiceSessionId: mockSession.item.id,
|
||||
},
|
||||
});
|
||||
const subjectiveAnswer = await request('/api/learning/answers', {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
method: 'POST',
|
||||
body: {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
questionId: ids.questionThree,
|
||||
answerText: '已经对照参考答案完成自评',
|
||||
selfJudgedCorrect: true,
|
||||
practiceSessionId: mockSession.item.id,
|
||||
},
|
||||
});
|
||||
assert.equal(subjectiveAnswer.item?.isCorrect, true, 'subjective self judgment should be persisted by backend');
|
||||
assert.equal(subjectiveAnswer.item?.selfJudged, true, 'subjective answer response should mark self judgment');
|
||||
|
||||
const mockReport = await request('/api/learning/practice-sessions/submit', {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
@@ -1139,14 +1166,18 @@ async function testCatalogAndLearning() {
|
||||
});
|
||||
assert.equal(mockReport.item?.practiceSessionId, mockSession.item.id, 'mock submit should create a report for the session');
|
||||
assert.equal(mockReport.item?.totalQuestions, 3, 'mock report should count session snapshot questions');
|
||||
assert.equal(mockReport.item?.answeredCount, 2, 'mock report should count latest submitted answers');
|
||||
assert.equal(mockReport.item?.correctCount, 1, 'mock report should count correct answers');
|
||||
assert.equal(mockReport.item?.answeredCount, 3, 'mock report should count latest submitted answers');
|
||||
assert.equal(mockReport.item?.correctCount, 2, 'mock report should count correct answers');
|
||||
assert.equal(mockReport.item?.wrongCount, 1, 'mock report should count wrong answers');
|
||||
assert.equal(mockReport.item?.unansweredCount, 1, 'mock report should count unanswered questions');
|
||||
assert.equal(mockReport.item?.score, 2, 'mock report should use backend scoring only');
|
||||
assert.equal(mockReport.item?.unansweredCount, 0, 'mock report should count unanswered questions');
|
||||
assert.equal(mockReport.item?.score, 4, 'mock report should use backend scoring only');
|
||||
assert.equal(mockReport.item?.totalScore, 100, 'mock report should keep configured paper total score');
|
||||
assert.ok(mockReport.item?.wrongQuestionIds?.includes(ids.questionTwo), 'mock report should include wrong question ids');
|
||||
assert.ok(mockReport.item?.questionResults?.some(item => item.questionId === ids.question && item.isCorrect === true), 'mock report should include per-question result');
|
||||
assert.ok(
|
||||
mockReport.item?.questionResults?.some(item => item.questionId === ids.questionThree && item.isCorrect === true && item.answerText === '已经对照参考答案完成自评'),
|
||||
'mock report should include backend-persisted subjective self judgment',
|
||||
);
|
||||
|
||||
const idempotentReport = await request('/api/learning/practice-sessions/submit', {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
|
||||
@@ -986,7 +986,7 @@ async function main() {
|
||||
),
|
||||
(
|
||||
$4, $2, $5, $6, $7, $8, $9, $10,
|
||||
'smoke-question-3', 'choice', '单选题', 1, 'published',
|
||||
'smoke-question-3', 'short_answer', '简答题', 1, 'published',
|
||||
'{"examTrack":"professional","school":"烟测学院"}'::jsonb
|
||||
)
|
||||
on conflict (id)
|
||||
@@ -996,6 +996,10 @@ async function main() {
|
||||
entry_id = excluded.entry_id,
|
||||
content_node_id = excluded.content_node_id,
|
||||
primary_collection_id = excluded.primary_collection_id,
|
||||
type = excluded.type,
|
||||
type_label = excluded.type_label,
|
||||
difficulty = excluded.difficulty,
|
||||
status = excluded.status,
|
||||
exam_markers = excluded.exam_markers,
|
||||
updated_at = now()
|
||||
`,
|
||||
@@ -1021,7 +1025,7 @@ async function main() {
|
||||
values
|
||||
($1, $2, $3, 'choice', 1, 2, true, '{"source":"smoke-seed"}'::jsonb),
|
||||
($1, $2, $4, 'choice', 2, 2, true, '{"source":"smoke-seed"}'::jsonb),
|
||||
($1, $2, $5, 'choice', 3, 2, true, '{"source":"smoke-seed"}'::jsonb)
|
||||
($1, $2, $5, 'subjective', 3, 2, true, '{"source":"smoke-seed"}'::jsonb)
|
||||
on conflict (tenant_id, collection_id, question_id)
|
||||
do update set section_key = excluded.section_key,
|
||||
sort_order = excluded.sort_order,
|
||||
@@ -1070,7 +1074,7 @@ async function main() {
|
||||
$3, $4, $5, $6, $7, $8,
|
||||
'smoke-mock-blueprint', '烟测全真模拟', 'mock_exam', 'collection', 10,
|
||||
120, 100, 60,
|
||||
'[{"key":"choice","title":"单选题","questionType":"choice","questionCount":10,"scoreEach":2}]'::jsonb,
|
||||
'[{"key":"choice","title":"单选题","questionType":"choice","questionCount":2,"scoreEach":2},{"key":"subjective","title":"主观题","questionType":"short_answer","questionCount":1,"scoreEach":2}]'::jsonb,
|
||||
'{"randomize":true,"showAnalysisAfterSubmit":false}'::jsonb,
|
||||
'active', 3, $9, $9
|
||||
)
|
||||
@@ -1118,9 +1122,9 @@ async function main() {
|
||||
1, '[1]'::jsonb, '4', '基础加法。'
|
||||
),
|
||||
(
|
||||
$6, $2, $7, 1, '3 + 3 = ?',
|
||||
'[{"label":"A","text":"5"},{"label":"B","text":"6"},{"label":"C","text":"7"}]'::jsonb,
|
||||
1, '[1]'::jsonb, '6', '基础加法。'
|
||||
$6, $2, $7, 1, '请简述多租户题库为什么必须以后端权限为准。',
|
||||
'[]'::jsonb,
|
||||
null, '[]'::jsonb, '后端需要统一校验租户、角色、资源和订单权益,前端只负责展示体验。', '主观题由学生查看参考答案后自评。'
|
||||
)
|
||||
on conflict (question_id, version_no)
|
||||
do update set content = excluded.content,
|
||||
|
||||
Reference in New Issue
Block a user