#!/usr/bin/env node 'use strict'; const assert = require('assert'); const http = require('http'); const { createServer, resetState } = require('./server'); const port = 4187; let server; function request(method, path, token, body, headers = {}) { return new Promise((resolve, reject) => { const data = body === undefined ? undefined : JSON.stringify(body); const req = http.request({ hostname: '127.0.0.1', port, path, method, headers: { Authorization: `Bearer ${token}`, ...(data ? { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) } : {}), ...headers } }, res => { let raw = ''; res.on('data', c => raw += c); res.on('end', () => resolve({ status: res.statusCode, body: JSON.parse(raw) })); }); req.on('error', reject); if (data) req.write(data); req.end(); }); } async function run() { resetState(); server = createServer().listen(port, '127.0.0.1'); const a1 = 'tenant-a-student-1'; const a2 = 'tenant-a-student-2'; const b1 = 'tenant-b-student-1'; let r = await request('GET', '/app-api/education/context', a1); assert.equal(r.body.data.tenantId, 'tenant-a'); r = await request('GET', '/app-api/education/questions/page?collectionId=col-a-core', a1); assert.equal(r.body.data.list[0].answer, undefined); assert.equal(r.body.data.list.length, 3); r = await request('POST', '/app-api/education/practice-session/create', a1, { clientSessionId: 'client-1', collectionId: 'col-a-core', questionCount: 3 }); const s = r.body.data; r = await request('POST', '/app-api/education/practice-session/create', a1, { clientSessionId: 'client-1', collectionId: 'col-a-core', questionCount: 3 }); assert.equal(r.body.data.id, s.id); r = await request('PUT', '/app-api/education/practice-session/answer', a1, { sessionId: s.id, questionSequence: 1, selectedAnswer: 'A', idempotencyKey: 'ans-1', clientSequence: 1, expectedSessionVersion: 0 }, { 'X-Harness-Fault': 'answer-timeout-after-commit' }); assert.equal(r.status, 504); r = await request('PUT', '/app-api/education/practice-session/answer', a1, { sessionId: s.id, questionSequence: 1, selectedAnswer: 'A', idempotencyKey: 'ans-1', clientSequence: 1, expectedSessionVersion: 0 }); assert.equal(r.status, 200); assert.equal(r.body.data.selectedAnswer, 'A'); r = await request('GET', `/app-api/education/practice-session/get?id=${s.id}`, a1); assert.equal(r.body.data.questions[0].selectedAnswer, 'A'); r = await request('PUT', '/app-api/education/practice-session/answer', a1, { sessionId: s.id, questionSequence: 2, selectedAnswer: 'B', idempotencyKey: 'ans-2', clientSequence: 2, expectedSessionVersion: 0 }); assert.equal(r.status, 409); r = await request('PUT', '/app-api/education/practice-session/answer', a1, { sessionId: s.id, questionSequence: 2, selectedAnswer: 'B', idempotencyKey: 'ans-2', clientSequence: 2, expectedSessionVersion: 1 }); assert.equal(r.status, 200); r = await request('GET', `/app-api/education/practice-session/get?id=${s.id}`, a2); assert.equal(r.status, 404); r = await request('POST', '/app-api/education/favorite/create', a1, { targetType: 'QUESTION', targetId: 'q-a-1' }); assert.equal(r.status, 200); r = await request('GET', '/app-api/education/favorite/page', b1); assert.equal(r.body.data.total, 0); r = await request('POST', '/app-api/education/practice-session/submit', a1, { sessionId: s.id, idempotencyKey: 'submit-1', expectedSessionVersion: 2 }); assert.equal(r.status, 200); assert.equal(r.body.data.details[0].answer, 'A'); r = await request('POST', '/app-api/education/practice-session/submit', a1, { sessionId: s.id, idempotencyKey: 'submit-1', expectedSessionVersion: 2 }); assert.equal(r.status, 200); r = await request('PUT', '/app-api/education/practice-session/answer', a1, { sessionId: s.id, questionSequence: 1, selectedAnswer: 'C', idempotencyKey: 'ans-3', clientSequence: 3, expectedSessionVersion: 3 }); assert.equal(r.status, 409); r = await request('GET', '/app-api/education/wrong-question/page', a1); assert.equal(r.body.data.total, 2); server.close(); process.stdout.write('education student harness contract tests passed\n'); } run().catch(err => { if (server) server.close(); console.error(err); process.exitCode = 1; });