49 lines
3.5 KiB
Python
49 lines
3.5 KiB
Python
|
|
"""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='''<!doctype html><html><head><style>
|
||
|
|
body{margin:0;font-family:Arial}.sf-section{min-height:160px;padding:20px;background:#f7f9fb;margin-bottom:12px}
|
||
|
|
.sf-layout-grid{display:grid;grid-template-columns:var(--sf-layout-cols);gap:8px}
|
||
|
|
.sf-layout-column{min-height:200px;background:#eee}
|
||
|
|
</style></head><body>
|
||
|
|
<section class="sf-section" data-block="a"><div><h1>First block</h1><p>hello</p></div></section>
|
||
|
|
<section class="sf-section" data-block="b"><div><h2>Second block</h2><p>description</p></div></section>
|
||
|
|
<section class="sf-section" data-block="c"><div><h2>Layout</h2><div class="sf-layout-grid" data-layout="c" style="--sf-layout-cols:1fr 1fr"><div class="sf-layout-column"><p>Left</p></div><div class="sf-layout-column"><p>Right</p></div></div></div></section>
|
||
|
|
</body></html>'''
|
||
|
|
|
||
|
|
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('<html><body><iframe id="preview" sandbox="allow-scripts" style="width:950px;height:850px"></iframe></body></html>')
|
||
|
|
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('</body>','<script>'+BRIDGE+'</script></body>'))
|
||
|
|
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()
|