import os from pathlib import Path import pytest if os.getenv("STACKCHAIN_RUN_RELEASE_E2E") != "1": pytest.skip("packaged mobile Following 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_following_queue_is_phone_usable_at_narrow_viewport(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 / "search-preview.js") page.add_script_tag(path=FRONTEND / "following.js") row = page.locator('[data-mobile-queue="following"]') expect(row).to_have_count(1) expect(row).to_contain_text("Issues and pull requests you watch") page.evaluate("""() => { globalThis.fetch = async () => ({ ok:true, json:async () => ({revision:1,items:[{ repository:'stackchain/api', kind:'pull', number:42, title:'Changed pull request with a long mobile title', state:'open', updated_at:'2026-08-23T05:00:00Z', has_unseen_change:true }]}) }); globalThis.followingReleaseQueue = attachFollowing(() => {}); globalThis.followingReleaseQueue.open(); }""") expect(page.locator("#following-sheet")).to_be_visible() expect(page.locator(".following-card")).to_be_visible() expect(page.locator(".following-card")).to_contain_text("New activity") expect(page.locator(".following-card")).to_contain_text("Pull request") expect(page.locator("#review-following")).to_have_text("Review new activity") assert page.locator("#review-following").bounding_box()["height"] >= 44 assert page.locator(".following-card").bounding_box()["height"] >= 44 assert page.locator("#close-following").bounding_box()["height"] >= 44 retire = page.locator("#watch-search-result") page.evaluate("""() => { document.querySelector('#following-sheet').close(); document.querySelector('#search-preview').classList.add('open'); const button = document.querySelector('#watch-search-result'); renderSearchPreviewWatch( {repository:'stackchain/api', number:42, kind:'issue', state:'closed', following:true, watching:true}, {status:'ready'}, button ); }""") expect(retire).to_be_visible() expect(retire).to_have_text("Stop watching & next") assert retire.bounding_box()["height"] >= 44 page.evaluate("""() => renderSearchPreviewWatch( {repository:'stackchain/api', number:42, kind:'pull', state:'open', watching:false}, {status:'ready'}, document.querySelector('#watch-search-result'))""") expect(retire).to_have_text("Watch pull request") assert retire.bounding_box()["height"] >= 44 overflow = page.evaluate("document.documentElement.scrollWidth > document.documentElement.clientWidth") assert overflow is False browser.close()