from datetime import UTC, datetime, timedelta import pytest from gewu.adapters.sqlite_node_removals import RemovalConflict, SQLiteNodeRemovalStore def test_removed_node_is_hidden_until_restored_and_restore_window_is_seven_days(tmp_path) -> None: store = SQLiteNodeRemovalStore(tmp_path / "node-removals.sqlite3") removed = store.request("dome", "node-a", "A node", "editor") assert store.is_hidden("dome", "node-a") assert store.list_restorable("dome") == (removed,) restore_window = datetime.fromisoformat(removed.restore_until) - datetime.fromisoformat( removed.requested_at ) assert restore_window == timedelta(days=7) restored = store.restore("dome", "node-a", "editor") assert restored == removed assert not store.is_hidden("dome", "node-a") assert store.list_restorable("dome") == () def test_expired_removal_stays_hidden_and_cannot_be_restored(tmp_path) -> None: store = SQLiteNodeRemovalStore(tmp_path / "node-removals.sqlite3") removed = store.request("dome", "node-a", "A node", "editor") with store._connect() as connection: connection.execute( "UPDATE node_removals SET restore_until=? WHERE removal_id=?", ((datetime.now(UTC) - timedelta(seconds=1)).isoformat(), removed.removal_id), ) assert store.is_hidden("dome", "node-a") assert store.list_restorable("dome") == () with pytest.raises(RemovalConflict, match="expired"): store.restore("dome", "node-a", "editor") def test_removal_survives_store_reopen_and_duplicate_removal_is_rejected(tmp_path) -> None: path = tmp_path / "node-removals.sqlite3" store = SQLiteNodeRemovalStore(path) store.request("dome", "node-a", "A node", "editor") reopened = SQLiteNodeRemovalStore(path) assert reopened.is_hidden("dome", "node-a") with pytest.raises(RemovalConflict): reopened.request("dome", "node-a", "A node", "editor")