File size: 3,148 Bytes
0815e01
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""The curriculum (add-lesson-schedule 2.1, 3.1): a date per lesson, who sets it, and what the path says about it."""
from datetime import timedelta

from mathly2 import clock
from mathly2.tests.test_skills_api import KID, KID_ID, MGR, MON, OTHER, TEACHER, auth, raw, world  # noqa: F401


def rows(client, who=KID):
    return {l["id"]: l for l in client.get("/api/path", headers=auth(who)).json()["lessons"]}


def put(client, dates, who=MGR):
    return client.put("/api/curriculum", json={"dates": dates}, headers=auth(who))


def test_a_manager_sets_changes_and_clears_a_date(world):
    client, _, bank = world
    first, second = bank.lessons[0]["id"], bank.lessons[1]["id"]
    got = client.get("/api/curriculum", headers=auth(MGR)).json()
    assert [r["id"] for r in got] == [l["id"] for l in bank.lessons] and all(r["due_date"] is None for r in got) and got[0]["month"]
    assert put(client, {first: "2026-11-03", second: "2026-12-01"}).json()[0]["due_date"] == "2026-11-03"
    assert put(client, {first: "2026-11-05", second: None}).status_code == 200
    now = {r["id"]: r["due_date"] for r in client.get("/api/curriculum", headers=auth(MGR)).json()}
    assert now[first] == "2026-11-05" and now[second] is None


def test_only_managers_change_it_and_bad_input_is_refused(world):
    client, _, bank = world
    first = bank.lessons[0]["id"]
    for who in (TEACHER, KID, OTHER):
        assert put(client, {first: "2026-11-03"}, who).status_code in (401, 403)
        assert client.get("/api/curriculum", headers=auth(who)).status_code in (401, 403)
    assert put(client, {"no-such-lesson": "2026-11-03"}).status_code == 422
    assert put(client, {first: "3.11"}).status_code == 422
    assert client.get("/api/curriculum", headers=auth(MGR)).json()[0]["due_date"] is None        # nothing changed


def test_a_lesson_is_behind_only_when_dated_past_and_not_completed(world):
    client, store, bank = world
    ids = [l["id"] for l in bank.lessons_with_skills()][:5]
    today = clock.school_day()
    yesterday, tomorrow = (today - timedelta(days=1)).isoformat(), (today + timedelta(days=7)).isoformat()
    put(client, {ids[0]: yesterday, ids[1]: tomorrow, ids[2]: yesterday, ids[3]: yesterday})   # ids[4]: no date
    path = client.get("/api/path", headers=auth()).json()
    by = {l["id"]: l for l in path["lessons"]}
    assert by[ids[0]]["behind"] is True and by[ids[0]]["due_date"] == yesterday
    assert by[ids[1]]["behind"] is False and by[ids[4]]["behind"] is False and by[ids[4]]["due_date"] is None
    # a completed lesson (all skills mastered) is not behind, and neither is one whose quiz was passed
    for skill in by[ids[2]]["skills"]:
        store.save_progress(KID_ID, skill["id"], started_at=MON, mastered_at=MON)
    assert rows(client)[ids[2]]["completed"] is True and rows(client)[ids[2]]["behind"] is False
    assert path["behind"] == 3                                                                  # before the third was completed
    after = client.get("/api/path", headers=auth()).json()
    assert after["behind"] == 2 and {l["id"] for l in after["lessons"] if l["behind"]} == {ids[0], ids[3]}