# Copyright (c) 2026 Krzysztof Rudnicki. MIT licence. """The mutable box: a swap that works, and one that must not take the bot down.""" from __future__ import annotations import json from typing import TYPE_CHECKING from signal_bot.pack_holder import PackHolder from signal_bot.pack_load import load from tests import pack_fixture if TYPE_CHECKING: from pathlib import Path import pytest def test_a_reload_publishes_what_is_now_on_disk(tmp_path: Path) -> None: root = pack_fixture.build(tmp_path / "pack") holder = PackHolder(load(root)) assert holder.pack.matching(frozenset({"p3"})) == ("gamma.png",) (root / "media" / "extra.png").write_bytes(pack_fixture.PIXEL) tags = json.loads((root / "tags.json").read_text(encoding="utf-8")) tags["extra.png"] = ["p3"] (root / "tags.json").write_text(json.dumps(tags), encoding="utf-8") assert holder.reload() is True assert holder.pack.matching(frozenset({"p3"})) == ("extra.png", "gamma.png") def test_a_pack_that_no_longer_loads_keeps_the_old_one_and_does_not_raise( tmp_path: Path, caplog: pytest.LogCaptureFixture ) -> None: """Restart=always turns a raised ConfigError into a restart loop.""" root = pack_fixture.build(tmp_path / "pack") holder = PackHolder(load(root)) before = holder.pack # Half a write: exactly what a page interrupted mid-save leaves behind. # (A tag naming a vanished file used to be the example here; since # 2026-09-04 that is skipped with a warning rather than refused.) (root / "tags.json").write_text('{"alfa.png": ["p1"', encoding="utf-8") assert holder.reload() is False assert holder.pack is before assert holder.pack.matching(frozenset({"p1"})) == ("alfa.png", "both.png", "clip.mp4") assert "no longer loads" in caplog.text def test_the_holder_reloads_from_the_directory_it_already_has(tmp_path: Path) -> None: root = pack_fixture.build(tmp_path / "pack") holder = PackHolder(load(root)) assert holder.reload() is True assert holder.pack.directory == root