chore: add reference docs, scripts, tests, demo, prototypes
- Reference docs: known issues, user journey, location redesign, mission merge plan - Scripts: fill_location_state, merge_missions, migrate_location, migrate_state - Tests: e2e test suite, asset entries unit tests - Demo: location board, hifi prototypes, test screenshots - Data backup: asset log entries and state nodes - Update .gitignore Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
"""Test the location board demo click functionality using Playwright."""
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
from playwright.async_api import async_playwright
|
||||
|
||||
DEMO_PATH = Path(__file__).resolve().parent / "location_board_demo.html"
|
||||
FILE_URL = f"file:///{DEMO_PATH.as_posix()}"
|
||||
|
||||
|
||||
async def main():
|
||||
async with async_playwright() as p:
|
||||
browser = await p.chromium.launch(headless=True)
|
||||
page = await browser.new_page(viewport={"width": 1400, "height": 900})
|
||||
await page.goto(FILE_URL, wait_until="commit", timeout=10000)
|
||||
await page.wait_for_timeout(3000) # let canvas render (skip font loading)
|
||||
|
||||
# --- Test 1: Check initial state ---
|
||||
scope = await page.text_content("#scope-indicator")
|
||||
print(f"Test 1 - Initial scope: {scope}")
|
||||
|
||||
# --- Test 2: Get canvas bounding box and try clicking a planet ---
|
||||
canvas = page.locator("#map-canvas")
|
||||
box = await canvas.bounding_box()
|
||||
if not box:
|
||||
print("ERROR: Canvas not found!")
|
||||
await browser.close()
|
||||
return
|
||||
|
||||
print(f"Canvas: x={box['x']:.0f} y={box['y']:.0f} w={box['width']:.0f} h={box['height']:.0f}")
|
||||
|
||||
# The solar system view has the sun at center of canvas
|
||||
# Planets orbit around it. Let's log JS state to see where bodies are.
|
||||
body_positions = await page.evaluate("""
|
||||
() => {
|
||||
const result = [];
|
||||
const keys = ['sun','mercury','venus','earth','mars','jupiter','saturn','uranus','neptune','pluto'];
|
||||
for (const k of keys) {
|
||||
const b = BD[k];
|
||||
if (b) result.push({
|
||||
key: k,
|
||||
name: b.n,
|
||||
sx: b._x,
|
||||
sy: b._y,
|
||||
r: b.r,
|
||||
hasMoons: (b.moons && typeof b.moons==='object') ? Object.keys(b.moons).join(',') : 'none'
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
""")
|
||||
print("\nBody positions (CSS pixels from canvas top-left):")
|
||||
for bp in body_positions:
|
||||
sx = bp['sx']
|
||||
sy = bp['sy']
|
||||
if sx is not None and sy is not None:
|
||||
# Convert to page coordinates (add canvas offset)
|
||||
px = sx + box['x']
|
||||
py = sy + box['y']
|
||||
print(f" {bp['name']:12s} screen=({sx:6.1f},{sy:6.1f}) page=({px:6.1f},{py:6.1f}) r={bp['r']} moons={bp['hasMoons']}")
|
||||
else:
|
||||
print(f" {bp['name']:12s} screen=(undefined) - NOT RENDERED")
|
||||
|
||||
# --- Test 3: Try clicking Jupiter ---
|
||||
jupiter = [b for b in body_positions if b['key'] == 'jupiter']
|
||||
if jupiter and jupiter[0]['sx'] is not None:
|
||||
jx = jupiter[0]['sx'] + box['x']
|
||||
jy = jupiter[0]['sy'] + box['y']
|
||||
jr = jupiter[0]['r'] + 5 # hit radius
|
||||
print(f"\nTest 3 - Clicking Jupiter at page ({jx:.0f}, {jy:.0f}) r={jr}")
|
||||
|
||||
# Take pre-click screenshot
|
||||
await page.screenshot(path=str(DEMO_PATH.parent / "pre_click.png"))
|
||||
print(" Screenshot: pre_click.png")
|
||||
|
||||
# Click
|
||||
await page.mouse.click(jx, jy)
|
||||
await page.wait_for_timeout(500)
|
||||
|
||||
scope_after = await page.text_content("#scope-indicator")
|
||||
back_visible = await page.evaluate("() => document.getElementById('back-btn').classList.contains('visible')")
|
||||
print(f" After click - scope: {scope_after}")
|
||||
print(f" Back button visible: {back_visible}")
|
||||
print(f" View stack: {await page.evaluate('() => JSON.stringify(viewStack)')}")
|
||||
|
||||
await page.screenshot(path=str(DEMO_PATH.parent / "post_click.png"))
|
||||
print(" Screenshot: post_click.png")
|
||||
else:
|
||||
print("\nTest 3 - Jupiter not found in rendered bodies!")
|
||||
|
||||
# --- Test 4: Check JS console for errors ---
|
||||
console_msgs = []
|
||||
page.on("console", lambda msg: console_msgs.append(f"[{msg.type}] {msg.text}"))
|
||||
# Trigger a re-render
|
||||
await page.evaluate("() => { render(); }")
|
||||
await page.wait_for_timeout(300)
|
||||
errors = [m for m in console_msgs if 'error' in m.lower() or 'Error' in m]
|
||||
if errors:
|
||||
print(f"\nJS errors: {errors}")
|
||||
else:
|
||||
print("\nNo JS errors detected")
|
||||
|
||||
# --- Test 5: Check didDrag state and event flow ---
|
||||
print("\n--- Event Debug ---")
|
||||
# Inject debug listener
|
||||
await page.evaluate("""
|
||||
() => {
|
||||
const canvas = document.getElementById('map-canvas');
|
||||
canvas.addEventListener('click', (e) => {
|
||||
console.log('CLICK on canvas at', e.clientX, e.clientY, 'didDrag=', window._didDrag || didDrag);
|
||||
}, true); // capture phase
|
||||
|
||||
// Store for inspection
|
||||
window._debugClick = (x, y) => {
|
||||
const r = canvas.getBoundingClientRect();
|
||||
const t = hitTest(x - r.left, y - r.top);
|
||||
console.log('hitTest result:', t, 'didDrag=', didDrag, 'dragOn=', dragOn);
|
||||
return t;
|
||||
};
|
||||
}
|
||||
""")
|
||||
|
||||
# Try click with explicit coordinates
|
||||
if jupiter and jupiter[0]['sx'] is not None:
|
||||
result = await page.evaluate(f"() => window._debugClick({jx - box['x']}, {jy - box['y']})")
|
||||
print(f"hitTest at Jupiter position result: {result}")
|
||||
|
||||
# Also try clicking center of canvas minus offset
|
||||
cx = box['width'] / 2
|
||||
cy = box['height'] / 2
|
||||
for offset_y in [0, -20, -50, -100, 50, 100]:
|
||||
test_x = cx
|
||||
test_y = cy + offset_y
|
||||
r = await page.evaluate(f"() => window._debugClick({test_x}, {test_y})")
|
||||
print(f" hitTest at canvas({test_x:.0f}, {test_y:.0f}): {r}")
|
||||
|
||||
await browser.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user