File size: 5,531 Bytes
0ba5932
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
"""Focus practice end to end: the class teacher gives skills to one student from the report; only that student sees
it, marked as personal, and the report counts only them."""
import socket
import threading
import time

import pytest

from app.main import create_app
from test_assignments import MemoryAssignments
from test_worksheets import MemoryWorksheets
from test_worksheets_browser import NoAnswers, uvicorn

playwright = pytest.importorskip("playwright.sync_api")
TEACHER, DANA, YOSSI = ("bbbbbbbb-0000-4000-8000-00000000000%d" % i for i in (1, 2, 3))
mail = {TEACHER: "teacher@test.invalid", DANA: "dana@test.invalid", YOSSI: "yossi@test.invalid"}


class SchoolAuth:
    url, key, secret = "https://test.invalid", "public-test", "server-test"
    teachers = developers = frozenset()

    def user(self, token):
        return {"id": token, "email": mail[token]} if token in mail else None

    def classes(self, fresh=False):
        return [{"id": 3, "name": "讟壮1", "lessons": ["t", "k"], "teachers": [mail[TEACHER]],
                 "emails": list(mail.values()), "nicknames": {}, "exams": []}]

    def access_for(self, _id, **kwargs):
        return None

    def user_accounts(self, emails):
        return {email: {"id": uid, "name": ""} for uid, email in mail.items() if email in emails}

    def _admin(self, path, method="GET", body=None, prefer=""):
        from app.auth import AuthUnavailable
        if path.startswith("/rest/v1/math_progress"):
            return []
        raise AuthUnavailable("supabase answered 404: no other tables here")


def session(browser, uid):
    ctx = browser.new_context(viewport={"width": 390, "height": 844}, is_mobile=True, has_touch=True)
    ctx.route("https://cdn.jsdelivr.net/**", lambda route: route.abort())
    ctx.add_init_script('''window.supabase={createClient:()=>({auth:{
      getSession:async()=>({data:{session:{access_token:"%s",user:{id:"%s"}}}}),
      onAuthStateChange:()=>({data:{subscription:{unsubscribe(){}}}}),signOut:async()=>{}
    }})};''' % (uid, uid))
    page = ctx.new_page()
    errors = []
    page.on("pageerror", lambda e: errors.append(str(e)))
    return page, errors


@pytest.fixture
def school():
    app = create_app(auth=SchoolAuth())
    app.state.assignments, app.state.worksheets, app.state.answers = MemoryAssignments(), MemoryWorksheets(), NoAnswers()
    with socket.socket() as sock:
        sock.bind(("127.0.0.1", 0))
        server = uvicorn().Server(uvicorn().Config(app, log_level="error"))
        thread = threading.Thread(target=server.run, kwargs={"sockets": [sock]}, daemon=True)
        thread.start()
        try:
            while not server.started:
                time.sleep(.01)
            yield f"http://127.0.0.1:{sock.getsockname()[1]}", app
        finally:
            server.should_exit = True
            thread.join(timeout=5)


def test_the_teacher_gives_focus_practice_to_one_student(school):
    url, app = school
    with playwright.sync_playwright() as p:
        browser = p.chromium.launch()
        try:
            teacher, t_errors = session(browser, TEACHER)
            teacher.goto(url)
            teacher.locator('[data-act="class-report"]').click()
            sheet = teacher.locator(".mx-report-sheet")
            sheet.locator("[data-report-tab=tasks]").click()
            sheet.locator("[data-asg-focus-new]").click()
            form = sheet.locator("[data-focus-form]")
            form.locator("button[type=submit]").click()
            playwright.expect(form.locator(".mx-row [role=status]")).to_have_text("讘讞专讜 诇驻讞讜转 转诇诪讬讚 讗讞讚.")
            form.locator('[name=student][value="dana@test.invalid"]').check()
            form.locator("details", has_text="讟讻谞讬拽讛 讗诇讙讘专讬转 1").locator("summary").click()
            form.locator('[name=skill][value="t_ext"]').check()
            form.locator("[name=title]").fill("讞讬讝讜拽 驻讬诇讜讙")
            form.locator("[name=due_on]").fill("2099-01-01")
            form.locator("button[type=submit]").click()
            card = sheet.locator(".mx-asg-t")
            playwright.expect(card).to_contain_text("讗讬砖讬")
            playwright.expect(card).to_contain_text("转专讙讜诇 诪诪讜拽讚 诇: dana")
            playwright.expect(card.locator(".mx-asg-count")).to_contain_text("0 诪转讜讱 1 转诇诪讬讚讬诐 住讬讬诪讜")   # only Dana counts
            (row,) = app.state.assignments.rows.values()
            assert row["student_emails"] == ["dana@test.invalid"] and row["items"] == [{"kind": "skill", "id": "t_ext"}]

            dana, d_errors = session(browser, DANA)
            dana.goto(url)
            dana.locator('.mx-nav [data-view="home"]').click()
            asg = dana.locator(".mx-asgs .mx-asg")
            playwright.expect(asg).to_contain_text("讞讬讝讜拽 驻讬诇讜讙")
            playwright.expect(asg.locator(".mx-asg-personal")).to_have_text("馃幆 讗讬砖讬")

            yossi, y_errors = session(browser, YOSSI)
            with yossi.expect_response(lambda r: "/api/math/assignments" in r.url) as got:
                yossi.goto(url)
            assert got.value.json()["assignments"] == []
            yossi.locator('.mx-nav [data-view="home"]').click()
            playwright.expect(yossi.locator(".mx-continue")).to_be_visible()
            playwright.expect(yossi.locator(".mx-asgs")).to_have_count(0)   # not given to Yossi
            assert not (t_errors or d_errors or y_errors), (t_errors, d_errors, y_errors)
        finally:
            browser.close()