# retoor import requests from tests.conftest import BASE_URL JSON = {"Accept": "application/json"} LAYOUT = ".feed-layout" LEFT = ".feed-layout > .sidebar-card" CENTRE = ".feed-layout > .feed-main" RIGHT = ".feed-layout > .feed-right" NAV_ENTRY = ".topnav-link[href='/quizzes']" NEW_QUIZ_BUTTON = ".quiz-actions a[href='/quizzes/new']" DEVII_BUTTON = ".quiz-actions button[data-devii-open]" SCOREBOARD = ".quiz-scoreboard-card" def _seed_quiz(title="Hub e2e quiz"): session = requests.Session() name = f"hub{abs(hash(title)) % 10**9}" session.post( f"{BASE_URL}/auth/signup", data={ "username": name, "email": f"{name}@t.dev", "password": "secret123", "confirm_password": "secret123", }, allow_redirects=True, ) slug = session.post( f"{BASE_URL}/quizzes/create", data={"title": title, "description": "d"}, headers=JSON ).json()["data"]["slug"] session.post( f"{BASE_URL}/quizzes/{slug}/questions", data={ "kind": "single_choice", "prompt": "Which journal mode allows concurrent readers?", "points": 2, "options": "DELETE\nWAL", "correct_indexes": "1", }, headers=JSON, ) session.post(f"{BASE_URL}/quizzes/{slug}/publish", headers=JSON) return slug def test_the_hub_renders_the_three_column_layout(page, app_server): _seed_quiz("Layout e2e quiz") page.goto(f"{BASE_URL}/quizzes", wait_until="domcontentloaded") page.locator(LAYOUT).wait_for(state="visible") assert page.locator(LEFT).count() == 1 assert page.locator(CENTRE).count() == 1 assert page.locator(RIGHT).count() == 1 def test_the_hub_has_a_visible_heading(page, app_server): page.goto(f"{BASE_URL}/quizzes", wait_until="domcontentloaded") heading = page.locator("h1.quiz-page-title") heading.wait_for(state="visible") assert heading.inner_text().strip() == "Quizzes" def test_the_nav_entry_is_visible_to_a_guest_and_active(page, app_server): page.goto(f"{BASE_URL}/quizzes", wait_until="domcontentloaded") entry = page.locator(NAV_ENTRY) entry.wait_for(state="visible") assert "active" in (entry.get_attribute("class") or "") def test_a_guest_sees_disabled_create_controls(page, app_server): page.goto(f"{BASE_URL}/quizzes", wait_until="domcontentloaded") page.locator(".quiz-actions").wait_for(state="visible") assert page.locator(NEW_QUIZ_BUTTON).get_attribute("aria-disabled") == "true" assert page.locator(DEVII_BUTTON).is_disabled() def test_a_guest_still_sees_the_list_and_the_scoreboard(page, app_server): _seed_quiz("Guest visible quiz") page.goto(f"{BASE_URL}/quizzes", wait_until="domcontentloaded") page.locator(SCOREBOARD).wait_for(state="visible") assert page.locator(".quiz-card").count() >= 1 def test_a_member_sees_enabled_create_controls(alice): page, _ = alice page.goto(f"{BASE_URL}/quizzes", wait_until="domcontentloaded") page.locator(NEW_QUIZ_BUTTON).wait_for(state="visible") assert page.locator(NEW_QUIZ_BUTTON).get_attribute("aria-disabled") is None assert page.locator(DEVII_BUTTON).is_enabled() def test_a_member_sees_the_personal_filters(alice): page, _ = alice page.goto(f"{BASE_URL}/quizzes", wait_until="domcontentloaded") page.locator(".sidebar-nav").wait_for(state="visible") for target in ("todo", "done", "mine", "drafts"): assert page.locator(f".sidebar-link[href='/quizzes?filter={target}']").count() == 1 def test_a_guest_sees_only_the_all_filter(page, app_server): page.goto(f"{BASE_URL}/quizzes", wait_until="domcontentloaded") page.locator(".sidebar-nav").wait_for(state="visible") assert page.locator(".sidebar-link[href='/quizzes?filter=todo']").count() == 0 assert page.locator(".sidebar-link[href='/quizzes?filter=all']").count() == 1 def test_a_quiz_card_shows_its_state_badge(alice): page, _ = alice slug = _seed_quiz("Badge e2e quiz") page.goto(f"{BASE_URL}/quizzes", wait_until="domcontentloaded") card = page.locator(f".quiz-card:has(a[href='/quizzes/{slug}'])").first card.wait_for(state="visible") assert card.locator(".quiz-state-todo").count() == 1 def test_a_quiz_card_shows_its_meta_chips(page, app_server): slug = _seed_quiz("Meta chips e2e quiz") page.goto(f"{BASE_URL}/quizzes", wait_until="domcontentloaded") card = page.locator(f".quiz-card:has(a[href='/quizzes/{slug}'])").first card.wait_for(state="visible") assert "1 questions" in card.inner_text() assert "2 points" in card.inner_text() def test_the_search_box_filters_the_list(page, app_server): slug = _seed_quiz("Unmistakable pelican quiz") page.goto(f"{BASE_URL}/quizzes?search=pelican", wait_until="domcontentloaded") page.locator(".feed-posts").wait_for(state="visible") assert page.locator(f".quiz-card:has(a[href='/quizzes/{slug}'])").count() == 1 def test_the_new_quiz_button_opens_the_create_form(alice): page, _ = alice page.goto(f"{BASE_URL}/quizzes", wait_until="domcontentloaded") page.locator(NEW_QUIZ_BUTTON).click() page.wait_for_url("**/quizzes/new", wait_until="domcontentloaded") page.locator("form.quiz-form").wait_for(state="visible") def test_the_devii_button_seeds_the_terminal_without_sending(alice): page, _ = alice page.goto(f"{BASE_URL}/quizzes", wait_until="domcontentloaded") trigger = page.locator(DEVII_BUTTON) trigger.wait_for(state="visible") prompt = trigger.get_attribute("data-devii-prompt") assert prompt and "import_quiz" in prompt trigger.click() terminal_input = page.locator("devii-terminal .devii-input") terminal_input.wait_for(state="visible", timeout=10000) assert terminal_input.input_value() == prompt assert page.locator("devii-terminal .devii-line-user").count() == 0 page.evaluate("window.app && window.app.devii && window.app.devii.close()") page.evaluate("window.localStorage.clear()") def test_opening_a_card_reaches_the_detail_page(page, app_server): slug = _seed_quiz("Card link e2e quiz") page.goto(f"{BASE_URL}/quizzes", wait_until="domcontentloaded") page.locator(f".quiz-card a.card-link[href='/quizzes/{slug}']").first.click() page.wait_for_url(f"**/quizzes/{slug}", wait_until="domcontentloaded") page.locator("h1.quiz-detail-title").wait_for(state="visible") def test_the_detail_page_shows_the_stats_strip(page, app_server): slug = _seed_quiz("Stats strip e2e quiz") page.goto(f"{BASE_URL}/quizzes/{slug}", wait_until="domcontentloaded") page.locator(".quiz-stats-strip").wait_for(state="visible") assert page.locator(".quiz-stat").count() == 5 def test_the_detail_page_offers_a_start_button_to_a_member(alice): page, _ = alice slug = _seed_quiz("Start button e2e quiz") page.goto(f"{BASE_URL}/quizzes/{slug}", wait_until="domcontentloaded") button = page.locator(".quiz-detail-actions button:has-text('Start quiz')") button.wait_for(state="visible") assert button.is_enabled() def test_the_detail_page_disables_start_for_a_guest(page, app_server): slug = _seed_quiz("Guest start e2e quiz") page.goto(f"{BASE_URL}/quizzes/{slug}", wait_until="domcontentloaded") button = page.locator(".quiz-detail-actions button:has-text('Start quiz')") button.wait_for(state="visible") assert button.is_disabled() def test_the_detail_page_carries_a_comment_section(page, app_server): slug = _seed_quiz("Comment section e2e quiz") page.goto(f"{BASE_URL}/quizzes/{slug}", wait_until="domcontentloaded") page.locator(".comments-section").wait_for(state="visible")