"""Tests for tagsync.platform_windows: sidecar writer + support matrix. Runs on any OS — the Windows-specific online-only stat test is skipped except on Windows. """ from __future__ import annotations import json from pathlib import Path import pytest from tagsync.platform_windows import ( XMP_WRITABLE_EXTS, WindowsWriter, ) # --- supports() -------------------------------------------------------------- def test_supports_xmp_formats(): w = WindowsWriter(exiftool="exiftool", write_sidecars=False) for ext in (".jpg", ".pdf", ".docx", ".mp4"): assert w.supports(Path(f"foo{ext}")), f"expected support for {ext}" def test_supports_rejects_unknown_without_sidecars(): w = WindowsWriter(exiftool="exiftool", write_sidecars=False) assert not w.supports(Path("archive.zip")) assert not w.supports(Path("notes.txt")) def test_supports_accepts_unknown_with_sidecars(): w = WindowsWriter(exiftool="exiftool", write_sidecars=True) assert w.supports(Path("archive.zip")) assert w.supports(Path("notes.txt")) def test_supports_is_case_insensitive(): w = WindowsWriter(exiftool="exiftool", write_sidecars=False) assert w.supports(Path("IMAGE.JPG")) assert w.supports(Path("report.PDF")) # --- sidecar writer --------------------------------------------------------- def test_sidecar_written_for_unsupported_type(tmp_path): w = WindowsWriter(exiftool="exiftool", write_sidecars=True) target = tmp_path / "archive.zip" target.touch() w.write_tags(target, ["project-alpha", "urgent"]) sidecar = tmp_path / "archive.zip.tags.json" assert sidecar.exists() data = json.loads(sidecar.read_text()) assert data == {"tags": ["project-alpha", "urgent"]} def test_sidecar_cleared_when_tags_empty(tmp_path): w = WindowsWriter(exiftool="exiftool", write_sidecars=True) target = tmp_path / "archive.zip" target.touch() (tmp_path / "archive.zip.tags.json").write_text('{"tags": ["x"]}') w.write_tags(target, []) assert not (tmp_path / "archive.zip.tags.json").exists() def test_sidecar_clear_nonexistent_is_ok(tmp_path): w = WindowsWriter(exiftool="exiftool", write_sidecars=True) target = tmp_path / "archive.zip" target.touch() # Should not raise even though no sidecar exists. w.write_tags(target, []) def test_unsupported_without_sidecars_raises(tmp_path): w = WindowsWriter(exiftool="exiftool", write_sidecars=False) target = tmp_path / "archive.zip" target.touch() with pytest.raises(RuntimeError): w.write_tags(target, ["tag"]) # --- exiftool invocation ---------------------------------------------------- # # We don't actually run exiftool; monkeypatch subprocess.run to capture args. def test_exiftool_args_are_well_formed(tmp_path, monkeypatch): captured = {} def fake_run(args, **kwargs): captured["args"] = args class R: returncode = 0 stderr = "" return R() import tagsync.platform_windows as pw monkeypatch.setattr(pw.subprocess, "run", fake_run) w = WindowsWriter(exiftool="exiftool", write_sidecars=False) target = tmp_path / "pic.jpg" target.touch() w.write_tags(target, ["alpha", "beta"]) args = captured["args"] assert args[0] == "exiftool" assert "-overwrite_original" in args # Subject should be cleared then appended for each tag. assert "-XMP-dc:Subject=" in args assert "-XMP-dc:Subject+=alpha" in args assert "-XMP-dc:Subject+=beta" in args assert str(target) in args def test_exiftool_failure_raises(tmp_path, monkeypatch): def fake_run(args, **kwargs): class R: returncode = 1 stderr = "bad things happened" return R() import tagsync.platform_windows as pw monkeypatch.setattr(pw.subprocess, "run", fake_run) w = WindowsWriter(exiftool="exiftool", write_sidecars=False) target = tmp_path / "pic.jpg" target.touch() with pytest.raises(RuntimeError, match="bad things happened"): w.write_tags(target, ["x"]) # --- online-only detection -------------------------------------------------- @pytest.mark.windows def test_is_online_only_returns_false_for_normal_files(tmp_path): w = WindowsWriter(exiftool="exiftool") f = tmp_path / "regular.txt" f.touch() assert w.is_online_only(f) is False def test_is_online_only_returns_false_when_attribute_unavailable(tmp_path): """On non-Windows, st_file_attributes doesn't exist -> should return False.""" w = WindowsWriter(exiftool="exiftool") f = tmp_path / "regular.txt" f.touch() assert w.is_online_only(f) is False