mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-09-16 21:22:20 +02:00
119 lines
4.6 KiB
Python
119 lines
4.6 KiB
Python
import json
|
|
import subprocess
|
|
import textwrap
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
PRECISION_MODULE = (ROOT / "static/js/editor/precision-guides.js").as_uri()
|
|
SNAP_MODULE = (ROOT / "static/js/editor/snap.js").as_uri()
|
|
MOVE_MODULE = (ROOT / "static/js/editor/tools/move.js").as_uri()
|
|
STATE_MODULE = (ROOT / "static/js/editor/state.js").as_uri()
|
|
|
|
|
|
def run_node(body: str):
|
|
script = textwrap.dedent(
|
|
f"""
|
|
import {{ chooseRulerStep, pointerToDocument }} from {json.dumps(PRECISION_MODULE)};
|
|
import {{ computeSnap }} from {json.dumps(SNAP_MODULE)};
|
|
import {{ createMoveTool }} from {json.dumps(MOVE_MODULE)};
|
|
import {{ state }} from {json.dumps(STATE_MODULE)};
|
|
globalThis.document = {{activeElement:null}};
|
|
{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_ruler_step_and_pointer_mapping_scale_with_viewport():
|
|
result = run_node(
|
|
"""
|
|
console.log(JSON.stringify({
|
|
steps:[chooseRulerStep(1),chooseRulerStep(0.25),chooseRulerStep(4)],
|
|
point:pointerToDocument(110,70,{left:10,top:20,width:200,height:100},400,200),
|
|
}));
|
|
"""
|
|
)
|
|
assert result == {
|
|
"steps": [50, 200, 20],
|
|
"point": {"x": 200, "y": 100},
|
|
}
|
|
|
|
|
|
def test_snap_targets_explicit_guides_and_grid():
|
|
result = run_node(
|
|
"""
|
|
const layer={id:'active',canvas:{width:20,height:10}};
|
|
const guides=computeSnap(layer,43,47,{
|
|
zoom:1,canvasW:300,canvasH:200,otherLayers:[],
|
|
verticalGuides:[50],horizontalGuides:[52],
|
|
});
|
|
const grid=computeSnap(layer,34,74,{
|
|
zoom:1,canvasW:300,canvasH:200,otherLayers:[],snapToGrid:true,gridSize:20,
|
|
});
|
|
console.log(JSON.stringify({guides,grid}));
|
|
"""
|
|
)
|
|
assert result["guides"]["x"] == 40
|
|
assert result["guides"]["y"] == 47
|
|
assert {"vertical": True, "x": 50} in result["guides"]["guides"]
|
|
assert {"vertical": False, "y": 52} in result["guides"]["guides"]
|
|
assert result["grid"]["x"] == 30
|
|
assert result["grid"]["y"] == 75
|
|
|
|
|
|
def test_move_modifier_inverts_persistent_snap_preference():
|
|
result = run_node(
|
|
"""
|
|
const layer={id:'photo',name:'Photo',canvas:{width:10,height:10},visible:true};
|
|
const canvas={width:200,height:200,getBoundingClientRect:()=>({left:0,top:0,width:200,height:200})};
|
|
Object.assign(state,{
|
|
mainCanvas:canvas,imgWidth:200,imgHeight:200,zoom:1,
|
|
layers:[layer],activeLayerId:layer.id,guides:{vertical:[37],horizontal:[]},
|
|
gridSize:20,snapToGrid:false,moving:false,transformActive:false,
|
|
});
|
|
const event=(x,ctrl=false)=>({clientX:x,clientY:30,preventDefault(){},ctrlKey:ctrl,metaKey:false});
|
|
function drag(enabled,ctrl) {
|
|
state.snapEnabled=enabled;
|
|
state.layerOffsets=new Map([[layer.id,{x:0,y:30}]]);
|
|
const tool=createMoveTool({activeLayer:()=>layer,saveState:()=>{},composite:()=>{}});
|
|
tool.begin(event(0,ctrl));
|
|
tool.drag(event(34,ctrl));
|
|
tool.end();
|
|
return state.layerOffsets.get(layer.id).x;
|
|
}
|
|
console.log(JSON.stringify({defaultOn:drag(true,false),invertedOff:drag(true,true),temporaryOn:drag(false,true)}));
|
|
"""
|
|
)
|
|
assert result == {"defaultOn": 32, "invertedOff": 34, "temporaryOn": 32}
|
|
|
|
|
|
def test_precision_controls_are_wired_and_cached_offline():
|
|
topbar = (ROOT / "static/js/editor/build/topbar.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")
|
|
|
|
for action in ("rulers", "grid", "snap", "snap-grid", "clear-guides"):
|
|
assert f'data-view-action="{action}"' in topbar
|
|
assert "saveState: _saveState" in editor
|
|
assert "schedulePersist: _schedulePersist" in editor
|
|
assert "_precisionGuides?.drawDocumentOverlay" in editor
|
|
assert "/static/js/editor/precision-guides.js" in service_worker
|
|
assert "/static/js/editor/wire-view-menu.js" in service_worker
|
|
|
|
|
|
def test_history_snapshots_include_and_restore_guides():
|
|
editor = (ROOT / "static/js/galleryEditor.js").read_text(encoding="utf-8")
|
|
assert "vertical: [...(state.guides?.vertical || [])]" in editor
|
|
assert "vertical: [...(snap.guides?.vertical || [])]" in editor
|
|
assert "saveState?.('Add guide')" in (
|
|
ROOT / "static/js/editor/precision-guides.js"
|
|
).read_text(encoding="utf-8")
|