File size: 4,049 Bytes
6ca3b92 f415181 9685699 | 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 | from types import SimpleNamespace
from app.services import learn_lesson_builder
def test_mock_provider_builds_a_cached_reading_lesson_without_external_calls(
monkeypatch, tmp_path
) -> None:
monkeypatch.setattr(
learn_lesson_builder,
"get_settings",
lambda: SimpleNamespace(ai_provider="mock"),
)
monkeypatch.setattr(learn_lesson_builder, "PUBLIC_ROOT", tmp_path)
monkeypatch.setattr(
learn_lesson_builder,
"generate_lesson_script",
lambda **_kwargs: (_ for _ in ()).throw(AssertionError("Groq should not run")),
)
monkeypatch.setattr(
learn_lesson_builder,
"synthesize_beats",
lambda *_args, **_kwargs: (_ for _ in ()).throw(
AssertionError("TTS should not run")
),
)
manifest = learn_lesson_builder.build_lesson(
topic="Python programming",
lesson_title="Python Programming",
level="beginner",
)
assert manifest["deliveryMode"] == "reading"
assert manifest["isFallback"] is True
assert "Local preview" in manifest["deliveryNotice"]
assert len(manifest["beats"]) >= 6
assert all(beat["audio_src"] == "" for beat in manifest["beats"])
assert "variables" in str(manifest).lower()
assert (tmp_path / "unowned" / manifest["lessonHash"] / "lesson.json").exists()
def test_provider_timeout_returns_bounded_reading_lesson(monkeypatch, tmp_path) -> None:
monkeypatch.setattr(
learn_lesson_builder,
"get_settings",
lambda: SimpleNamespace(ai_provider="sarvam"),
)
monkeypatch.setattr(learn_lesson_builder, "PUBLIC_ROOT", tmp_path)
monkeypatch.setattr(learn_lesson_builder, "_lesson_sync_tts_enabled", lambda: False)
monkeypatch.setattr(learn_lesson_builder, "_lesson_generation_budget_seconds", lambda: 1.0)
monkeypatch.setattr(
learn_lesson_builder,
"_script_llm_providers",
lambda: [{"name": "test", "call": lambda _prompt: (_ for _ in ()).throw(TimeoutError())}],
)
monkeypatch.setattr(
learn_lesson_builder,
"synthesize_beats",
lambda *_args, **_kwargs: (_ for _ in ()).throw(AssertionError("TTS must not run")),
)
manifest = learn_lesson_builder.build_lesson(
topic="Basic Python for data analysis",
lesson_title="Python foundations",
level="beginner",
)
assert manifest["deliveryMode"] == "reading"
assert manifest["isFallback"] is True
assert "reading" in manifest["deliveryNotice"].lower()
assert manifest["beats"]
def test_authored_lesson_can_return_reading_mode_without_audio(monkeypatch, tmp_path) -> None:
monkeypatch.setattr(
learn_lesson_builder,
"get_settings",
lambda: SimpleNamespace(ai_provider="sarvam"),
)
monkeypatch.setattr(learn_lesson_builder, "PUBLIC_ROOT", tmp_path)
monkeypatch.setattr(learn_lesson_builder, "_lesson_sync_tts_enabled", lambda: False)
monkeypatch.setattr(
learn_lesson_builder,
"generate_lesson_script",
lambda **_kwargs: {
"lesson_title": "Authored lesson",
"summary": "A real authored reading class.",
"objectives": ["Explain the idea"],
"beats": [
{
"kind": "explain",
"narration": "This is a complete authored explanation that a student can read and study without waiting for a voice asset.",
"board_heading": "Core idea",
"board_lines": ["Reason first"],
}
],
"notes": ["A useful note."],
"flashcards": [{"front": "What matters?", "back": "The reason."}],
},
)
manifest = learn_lesson_builder.build_lesson(
topic="A real topic",
lesson_title="Authored lesson",
level="beginner",
)
assert manifest["deliveryMode"] == "reading"
assert manifest["summary"] == "A real authored reading class."
assert manifest["beats"][0]["audio_src"] == ""
|