Download tests/test_home_browser.py from wzender/mathly: direct link, hf CLI and curl.
- Browser
- Download file 8.62 kB
-
https://huggingface.co/spaces/wzender/mathly/resolve/main/tests/test_home_browser.py
- Command line
-
hf download hf://spaces/wzender/mathly/tests/test_home_browser.py
-
curl -L -o test_home_browser.py https://huggingface.co/spaces/wzender/mathly/resolve/main/tests/test_home_browser.py
8.62 kB
| """Home and path tabs (openspec student-home-and-exam-quizzes): home shows only what has a date or needs the student, | |
| the path tab holds the self-paced learning, and a class teacher keeps their classes.""" | |
| from datetime import date, datetime, timedelta, timezone | |
| import pytest | |
| from test_exam_prep_browser import ExamAuth, exam_server, with_progress # noqa: F401 (a fixture) | |
| from test_focus_browser import DANA, TEACHER, session | |
| playwright = pytest.importorskip("playwright.sync_api") | |
| COMMENT = {"attempt_id": "a1", "question": "驻讬诇讜讙 诪讜专讞讘", "score": 80, "question_id": "t_ext"} | |
| def days_from_now(n): | |
| return (date.today() + timedelta(days=n)).isoformat() | |
| def to_math(page): | |
| """With exams the app asks for the subject first; without, it goes straight to math.""" | |
| page.locator('[data-subject="诪转诪讟讬拽讛"], #mathView .mx-top').first.wait_for() | |
| if page.locator('[data-subject="诪转诪讟讬拽讛"]').count(): | |
| page.locator('[data-subject="诪转诪讟讬拽讛"]').click() | |
| def open_home(browser, url, comments=()): | |
| page, errors = session(browser, DANA) | |
| page.route("**/api/math/teacher-comments", lambda route: route.fulfill(json={"comments": list(comments)})) | |
| def me(route): # comments are loaded only where answer scans are on | |
| reply = route.fetch() | |
| route.fulfill(response=reply, json={**reply.json(), "answer_scans": True}) | |
| page.route("**/api/me", me) | |
| page.goto(url) | |
| to_math(page) | |
| return page, errors | |
| def test_home_shows_what_is_due_in_order_and_no_trail(exam_server): | |
| url, auth = exam_server | |
| auth.exams = [{"subject": "诪转诪讟讬拽讛", "date": days_from_now(5), "units": ["t"], "note": ""}] | |
| with playwright.sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| try: | |
| page, errors = open_home(browser, url, [COMMENT]) | |
| nav = page.locator(".mx-nav button") | |
| playwright.expect(nav.locator("span")).to_have_text(["讘讬转", "诪住诇讜诇", "爪讬讜谞讬诐", "讛讗讜住祝"]) | |
| playwright.expect(page.locator('.mx-nav [data-view="home"]')).to_have_attribute("aria-current", "page") | |
| home = page.locator(".mx-home") | |
| exam = home.locator(".mx-home-exam") | |
| playwright.expect(exam).to_contain_text("诪讘讞谉 讘诪转诪讟讬拽讛") | |
| playwright.expect(exam).to_contain_text("注讜讚 5 讬诪讬诐") | |
| playwright.expect(page.locator(".mx-teacher-comment")).to_contain_text("驻讬诇讜讙 诪讜专讞讘") | |
| playwright.expect(page.locator(".mx-continue")).to_be_visible() | |
| # the order: exam, quizzes, due work, comments, then the way to the path | |
| order = page.evaluate("""() => [...document.querySelector('.mx-home').children].map(el => | |
| el.matches('.mx-home-exam') ? 'exam' : el.matches('.mx-hq') ? 'quiz' | |
| : el.matches('.mx-tasks-sum, .mx-grades-btn, .mx-asgs') ? 'due' : el.matches('.mx-teacher-comment') ? 'comment' | |
| : el.matches('.mx-continue') ? 'continue' : el.className)""") | |
| assert order.index("exam") < order.index("quiz") < order.index("due") < order.index("comment") < order.index("continue"), order | |
| # nothing of the path on home | |
| for sel in (".mx-trail", ".mx-daily", ".mx-review", ".mx-patterns"): | |
| playwright.expect(page.locator(sel)).to_have_count(0) | |
| # the exam opens its preparation | |
| exam.click() | |
| playwright.expect(page.locator(".mx-prep-sheet #mxTitle")).to_have_text("讛讻谞讛 诇诪讘讞谉 讘诪转诪讟讬拽讛") | |
| assert not errors, errors | |
| finally: | |
| browser.close() | |
| def test_seen_comments_are_not_on_home_and_an_exam_without_units_has_no_preparation(exam_server): | |
| url, auth = exam_server | |
| auth.exams = [{"subject": "诪转诪讟讬拽讛", "date": days_from_now(9)}] | |
| with playwright.sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| try: | |
| page, errors = open_home(browser, url) | |
| exam = page.locator(".mx-home-exam") | |
| playwright.expect(exam).to_contain_text("注讜讚 9 讬诪讬诐") | |
| playwright.expect(exam.locator("[data-prep]")).to_have_count(0) | |
| assert exam.evaluate("el => el.tagName") == "DIV" # nothing to open | |
| playwright.expect(page.locator(".mx-teacher-comment")).to_have_count(0) | |
| assert not errors, errors | |
| finally: | |
| browser.close() | |
| def open_questions_only(route): | |
| """The skills with no multiple-choice question: no quiz can be offered.""" | |
| graph = route.fetch().json() | |
| for skill in graph["skills"]: | |
| for q in skill.get("questions", []): | |
| q.pop("choices", None) | |
| route.fulfill(json=graph) | |
| def test_home_is_never_empty_and_continue_opens_the_path_at_the_next_topic(exam_server): | |
| url, auth = exam_server | |
| auth.exams = [] # no exam, no quiz, nothing due | |
| with playwright.sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| try: | |
| page, errors = session(browser, DANA) | |
| page.route("**/api/math/skills", open_questions_only) | |
| page.goto(url) | |
| to_math(page) | |
| playwright.expect(page.locator(".mx-home-empty")).to_have_text("讗讬谉 讻专讙注 诪砖讛讜 诇讛讙讬砖 讗讜 诪讘讞谉 拽专讜讘.") | |
| playwright.expect(page.locator(".mx-continue")).to_be_visible() | |
| assert not errors, errors | |
| finally: | |
| browser.close() | |
| with playwright.sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| try: | |
| page, errors = open_home(browser, url) | |
| playwright.expect(page.locator(".mx-home-empty")).to_have_count(0) # a quiz is offered | |
| page.locator(".mx-continue").click() | |
| playwright.expect(page.locator('.mx-nav [data-view="path"]')).to_have_attribute("aria-current", "page") | |
| playwright.expect(page.locator(".mx-star.st-next")).to_be_in_viewport() | |
| assert not errors, errors | |
| finally: | |
| browser.close() | |
| def ago(days): | |
| return (datetime.now(timezone.utc) - timedelta(days=days)).isoformat() | |
| def test_the_path_tab_holds_review_and_the_collection_jumps_to_a_unit(exam_server): | |
| url, auth = exam_server | |
| auth.exams = [] | |
| old = ago(30) | |
| due = {"t_ext": old, "t_simplify": old, "t_ext_eq": old} | |
| with playwright.sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| try: | |
| page, errors = session(browser, DANA) | |
| with_progress(page, {"done": due, "seen": due, "review": {k: {"box": 0, "due": "2020-01-01"} for k in due}, "updated": 1}) | |
| page.goto(url) | |
| to_math(page) | |
| playwright.expect(page.locator(".mx-review")).to_have_count(0) # not on home | |
| page.locator('.mx-nav [data-view="path"]').click() | |
| playwright.expect(page.locator(".mx-review")).to_be_visible() | |
| playwright.expect(page.locator(".mx-daily")).to_be_visible() | |
| # path order: daily goal, review, then the trail | |
| order = page.evaluate("""() => ['.mx-daily', '.mx-review', '.mx-trail'].map(s => | |
| [...document.querySelectorAll('#mathView *')].indexOf(document.querySelector(s)))""") | |
| assert order == sorted(order) and -1 not in order, order | |
| page.locator('.mx-nav [data-view="sky"]').click() | |
| page.locator('.mx-con-card[data-unit="k"]').click() | |
| playwright.expect(page.locator('.mx-nav [data-view="path"]')).to_have_attribute("aria-current", "page") | |
| playwright.expect(page.locator("#mx-unit-k")).to_be_in_viewport() | |
| assert not errors, errors | |
| finally: | |
| browser.close() | |
| def test_a_class_teacher_keeps_the_classes_and_has_no_path_tab(exam_server): | |
| url, auth = exam_server | |
| with playwright.sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| try: | |
| page, errors = session(browser, TEACHER) | |
| page.goto(url) | |
| to_math(page) | |
| playwright.expect(page.locator(".mx-classes")).to_be_visible() | |
| playwright.expect(page.locator('.mx-nav [data-view="path"]')).to_have_count(0) | |
| # the student preview has both tabs | |
| page.locator(".mx-myclass").first.click() | |
| page.locator('[data-act="preview-on"]').click() | |
| to_math(page) | |
| playwright.expect(page.locator('.mx-nav [data-view="path"]')).to_have_count(1) | |
| playwright.expect(page.locator(".mx-continue")).to_be_visible() | |
| assert not errors, errors | |
| finally: | |
| browser.close() | |