feat: background tasks manager and book sentence mining for CEFR tests
This commit is contained in:
+74
-4
@@ -1393,11 +1393,10 @@ def test_cefr_testing_and_gap_ingestion():
|
||||
assert "clue" in q1
|
||||
assert len(q1["options"]) == 4
|
||||
|
||||
# 5. Answer INCORRECTLY -> Automated Dual Gap Ingestion (target + selected option)
|
||||
# Pick a distractor from the question's actual options
|
||||
# Find option that is not correct (we test with the first distractor)
|
||||
# Let's inspect options and find one that is wrong
|
||||
wrong_opt = [opt for opt in q1["options"] if opt.lower() != q1.get("term", "").lower()][0]
|
||||
with get_db() as conn:
|
||||
correct_term = conn.execute("SELECT term FROM cefr_questions WHERE id = ?", (q1["id"],)).fetchone()["term"]
|
||||
wrong_opt = [opt for opt in q1["options"] if opt.lower() != correct_term.lower()][0]
|
||||
|
||||
ans_wrong = client.post("/api/cefr/answer", json={
|
||||
"question_id": q1["id"],
|
||||
@@ -1576,6 +1575,77 @@ def test_grammar_engine_and_handwritten_journaling():
|
||||
assert u1_after["handwritten_logged"] is True
|
||||
|
||||
|
||||
def test_background_tasks_and_book_mining():
|
||||
# 1. Unauthenticated check
|
||||
client.cookies.clear()
|
||||
unauth = client.post("/api/tasks/mine-books", json={"level": "A1", "count": 2})
|
||||
assert unauth.status_code == 401
|
||||
|
||||
# 2. Login
|
||||
login_res = client.post("/api/login", json={"username": "testadmin", "password": "testpass12345"})
|
||||
assert login_res.status_code == 200
|
||||
|
||||
# 3. Create a book with known vocabulary
|
||||
book_resp = client.post("/api/books", json={
|
||||
"title": "Adventures in London",
|
||||
"author": "Arthur Conan Doyle",
|
||||
"content": "Chapter 1: The Arrival\nThey decided to invite their neighbor for breakfast. The journey was long and dangerous.\n\nChapter 2: The Mystery\nHe could not remember where he left his expensive ticket.",
|
||||
"source_type": "text"
|
||||
})
|
||||
assert book_resp.status_code == 200
|
||||
book_id = book_resp.json()["id"]
|
||||
|
||||
# 4. Start mining task
|
||||
mine_resp = client.post("/api/tasks/mine-books", json={
|
||||
"book_id": book_id,
|
||||
"level": "A1",
|
||||
"count": 2
|
||||
})
|
||||
assert mine_resp.status_code == 200
|
||||
data = mine_resp.json()
|
||||
assert data["status"] == "ok"
|
||||
assert "task_id" in data
|
||||
task_id = data["task_id"]
|
||||
|
||||
# 5. Check task status via active and ID endpoint
|
||||
active_resp = client.get("/api/tasks/active")
|
||||
assert active_resp.status_code == 200
|
||||
|
||||
# Wait briefly or poll task status
|
||||
import time
|
||||
t_data = None
|
||||
for _ in range(30):
|
||||
t_res = client.get(f"/api/tasks/{task_id}")
|
||||
assert t_res.status_code == 200
|
||||
t_data = t_res.json()["task"]
|
||||
if t_data["status"] in ("completed", "failed", "cancelled"):
|
||||
break
|
||||
time.sleep(0.1)
|
||||
|
||||
assert t_data is not None
|
||||
assert t_data["status"] == "completed"
|
||||
assert t_data["progress_current"] > 0
|
||||
|
||||
# 6. Verify quiz retrieval includes source book metadata
|
||||
quiz_res = client.get("/api/cefr/quiz?level=A1&count=20")
|
||||
assert quiz_res.status_code == 200
|
||||
items = quiz_res.json()["quiz"]
|
||||
book_items = [q for q in items if q.get("source_book_title") == "Adventures in London"]
|
||||
assert len(book_items) > 0
|
||||
assert book_items[0]["source_book_title"] == "Adventures in London"
|
||||
assert "source_chapter_title" in book_items[0]
|
||||
|
||||
# 7. Test task cancellation
|
||||
from app.tasks import create_task
|
||||
with get_db() as conn:
|
||||
task_id_pending = create_task(conn, 1, "mine_books", total=10)
|
||||
cancel_resp = client.post(f"/api/tasks/{task_id_pending}/cancel")
|
||||
assert cancel_resp.status_code == 200
|
||||
assert cancel_resp.json()["status"] == "ok"
|
||||
assert cancel_resp.json()["cancelled"] is True
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user