154 lines
6 KiB
Python
154 lines
6 KiB
Python
"""Tests for scripts/merge_prefs.py"""
|
|
import shutil
|
|
from pathlib import Path
|
|
from xml.etree import ElementTree as ET
|
|
|
|
import pytest
|
|
|
|
import merge_prefs
|
|
|
|
FIXTURES = Path(__file__).parent / "fixtures"
|
|
|
|
|
|
def _parse(path: Path) -> ET.Element:
|
|
return ET.parse(path).getroot()
|
|
|
|
|
|
def _attr(root: ET.Element, *id_path: str) -> dict:
|
|
"""Walk id_path through nested <group id=...> elements, return attribs."""
|
|
node = root
|
|
for id_val in id_path:
|
|
node = next(
|
|
(c for c in node if c.get("id") == id_val), None
|
|
)
|
|
assert node is not None, f"Node with id={id_val!r} not found"
|
|
return dict(node.attrib)
|
|
|
|
|
|
# ── merge into existing prefs ─────────────────────────────────────────────────
|
|
|
|
def test_merge_changes_patched_attributes(tmp_path):
|
|
prefs = tmp_path / "preferences.xml"
|
|
shutil.copy(FIXTURES / "prefs-fresh.xml", prefs)
|
|
merge_prefs.merge(prefs, FIXTURES / "patch-minimal.xml", "cc")
|
|
root = _parse(prefs)
|
|
assert _attr(root, "options", "scroll")["mousewheel-zoom"] == "false"
|
|
assert _attr(root, "options", "zoom")["mousewheel-zoom-ctrl"] == "true"
|
|
assert _attr(root, "tools", "nodes")["square-handles"] == "true"
|
|
|
|
|
|
def test_merge_creates_missing_nodes(tmp_path):
|
|
prefs = tmp_path / "preferences.xml"
|
|
shutil.copy(FIXTURES / "prefs-fresh.xml", prefs)
|
|
merge_prefs.merge(prefs, FIXTURES / "patch-minimal.xml", "cc")
|
|
root = _parse(prefs)
|
|
assert _attr(root, "options", "new-group")["new-attr"] == "new-value"
|
|
|
|
|
|
def test_merge_preserves_user_nodes(tmp_path):
|
|
prefs = tmp_path / "preferences.xml"
|
|
shutil.copy(FIXTURES / "prefs-user-custom.xml", prefs)
|
|
merge_prefs.merge(prefs, FIXTURES / "patch-minimal.xml", "cc")
|
|
root = _parse(prefs)
|
|
assert _attr(root, "options", "user-custom-setting")["my-value"] == "keep-this"
|
|
assert _attr(root, "tools", "user-tool-pref")["color"] == "#ff0000"
|
|
|
|
|
|
def test_merge_preserves_existing_unknown_attributes(tmp_path):
|
|
prefs = tmp_path / "preferences.xml"
|
|
shutil.copy(FIXTURES / "prefs-user-custom.xml", prefs)
|
|
merge_prefs.merge(prefs, FIXTURES / "patch-minimal.xml", "cc")
|
|
root = _parse(prefs)
|
|
assert _attr(root, "tools", "nodes").get("user-pref") == "preserved"
|
|
|
|
|
|
def test_merge_is_idempotent(tmp_path):
|
|
prefs = tmp_path / "preferences.xml"
|
|
shutil.copy(FIXTURES / "prefs-fresh.xml", prefs)
|
|
merge_prefs.merge(prefs, FIXTURES / "patch-minimal.xml", "cc")
|
|
content_after_first = prefs.read_text()
|
|
merge_prefs.merge(prefs, FIXTURES / "patch-minimal.xml", "cc")
|
|
content_after_second = prefs.read_text()
|
|
assert content_after_first == content_after_second
|
|
|
|
|
|
# ── lenient: no prefs file ────────────────────────────────────────────────────
|
|
|
|
def test_merge_creates_prefs_when_missing(tmp_path):
|
|
prefs = tmp_path / "inkscape" / "preferences.xml"
|
|
merge_prefs.merge(prefs, FIXTURES / "patch-minimal.xml", "cc")
|
|
assert prefs.exists()
|
|
root = _parse(prefs)
|
|
assert _attr(root, "options", "scroll")["mousewheel-zoom"] == "false"
|
|
|
|
|
|
def test_merge_creates_parent_dirs_when_missing(tmp_path):
|
|
prefs = tmp_path / "deep" / "nested" / "dir" / "preferences.xml"
|
|
merge_prefs.merge(prefs, FIXTURES / "patch-minimal.xml", "cc")
|
|
assert prefs.exists()
|
|
|
|
|
|
# ── preset overrides ──────────────────────────────────────────────────────────
|
|
|
|
def test_preset_cc_sets_keys_file(tmp_path):
|
|
prefs = tmp_path / "preferences.xml"
|
|
shutil.copy(FIXTURES / "prefs-fresh.xml", prefs)
|
|
merge_prefs.merge(prefs, FIXTURES / "patch-minimal.xml", "cc")
|
|
root = _parse(prefs)
|
|
assert _attr(root, "options", "keyboard")["file"] == "illustrator-cc"
|
|
|
|
|
|
def test_preset_cs6_sets_keys_file(tmp_path):
|
|
prefs = tmp_path / "preferences.xml"
|
|
shutil.copy(FIXTURES / "prefs-fresh.xml", prefs)
|
|
merge_prefs.merge(prefs, FIXTURES / "patch-minimal.xml", "cs6")
|
|
root = _parse(prefs)
|
|
assert _attr(root, "options", "keyboard")["file"] == "illustrator-cs6"
|
|
|
|
|
|
def test_preset_cc_sets_px_units(tmp_path):
|
|
prefs = tmp_path / "preferences.xml"
|
|
shutil.copy(FIXTURES / "prefs-fresh.xml", prefs)
|
|
merge_prefs.merge(prefs, FIXTURES / "patch-minimal.xml", "cc")
|
|
root = _parse(prefs)
|
|
assert _attr(root, "options", "units")["doc"] == "px"
|
|
|
|
|
|
def test_preset_cs6_sets_pt_units(tmp_path):
|
|
prefs = tmp_path / "preferences.xml"
|
|
shutil.copy(FIXTURES / "prefs-fresh.xml", prefs)
|
|
merge_prefs.merge(prefs, FIXTURES / "patch-minimal.xml", "cs6")
|
|
root = _parse(prefs)
|
|
assert _attr(root, "options", "units")["doc"] == "pt"
|
|
|
|
|
|
# ── error handling ────────────────────────────────────────────────────────────
|
|
|
|
def test_merge_raises_on_malformed_prefs(tmp_path):
|
|
prefs = tmp_path / "preferences.xml"
|
|
prefs.write_text("this is not xml")
|
|
with pytest.raises(ET.ParseError):
|
|
merge_prefs.merge(prefs, FIXTURES / "patch-minimal.xml", "cc")
|
|
|
|
|
|
def test_merge_raises_on_missing_patch(tmp_path):
|
|
prefs = tmp_path / "preferences.xml"
|
|
shutil.copy(FIXTURES / "prefs-fresh.xml", prefs)
|
|
with pytest.raises(FileNotFoundError):
|
|
merge_prefs.merge(prefs, tmp_path / "nonexistent-patch.xml", "cc")
|
|
|
|
|
|
def test_merge_raises_on_malformed_patch(tmp_path):
|
|
prefs = tmp_path / "preferences.xml"
|
|
shutil.copy(FIXTURES / "prefs-fresh.xml", prefs)
|
|
bad_patch = tmp_path / "bad-patch.xml"
|
|
bad_patch.write_text("not xml at all")
|
|
with pytest.raises(ET.ParseError):
|
|
merge_prefs.merge(prefs, bad_patch, "cc")
|
|
|
|
|
|
def test_merge_raises_on_invalid_preset(tmp_path):
|
|
prefs = tmp_path / "preferences.xml"
|
|
shutil.copy(FIXTURES / "prefs-fresh.xml", prefs)
|
|
with pytest.raises(ValueError, match="Unknown preset"):
|
|
merge_prefs.merge(prefs, FIXTURES / "patch-minimal.xml", "bad-preset")
|