Files
odysseus/tests/test_editor_quick_edit_warp_text.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

51 lines
2.5 KiB
Python

"""Quick Edit support for Photoshop's Type ▸ Warp ("warp the text").
The editor already had a full retained-text warp pipeline (static/js/editor/
text-layer.js `warpCanvas`, and `warp`/`warpAmount` on the text data), but the
Quick Edit client fast path never routed a warp request, so "warp the text"
fell through to "No built-in quick action matched". These tests pin the new
deterministic branch in galleryEditor.js `_executeQuickEditLocal`.
"""
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
EDITOR = (ROOT / "static" / "js" / "galleryEditor.js").read_text(encoding="utf-8")
TEXT_LAYER = (ROOT / "static" / "js" / "editor" / "text-layer.js").read_text(encoding="utf-8")
COVERAGE = (ROOT / "docs" / "QUICKEDIT_COVERAGE.md").read_text(encoding="utf-8")
def test_warp_branch_applies_style_and_amount():
assert "// --- Type ▸ Warp (deterministic) ---" in EDITOR
assert "const _warpWord = /\\bwarp(?:ed)?\\b/.test(p);" in EDITOR
assert "const _warpTextWord = /\\b(?:text|title|caption|heading|word|lettering|type)\\b/.test(p);" in EDITOR
assert "_rerenderTextLayer(_wLayer, { ..._wLayer.text, warp: style, warpAmount: _wAmount });" in EDITOR
assert "_saveState('Warp text');" in EDITOR
assert "_setAiCommandStatus(style === 'none' ? 'Removed the text warp.' : `Warped the text (${style}).`, 'done');" in EDITOR
def test_warp_maps_every_photoshop_style():
for style in ("arc", "arch", "bulge", "inflate", "squeeze", "fisheye", "wave", "rise", "twist", "flag"):
assert f"style = '{style}'" in EDITOR, style
assert "style = 'none'" in EDITOR
assert "const _wAm = p.match(/\\b(?:by|amount|to)\\s*(-?\\d{1,3})\\b/);" in EDITOR
assert "Math.max(-100, Math.min(100, Math.round(Number(_wAm[1])))) : 50" in EDITOR
def test_warp_runs_before_generic_text_edit():
warp_idx = EDITOR.index("// --- Type ▸ Warp (deterministic) ---")
text_idx = EDITOR.index("// --- Text edit (deterministic) ---")
assert warp_idx < text_idx
def test_warp_infrastructure_exists():
assert "export function warpCanvas(base, style, amount)" in TEXT_LAYER
assert "export const WARP_STYLES" in TEXT_LAYER
assert "warp: WARP_STYLES.includes(value.warp) ? value.warp : 'none'," in TEXT_LAYER
assert "warpAmount: finite(value.warpAmount, DEFAULT_TEXT_DATA.warpAmount, -100, 100)," in TEXT_LAYER
assert "function _rerenderTextLayer(layer, nextText, preserveCenter = true)" in EDITOR
def test_coverage_row_marked_ok():
assert "| Type → Warp | \"warp the text\" | `_rerenderTextLayer` (warp) | ✔ | ✔ | ✔ | OK |" in COVERAGE