Files
romm/backend/tests/models/test_base.py
Georges-Antoine Assi 987e351113 refactor: derive file-name columns via @validates
Centralize the *_no_tags / *_no_ext / *_extension columns (derived from a
file name) behind @validates hooks instead of computing them by hand at
every write site:

- Add pure helpers (compute_file_name_parts and friends) to models.base;
  the filesystem base handler now delegates to them.
- Add @validates on Rom (fs_name), BaseAsset (file_name, inherited by all
  asset subclasses), and Firmware (file_name).
- update_rom keeps the fs_name-derived columns in sync on bulk update(),
  which also fixes the rename path never updating fs_extension.
- Drop the now-redundant computations at the scan/rename call sites.

Also fix the migration backfill loop and a pre-existing list[str | None]
type mismatch surfaced in scan_handler. Add tests for the helpers, the
validators, and the update_rom bulk-sync path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 21:14:16 -04:00

82 lines
2.5 KiB
Python

import pytest
from models.assets import Save
from models.base import compute_file_name_parts
from models.firmware import Firmware
from models.rom import Rom, compute_name_sort_key
@pytest.mark.parametrize(
("file_name", "no_tags", "no_ext", "extension"),
[
("Sonic (USA) [!].md", "Sonic", "Sonic (USA) [!]", "md"),
("game.tar.gz", "game", "game", "tar.gz"),
("README", "README", "README", ""),
(
"Final Fantasy VII (Disc 1).bin",
"Final Fantasy VII",
"Final Fantasy VII (Disc 1)",
"bin",
),
],
)
def test_compute_file_name_parts(file_name, no_tags, no_ext, extension):
parts = compute_file_name_parts(file_name)
assert parts.no_tags == no_tags
assert parts.no_ext == no_ext
assert parts.extension == extension
@pytest.mark.parametrize(
("name", "expected"),
[
("The Legend of Zelda 2", "legend of zelda 000000000002"),
("A Bug's Life", "bug's life"),
("Final Fantasy 10", "final fantasy 000000000010"),
(None, ""),
],
)
def test_compute_name_sort_key(name, expected):
assert compute_name_sort_key(name) == expected
def test_rom_validator_derives_fs_name_parts_on_construction():
rom = Rom(fs_name="The Legend of Zelda (USA) (Rev 1).z64")
assert rom.fs_name_no_tags == "The Legend of Zelda"
assert rom.fs_name_no_ext == "The Legend of Zelda (USA) (Rev 1)"
assert rom.fs_extension == "z64"
# The validator only fires on assignment; name was never set, so its
# derived column keeps the column default rather than being computed.
assert rom.name_sort_key is None
def test_rom_validator_resyncs_on_mutation():
rom = Rom(fs_name="old.zip", name="The Old Game")
assert rom.name_sort_key == "old game"
rom.fs_name = "Sonic (Europe).md"
rom.name = "A New Game 2"
assert rom.fs_name_no_tags == "Sonic"
assert rom.fs_extension == "md"
assert rom.name_sort_key == "new game 000000000002"
def test_asset_validator_derives_file_name_parts():
# Defined on the abstract BaseAsset, inherited by every asset subclass.
save = Save(file_name="Sonic [!] (proto).srm")
assert save.file_name_no_tags == "Sonic"
assert save.file_name_no_ext == "Sonic [!] (proto)"
assert save.file_extension == "srm"
def test_firmware_validator_derives_file_name_parts():
firmware = Firmware(file_name="bios (world).bin")
assert firmware.file_name_no_tags == "bios"
assert firmware.file_name_no_ext == "bios (world)"
assert firmware.file_extension == "bin"