137 lines
3.9 KiB
Python
137 lines
3.9 KiB
Python
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from serato_doctor.crate_parser import (
|
|
classify_crate,
|
|
clean_path,
|
|
load_crate,
|
|
load_library_crates,
|
|
parse_crate,
|
|
parse_crates,
|
|
path_markers,
|
|
)
|
|
from serato_doctor.models.crate import CrateKind
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("artifact", "expected"),
|
|
[
|
|
("song.mp漳", "song.mp3"),
|
|
("song.m4愠", "song.m4a"),
|
|
("song.wa瘠", "song.wav"),
|
|
("song.ai映", "song.aif"),
|
|
],
|
|
)
|
|
def test_clean_path_repairs_known_extension_artifacts(artifact, expected):
|
|
assert clean_path(artifact) == expected
|
|
|
|
|
|
def test_parse_crate_extracts_references(tmp_path):
|
|
crate_path = tmp_path / "House.crate"
|
|
crate_text = (
|
|
"header"
|
|
"Users/sample-user/OneDrive/Jukebox/House/First.mp漳牴k"
|
|
"metadata"
|
|
"Users/sample-user/OneDrive/Jukebox/House/Second.m4愠otrk"
|
|
)
|
|
crate_path.write_bytes(crate_text.encode("utf-16-le"))
|
|
|
|
crate = load_crate(crate_path)
|
|
|
|
assert crate.path == crate_path
|
|
assert [reference.filename for reference in crate.references] == [
|
|
"First.mp3",
|
|
"Second.m4a",
|
|
]
|
|
assert parse_crate(crate_path) == list(crate.references)
|
|
|
|
|
|
def test_parse_crate_ignores_record_without_stop_marker(tmp_path):
|
|
crate_path = Path(tmp_path) / "Incomplete.crate"
|
|
crate_path.write_bytes(
|
|
"Users/sample-user/OneDrive/Jukebox/House/Incomplete.mp3".encode(
|
|
"utf-16-le"
|
|
)
|
|
)
|
|
|
|
assert parse_crate(crate_path) == []
|
|
|
|
|
|
def test_parse_crate_uses_configured_reference_root(tmp_path):
|
|
crate_path = tmp_path / "Migrated.crate"
|
|
crate_path.write_bytes(
|
|
"Archive/Old Library/House/Track.mp3otrk".encode("utf-16-le")
|
|
)
|
|
|
|
references = parse_crate(crate_path, [Path("/Archive/Old Library")])
|
|
|
|
assert references[0].path == Path("/Archive/Old Library/House/Track.mp3")
|
|
|
|
|
|
def test_default_path_markers_do_not_contain_a_username():
|
|
assert path_markers([]) == ("Users/", "Volumes/")
|
|
|
|
|
|
def test_parse_crates_reuses_configured_roots_for_every_crate(tmp_path):
|
|
for name in ("First", "Second"):
|
|
(tmp_path / f"{name}.crate").write_bytes(
|
|
f"Archive/Jukebox/{name}.mp3otrk".encode("utf-16-le")
|
|
)
|
|
|
|
references = parse_crates(
|
|
tmp_path, (root for root in [Path("/Archive/Jukebox")])
|
|
)
|
|
|
|
assert {reference.filename for reference in references} == {
|
|
"First.mp3",
|
|
"Second.mp3",
|
|
}
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
("relative_path", "expected"),
|
|
[
|
|
("_Serato_/Subcrates/House.crate", CrateKind.STATIC),
|
|
("_Serato_/SmartCrates/Warmup.scrate", CrateKind.SMART),
|
|
("_Serato_/Subcrates/Compatible by key.crate", CrateKind.SMART),
|
|
("fixtures/Unknown.crate", CrateKind.UNKNOWN),
|
|
],
|
|
)
|
|
def test_classify_crate_uses_provenance_and_known_dynamic_name(
|
|
tmp_path, relative_path, expected
|
|
):
|
|
assert classify_crate(tmp_path / relative_path) is expected
|
|
|
|
|
|
def test_smart_crate_preserves_encoded_hierarchy(tmp_path):
|
|
crate_path = (
|
|
tmp_path / "_Serato_" / "SmartCrates" / "Compatible by key≫≫10A.scrate"
|
|
)
|
|
crate_path.parent.mkdir(parents=True)
|
|
crate_path.write_bytes(b"")
|
|
crate = load_crate(crate_path)
|
|
|
|
assert crate.kind is CrateKind.SMART
|
|
assert crate.hierarchy == ("Compatible by key", "10A")
|
|
assert crate.display_name == "10A"
|
|
assert crate.is_smart_definition
|
|
|
|
|
|
def test_load_library_crates_discovers_scrate_definitions(tmp_path):
|
|
smart_folder = tmp_path / "SmartCrates"
|
|
static_folder = tmp_path / "Subcrates"
|
|
smart_folder.mkdir()
|
|
static_folder.mkdir()
|
|
(smart_folder / "New EDM.scrate").write_bytes(b"")
|
|
(smart_folder / "Re-Drums.scrate").write_bytes(b"")
|
|
(static_folder / "House.crate").write_bytes(b"")
|
|
|
|
crates = load_library_crates(tmp_path)
|
|
|
|
assert [(crate.path.name, crate.kind) for crate in crates] == [
|
|
("New EDM.scrate", CrateKind.SMART),
|
|
("Re-Drums.scrate", CrateKind.SMART),
|
|
("House.crate", CrateKind.STATIC),
|
|
]
|