Download tests/test_exam_prep_browser.py from wzender/mathly: direct link, hf CLI and curl.
- Browser
- Download file 13.2 kB
-
https://huggingface.co/spaces/wzender/mathly/resolve/main/tests/test_exam_prep_browser.py
- Command line
-
hf download hf://spaces/wzender/mathly/tests/test_exam_prep_browser.py
-
curl -L -o test_exam_prep_browser.py https://huggingface.co/spaces/wzender/mathly/resolve/main/tests/test_exam_prep_browser.py
13.2 kB
| """Preparing for an exam: the exam names its units, and the student sees how ready they are and a plan of steps, with a | |
| daily amount and each step checked off from their progress.""" | |
| import json | |
| import socket | |
| import threading | |
| import time | |
| from datetime import date, datetime, timedelta, timezone | |
| import pytest | |
| from app.main import create_app | |
| from test_assignments import MemoryAssignments | |
| from test_focus_browser import DANA, SchoolAuth, mail, session | |
| from test_worksheets import MemoryWorksheets | |
| from test_worksheets_browser import NoAnswers, uvicorn | |
| playwright = pytest.importorskip("playwright.sync_api") | |
| class ExamAuth(SchoolAuth): | |
| exams = [] | |
| def classes(self, fresh=False): | |
| return [{**super().classes()[0], "exams": self.exams}] | |
| def exam_server(): | |
| auth = ExamAuth() | |
| app = create_app(auth=auth) | |
| 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]}", auth | |
| finally: | |
| server.should_exit = True | |
| thread.join(timeout=5) | |
| def ago(days): | |
| return (datetime.now(timezone.utc) - timedelta(days=days)).isoformat() | |
| # unit t: t_ext finished lately, t_simplify finished long ago (fading), t_ext_eq tried, t_area and t_formulas not started | |
| PROGRESS = {"done": {"t_ext": ago(1), "t_simplify": ago(40)}, "seen": {"t_ext": ago(1), "t_simplify": ago(40), "t_ext_eq": ago(2)}, | |
| "tries": {"t_ext_eq": 2}, "updated": 1} | |
| def with_progress(page, progress): | |
| k = json.dumps("mathly.progress.v1:" + mail[DANA]) # only the first time: a reload keeps what the page saved | |
| page.add_init_script("if(!localStorage.getItem(%s)) localStorage.setItem(%s, %s)" % (k, k, json.dumps(json.dumps(progress)))) | |
| def test_the_student_sees_readiness_and_a_plan_with_a_daily_amount(exam_server): | |
| url, auth = exam_server | |
| auth.exams = [{"subject": "מתמטיקה", "date": (date.today() + timedelta(days=3)).isoformat(), "units": ["t"], "note": "פרק 3"}] | |
| with playwright.sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| try: | |
| page, errors = session(browser, DANA) | |
| with_progress(page, PROGRESS) | |
| page.goto(url) | |
| page.locator('[data-subject="מתמטיקה"]').click() | |
| page.locator(".mx-prep-open").click() | |
| prep = page.locator(".mx-prep-sheet") | |
| playwright.expect(prep.locator("#mxTitle")).to_have_text("הכנה למבחן במתמטיקה") | |
| playwright.expect(prep).to_contain_text("חומר למבחן: טכניקה אלגברית 1") | |
| playwright.expect(prep).to_contain_text("פרק 3") | |
| playwright.expect(prep.locator(".mx-prep-sum")).to_have_text("2 מתוך 5 מיומנויות הושלמו · 1 דועכות") | |
| playwright.expect(prep.locator(".mx-prep-skills li")).to_have_count(5) | |
| playwright.expect(prep.locator('.mx-prep-skills li[data-state="fading"]')).to_have_count(1) | |
| steps = prep.locator(".mx-prep-step") | |
| playwright.expect(steps).to_have_count(8) # 3 not finished, 1 fading, the unit's quiz, the three quizzes | |
| playwright.expect(prep.locator(".mx-prep-plan")).to_contain_text("3 צעדים ביום") | |
| playwright.expect(prep.locator(".mx-prep-step.today")).to_have_count(3) | |
| playwright.expect(steps.nth(0)).to_contain_text("ללמוד ולסיים") | |
| playwright.expect(steps.nth(5)).to_contain_text("מבחן תרגול 1") | |
| playwright.expect(steps.nth(6)).to_contain_text("מבחן תרגול 2") | |
| playwright.expect(steps.nth(7)).to_contain_text("מבחן תרגול כמו במבחן") | |
| # a step done from progress made after the plan was opened | |
| page.evaluate("""() => { const k = Object.keys(localStorage).find(k => k.startsWith('mathly.progress.v1:')); | |
| const P = JSON.parse(localStorage.getItem(k)); P.done.t_area = new Date().toISOString(); localStorage.setItem(k, JSON.stringify(P)); }""") | |
| page.reload() | |
| page.locator('[data-subject="מתמטיקה"]').click() | |
| page.locator(".mx-prep-open").click() | |
| playwright.expect(prep.locator(".mx-prep-step.done")).to_have_count(1) | |
| playwright.expect(prep.locator(".mx-prep-step.done")).to_contain_text("השוואת שטחים") | |
| # the first quiz's step starts it, over the exam's units only; handed in, the step is done | |
| prep.locator('[data-hq="s1"]').click() | |
| sheet = page.locator(".mx-quiz-sheet") | |
| playwright.expect(sheet.locator(".mx-uchip")).to_have_text("מבחן תרגול 1") | |
| n = sheet.locator(".mx-quiz-dots button").count() | |
| for i in range(n): | |
| sheet.locator(".mx-choices button[data-right]").first.click() | |
| sheet.locator("[data-act=quiz-submit]" if i == n - 1 else "[data-act=quiz-next]").click() | |
| playwright.expect(sheet.locator("#mxTitle")).to_have_text(f"{n} מתוך {n} נכונות") | |
| qs = page.evaluate("""() => { const k = Object.keys(localStorage).find(k => k.startsWith('mathly.progress.v1:')); | |
| return JSON.parse(localStorage.getItem(k)).quizzes.at(-1).qs; }""") | |
| assert qs and all(q.startswith("t_") for q in qs) | |
| sheet.locator(".mx-x").click() | |
| page.locator(".mx-prep-open").click() | |
| playwright.expect(prep.locator(".mx-prep-step.done", has_text="מבחן תרגול 1")).to_have_count(1) | |
| assert not errors, errors | |
| finally: | |
| browser.close() | |
| def test_the_day_before_the_exam_the_plan_has_no_daily_amount(exam_server): | |
| url, auth = exam_server | |
| auth.exams = [{"subject": "מתמטיקה", "date": (date.today() + timedelta(days=1)).isoformat(), "units": ["t"]}, | |
| {"subject": "מתמטיקה", "date": (date.today() + timedelta(days=9)).isoformat()}] # no units: no preparation | |
| with playwright.sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| try: | |
| page, errors = session(browser, DANA) | |
| with_progress(page, PROGRESS) | |
| page.goto(url) | |
| page.locator('[data-subject="מתמטיקה"]').click() | |
| playwright.expect(page.locator(".mx-prep-open")).to_have_count(1) | |
| page.locator(".mx-prep-open").click() | |
| prep = page.locator(".mx-prep-sheet") | |
| playwright.expect(prep.locator(".mx-uchip")).to_have_text("מחר") | |
| playwright.expect(prep.locator(".mx-prep-step")).to_have_count(8) # the three quizzes at the end | |
| playwright.expect(prep.locator(".mx-prep-plan")).not_to_contain_text("צעדים ביום") | |
| playwright.expect(prep.locator(".mx-prep-step.today")).to_have_count(0) | |
| assert not errors, errors | |
| finally: | |
| browser.close() | |
| def test_the_teacher_names_the_units_and_sees_how_ready_the_class_is(exam_server): | |
| from test_focus_browser import TEACHER | |
| url, auth = exam_server | |
| auth.exams = [{"subject": "מתמטיקה", "date": (date.today() + timedelta(days=5)).isoformat()}] | |
| saved = [] | |
| def save(class_id, exams): | |
| saved.append(exams) | |
| auth.exams = exams | |
| auth.save_class_exams = save | |
| with playwright.sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| try: | |
| page, errors = session(browser, TEACHER) | |
| page.goto(url) | |
| page.locator('[data-act="class-report"]').click() | |
| sheet = page.locator(".mx-report-sheet") | |
| sheet.locator("[data-report-tab=exams]").click() | |
| form = sheet.locator("[data-exam-form]") | |
| playwright.expect(sheet.locator(".mx-exam-t")).to_contain_text("בחרו את היחידות של המבחן") | |
| form.locator('[name=unit][value="t"]').check() | |
| form.locator("[name=note]").fill("פרק 3") | |
| form.locator("button[type=submit]").click() | |
| playwright.expect(sheet.locator(".mx-report")).to_contain_text("החומר למבחן נשמר") | |
| assert saved[-1][0]["units"] == ["t"] and saved[-1][0]["note"] == "פרק 3" | |
| playwright.expect(sheet.locator(".mx-exam-t .mx-report-table tbody tr")).to_have_count(5) # the 5 skills of t | |
| playwright.expect(sheet.locator(".mx-exam-t")).to_contain_text("הכי רחוקים מהחומר") | |
| assert not errors, errors | |
| finally: | |
| browser.close() | |
| def test_a_plan_saved_with_the_old_practice_exam_step_gets_the_three_quizzes(exam_server): | |
| url, auth = exam_server | |
| when = (date.today() + timedelta(days=5)).isoformat() | |
| auth.exams = [{"subject": "מתמטיקה", "date": when, "units": ["t"], "note": ""}] | |
| old = {**PROGRESS, "prep": {f"3|מתמטיקה|{when}": {"opened": ago(1), "steps": [{"k": "skill", "id": "t_area"}, {"k": "exam"}]}}} | |
| with playwright.sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| try: | |
| page, errors = session(browser, DANA) | |
| with_progress(page, old) | |
| page.goto(url) | |
| page.locator('[data-subject="מתמטיקה"]').click() | |
| page.locator(".mx-prep-open").click() | |
| steps = page.locator(".mx-prep-sheet .mx-prep-step") | |
| playwright.expect(steps).to_have_count(4) | |
| playwright.expect(steps.nth(1)).to_contain_text("מבחן תרגול 1") | |
| playwright.expect(steps.nth(3)).to_contain_text("מבחן תרגול כמו במבחן") | |
| assert not errors, errors | |
| finally: | |
| browser.close() | |
| def test_home_highlights_the_lessons_to_finish_before_the_next_exam(exam_server): | |
| url, auth = exam_server | |
| auth.exams = [{"subject": "מתמטיקה", "date": (date.today() + timedelta(days=4)).isoformat(), "units": ["t", "k"]}] | |
| with playwright.sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| try: | |
| page, errors = session(browser, DANA) | |
| with_progress(page, {**PROGRESS, "done": {**PROGRESS["done"], **{s: ago(1) for s in ("k_def", "k_angles", "k_diag", "k_axes")}}}) | |
| page.goto(url) | |
| page.locator('[data-subject="מתמטיקה"]').click() | |
| page.locator('.mx-nav [data-view="home"]').click() | |
| lessons = page.locator(".mx-home-lessons") | |
| playwright.expect(lessons.locator("h3")).to_have_text("להשלים לפני המבחן: שיעור אחד") | |
| playwright.expect(lessons.locator("li.todo")).to_have_count(1) # unit t: 2 of 5 skills | |
| playwright.expect(lessons.locator("li.todo")).to_contain_text("2 מתוך 5 מיומנויות") | |
| playwright.expect(lessons.locator("li.done")).to_contain_text("✓ הושלם") # unit k: all done | |
| lessons.locator("li.todo button").click() # opens the lesson on the path | |
| playwright.expect(page.locator('.mx-nav [data-view="path"]')).to_have_attribute("aria-current", "page") | |
| assert not errors, errors | |
| finally: | |
| browser.close() | |
| def test_the_teacher_adds_and_deletes_an_exam_on_the_classs_table(exam_server): | |
| from test_focus_browser import TEACHER | |
| url, auth = exam_server | |
| auth.exams = [] | |
| def save(class_id, exams): | |
| auth.exams = exams | |
| auth.save_class_exams = save | |
| day = (date.today() + timedelta(days=12)).isoformat() | |
| with playwright.sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| try: | |
| page, errors = session(browser, TEACHER) | |
| page.on("dialog", lambda d: d.accept()) | |
| page.goto(url) | |
| page.locator('[data-act="class-report"]').click() | |
| sheet = page.locator(".mx-report-sheet") | |
| sheet.locator("[data-report-tab=exams]").click() | |
| playwright.expect(sheet.locator(".mx-report")).to_contain_text("אין מבחנים קרובים") | |
| form = sheet.locator("[data-exam-add]") | |
| form.locator("[name=date]").fill(day) | |
| form.locator('[name=unit][value="t"]').check() | |
| form.locator("[name=note]").fill("פרק 3") | |
| form.locator("button[type=submit]").click() | |
| playwright.expect(sheet.locator(".mx-flash")).to_contain_text("נוסף ללוח") | |
| playwright.expect(sheet.locator(".mx-exam-t h4")).to_contain_text("מתמטיקה") | |
| assert auth.exams == [{"subject": "מתמטיקה", "date": day, "units": ["t"], "note": "פרק 3"}] | |
| sheet.locator("[data-exam-del]").click() | |
| playwright.expect(sheet.locator(".mx-flash")).to_contain_text("נמחק") | |
| assert auth.exams == [] | |
| assert not errors, errors | |
| finally: | |
| browser.close() | |