import os from pathlib import Path import pytest if os.getenv("STACKCHAIN_RUN_RELEASE_E2E") != "1": pytest.skip("packaged pinned-work journey runs only in its gated CI job", allow_module_level=True) pytest.importorskip("playwright.sync_api") from playwright.sync_api import expect, sync_playwright ROOT = Path(__file__).parents[2] FRONTEND = ROOT / "frontend" @pytest.mark.parametrize("viewport", [ {"width": 320, "height": 568}, {"width": 390, "height": 844}, ]) def test_operator_pins_and_reopens_frequent_work_without_phone_overflow(viewport): with sync_playwright() as playwright: browser = playwright.chromium.launch(headless=True) page = browser.new_page(viewport=viewport) page.set_content((FRONTEND / "index.html").read_text()) page.add_style_tag(path=FRONTEND / "dashboard.css") page.add_script_tag(path=FRONTEND / "mobile-recent-work.js") page.evaluate("""() => { const values = new Map(); const storage = { getItem:key => values.get(key) || null, setItem:(key, value) => values.set(key, value), }; window.opened = []; window.recentWork = createMobileRecentWork({ storage, getLogin:() => 'timmy', document, section:document.querySelector('#mobile-recent-work'), list:document.querySelector('#mobile-recent-work-list'), pinnedSection:document.querySelector('#mobile-pinned-work'), pinnedList:document.querySelector('#mobile-pinned-work-list'), pinnedToggle:document.querySelector('#mobile-pinned-work-toggle'), detailPins:document.querySelectorAll('[data-current-work-pin]'), status:document.querySelector('#mobile-recent-work-status'), openRoute:route => window.opened.push(route), }); for (let number=1; number<=20; number += 1) { const item = { kind:'issue', repository:'stackchain/stackchain-dashboard', number, title:'Pinned mobile work ' + number, }; window.recentWork.record(item); window.recentWork.pin(item); } document.querySelector('#mobile-queue-sheet').showModal(); }""") expect(page.locator("#mobile-pinned-work")).to_be_visible() expect(page.locator("#mobile-recent-work")).to_be_hidden() expect(page.locator("#mobile-pinned-work-list .mobile-recent-work-row")).to_have_count(3) expect(page.locator("#mobile-recent-work-status")).to_have_text("Sync pending.") toggle = page.locator("#mobile-pinned-work-toggle") open_button = page.get_by_role( "button", name="Open Pinned mobile work 20, issue stackchain/stackchain-dashboard #20" ).first pin_button = page.get_by_role( "button", name="Unpin Pinned mobile work 20" ) for control in (open_button, pin_button, toggle): bounds = control.bounding_box() assert bounds and bounds["height"] >= 44 assert bounds["x"] >= 0 and bounds["x"] + bounds["width"] <= viewport["width"] assert page.evaluate("document.documentElement.scrollWidth <= window.innerWidth") toggle.click() expect(page.locator("#mobile-pinned-work-list .mobile-recent-work-row")).to_have_count(20) expect(toggle).to_have_text("Show fewer") assert toggle.get_attribute("aria-expanded") == "true" toggle.click() expect(page.locator("#mobile-pinned-work-list .mobile-recent-work-row")).to_have_count(3) open_button.focus() open_button.press("Enter") assert page.evaluate("window.opened") == [ "#/my-work/issue/stackchain/stackchain-dashboard/20" ] page.evaluate("""() => { document.querySelector('#mobile-queue-sheet').close(); document.querySelector('#issue-sheet').classList.add('open'); window.recentWork.setCurrent({ kind:'issue', repository:'stackchain/stackchain-dashboard', number:1489, title:'Pin the current item from mobile detail', }); }""") detail_pin = page.get_by_role( "button", name="Pin Pin the current item from mobile detail" ) expect(detail_pin).to_be_visible() bounds = detail_pin.bounding_box() assert bounds and bounds["height"] >= 44 assert bounds["x"] >= 0 and bounds["x"] + bounds["width"] <= viewport["width"] assert page.evaluate("document.documentElement.scrollWidth <= window.innerWidth") detail_pin.focus() detail_pin.press("Enter") expect(detail_pin).to_have_text("Pinned") expect(detail_pin).to_have_attribute("aria-pressed", "true") assert page.evaluate("window.recentWork.pinned()[0].number") == 1489 browser.close()