feat(cefr): CEFR level testing and automated gap ingestion engine (Task 15)
This commit is contained in:
1 parent
1c3f03a64c
commit
3fae321322
11 files changed
+2926
-10
No files matched your search
@@ -1359,5 +1359,92 @@ def test_phrasal_verb_detector_unit_and_integration():
|
||||
assert after_data["phrasal_verb"]["library_card"] is not None
|
||||
|
||||
|
||||
def test_cefr_testing_and_gap_ingestion():
|
||||
# 1. Unauthenticated check
|
||||
client.cookies.clear()
|
||||
unauth = client.get("/api/cefr/levels")
|
||||
assert unauth.status_code == 401
|
||||
|
||||
# 2. Authenticated user login
|
||||
login_res = client.post("/api/login", json={"username": "testadmin", "password": "testpass12345"})
|
||||
assert login_res.status_code == 200
|
||||
|
||||
# 3. Check level summaries
|
||||
levels_res = client.get("/api/cefr/levels")
|
||||
assert levels_res.status_code == 200
|
||||
levels = levels_res.json()["levels"]
|
||||
assert len(levels) == 4
|
||||
level_map = {l["level"]: l for l in levels}
|
||||
assert "A1" in level_map and "A2" in level_map and "B1" in level_map and "B2" in level_map
|
||||
assert level_map["A1"]["total_questions"] == 40
|
||||
assert level_map["A2"]["total_questions"] == 40
|
||||
assert level_map["B1"]["total_questions"] == 40
|
||||
assert level_map["B2"]["total_questions"] == 40
|
||||
|
||||
# 4. Fetch quiz batch
|
||||
quiz_res = client.get("/api/cefr/quiz?level=A2&count=5")
|
||||
assert quiz_res.status_code == 200
|
||||
quiz_data = quiz_res.json()
|
||||
assert quiz_data["level"] == "A2"
|
||||
assert len(quiz_data["quiz"]) == 5
|
||||
q1 = quiz_data["quiz"][0]
|
||||
assert "id" in q1
|
||||
assert "sentence" in q1
|
||||
assert "clue" in q1
|
||||
assert len(q1["options"]) == 4
|
||||
|
||||
# 5. Answer INCORRECTLY -> Automated Gap Ingestion into SRS!
|
||||
wrong_opt = "__completely_wrong_option__"
|
||||
ans_wrong = client.post("/api/cefr/answer", json={
|
||||
"question_id": q1["id"],
|
||||
"selected_option": wrong_opt
|
||||
})
|
||||
assert ans_wrong.status_code == 200
|
||||
w_data = ans_wrong.json()
|
||||
assert w_data["correct"] is False
|
||||
assert w_data["card_created"] is True
|
||||
assert w_data["card_id"] is not None
|
||||
assert w_data["correct_option"] != ""
|
||||
assert w_data["explanation"] != ""
|
||||
|
||||
# Verify the card was actually created in vocabulary_cards with state 'learning' and level tag
|
||||
card_res = client.get(f"/api/cards/{w_data['card_id']}")
|
||||
assert card_res.status_code == 200
|
||||
ingested_card = card_res.json()
|
||||
assert ingested_card["srs_state"] == "learning"
|
||||
assert "level-a2" in ingested_card["tags"]
|
||||
assert "cefr-test" in ingested_card["tags"]
|
||||
|
||||
# 6. Check that mode='mistakes' returns this question
|
||||
mistakes_res = client.get("/api/cefr/quiz?level=A2&mode=mistakes")
|
||||
assert mistakes_res.status_code == 200
|
||||
m_data = mistakes_res.json()
|
||||
assert any(q["id"] == q1["id"] for q in m_data["quiz"])
|
||||
|
||||
# 7. Now answer CORRECTLY
|
||||
ans_correct = client.post("/api/cefr/answer", json={
|
||||
"question_id": q1["id"],
|
||||
"selected_option": w_data["correct_option"]
|
||||
})
|
||||
assert ans_correct.status_code == 200
|
||||
c_data = ans_correct.json()
|
||||
assert c_data["correct"] is True
|
||||
assert c_data["card_created"] is False
|
||||
|
||||
# 8. Check level summary reflects mastered count
|
||||
levels_res2 = client.get("/api/cefr/levels")
|
||||
l2_map = {l["level"]: l for l in levels_res2.json()["levels"]}
|
||||
assert l2_map["A2"]["mastered_count"] >= 1
|
||||
assert l2_map["A2"]["srs_cards_count"] >= 1
|
||||
|
||||
# 9. Test level reset
|
||||
reset_res = client.post("/api/cefr/reset", json={"level": "A2"})
|
||||
assert reset_res.status_code == 200
|
||||
levels_res3 = client.get("/api/cefr/levels")
|
||||
l3_map = {l["level"]: l for l in levels_res3.json()["levels"]}
|
||||
assert l3_map["A2"]["mastered_count"] == 0
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user