"""Drive the real Movim frontend served by movim-rs with a headless Chromium.""" import asyncio, sys, os from playwright.async_api import async_playwright BASE = "http://127.0.0.1:8099" OUT = os.path.dirname(os.path.abspath(__file__)) + "/shots" os.makedirs(OUT, exist_ok=True) async def login(browser, jid, password, name): ctx = await browser.new_context(viewport={"width": 1400, "height": 900}) page = await ctx.new_page() errors = [] page.on("pageerror", lambda e: errors.append(f"[{name}] pageerror: {e} {e.stack[:600] if e.stack else ''}")) page.on("console", lambda m: m.type == "error" and errors.append(f"[{name}] console: {m.text}")) await page.goto(BASE + "/login") await page.wait_for_selector("#login_widget input[type=submit]:not([disabled])", timeout=15000) await page.fill("input#username", jid) await page.fill("input#password", password) await page.click("#login_widget input[type=submit]") await page.wait_for_url("**/chat**", timeout=30000) await page.wait_for_timeout(3000) await page.screenshot(path=f"{OUT}/{name}_1_chat.png") return ctx, page, errors async def main(): async with async_playwright() as p: browser = await p.chromium.launch() actx, alice, aerr = await login(browser, "alice@localhost", "alicepass", "alice") bctx, bob, berr = await login(browser, "bob@localhost", "bobpass", "bob") # Alice opens the discussion with Bob await alice.goto(BASE + "/chat/bob@localhost") await alice.wait_for_selector("#chat_textarea", timeout=15000) await alice.wait_for_timeout(2000) await alice.fill("#chat_textarea", "Hello from the browser 🙂") await alice.press("#chat_textarea", "Enter") await alice.wait_for_timeout(2000) await alice.screenshot(path=f"{OUT}/alice_2_sent.png") # Bob sees the chat in the list and opens it await bob.wait_for_timeout(1000) await bob.screenshot(path=f"{OUT}/bob_2_list.png") await bob.goto(BASE + "/chat/alice@localhost") await bob.wait_for_selector("#chat_textarea", timeout=15000) await bob.wait_for_timeout(2500) await bob.screenshot(path=f"{OUT}/bob_3_chat.png") bubbles = await bob.locator("#chat_widget .bubble p").all_inner_texts() print("bob bubbles:", bubbles[-5:]) # Mobile layout mctx = await browser.new_context(viewport={"width": 400, "height": 800}, storage_state=await bctx.storage_state()) mobile = await mctx.new_page() await mobile.goto(BASE + "/chat") await mobile.wait_for_timeout(3000) await mobile.screenshot(path=f"{OUT}/bob_4_mobile.png") for e in aerr + berr: print(e) await browser.close() if __name__ == "__main__": asyncio.run(main())