Spaces:
Running
Running
| import { describe, expect, it } from 'vitest' | |
| import { extractQuestions, parseQuestionsJson, readJsonFile } from './JSONUploadForm' | |
| const validMCQ = { | |
| question_type: 'mcq', | |
| question_text: 'What is binary search complexity?', | |
| options: ['O(n)', 'O(log n)', 'O(n log n)', 'O(1)'], | |
| correct_answer: 'B', | |
| marks: 1, | |
| negative_marks: 0.33, | |
| subject: 'Algorithms', | |
| } | |
| describe('JSONUploadForm JSON parsing', () => { | |
| it('parses the expected object schema and normalizes question values', () => { | |
| const questions = parseQuestionsJson(JSON.stringify({ questions: [validMCQ] })) | |
| expect(questions).toHaveLength(1) | |
| expect(questions[0]).toMatchObject({ | |
| question_type: 'mcq', | |
| question_text: validMCQ.question_text, | |
| options: validMCQ.options, | |
| correct_answer: 'B', | |
| marks: 1, | |
| negative_marks: 0.33, | |
| }) | |
| }) | |
| it('accepts an array root for pasted questions', () => { | |
| const questions = extractQuestions([validMCQ]) | |
| expect(questions).toHaveLength(1) | |
| expect(questions[0].question_text).toBe(validMCQ.question_text) | |
| }) | |
| it('normalizes MSQ answers and removes negative marks for non-MCQ questions', () => { | |
| const questions = extractQuestions([ | |
| { | |
| ...validMCQ, | |
| question_type: 'msq', | |
| correct_answer: 'A, C', | |
| negative_marks: 0.66, | |
| }, | |
| ]) | |
| expect(questions[0].correct_answer).toBe('A,C') | |
| expect(questions[0].negative_marks).toBe(0) | |
| }) | |
| it('rejects malformed JSON with a clear error', () => { | |
| expect(() => parseQuestionsJson('{ "questions": [ }')).toThrow(/Invalid JSON:/) | |
| }) | |
| it('rejects roots that do not match the expected schema', () => { | |
| expect(() => extractQuestions({ items: [validMCQ] })).toThrow( | |
| 'JSON root must be an array or an object with a "questions" array', | |
| ) | |
| }) | |
| it('rejects empty question arrays', () => { | |
| expect(() => extractQuestions({ questions: [] })).toThrow('JSON does not contain any questions') | |
| }) | |
| it('rejects question objects with invalid fields', () => { | |
| expect(() => extractQuestions([{ ...validMCQ, options: ['A', 'B'] }])).toThrow( | |
| 'Question 1 options must contain exactly 4 non-empty strings', | |
| ) | |
| }) | |
| it('reads a JSON file before validation', async () => { | |
| const file = new File([JSON.stringify({ questions: [validMCQ] })], 'questions.json', { | |
| type: 'application/json', | |
| }) | |
| const text = await readJsonFile(file) | |
| const questions = parseQuestionsJson(text) | |
| expect(questions).toHaveLength(1) | |
| expect(questions[0].correct_answer).toBe('B') | |
| }) | |
| }) | |