mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-09-14 20:22:22 +02:00
109 lines
3.7 KiB
Python
109 lines
3.7 KiB
Python
import json
|
|
import subprocess
|
|
import textwrap
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
MODULE = (ROOT / "static/js/editor/canvas-navigation.js").as_uri()
|
|
|
|
|
|
def run_node(body: str):
|
|
script = textwrap.dedent(
|
|
f"""
|
|
import {{
|
|
applyCanvasPan, isDirectPanIntent, nextPanOffset, syncPanCursor,
|
|
}} from {json.dumps(MODULE)};
|
|
{body}
|
|
"""
|
|
)
|
|
result = subprocess.run(
|
|
["node", "--input-type=module", "-e", script],
|
|
cwd=ROOT,
|
|
text=True,
|
|
capture_output=True,
|
|
check=True,
|
|
)
|
|
return json.loads(result.stdout)
|
|
|
|
|
|
def test_pan_intent_covers_hand_space_and_middle_mouse():
|
|
result = run_node(
|
|
"""
|
|
console.log(JSON.stringify({
|
|
hand:isDirectPanIntent('hand',false,0),
|
|
space:isDirectPanIntent('brush',true,0),
|
|
middle:isDirectPanIntent('brush',false,1),
|
|
brush:isDirectPanIntent('brush',false,0),
|
|
}));
|
|
"""
|
|
)
|
|
assert result == {"hand": True, "space": True, "middle": True, "brush": False}
|
|
|
|
|
|
def test_pan_math_uses_drag_origin_instead_of_accumulating_deltas():
|
|
result = run_node(
|
|
"""
|
|
const first = nextPanOffset({x:100,y:80},{x:12,y:-5},{x:145,y:110});
|
|
const second = nextPanOffset({x:100,y:80},{x:12,y:-5},{x:90,y:60});
|
|
console.log(JSON.stringify({first,second}));
|
|
"""
|
|
)
|
|
assert result == {
|
|
"first": {"x": 57, "y": 25},
|
|
"second": {"x": 2, "y": -25},
|
|
}
|
|
|
|
|
|
def test_apply_pan_updates_state_canvas_overlay_and_cursor_classes():
|
|
result = run_node(
|
|
"""
|
|
const classes = new Set();
|
|
const area = {
|
|
dataset:{},
|
|
classList:{
|
|
toggle(name,on) { if (on) classes.add(name); else classes.delete(name); },
|
|
},
|
|
};
|
|
const state = {
|
|
tool:'hand', spacePanActive:false,
|
|
mainCanvas:{style:{}}, transformOverlay:{style:{}},
|
|
};
|
|
applyCanvasPan(state,area,17,-9);
|
|
syncPanCursor(state,area,false);
|
|
const ready = [...classes];
|
|
syncPanCursor(state,area,true);
|
|
console.log(JSON.stringify({
|
|
pan:[state.panX,state.panY], dataset:area.dataset,
|
|
main:state.mainCanvas.style.transform,
|
|
overlay:state.transformOverlay.style.transform,
|
|
ready, panning:[...classes],
|
|
}));
|
|
"""
|
|
)
|
|
assert result["pan"] == [17, -9]
|
|
assert result["dataset"] == {"panX": "17", "panY": "-9"}
|
|
assert result["main"] == "translate3d(17px, -9px, 0)"
|
|
assert result["overlay"] == result["main"]
|
|
assert result["ready"] == ["ge-pan-ready"]
|
|
assert result["panning"] == ["ge-panning"]
|
|
|
|
|
|
def test_hand_navigation_is_wired_to_toolbar_keyboard_and_offline_graph():
|
|
toolbar = (ROOT / "static/js/editor/build/toolbar.js").read_text(encoding="utf-8")
|
|
keyboard = (ROOT / "static/js/editor/keyboard-shortcuts.js").read_text(encoding="utf-8")
|
|
events = (ROOT / "static/js/editor/canvas-events.js").read_text(encoding="utf-8")
|
|
editor = (ROOT / "static/js/galleryEditor.js").read_text(encoding="utf-8")
|
|
service_worker = (ROOT / "static/sw.js").read_text(encoding="utf-8")
|
|
|
|
assert "{ id: 'hand', label: 'Hand'" in toolbar
|
|
assert "key: 'H'" in toolbar
|
|
assert "e.code === 'Space'" in keyboard
|
|
assert "setTemporaryPan?.(true)" in keyboard
|
|
assert "isDirectPanIntent(state.tool, state.spacePanActive" in events
|
|
assert "transformPointerId = e.pointerId" in events
|
|
assert "canvasArea.setPointerCapture(transformPointerId)" in events
|
|
assert "continueDraw(e)" in events
|
|
assert "canvasNavigation?.updateCursor()" in editor
|
|
assert "/static/js/editor/canvas-navigation.js" in service_worker
|