#!/usr/bin/env python3 """Drives the real page in headless Chromium (Playwright for Python) against the running app + stub. Prints a transcript to stdout. Needs: pip install playwright && playwright install chromium.""" import sys, time, urllib.request from playwright.sync_api import sync_playwright APP = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:38180" STUB = sys.argv[2] if len(sys.argv) > 2 else "http://localhost:38181" def stub(path): return urllib.request.urlopen(STUB + path, data=b"" if "config" in path else None).read().decode().strip() def ask(page, text): n = page.locator(".msg.bot").count() page.fill("input[name=message]", text) page.click("form button") page.wait_for_selector(f".msg.bot >> nth={n}") return int(page.locator(".msg.bot span[id^=out-]").last.get_attribute("id")[4:]) def wait_done(page, n, timeout=20000): page.wait_for_function(f"!document.querySelector('#stop-{n}')", timeout=timeout) def bot_text(page, n): return page.locator(f"#out-{n}").inner_text() with sync_playwright() as p: b = p.chromium.launch() ctx = b.new_context() page = ctx.new_page() dialogs = [] page.on("dialog", lambda d: (dialogs.append(d.message), d.dismiss())) page.goto(APP + "/") print("== turn 1 (session A)") n = ask(page, "My name is Asha and I like tea"); wait_done(page, n) print("A1:", repr(bot_text(page, n))) print("== turn 2 (session A, same cookie)") n = ask(page, "What did I just tell you?"); wait_done(page, n) print("A2:", repr(bot_text(page, n))) print("cookies:", [c["name"] for c in ctx.cookies()]) print("== turn 1 (session B, fresh browser context, no cookie)") ctx2 = b.new_context(); page2 = ctx2.new_page(); page2.goto(APP + "/") n = ask(page2, "What did I just tell you?"); wait_done(page2, n) print("B1:", repr(bot_text(page2, n))) print("== New conversation button in session A, then ask again") page.click("text=New conversation"); time.sleep(0.5) n = ask(page, "Do you remember me?"); wait_done(page, n) print("A3:", repr(bot_text(page, n))) print("== model output containing markup") n = ask(page, "html please"); wait_done(page, n) print("rendered text:", repr(bot_text(page, n))) print(" elements created inside the answer:", page.locator(f"#out-{n} b").count()) print(" elements created inside the answer:", page.locator(f"#out-{n} img").count()) print("alert dialogs fired:", len(dialogs)) print("== stop button") stub("/stub/config?delayMs=50") n = ask(page, "count 200") page.wait_for_function(f"document.querySelector('#out-{n}').innerText.length > 30") before = bot_text(page, n) t0 = time.time(); page.click(f"#stop-{n}") page.wait_for_function(f"!document.querySelector('#stop-{n}')") time.sleep(1.5) after = bot_text(page, n) print("text at click :", repr(before)) print("text 1.5 s on :", repr(after)) print("grew after stop:", len(after.replace(' [stopped]','')) > len(before.replace(' [stopped]','')) + 6) stub("/stub/config?delayMs=20") b.close()