test_restore_windows_paths_3501.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. """The restore converts a Windows backup's paths, and a failure there does not fail it (#3501)."""
  2. import sqlite3
  3. from unittest.mock import AsyncMock, patch
  4. import pytest
  5. from backend.app.core.config import settings as app_settings
  6. async def _restore(async_client, monkeypatch, tmp_path, convert):
  7. from backend.app.api.routes.settings import create_backup_zip
  8. # Keep the restored database separate from the integration-test engine.
  9. db_path = tmp_path / "bambuddy.db"
  10. with sqlite3.connect(db_path) as db:
  11. db.execute("CREATE TABLE backup_marker (id INTEGER PRIMARY KEY)")
  12. monkeypatch.setenv("DATA_DIR", str(tmp_path))
  13. monkeypatch.setattr(app_settings, "base_dir", tmp_path)
  14. monkeypatch.setattr(app_settings, "database_url", f"sqlite+aiosqlite:///{db_path}")
  15. zip_path, _ = await create_backup_zip(output_path=tmp_path)
  16. with (
  17. patch("backend.app.core.database.close_all_connections", new_callable=AsyncMock),
  18. patch("backend.app.core.database.reinitialize_database", new_callable=AsyncMock),
  19. patch("backend.app.core.database.init_db", new_callable=AsyncMock),
  20. patch("backend.app.core.database.invalidate_all_sessions", new_callable=AsyncMock),
  21. patch("backend.app.services.print_scheduler.scheduler.stop"),
  22. patch("backend.app.services.smart_plug_manager.smart_plug_manager.stop_scheduler"),
  23. patch("backend.app.services.notification_service.notification_service.stop_digest_scheduler"),
  24. patch("backend.app.services.backup_paths.convert_windows_paths", convert),
  25. ):
  26. return await async_client.post(
  27. "/api/v1/settings/restore",
  28. files={"file": ("backup.zip", zip_path.read_bytes(), "application/zip")},
  29. )
  30. @pytest.mark.asyncio
  31. @pytest.mark.integration
  32. @pytest.mark.sqlite_only # backs up and restores the app's own SQLite database file
  33. async def test_the_restore_converts_the_paths(async_client, monkeypatch, tmp_path):
  34. convert = AsyncMock(return_value=0)
  35. response = await _restore(async_client, monkeypatch, tmp_path, convert)
  36. assert response.status_code == 200, response.text
  37. convert.assert_awaited_once()
  38. assert convert.await_args.args[1] == tmp_path
  39. @pytest.mark.asyncio
  40. @pytest.mark.integration
  41. @pytest.mark.sqlite_only
  42. async def test_a_failed_conversion_does_not_fail_the_restore(async_client, monkeypatch, tmp_path):
  43. convert = AsyncMock(side_effect=RuntimeError("boom"))
  44. response = await _restore(async_client, monkeypatch, tmp_path, convert)
  45. assert response.status_code == 200, response.text
  46. assert response.json()["success"] is True