File size: 4,198 Bytes
1e52a1f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
"""Tests for quiz-maker skill: JSON parse, fallback, and export smoke."""

from pathlib import Path

from agent.models import QuizMakerInput, QuizOutline, QuizQuestion
from agent.prompts import fallback_quiz, quiz_max_tokens, quiz_to_markdown
from agent.runner import AgentRunner
from agent.tools.quiz import create_quiz, create_quiz_docx, create_quiz_html


def test_quiz_max_tokens_scales_with_question_count():
    assert quiz_max_tokens(5) == 1020
    assert quiz_max_tokens(3) == 660
    assert quiz_max_tokens(12) == 1536


def test_parse_quiz_outline_normalizes_count():
    runner = AgentRunner()
    raw = (
        '{"title": "Science Quiz", "instructions": "Circle one.", "questions": ['
        '{"prompt": "Q1?", "choices": ["a", "b", "c", "d"], "correct_index": 0, "explanation": "e1"},'
        '{"prompt": "Q2?", "choices": ["a", "b", "c", "d"], "correct_index": 1, "explanation": "e2"},'
        '{"prompt": "Q3?", "choices": ["a", "b", "c", "d"], "correct_index": 2, "explanation": "e3"}'
        "]}"
    )
    outline = runner._parse_quiz_outline(raw, expected_questions=5)
    assert len(outline.questions) == 5
    assert outline.title == "Science Quiz"


def test_parse_quiz_outline_trims_extra_questions():
    runner = AgentRunner()
    questions = ",".join(
        f'{{"prompt": "Q{i}?", "choices": ["a","b","c","d"], "correct_index": 0, "explanation": ""}}'
        for i in range(1, 8)
    )
    raw = f'{{"title": "Long", "questions": [{questions}]}}'
    outline = runner._parse_quiz_outline(raw, expected_questions=5)
    assert len(outline.questions) == 5


def test_parse_quiz_outline_or_error_empty():
    runner = AgentRunner()
    outline, err = runner._parse_quiz_outline_or_error("", 5, None)
    assert outline is None
    assert "empty" in err.lower()


def test_fallback_quiz_has_requested_count():
    req = QuizMakerInput(topic="Fractions", grade="5", question_count=7)
    outline = fallback_quiz(req)
    assert len(outline.questions) == 7
    assert "Fractions" in outline.title
    assert all(len(q.choices) == 4 for q in outline.questions)


def test_quiz_to_markdown_includes_answers():
    outline = QuizOutline(
        title="Test",
        instructions="Read carefully.",
        questions=[
            QuizQuestion(
                prompt="2+2?",
                choices=["4", "3", "5", "6"],
                correct_index=0,
                explanation="Basic addition.",
            ),
            QuizQuestion(
                prompt="3+3?",
                choices=["6", "5", "7", "8"],
                correct_index=0,
                explanation="Also addition.",
            ),
            QuizQuestion(
                prompt="1+1?",
                choices=["2", "1", "3", "4"],
                correct_index=0,
                explanation="Easy.",
            ),
        ],
    )
    md = quiz_to_markdown(outline)
    assert "2+2?" in md
    assert "**Answer:** A" in md


def test_create_quiz_docx_and_html(tmp_path: Path):
    outline = QuizOutline(
        title="Smoke Quiz",
        instructions="Circle the best answer.",
        questions=[
            QuizQuestion(
                prompt="Sample?",
                choices=["Yes", "No", "Maybe", "Sometimes"],
                correct_index=0,
                explanation="Because.",
            ),
            QuizQuestion(
                prompt="Another?",
                choices=["A", "B", "C", "D"],
                correct_index=2,
                explanation="C is correct.",
            ),
            QuizQuestion(
                prompt="Third?",
                choices=["1", "2", "3", "4"],
                correct_index=1,
                explanation="Two.",
            ),
        ],
    )
    docx_path = tmp_path / "quiz.docx"
    html_path = tmp_path / "quiz.html"
    create_quiz_docx(outline, docx_path)
    create_quiz_html(outline, html_path)
    assert docx_path.stat().st_size > 100
    html_text = html_path.read_text(encoding="utf-8")
    assert "Smoke Quiz" in html_text
    assert "Answer key" in html_text

    paths = create_quiz(outline, tmp_path / "out", stem="worksheet")
    assert paths["docx"].exists()
    assert paths["html"].exists()