feat(listening): interactive listening comprehension trainer with neural voiceover and auto-evaluation

This commit is contained in:
2026-10-07 10:57:10 +03:00
parent a6fb4349e9
commit 7893b353aa
8 changed files with 1026 additions and 3 deletions
+70
View File
@@ -2280,6 +2280,76 @@ def test_piper_tts_endpoints_and_caching():
assert "/api/audio/" in card_data["context_audio_url"]
def test_listening_exercise_and_check():
login_resp = client.post("/api/login", json={"username": "testadmin", "password": "testpass12345"})
assert login_resp.status_code == 200
token = login_resp.cookies.get(config.SESSION_COOKIE_NAME)
auth_headers = {"Cookie": f"{config.SESSION_COOKIE_NAME}={token}"}
# 1. Fetch listening exercise for tech topic
resp = client.get("/api/listening/exercise?topic=tech&level=B1", headers=auth_headers)
assert resp.status_code == 200
ex = resp.json()
assert "id" in ex
assert ex["topic"] == "tech"
assert "story" in ex
assert "question" in ex
assert "/api/audio/" in ex["story_audio_url"]
assert "/api/audio/" in ex["question_audio_url"]
# Check that client cannot inspect ideal_answer or keywords before submitting
assert "ideal_answer" not in ex
assert "keywords" not in ex
# 2. Check evaluation: correct answer for tech-01
check_resp = client.post(
"/api/listening/check",
json={
"scenario_id": "tech-01",
"user_answer": "At midnight to minimize downtime",
},
headers=auth_headers,
)
assert check_resp.status_code == 200
res = check_resp.json()
assert res["is_correct"] is True
assert res["score"] == 100
assert "midnight" in res["ideal_answer"].lower()
assert "story" in res
assert "story_ru" in res
# 3. Check evaluation: wrong answer for tech-01
check_wrong = client.post(
"/api/listening/check",
json={
"scenario_id": "tech-01",
"user_answer": "Tomorrow morning at sunrise",
},
headers=auth_headers,
)
assert check_wrong.status_code == 200
res_wrong = check_wrong.json()
assert res_wrong["is_correct"] is False
assert res_wrong["score"] < 50
# 4. Check exercise from user's vocabulary cards
# First ensure a card with context sentence exists
client.post(
"/api/cards",
json={
"term": "refactoring",
"translation": "рефакторинг",
"context_sentence": "Clean architecture requires continuous refactoring of legacy components.",
},
headers=auth_headers,
)
card_ex_resp = client.get("/api/listening/exercise?topic=cards", headers=auth_headers)
assert card_ex_resp.status_code == 200
card_ex = card_ex_resp.json()
assert card_ex["topic"] == "cards"
assert "/api/audio/" in card_ex["story_audio_url"]