"""Chromium-backed canvas interaction smoke without accessing a network endpoint. Tests the shipped studio-canvas-bridge.js in a real sandboxed srcdoc iframe. Server-authenticated editor E2E is separately covered by studio_canvas_smoke_v822.py. """ from pathlib import Path from playwright.sync_api import sync_playwright ROOT=Path(__file__).resolve().parents[1] BRIDGE=(ROOT/'app/static/studio-canvas-bridge.js').read_text(encoding='utf-8') DOC='''

First block

hello

Second block

description

Layout

Left

Right

''' def run(): # `iframe.srcdoc` is used here just as in the production editor. with sync_playwright() as playwright: browser=playwright.chromium.launch(headless=True,executable_path='/usr/bin/chromium',args=['--no-sandbox']) page=browser.new_page(viewport={'width':1280,'height':950}) page.set_content('') page.evaluate('''content=>{window.events=[];window.addEventListener('message',e=>{if(e.source===document.querySelector('iframe').contentWindow)events.push(e.data)});document.querySelector('iframe').srcdoc=content;}''',DOC.replace('','')) frame=page.frame_locator('#preview') frame.locator('.sf-canvas-toolbar').first.wait_for(state='attached',timeout=8000) assert frame.locator('.sf-canvas-toolbar').count()==3 frame.locator('.sf-section[data-block="a"]').click(position={'x':50,'y':80}) assert frame.locator('.sf-section.sf-canvas-selected[data-block="a"]').count()==1 assert page.evaluate('events.some(x=>x.action==="select"&&x.blockId==="a")') frame.locator('.sf-section[data-block="a"]').hover() frame.locator('.sf-section[data-block="a"] > .sf-canvas-toolbar [data-action="duplicate"]').click() assert page.evaluate('events.some(x=>x.action==="duplicate"&&x.blockId==="a")') frame.locator('.sf-section[data-block="a"]').hover() frame.locator('.sf-section[data-block="a"] > .sf-canvas-toolbar [data-action="add-after"]').click() assert page.evaluate('events.some(x=>x.action==="add-after"&&x.blockId==="a")') frame.locator('.sf-section[data-block="c"]').hover() assert frame.locator('.sf-canvas-resize').count()==1 # Verify a real keyboard resize message using the same bounds as production. frame.locator('.sf-canvas-resize').focus() frame.locator('.sf-canvas-resize').press('ArrowRight') assert page.evaluate('events.some(x=>x.action==="resize-columns"&&x.blockId==="c"&&x.widths[0]>1)') assert not page.evaluate('events.some(x=>x.action==="execute")') print('PASS: Chromium sandbox canvas selected, duplicate, add-after, keyboard column resize / postMessage') browser.close() if __name__=='__main__':run()