mirror of
https://github.com/rommapp/romm.git
synced 2026-04-23 06:54:40 +00:00
654 lines
23 KiB
Python
654 lines
23 KiB
Python
"""Tests for sync endpoints."""
|
|
|
|
from datetime import datetime, timedelta, timezone
|
|
from unittest import mock
|
|
|
|
from fastapi import status
|
|
|
|
from handler.database import (
|
|
db_device_handler,
|
|
db_device_save_sync_handler,
|
|
db_play_session_handler,
|
|
db_sync_session_handler,
|
|
)
|
|
from models.assets import Save
|
|
from models.device import Device, SyncMode
|
|
from models.rom import Rom
|
|
from models.user import User
|
|
|
|
|
|
class TestSyncNegotiate:
|
|
def test_negotiate_new_client_save(
|
|
self, client, access_token: str, admin_user: User, rom: Rom
|
|
):
|
|
"""Client has a save the server doesn't -> upload."""
|
|
device = db_device_handler.add_device(
|
|
Device(id="neg-dev-1", user_id=admin_user.id, sync_enabled=True)
|
|
)
|
|
|
|
response = client.post(
|
|
"/api/sync/negotiate",
|
|
json={
|
|
"device_id": device.id,
|
|
"saves": [
|
|
{
|
|
"rom_id": rom.id,
|
|
"file_name": "new_save.sav",
|
|
"updated_at": "2026-01-10T00:00:00Z",
|
|
"file_size_bytes": 1024,
|
|
}
|
|
],
|
|
},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
data = response.json()
|
|
assert data["total_upload"] == 1
|
|
assert data["operations"][0]["action"] == "upload"
|
|
|
|
def test_negotiate_server_has_save_client_doesnt(
|
|
self, client, access_token: str, admin_user: User, save: Save
|
|
):
|
|
"""Server has a save the client doesn't mention -> download."""
|
|
device = db_device_handler.add_device(
|
|
Device(id="neg-dev-2", user_id=admin_user.id, sync_enabled=True)
|
|
)
|
|
|
|
response = client.post(
|
|
"/api/sync/negotiate",
|
|
json={
|
|
"device_id": device.id,
|
|
"saves": [],
|
|
},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
data = response.json()
|
|
assert data["total_download"] >= 1
|
|
|
|
def test_negotiate_identical_hashes(
|
|
self, client, access_token: str, admin_user: User, rom: Rom, save: Save
|
|
):
|
|
"""Matching hash -> no_op."""
|
|
device = db_device_handler.add_device(
|
|
Device(id="neg-dev-3", user_id=admin_user.id, sync_enabled=True)
|
|
)
|
|
|
|
response = client.post(
|
|
"/api/sync/negotiate",
|
|
json={
|
|
"device_id": device.id,
|
|
"saves": [
|
|
{
|
|
"rom_id": save.rom_id,
|
|
"file_name": save.file_name,
|
|
"content_hash": save.content_hash,
|
|
"updated_at": save.updated_at.isoformat(),
|
|
"file_size_bytes": 100,
|
|
}
|
|
],
|
|
},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
data = response.json()
|
|
# If save has a hash, should be no_op; otherwise download/upload by timestamp
|
|
assert "session_id" in data
|
|
|
|
def test_negotiate_device_not_found(self, client, access_token: str):
|
|
response = client.post(
|
|
"/api/sync/negotiate",
|
|
json={"device_id": "nonexistent", "saves": []},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
assert response.status_code == status.HTTP_404_NOT_FOUND
|
|
|
|
def test_negotiate_sync_disabled(self, client, access_token: str, admin_user: User):
|
|
device = db_device_handler.add_device(
|
|
Device(id="neg-dev-disabled", user_id=admin_user.id, sync_enabled=False)
|
|
)
|
|
|
|
response = client.post(
|
|
"/api/sync/negotiate",
|
|
json={"device_id": device.id, "saves": []},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
|
|
|
def test_negotiate_creates_session(
|
|
self, client, access_token: str, admin_user: User
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(id="neg-dev-session", user_id=admin_user.id, sync_enabled=True)
|
|
)
|
|
|
|
response = client.post(
|
|
"/api/sync/negotiate",
|
|
json={"device_id": device.id, "saves": []},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
data = response.json()
|
|
assert "session_id" in data
|
|
assert data["session_id"] > 0
|
|
|
|
|
|
class TestSyncSessions:
|
|
def test_complete_session(self, client, access_token: str, admin_user: User):
|
|
device = db_device_handler.add_device(
|
|
Device(id="session-dev-1", user_id=admin_user.id)
|
|
)
|
|
sync_session = db_sync_session_handler.create_session(
|
|
device_id=device.id, user_id=admin_user.id
|
|
)
|
|
|
|
response = client.post(
|
|
f"/api/sync/sessions/{sync_session.id}/complete",
|
|
json={"operations_completed": 5, "operations_failed": 1},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
data = response.json()
|
|
assert data["session"]["status"] == "COMPLETED"
|
|
assert data["session"]["operations_completed"] == 5
|
|
assert data["session"]["operations_failed"] == 1
|
|
assert data["play_session_ingest"] is None
|
|
|
|
def test_complete_session_not_found(self, client, access_token: str):
|
|
response = client.post(
|
|
"/api/sync/sessions/99999/complete",
|
|
json={"operations_completed": 0, "operations_failed": 0},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
assert response.status_code == status.HTTP_404_NOT_FOUND
|
|
|
|
def test_complete_already_completed_session(
|
|
self, client, access_token: str, admin_user: User
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(id="session-dev-completed", user_id=admin_user.id)
|
|
)
|
|
sync_session = db_sync_session_handler.create_session(
|
|
device_id=device.id, user_id=admin_user.id
|
|
)
|
|
db_sync_session_handler.complete_session(session_id=sync_session.id)
|
|
|
|
response = client.post(
|
|
f"/api/sync/sessions/{sync_session.id}/complete",
|
|
json={"operations_completed": 0, "operations_failed": 0},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
|
|
|
def test_list_sessions(self, client, access_token: str, admin_user: User):
|
|
device = db_device_handler.add_device(
|
|
Device(id="session-dev-list", user_id=admin_user.id)
|
|
)
|
|
db_sync_session_handler.create_session(
|
|
device_id=device.id, user_id=admin_user.id
|
|
)
|
|
db_sync_session_handler.create_session(
|
|
device_id=device.id, user_id=admin_user.id
|
|
)
|
|
|
|
response = client.get(
|
|
"/api/sync/sessions",
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
data = response.json()
|
|
assert len(data) == 2
|
|
|
|
def test_list_sessions_filter_by_device(
|
|
self, client, access_token: str, admin_user: User
|
|
):
|
|
dev_a = db_device_handler.add_device(
|
|
Device(id="session-dev-a", user_id=admin_user.id)
|
|
)
|
|
dev_b = db_device_handler.add_device(
|
|
Device(id="session-dev-b", user_id=admin_user.id)
|
|
)
|
|
db_sync_session_handler.create_session(
|
|
device_id=dev_a.id, user_id=admin_user.id
|
|
)
|
|
db_sync_session_handler.create_session(
|
|
device_id=dev_b.id, user_id=admin_user.id
|
|
)
|
|
|
|
response = client.get(
|
|
f"/api/sync/sessions?device_id={dev_a.id}",
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
data = response.json()
|
|
assert len(data) == 1
|
|
assert data[0]["device_id"] == dev_a.id
|
|
|
|
def test_get_session(self, client, access_token: str, admin_user: User):
|
|
device = db_device_handler.add_device(
|
|
Device(id="session-dev-get", user_id=admin_user.id)
|
|
)
|
|
sync_session = db_sync_session_handler.create_session(
|
|
device_id=device.id, user_id=admin_user.id
|
|
)
|
|
|
|
response = client.get(
|
|
f"/api/sync/sessions/{sync_session.id}",
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
data = response.json()
|
|
assert data["id"] == sync_session.id
|
|
assert data["device_id"] == device.id
|
|
|
|
def test_get_session_not_found(self, client, access_token: str):
|
|
response = client.get(
|
|
"/api/sync/sessions/99999",
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
assert response.status_code == status.HTTP_404_NOT_FOUND
|
|
|
|
|
|
class TestSyncUserIsolation:
|
|
def test_cannot_negotiate_with_other_users_device(
|
|
self, client, editor_access_token: str, admin_user: User
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(id="admin-sync-dev", user_id=admin_user.id, sync_enabled=True)
|
|
)
|
|
|
|
response = client.post(
|
|
"/api/sync/negotiate",
|
|
json={"device_id": device.id, "saves": []},
|
|
headers={"Authorization": f"Bearer {editor_access_token}"},
|
|
)
|
|
assert response.status_code == status.HTTP_404_NOT_FOUND
|
|
|
|
def test_cannot_complete_other_users_session(
|
|
self, client, editor_access_token: str, admin_user: User
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(id="admin-session-dev", user_id=admin_user.id)
|
|
)
|
|
sync_session = db_sync_session_handler.create_session(
|
|
device_id=device.id, user_id=admin_user.id
|
|
)
|
|
|
|
response = client.post(
|
|
f"/api/sync/sessions/{sync_session.id}/complete",
|
|
json={"operations_completed": 0, "operations_failed": 0},
|
|
headers={"Authorization": f"Bearer {editor_access_token}"},
|
|
)
|
|
assert response.status_code == status.HTTP_404_NOT_FOUND
|
|
|
|
def test_sessions_only_return_own(
|
|
self,
|
|
client,
|
|
access_token: str,
|
|
editor_access_token: str,
|
|
admin_user: User,
|
|
editor_user: User,
|
|
):
|
|
admin_dev = db_device_handler.add_device(
|
|
Device(id="admin-iso-dev", user_id=admin_user.id)
|
|
)
|
|
editor_dev = db_device_handler.add_device(
|
|
Device(id="editor-iso-dev", user_id=editor_user.id)
|
|
)
|
|
db_sync_session_handler.create_session(
|
|
device_id=admin_dev.id, user_id=admin_user.id
|
|
)
|
|
db_sync_session_handler.create_session(
|
|
device_id=editor_dev.id, user_id=editor_user.id
|
|
)
|
|
|
|
admin_resp = client.get(
|
|
"/api/sync/sessions",
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
editor_resp = client.get(
|
|
"/api/sync/sessions",
|
|
headers={"Authorization": f"Bearer {editor_access_token}"},
|
|
)
|
|
|
|
assert len(admin_resp.json()) == 1
|
|
assert admin_resp.json()[0]["device_id"] == admin_dev.id
|
|
assert len(editor_resp.json()) == 1
|
|
assert editor_resp.json()[0]["device_id"] == editor_dev.id
|
|
|
|
|
|
class TestPushPullTrigger:
|
|
def test_trigger_push_pull(self, client, access_token: str, admin_user: User):
|
|
device = db_device_handler.add_device(
|
|
Device(
|
|
id="pp-dev-1",
|
|
user_id=admin_user.id,
|
|
sync_mode=SyncMode.PUSH_PULL,
|
|
sync_enabled=True,
|
|
)
|
|
)
|
|
|
|
with mock.patch("endpoints.sync.high_prio_queue") as mock_queue:
|
|
response = client.post(
|
|
f"/api/sync/devices/{device.id}/push-pull",
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
data = response.json()
|
|
assert data["device_id"] == device.id
|
|
assert data["status"] == "PENDING"
|
|
mock_queue.enqueue.assert_called_once()
|
|
|
|
def test_trigger_push_pull_wrong_mode(
|
|
self, client, access_token: str, admin_user: User
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(
|
|
id="pp-dev-wrong-mode",
|
|
user_id=admin_user.id,
|
|
sync_mode=SyncMode.API,
|
|
sync_enabled=True,
|
|
)
|
|
)
|
|
|
|
response = client.post(
|
|
f"/api/sync/devices/{device.id}/push-pull",
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
|
|
|
def test_trigger_push_pull_sync_disabled(
|
|
self, client, access_token: str, admin_user: User
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(
|
|
id="pp-dev-disabled",
|
|
user_id=admin_user.id,
|
|
sync_mode=SyncMode.PUSH_PULL,
|
|
sync_enabled=False,
|
|
)
|
|
)
|
|
|
|
response = client.post(
|
|
f"/api/sync/devices/{device.id}/push-pull",
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
|
|
|
def test_trigger_push_pull_device_not_found(self, client, access_token: str):
|
|
response = client.post(
|
|
"/api/sync/devices/nonexistent/push-pull",
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
assert response.status_code == status.HTTP_404_NOT_FOUND
|
|
|
|
def test_trigger_push_pull_passes_session_id(
|
|
self, client, access_token: str, admin_user: User
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(
|
|
id="pp-dev-sid",
|
|
user_id=admin_user.id,
|
|
sync_mode=SyncMode.PUSH_PULL,
|
|
sync_enabled=True,
|
|
)
|
|
)
|
|
|
|
with mock.patch("endpoints.sync.high_prio_queue") as mock_queue:
|
|
response = client.post(
|
|
f"/api/sync/devices/{device.id}/push-pull",
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
call_kwargs = mock_queue.enqueue.call_args
|
|
assert "session_id" in call_kwargs.kwargs
|
|
|
|
|
|
class TestNegotiateAdvanced:
|
|
def test_negotiate_untracked_save_returns_noop(
|
|
self, client, access_token: str, admin_user: User, save: Save
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(id="neg-untrack-dev", user_id=admin_user.id, sync_enabled=True)
|
|
)
|
|
db_device_save_sync_handler.set_untracked(
|
|
device_id=device.id, save_id=save.id, untracked=True
|
|
)
|
|
|
|
response = client.post(
|
|
"/api/sync/negotiate",
|
|
json={
|
|
"device_id": device.id,
|
|
"saves": [
|
|
{
|
|
"rom_id": save.rom_id,
|
|
"file_name": save.file_name,
|
|
"content_hash": "different_hash",
|
|
"updated_at": "2026-03-01T00:00:00Z",
|
|
"file_size_bytes": 100,
|
|
}
|
|
],
|
|
},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
data = response.json()
|
|
noop_ops = [op for op in data["operations"] if op["action"] == "no_op"]
|
|
assert len(noop_ops) >= 1
|
|
|
|
def test_negotiate_server_save_not_mentioned_by_client(
|
|
self, client, access_token: str, admin_user: User, save: Save
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(id="neg-miss-dev", user_id=admin_user.id, sync_enabled=True)
|
|
)
|
|
|
|
response = client.post(
|
|
"/api/sync/negotiate",
|
|
json={"device_id": device.id, "saves": []},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
data = response.json()
|
|
download_ops = [op for op in data["operations"] if op["action"] == "download"]
|
|
assert len(download_ops) >= 1
|
|
assert any(op["save_id"] == save.id for op in download_ops)
|
|
|
|
def test_negotiate_deleted_by_client_skipped(
|
|
self, client, access_token: str, admin_user: User, save: Save
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(id="neg-del-dev", user_id=admin_user.id, sync_enabled=True)
|
|
)
|
|
db_device_save_sync_handler.upsert_sync(
|
|
device_id=device.id,
|
|
save_id=save.id,
|
|
synced_at=datetime.now(timezone.utc),
|
|
)
|
|
|
|
response = client.post(
|
|
"/api/sync/negotiate",
|
|
json={"device_id": device.id, "saves": []},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
data = response.json()
|
|
ops_for_save = [op for op in data["operations"] if op.get("save_id") == save.id]
|
|
assert len(ops_for_save) == 0
|
|
|
|
def test_complete_failed_session_rejected(
|
|
self, client, access_token: str, admin_user: User
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(id="sess-failed-dev", user_id=admin_user.id)
|
|
)
|
|
sync_session = db_sync_session_handler.create_session(
|
|
device_id=device.id, user_id=admin_user.id
|
|
)
|
|
db_sync_session_handler.fail_session(sync_session.id, error_message="test")
|
|
|
|
response = client.post(
|
|
f"/api/sync/sessions/{sync_session.id}/complete",
|
|
json={"operations_completed": 0, "operations_failed": 0},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
|
|
|
def test_complete_cancelled_session_rejected(
|
|
self, client, access_token: str, admin_user: User
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(id="sess-cancel-dev", user_id=admin_user.id)
|
|
)
|
|
db_sync_session_handler.create_session(
|
|
device_id=device.id, user_id=admin_user.id
|
|
)
|
|
db_sync_session_handler.cancel_active_sessions(device.id, admin_user.id)
|
|
|
|
sessions = db_sync_session_handler.get_sessions(
|
|
admin_user.id, device_id=device.id
|
|
)
|
|
cancelled = sessions[0]
|
|
|
|
response = client.post(
|
|
f"/api/sync/sessions/{cancelled.id}/complete",
|
|
json={"operations_completed": 0, "operations_failed": 0},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
|
|
|
|
|
def _play_session(rom_id=None, start_offset_hours=-1, duration_minutes=30):
|
|
now = datetime.now(timezone.utc)
|
|
start = now + timedelta(hours=start_offset_hours)
|
|
end = start + timedelta(minutes=duration_minutes)
|
|
return {
|
|
"rom_id": rom_id,
|
|
"start_time": start.isoformat(),
|
|
"end_time": end.isoformat(),
|
|
"duration_ms": duration_minutes * 60 * 1000,
|
|
}
|
|
|
|
|
|
class TestSyncCompleteWithPlaySessions:
|
|
def test_complete_with_play_sessions(
|
|
self, client, access_token: str, admin_user: User, rom: Rom
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(id="sync-ps-dev-1", user_id=admin_user.id)
|
|
)
|
|
sync_session = db_sync_session_handler.create_session(
|
|
device_id=device.id, user_id=admin_user.id
|
|
)
|
|
|
|
response = client.post(
|
|
f"/api/sync/sessions/{sync_session.id}/complete",
|
|
json={
|
|
"operations_completed": 1,
|
|
"operations_failed": 0,
|
|
"play_sessions": [
|
|
_play_session(rom_id=rom.id, start_offset_hours=-2),
|
|
_play_session(rom_id=rom.id, start_offset_hours=-4),
|
|
],
|
|
},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
data = response.json()
|
|
assert data["session"]["status"] == "COMPLETED"
|
|
assert data["play_session_ingest"] is not None
|
|
assert data["play_session_ingest"]["created_count"] == 2
|
|
assert data["play_session_ingest"]["skipped_count"] == 0
|
|
|
|
def test_play_sessions_have_sync_session_id(
|
|
self, client, access_token: str, admin_user: User, rom: Rom
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(id="sync-ps-dev-2", user_id=admin_user.id)
|
|
)
|
|
sync_session = db_sync_session_handler.create_session(
|
|
device_id=device.id, user_id=admin_user.id
|
|
)
|
|
|
|
client.post(
|
|
f"/api/sync/sessions/{sync_session.id}/complete",
|
|
json={
|
|
"operations_completed": 0,
|
|
"operations_failed": 0,
|
|
"play_sessions": [
|
|
_play_session(rom_id=rom.id, start_offset_hours=-3),
|
|
],
|
|
},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
sessions = db_play_session_handler.get_sessions(
|
|
user_id=admin_user.id, rom_id=rom.id
|
|
)
|
|
assert len(sessions) >= 1
|
|
linked = [s for s in sessions if s.sync_session_id == sync_session.id]
|
|
assert len(linked) == 1
|
|
|
|
def test_play_sessions_use_device_from_sync_session(
|
|
self, client, access_token: str, admin_user: User, rom: Rom
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(id="sync-ps-dev-3", user_id=admin_user.id)
|
|
)
|
|
sync_session = db_sync_session_handler.create_session(
|
|
device_id=device.id, user_id=admin_user.id
|
|
)
|
|
|
|
client.post(
|
|
f"/api/sync/sessions/{sync_session.id}/complete",
|
|
json={
|
|
"operations_completed": 0,
|
|
"operations_failed": 0,
|
|
"play_sessions": [
|
|
_play_session(rom_id=rom.id, start_offset_hours=-5),
|
|
],
|
|
},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
sessions = db_play_session_handler.get_sessions(
|
|
user_id=admin_user.id, rom_id=rom.id
|
|
)
|
|
assert len(sessions) >= 1
|
|
assert sessions[0].device_id == device.id
|
|
|
|
def test_complete_without_play_sessions_backward_compatible(
|
|
self, client, access_token: str, admin_user: User
|
|
):
|
|
device = db_device_handler.add_device(
|
|
Device(id="sync-ps-dev-4", user_id=admin_user.id)
|
|
)
|
|
sync_session = db_sync_session_handler.create_session(
|
|
device_id=device.id, user_id=admin_user.id
|
|
)
|
|
|
|
response = client.post(
|
|
f"/api/sync/sessions/{sync_session.id}/complete",
|
|
json={"operations_completed": 3, "operations_failed": 0},
|
|
headers={"Authorization": f"Bearer {access_token}"},
|
|
)
|
|
|
|
assert response.status_code == status.HTTP_200_OK
|
|
data = response.json()
|
|
assert data["session"]["status"] == "COMPLETED"
|
|
assert data["play_session_ingest"] is None
|