Files
romm/backend/tests/test_sync_watcher.py
T
nendo c59ea7790c test: add coverage for sync session handler, sync watcher, device masking, and auth utils
- test_sync_sessions_handler: increment_operations_completed (atomic
  counter, no-op on missing), NoResultFound on update/complete/fail
  with nonexistent session
- test_sync_watcher: _extract_device_and_platform path parsing (valid,
  non-incoming, too few parts, nested, outside base), _ensure_conflicts_dir
  creation and idempotency, process_sync_changes empty/disabled
- test_sync (endpoints): negotiate with untracked saves (no_op),
  server saves not mentioned by client (download), deleted-by-client
  detection (skip), complete on FAILED/CANCELLED session (400),
  trigger_push_pull passes session_id in enqueue kwargs
- test_device (endpoints): sync_config SSH credential masking
  (ssh_password/ssh_key_path -> "********"), null config passthrough,
  config without sensitive fields
- test_utils_auth: _get_device_name UA parsing (browser+OS, browser
  only, OS only, neither), create_or_find_web_device (creates new,
  returns existing on fingerprint match, updates last_seen)
2026-03-16 11:19:30 +09:00

113 lines
3.7 KiB
Python

import os
import shutil
import tempfile
from pathlib import Path
from unittest.mock import patch
import pytest
from handler.filesystem.sync_handler import FSSyncHandler
class TestExtractDeviceAndPlatform:
@pytest.fixture
def temp_dir(self):
d = tempfile.mkdtemp()
yield d
shutil.rmtree(d, ignore_errors=True)
@pytest.fixture
def handler(self):
return FSSyncHandler.__new__(FSSyncHandler)
@pytest.fixture(autouse=True)
def patch_base_path(self, handler: FSSyncHandler, temp_dir):
handler.base_path = Path(temp_dir)
with patch("sync_watcher.fs_sync_handler", handler):
yield
def test_extract_valid_incoming_path(self, temp_dir):
from sync_watcher import _extract_device_and_platform
path = os.path.join(temp_dir, "device-1", "incoming", "gba", "save.sav")
result = _extract_device_and_platform(path)
assert result == ("device-1", "gba", "save.sav")
def test_extract_non_incoming_path_returns_none(self, temp_dir):
from sync_watcher import _extract_device_and_platform
path = os.path.join(temp_dir, "device-1", "outgoing", "gba", "save.sav")
result = _extract_device_and_platform(path)
assert result is None
def test_extract_too_few_parts_returns_none(self, temp_dir):
from sync_watcher import _extract_device_and_platform
path = os.path.join(temp_dir, "device-1", "incoming")
result = _extract_device_and_platform(path)
assert result is None
def test_extract_deeply_nested_returns_leaf_filename(self, temp_dir):
from sync_watcher import _extract_device_and_platform
path = os.path.join(
temp_dir, "device-1", "incoming", "gba", "subdir", "save.sav"
)
result = _extract_device_and_platform(path)
assert result == ("device-1", "gba", "save.sav")
def test_extract_path_outside_base_returns_none(self):
from sync_watcher import _extract_device_and_platform
result = _extract_device_and_platform("/totally/different/path")
assert result is None
class TestEnsureConflictsDir:
@pytest.fixture
def temp_dir(self):
d = tempfile.mkdtemp()
yield d
shutil.rmtree(d, ignore_errors=True)
@pytest.fixture
def handler(self):
return FSSyncHandler.__new__(FSSyncHandler)
@pytest.fixture(autouse=True)
def patch_base_path(self, handler: FSSyncHandler, temp_dir):
handler.base_path = Path(temp_dir)
with patch("sync_watcher.fs_sync_handler", handler):
yield
def test_creates_directory_and_returns_path(self, temp_dir):
from sync_watcher import _ensure_conflicts_dir
result = _ensure_conflicts_dir("device-1", "gba")
expected = os.path.join(temp_dir, "device-1", "conflicts", "gba")
assert result == expected
assert os.path.isdir(expected)
def test_idempotent_no_error_on_second_call(self, temp_dir):
from sync_watcher import _ensure_conflicts_dir
_ensure_conflicts_dir("device-1", "gba")
result = _ensure_conflicts_dir("device-1", "gba")
expected = os.path.join(temp_dir, "device-1", "conflicts", "gba")
assert result == expected
assert os.path.isdir(expected)
class TestProcessSyncChanges:
def test_empty_changes_returns_immediately(self):
with patch("sync_watcher.ENABLE_SYNC_FOLDER_WATCHER", True):
from sync_watcher import process_sync_changes
process_sync_changes([])
def test_disabled_watcher_returns_immediately(self):
with patch("sync_watcher.ENABLE_SYNC_FOLDER_WATCHER", False):
from sync_watcher import process_sync_changes
process_sync_changes([("added", "/some/path/file.sav")])