From d4b82d98b2ac25f562fdd7f705a1289f4f40929d Mon Sep 17 00:00:00 2001 From: Will Miao Date: Fri, 18 Sep 2026 00:09:34 +0800 Subject: [PATCH] test(recipes): pin the manual rebuild as the escape hatch from a skipped prune The prune guard intentionally leaves the in-memory view empty while the stored cache keeps the user's recipes, so there has to be a documented way to accept the on-disk truth. That route is an explicit rebuild, which clears the stored cache before a full directory scan. Cover it so the FAQ recovery steps stay true. --- .../services/test_recipe_cache_prune_guard.py | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/services/test_recipe_cache_prune_guard.py b/tests/services/test_recipe_cache_prune_guard.py index 12f44dde..521ce986 100644 --- a/tests/services/test_recipe_cache_prune_guard.py +++ b/tests/services/test_recipe_cache_prune_guard.py @@ -243,6 +243,32 @@ def test_sync_init_persists_when_recipes_are_found(guard_scanner, tmp_path: Path assert [recipe["id"] for recipe in persisted.raw_data] == ["fresh"] +def test_force_refresh_scan_persists_an_empty_result(guard_scanner, tmp_path: Path): + """A manual rebuild stays the escape hatch from a skipped prune. + + The startup guard deliberately keeps a stale cache, which leaves the in-memory + view empty until the files come back. An explicit rebuild must be able to land + on the real (empty) filesystem state instead, otherwise there is no way out. + The route to it is `refresh_cache(force=True)`, which clears the stored cache + first and then does a full directory scan. + """ + scanner, cache = guard_scanner + gone = tmp_path / "old-location" / "kept.recipe.json" + _write_recipe_json(gone, "kept") + assert cache.save_cache( + [{"id": "kept", "title": "Recipe kept"}], {"kept": str(gone)} + ) + gone.unlink() + + # Simulate the explicit rebuild: clear the stored cache, then full scan. + assert cache.save_cache([], {}) is True + scanner._initialize_recipe_cache_sync() + + assert scanner._prune_skipped is False + persisted = cache.load_cache() + assert persisted is None or persisted.raw_data == [] + + def test_save_cache_skip_if_empty_preserves_existing_rows(tmp_path: Path): """The storage-level backstop refuses to empty a populated cache.""" cache = PersistentRecipeCache(db_path=str(tmp_path / "recipe_cache.sqlite"))