Add known working config profile for reverting changes
This commit is contained in:
@@ -861,6 +861,97 @@ sha256 = "{sha256_file(asset)}"
|
||||
self.assertIn("example", updated["plugins"])
|
||||
self.assertNotIn("example", updated["disabledPlugins"])
|
||||
|
||||
def test_save_and_restore_known_good_set(self) -> None:
|
||||
from plugin_helper.operations import restore_known_good_set, save_known_good_set
|
||||
from plugin_helper.state import load_known_good_state, save_installed_state
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
work = Path(tmp)
|
||||
instance_root = work / "instances"
|
||||
instance = instance_root / "1.40.8"
|
||||
state = work / "state"
|
||||
registry_dir = work / "registry"
|
||||
locks_dir = work / "locks"
|
||||
registry_dir.mkdir()
|
||||
locks_dir.mkdir()
|
||||
instance.mkdir(parents=True)
|
||||
(instance / "Beat Saber_Data").mkdir()
|
||||
(instance / "Plugins").mkdir()
|
||||
|
||||
plugins_state: dict[str, dict] = {}
|
||||
registry_entries: list[str] = []
|
||||
lock_entries: list[str] = []
|
||||
for plugin_id, name, filename in (
|
||||
("alpha", "Alpha", "Alpha.dll"),
|
||||
("beta", "Beta", "Beta.dll"),
|
||||
("gamma", "Gamma", "Gamma.dll"),
|
||||
):
|
||||
asset = plugin_downloads_dir(state, "1.40.8", plugin_id) / filename
|
||||
asset.write_bytes(f"{plugin_id} dll".encode())
|
||||
registry_entries.append(
|
||||
f"""
|
||||
[[plugins]]
|
||||
id = "{plugin_id}"
|
||||
name = "{name}"
|
||||
repo = "owner/{plugin_id}"
|
||||
asset_patterns = ["*.dll"]
|
||||
install_strategy = "dll-to-plugins"
|
||||
""".lstrip()
|
||||
)
|
||||
lock_entries.append(
|
||||
f"""
|
||||
[[plugins]]
|
||||
id = "{plugin_id}"
|
||||
repo = "owner/{plugin_id}"
|
||||
tag = "v1.0.0"
|
||||
asset = "{filename}"
|
||||
sha256 = "{sha256_file(asset)}"
|
||||
""".lstrip()
|
||||
)
|
||||
if plugin_id in ("alpha", "beta"):
|
||||
(instance / "Plugins" / filename).write_bytes(f"{plugin_id} dll".encode())
|
||||
plugins_state[plugin_id] = {
|
||||
"installedAt": "2026-06-14T17:18:40Z",
|
||||
"files": [{"path": f"Plugins/{filename}", "sha256": sha256_file(asset), "size": asset.stat().st_size}],
|
||||
}
|
||||
|
||||
(registry_dir / "plugins.toml").write_text("".join(registry_entries), encoding="utf-8")
|
||||
(locks_dir / "1.40.8.lock.toml").write_text(
|
||||
f"""
|
||||
beat_saber_version = "1.40.8"
|
||||
instance = "1.40.8"
|
||||
{"".join(lock_entries)}
|
||||
""".lstrip(),
|
||||
encoding="utf-8",
|
||||
)
|
||||
save_installed_state(state, "1.40.8", {"instance": "1.40.8", "plugins": plugins_state, "disabledPlugins": {}})
|
||||
|
||||
known_good = save_known_good_set(instance="1.40.8", state_root=state)
|
||||
self.assertEqual(known_good["pluginIds"], ["alpha", "beta"])
|
||||
self.assertEqual(load_known_good_state(state, "1.40.8")["pluginIds"], ["alpha", "beta"])
|
||||
|
||||
# Simulate the user disabling alpha and a new mod pulling in gamma as a dependency.
|
||||
disable_plugin("1.40.8", instance, state, "alpha", False)
|
||||
with patch("plugin_helper.operations.repo_root", return_value=work):
|
||||
enable_disabled_plugin(
|
||||
instance="1.40.8",
|
||||
instance_path=instance,
|
||||
state_root=state,
|
||||
plugin_id="gamma",
|
||||
repo=work,
|
||||
)
|
||||
|
||||
result = restore_known_good_set(instance="1.40.8", instance_path=instance, state_root=state, repo=work)
|
||||
|
||||
self.assertEqual(result["disabled"], ["gamma"])
|
||||
self.assertEqual(result["enabled"], ["alpha"])
|
||||
self.assertEqual(result["disableErrors"], [])
|
||||
self.assertEqual(result["enableErrors"], [])
|
||||
|
||||
updated = load_installed_state(state, "1.40.8")
|
||||
self.assertEqual(set(updated["plugins"]), {"alpha", "beta"})
|
||||
self.assertIn("gamma", updated["disabledPlugins"])
|
||||
|
||||
def test_zip_to_pending_targets_ipa_pending(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
work = Path(tmp)
|
||||
@@ -1892,6 +1983,51 @@ class PluginHelperTuiTests(unittest.IsolatedAsyncioTestCase):
|
||||
self.assertNotIn("example", updated["disabledPlugins"])
|
||||
self.assertIn("Enabled 1 plugins", app.status_message)
|
||||
|
||||
async def test_save_known_good_records_currently_enabled_plugins(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
app, _instance, state = _make_two_plugin_tui_fixture(Path(tmp))
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press("s")
|
||||
await pilot.pause()
|
||||
|
||||
from plugin_helper.state import load_known_good_state
|
||||
|
||||
known_good = load_known_good_state(state, "1.40.8")
|
||||
self.assertEqual(known_good["pluginIds"], ["alpha", "beta"])
|
||||
self.assertIn("Saved known-good set: 2 enabled plugins", app.status_message)
|
||||
|
||||
async def test_restore_known_good_reverts_manual_changes(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
app, instance, state = _make_two_plugin_tui_fixture(Path(tmp))
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press("s")
|
||||
await pilot.pause()
|
||||
# Manually disable beta after saving the known-good set.
|
||||
await pilot.press("down")
|
||||
await pilot.press("space")
|
||||
await pilot.pause()
|
||||
self.assertFalse((instance / "Plugins" / "Beta.dll").exists())
|
||||
|
||||
await pilot.press("g")
|
||||
await pilot.pause()
|
||||
self.assertIn("Restored known-good set", app.status_message)
|
||||
|
||||
self.assertTrue((instance / "Plugins" / "Beta.dll").exists())
|
||||
updated = load_installed_state(state, "1.40.8")
|
||||
self.assertEqual(set(updated["plugins"]), {"alpha", "beta"})
|
||||
|
||||
async def test_restore_known_good_without_saved_set_reports_status(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
app, _instance, _state = _make_two_plugin_tui_fixture(Path(tmp))
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press("g")
|
||||
await pilot.pause()
|
||||
|
||||
self.assertIn("No known-good set saved yet", app.status_message)
|
||||
|
||||
async def test_space_reports_hash_mismatch_without_state_update(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
app, instance, state = _make_tui_fixture(Path(tmp), hash_mismatch=True)
|
||||
|
||||
Reference in New Issue
Block a user