| """Phase 4 C-F persistence: phase3 activity + Learn Anything roadmaps.""" | |
| from __future__ import annotations | |
| def _signup(client, *, email: str, password: str = "Pass123!beta", name: str = "Test User") -> str: | |
| resp = client.post("/auth/signup", json={"name": name, "email": email, "password": password}) | |
| assert resp.status_code == 201, f"signup failed: {resp.status_code} {resp.text}" | |
| return resp.json()["access_token"] | |
| def _auth(token: str) -> dict: | |
| return {"Authorization": f"Bearer {token}"} | |
| class TestPhase3Activity: | |
| def test_upsert_get_and_replace(self, auth_client): | |
| token = _signup(auth_client, email="p3-a@tuition.test") | |
| auth_client.post( | |
| "/phase3-activity", | |
| headers=_auth(token), | |
| json={"data": {"pyqScore": 6, "pyqMaxScore": 8, "weakTopicsAdded": ["tax"]}}, | |
| ) | |
| got = auth_client.get("/phase3-activity/me", headers=_auth(token)) | |
| assert got.status_code == 200 | |
| assert got.json()["data"]["pyqScore"] == 6 | |
| auth_client.post("/phase3-activity", headers=_auth(token), json={"data": {"pyqScore": 8}}) | |
| assert auth_client.get("/phase3-activity/me", headers=_auth(token)).json()["data"]["pyqScore"] == 8 | |
| def test_404_when_empty_and_auth_required(self, auth_client): | |
| token = _signup(auth_client, email="p3-empty@tuition.test") | |
| assert auth_client.get("/phase3-activity/me", headers=_auth(token)).status_code == 404 | |
| optional = auth_client.get( | |
| "/phase3-activity/me?optional=true", | |
| headers=_auth(token), | |
| ) | |
| assert optional.status_code == 200 | |
| assert optional.json() is None | |
| assert auth_client.get("/phase3-activity/me").status_code in (401, 403) | |
| def test_isolation(self, auth_client): | |
| a = _signup(auth_client, email="p3-alice@tuition.test", name="Alice") | |
| b = _signup(auth_client, email="p3-bob@tuition.test", name="Bob") | |
| auth_client.post("/phase3-activity", headers=_auth(a), json={"data": {"pyqScore": 5}}) | |
| assert auth_client.get("/phase3-activity/me", headers=_auth(b)).status_code == 404 | |
| class TestLearnAnythingRoadmaps: | |
| def test_upsert_list_get(self, auth_client): | |
| token = _signup(auth_client, email="road-a@tuition.test") | |
| first = auth_client.post( | |
| "/learn-anything-roadmaps", | |
| headers=_auth(token), | |
| json={ | |
| "roadmap_id": "deep-learning", | |
| "data": { | |
| "id": "deep-learning", | |
| "topic": "Deep Learning", | |
| "weeklyModules": [{"week": "Week 1", "title": "Foundations", "tasks": ["Tensors"]}], | |
| }, | |
| }, | |
| ) | |
| second = auth_client.post( | |
| "/learn-anything-roadmaps", | |
| headers=_auth(token), | |
| json={ | |
| "roadmap_id": "python", | |
| "data": { | |
| "id": "python", | |
| "topic": "Python", | |
| "weeklyModules": [{"week": "Week 1", "title": "Basics", "tasks": ["Variables"]}], | |
| }, | |
| }, | |
| ) | |
| assert first.status_code == 200, first.text | |
| assert second.status_code == 200, second.text | |
| rows = auth_client.get("/learn-anything-roadmaps", headers=_auth(token)).json() | |
| assert {r["roadmap_id"] for r in rows} == {"deep-learning", "python"} | |
| one = auth_client.get("/learn-anything-roadmaps/deep-learning", headers=_auth(token)) | |
| assert one.status_code == 200 | |
| assert one.json()["data"]["topic"] == "Deep Learning" | |
| def test_upsert_replaces_same_id(self, auth_client): | |
| token = _signup(auth_client, email="road-replace@tuition.test") | |
| created = auth_client.post( | |
| "/learn-anything-roadmaps", | |
| headers=_auth(token), | |
| json={ | |
| "roadmap_id": "ml", | |
| "data": { | |
| "id": "ml", | |
| "topic": "Machine Learning", | |
| "weeklyModules": [{"week": "Week 1", "title": "Start", "tasks": ["Overview"]}], | |
| }, | |
| }, | |
| ) | |
| assert created.status_code == 200, created.text | |
| replaced = auth_client.post( | |
| "/learn-anything-roadmaps", | |
| headers=_auth(token), | |
| json={ | |
| "roadmap_id": "ml", | |
| "data": { | |
| "id": "ml", | |
| "topic": "Machine Learning", | |
| "weeklyModules": [{"week": "Week 1", "title": "Start", "tasks": ["Overview"]}], | |
| "topicStatus": {"Week 1::0": "covered"}, | |
| }, | |
| }, | |
| ) | |
| assert replaced.status_code == 409 | |
| assert replaced.json()["detail"]["code"] == "ROADMAP_COMMAND_REQUIRED" | |
| command = auth_client.post( | |
| "/learn-anything-roadmaps/ml/commands", | |
| headers=_auth(token), | |
| json={ | |
| "client_command_id": "phase3-cover-overview", | |
| "command": "set_topic_status", | |
| "topic_key": "Week 1::0", | |
| "status": "covered", | |
| }, | |
| ) | |
| assert command.status_code == 200, command.text | |
| rows = auth_client.get("/learn-anything-roadmaps", headers=_auth(token)).json() | |
| assert len(rows) == 1 | |
| assert rows[0]["data"]["topicStatus"]["Week 1::0"] == "covered" | |
| def test_isolation_and_auth(self, auth_client): | |
| a = _signup(auth_client, email="road-alice@tuition.test", name="Alice") | |
| b = _signup(auth_client, email="road-bob@tuition.test", name="Bob") | |
| created = auth_client.post( | |
| "/learn-anything-roadmaps", | |
| headers=_auth(a), | |
| json={ | |
| "roadmap_id": "ml", | |
| "data": { | |
| "id": "ml", | |
| "topic": "ML", | |
| "weeklyModules": [{"week": "Week 1", "title": "Start", "tasks": ["Overview"]}], | |
| }, | |
| }, | |
| ) | |
| assert created.status_code == 200, created.text | |
| assert auth_client.get("/learn-anything-roadmaps", headers=_auth(b)).json() == [] | |
| assert auth_client.get("/learn-anything-roadmaps/ml", headers=_auth(b)).status_code == 404 | |
| assert auth_client.get("/learn-anything-roadmaps").status_code in (401, 403) | |