"""Reproduce: testimonials cards blank after SPA navigation from another page.""" from playwright.sync_api import sync_playwright import sys, io sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') BASE = "https://www.goodwalk.co.nz" def run(): with sync_playwright() as p: browser = p.chromium.launch() for label, ctx_opts in [ ("mobile", {"viewport": {"width": 390, "height": 844}, "is_mobile": True, "has_touch": True, "user_agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 Mobile/15E148 Safari/604.1"}), ]: print(f"\n=== {label} ===") ctx = browser.new_context(**ctx_opts) page = ctx.new_page() logs = [] page.on("console", lambda m, L=logs: L.append(f"[{m.type}] {m.text}")) page.on("pageerror", lambda e, L=logs: L.append(f"[pageerror] {e}")) print(" Loading homepage…") page.goto(BASE + "/", wait_until="networkidle", timeout=30000) page.wait_for_timeout(800) all_links = page.locator('a[href*="testimonials"]').all() print(f" testimonials links found: {len(all_links)}") for a in all_links[:5]: print(f" href={a.get_attribute('href')!r} visible={a.is_visible()}") # Try opening mobile menu (hamburger) then click testimonials burger = page.locator('button[aria-label*="menu" i], button.header-burger, [aria-label*="open" i]').first if burger.count() and burger.is_visible(): burger.click() page.wait_for_timeout(400) # Click first now-visible testimonials link (SPA nav, no reload) visible_link = None for a in page.locator('a[href*="testimonials"]').all(): if a.is_visible(): visible_link = a break if visible_link is None: print(" no visible link to click") return print(" clicking testimonials link…") with page.expect_navigation(wait_until="load", timeout=5000) as nav_info: visible_link.click() print(f" nav type detected: same-document={nav_info.value is None}") page.wait_for_timeout(2000) page.wait_for_timeout(2500) print(f" url now: {page.url}") section = page.locator(".testimonials-page-grid-section") print(f" section count: {section.count()}") if section.count(): classes = section.first.get_attribute("class") print(f" section classes: {classes!r}") cards = page.locator(".testimonials-page-card") print(f" cards count: {cards.count()}") if cards.count(): first = cards.first computed = first.evaluate("el => { const cs = getComputedStyle(el); return { opacity: cs.opacity, transform: cs.transform }; }") print(f" first card computed: {computed}") last = cards.last last_comp = last.evaluate("el => { const cs = getComputedStyle(el); return { opacity: cs.opacity }; }") print(f" last card computed: {last_comp}") page.screenshot(path=f"scripts/testimonials-spa-{label}.png", full_page=True) print(f" screenshot: scripts/testimonials-spa-{label}.png") # Now scroll and recheck page.mouse.wheel(0, 600) page.wait_for_timeout(500) if cards.count(): op_after = cards.first.evaluate("el => getComputedStyle(el).opacity") print(f" first card opacity after scroll 600px: {op_after}") page.screenshot(path=f"scripts/testimonials-spa-scrolled-{label}.png", full_page=True) if logs: print(" console:") for l in logs[-12:]: print(f" {l}") ctx.close() browser.close() run()