const { describe, it, before, after } = require('node:test'); const assert = require('node:assert/strict'); const { db, inject, getToken, cleanup } = require('./setup'); after(() => cleanup()); describe('Sessions', () => { let token, userId; before(async () => { const u = await getToken('student'); token = u.token; userId = u.userId; // Ensure subject + questions exist const subj = db.prepare('SELECT id FROM subjects WHERE slug = ?').get('chem'); if (!subj) { db.prepare("INSERT INTO subjects (slug, name, icon) VALUES ('chem', 'Химия', 'atom')").run(); } const subjId = db.prepare('SELECT id FROM subjects WHERE slug = ?').get('chem').id; // Create some questions const ins = db.prepare('INSERT INTO questions (subject_id, text, difficulty) VALUES (?, ?, 1)'); for (let i = 0; i < 5; i++) { const qId = ins.run(subjId, `Test question ${i + 1}`).lastInsertRowid; // Add options db.prepare('INSERT INTO options (question_id, text, is_correct) VALUES (?, ?, ?)').run(qId, 'Wrong', 0); db.prepare('INSERT INTO options (question_id, text, is_correct) VALUES (?, ?, ?)').run(qId, 'Correct', 1); } }); it('validates subject_slug required', async () => { const res = await inject('POST', '/api/sessions', { mode: 'exam' }, token); assert.equal(res.status, 400); }); it('validates mode enum', async () => { const res = await inject('POST', '/api/sessions', { subject_slug: 'chem', mode: 'invalid' }, token); assert.equal(res.status, 400); }); it('validates count range', async () => { const res = await inject('POST', '/api/sessions', { subject_slug: 'chem', count: 999 }, token); assert.equal(res.status, 400); }); it('starts a session successfully', async () => { const res = await inject('POST', '/api/sessions', { subject_slug: 'chem', count: 3, mode: 'exam' }, token); assert.equal(res.status, 201); assert.ok(res.body.session_id); assert.equal(res.body.mode, 'exam'); assert.ok(res.body.questions.length > 0); }); it('submits an answer', async () => { // Start fresh session const s = await inject('POST', '/api/sessions', { subject_slug: 'chem', count: 2, mode: 'practice' }, token); const sessionId = s.body.session_id; const q = s.body.questions[0]; const res = await inject('POST', `/api/sessions/${sessionId}/answer`, { question_id: q.id, option_id: q.options[0].id }, token); assert.equal(res.status, 200); assert.ok('is_correct' in res.body); }); it('validates answer question_id required', async () => { const s = await inject('POST', '/api/sessions', { subject_slug: 'chem', count: 2 }, token); const sessionId = s.body.session_id; const res = await inject('POST', `/api/sessions/${sessionId}/answer`, {}, token); assert.equal(res.status, 400); }); it('finishes a session', async () => { const s = await inject('POST', '/api/sessions', { subject_slug: 'chem', count: 1 }, token); const sessionId = s.body.session_id; const res = await inject('POST', `/api/sessions/${sessionId}/finish`, {}, token); assert.equal(res.status, 200); assert.ok('score' in res.body); }); it('returns session history', async () => { const res = await inject('GET', '/api/sessions/history', null, token); assert.equal(res.status, 200); assert.ok(Array.isArray(res.body.rows)); }); it('rejects session start without auth', async () => { const res = await inject('POST', '/api/sessions', { subject_slug: 'chem' }); assert.equal(res.status, 401); }); });