from __future__ import annotations import json from unittest.mock import MagicMock, patch from django.test import SimpleTestCase, override_settings from pobsync_backend import updater class UpdaterTests(SimpleTestCase): @override_settings( POBSYNC_UPDATE_RELEASES_URL="https://code.example.test/api/v1/repos/owner/pobsync/releases", POBSYNC_UPDATE_RELEASES_TOKEN="secret", ) def test_fetch_latest_release_reads_first_gitea_release(self) -> None: response = MagicMock() response.__enter__.return_value.read.return_value = json.dumps( [ { "tag_name": "v1.2.0", "name": "1.2.0", "html_url": "https://code.example.test/releases/v1.2.0", } ] ).encode("utf-8") with patch("pobsync_backend.updater.urlopen", return_value=response) as urlopen: release = updater.fetch_latest_release() self.assertEqual(release["tag_name"], "v1.2.0") request = urlopen.call_args.args[0] self.assertEqual(request.full_url, "https://code.example.test/api/v1/repos/owner/pobsync/releases") self.assertEqual(request.headers["Authorization"], "token secret") @override_settings(POBSYNC_UPDATE_RELEASES_URL="") def test_collect_update_status_reports_unconfigured_release_check(self) -> None: with patch("pobsync_backend.updater._git_status", return_value={"branch": "master"}): status = updater.collect_update_status(check_release=True) self.assertFalse(status["release_check_configured"]) self.assertEqual(status["release_error"], "POBSYNC_UPDATE_RELEASES_URL is not configured.") self.assertIsNone(status["update_available"]) @override_settings(POBSYNC_UPDATE_GIT_REMOTE="upstream") def test_run_git_fetch_uses_configured_remote(self) -> None: completed = MagicMock(returncode=0, stdout="ok", stderr="") with patch("pobsync_backend.updater.subprocess.run", return_value=completed) as run: result = updater.run_git_fetch() self.assertTrue(result.ok) self.assertEqual(result.command, ["git", "fetch", "--tags", "--prune", "upstream"]) run.assert_called_once() @override_settings(POBSYNC_UPDATE_GIT_REMOTE="origin") def test_run_git_pull_rejects_detached_checkout(self) -> None: with patch("pobsync_backend.updater._git_current_branch", return_value=""): result = updater.run_git_pull() self.assertFalse(result.ok) self.assertEqual(result.exit_code, 2) self.assertIn("not on a branch", result.stderr) @override_settings(POBSYNC_UPDATE_COMMAND="sudo -n scripts/update-systemd --verbose") def test_run_native_update_splits_configured_command(self) -> None: completed = MagicMock(returncode=1, stdout="", stderr="sudo failed") with patch("pobsync_backend.updater.subprocess.run", return_value=completed): result = updater.run_native_update() self.assertFalse(result.ok) self.assertEqual(result.command, ["sudo", "-n", "scripts/update-systemd", "--verbose"]) self.assertEqual(result.stderr, "sudo failed")