Files
odysseus/tests/test_editor_quick_edit_combine_shapes.py
T
pewdiepie-archdaemonandClaude Opus 5.5 5fac693c1c feat(photo-editor): Ajax Image Editor client (Photoshop-parity tools)
Photoshop-parity editor client: layers, selection/masking, brushes,
smart filters, LUT import, Quick Edit, mobile gestures, workspaces,
batch operations, and the service-worker versioning (v978->v1006).

Source: vendor/photocraft (ad1cff44) photo-editor client files, merged
onto upstream/dev (a8c147b2). Conflict resolution documented in
pr_work/A_conflicts.md; editor files taken from vendor/photocraft
(upstream's editor is an earlier snapshot of the same feature).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 11:57:35 +00:00

69 lines
2.6 KiB
Python

import re
from pathlib import Path
GALLERY = Path(__file__).resolve().parents[1] / "static" / "js" / "galleryEditor.js"
DOC = Path(__file__).resolve().parents[1] / "docs" / "QUICKEDIT_COVERAGE.md"
BLOCK = "// --- Layer ▸ Combine (unite / subtract / intersect / exclude) ---"
def _src():
return GALLERY.read_text(encoding="utf-8")
def _block():
src = _src()
start = src.index(BLOCK)
return src[start:src.index("// --- Rasterize (Layer ▸ Rasterize) ---", start)]
def test_combine_block_routes_combine_selected_shapes():
src = _src()
assert BLOCK in src
assert re.search(r"if \(/\\b\(\?:unite\|combine\|merge\|intersect\|exclude\|subtract\)\\b", src)
assert "\\b(?:shapes?|rectangles?|ellipses?|circles?)\\b/.test(p)" in src
assert "const _combineShapes = (state.layers || []).filter((l) => l && (l.kind === 'shape' || l.shape));" in src
assert "_combineLayers(_combineShapes, _combineOp, { width: state.imgWidth, height: state.imgHeight, offsets: _cOffsets });" in src
assert "`Combined the shapes (${_combineOp}).`" in src
def test_combine_guards_two_or_more_shapes():
block = _block()
assert "if (_combineShapes.length < 2) {" in block
assert "'Add at least two shapes to combine.'" in block
assert "state.selectedLayerIds = [_cBase.id];" in block
assert "state.activeLayerId = _cBase.id;" in block
def test_combine_op_resolution():
block = _block()
assert "const _combineOp = /\\bintersect\\b/.test(p) ? 'intersect'" in block
assert ": /\\bexclude\\b/.test(p) ? 'exclude'" in block
assert ": (/\\bsubtract\\b/.test(p) || /\\bminus\\b/.test(p)) ? 'subtract'" in block
assert ": 'unite';" in block
def test_combine_requires_shape_noun_and_ordering():
src_block = _block()
# the verb must be paired with a shape noun (keeps us clear of merge/flatten)
assert "shapes?|rectangles?|ellipses?|circles?" in src_block
src = _src()
i_transform = src.index("// --- Edit ▸ Free Transform (deterministic) ---")
i_combine = src.index(BLOCK)
i_raster = src.index("// --- Rasterize (Layer ▸ Rasterize) ---")
assert i_transform < i_combine < i_raster
def test_combine_infrastructure_present():
src = _src()
assert "combineLayers as _combineLayers" in src
assert "function _combineSelectedShapes(op) {" in src
assert "combineShapes: (op) => _combineSelectedShapes(op)" in src
def test_coverage_doc_has_layer_combine_row():
doc = DOC.read_text(encoding="utf-8")
assert "Layer → Combine" in doc
assert "`_combineSelectedShapes`" in doc
assert re.search(r"Layer → Combine[^\n]*\|\s*OK[^\n]*\|", doc)