mirror of
https://github.com/rommapp/romm.git
synced 2026-06-28 06:46:00 +00:00
test: add tests for library structure detection in FSPlatformsHandler
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from fastapi import status
|
||||
from fastapi.testclient import TestClient
|
||||
from main import app
|
||||
|
||||
from exceptions.fs_exceptions import PlatformAlreadyExistsException
|
||||
from utils import get_version
|
||||
|
||||
|
||||
@@ -68,3 +71,256 @@ def test_heartbeat_metadata(client):
|
||||
def test_heartbeat_metadata_unknown_source(client):
|
||||
response = client.get("/api/heartbeat/metadata/unknown")
|
||||
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
||||
|
||||
|
||||
def test_get_setup_library_info_structure_a_detected(
|
||||
self, client, admin_user, access_token
|
||||
):
|
||||
"""Test get_setup_library_info with Structure A detected"""
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.detect_library_structure"
|
||||
) as mock_detect:
|
||||
mock_detect.return_value = "A"
|
||||
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.get_platforms"
|
||||
) as mock_get_platforms:
|
||||
mock_get_platforms.return_value = ["n64", "psx"]
|
||||
|
||||
with patch("os.path.exists", return_value=True):
|
||||
with patch("os.listdir") as mock_listdir:
|
||||
mock_listdir.side_effect = [
|
||||
["game1.z64", "game2.z64"], # n64 roms
|
||||
["game1.iso"], # psx roms
|
||||
]
|
||||
|
||||
response = client.get(
|
||||
"/api/setup/library",
|
||||
headers={"Authorization": f"Bearer {access_token}"},
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
data = response.json()
|
||||
|
||||
assert data["detected_structure"] == "A"
|
||||
assert len(data["existing_platforms"]) == 2
|
||||
assert data["existing_platforms"][0]["fs_slug"] == "n64"
|
||||
assert data["existing_platforms"][0]["rom_count"] == 2
|
||||
assert data["existing_platforms"][1]["fs_slug"] == "psx"
|
||||
assert data["existing_platforms"][1]["rom_count"] == 1
|
||||
assert "supported_platforms" in data
|
||||
|
||||
|
||||
def test_get_setup_library_info_structure_b_detected(
|
||||
self, client, admin_user, access_token
|
||||
):
|
||||
"""Test get_setup_library_info with Structure B detected"""
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.detect_library_structure"
|
||||
) as mock_detect:
|
||||
mock_detect.return_value = "B"
|
||||
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.get_platforms"
|
||||
) as mock_get_platforms:
|
||||
mock_get_platforms.return_value = ["gba"]
|
||||
|
||||
with patch("os.path.exists", return_value=True):
|
||||
with patch("os.listdir") as mock_listdir:
|
||||
mock_listdir.return_value = ["game1.gba", "game2.gba", "game3.gba"]
|
||||
|
||||
response = client.get(
|
||||
"/api/setup/library",
|
||||
headers={"Authorization": f"Bearer {access_token}"},
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
data = response.json()
|
||||
|
||||
assert data["detected_structure"] == "B"
|
||||
assert len(data["existing_platforms"]) == 1
|
||||
assert data["existing_platforms"][0]["fs_slug"] == "gba"
|
||||
assert data["existing_platforms"][0]["rom_count"] == 3
|
||||
|
||||
|
||||
def test_get_setup_library_info_no_structure_detected(
|
||||
self, client, admin_user, access_token
|
||||
):
|
||||
"""Test get_setup_library_info when no structure is detected"""
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.detect_library_structure"
|
||||
) as mock_detect:
|
||||
mock_detect.return_value = None
|
||||
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.get_platforms"
|
||||
) as mock_get_platforms:
|
||||
mock_get_platforms.return_value = []
|
||||
|
||||
response = client.get(
|
||||
"/api/setup/library",
|
||||
headers={"Authorization": f"Bearer {access_token}"},
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
data = response.json()
|
||||
|
||||
assert data["detected_structure"] is None
|
||||
assert data["existing_platforms"] == []
|
||||
assert "supported_platforms" in data
|
||||
|
||||
|
||||
def test_get_setup_library_info_handles_errors(self, client, admin_user, access_token):
|
||||
"""Test get_setup_library_info handles filesystem errors gracefully"""
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.detect_library_structure"
|
||||
) as mock_detect:
|
||||
mock_detect.return_value = "A"
|
||||
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.get_platforms"
|
||||
) as mock_get_platforms:
|
||||
# Simulate error retrieving platforms
|
||||
mock_get_platforms.side_effect = Exception("Filesystem error")
|
||||
|
||||
response = client.get(
|
||||
"/api/setup/library",
|
||||
headers={"Authorization": f"Bearer {access_token}"},
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
data = response.json()
|
||||
|
||||
# Should return empty platforms list on error
|
||||
assert data["existing_platforms"] == []
|
||||
|
||||
|
||||
def test_create_setup_platforms_success(self, client, admin_user, access_token):
|
||||
"""Test create_setup_platforms successfully creates platforms"""
|
||||
platform_slugs = ["n64", "psx", "gba"]
|
||||
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.detect_library_structure"
|
||||
) as mock_detect:
|
||||
mock_detect.return_value = "A"
|
||||
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.add_platform"
|
||||
) as mock_add_platform:
|
||||
mock_add_platform.return_value = None # Successful creation
|
||||
|
||||
response = client.post(
|
||||
"/api/setup/platforms",
|
||||
json=platform_slugs,
|
||||
headers={"Authorization": f"Bearer {access_token}"},
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
data = response.json()
|
||||
|
||||
assert data["success"] is True
|
||||
assert data["created_count"] == 3
|
||||
assert "Successfully created 3 platform folder(s)" in data["message"]
|
||||
assert mock_add_platform.call_count == 3
|
||||
|
||||
|
||||
def test_create_setup_platforms_empty_list(self, client, admin_user, access_token):
|
||||
"""Test create_setup_platforms with empty platform list"""
|
||||
response = client.post(
|
||||
"/api/setup/platforms",
|
||||
json=[],
|
||||
headers={"Authorization": f"Bearer {access_token}"},
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
data = response.json()
|
||||
|
||||
assert data["success"] is True
|
||||
assert data["created_count"] == 0
|
||||
assert data["message"] == "No platforms selected"
|
||||
|
||||
|
||||
def test_create_setup_platforms_creates_structure_a_when_none_exists(
|
||||
self, client, admin_user, access_token
|
||||
):
|
||||
"""Test create_setup_platforms creates Structure A when no structure detected"""
|
||||
platform_slugs = ["n64"]
|
||||
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.detect_library_structure"
|
||||
) as mock_detect:
|
||||
mock_detect.return_value = None # No structure detected
|
||||
|
||||
with patch("os.makedirs") as mock_makedirs:
|
||||
with patch("endpoints.heartbeat.fs_platform_handler.add_platform"):
|
||||
response = client.post(
|
||||
"/api/setup/platforms",
|
||||
json=platform_slugs,
|
||||
headers={"Authorization": f"Bearer {access_token}"},
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
# Should create roms folder first
|
||||
mock_makedirs.assert_called_once()
|
||||
assert "roms" in str(mock_makedirs.call_args[0][0])
|
||||
|
||||
|
||||
def test_create_setup_platforms_skips_existing_platforms(
|
||||
self, client, admin_user, access_token
|
||||
):
|
||||
"""Test create_setup_platforms skips platforms that already exist"""
|
||||
platform_slugs = ["n64", "psx", "gba"]
|
||||
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.detect_library_structure"
|
||||
) as mock_detect:
|
||||
mock_detect.return_value = "A"
|
||||
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.add_platform"
|
||||
) as mock_add_platform:
|
||||
# First platform already exists, second succeeds, third succeeds
|
||||
mock_add_platform.side_effect = [
|
||||
PlatformAlreadyExistsException("n64"),
|
||||
None,
|
||||
None,
|
||||
]
|
||||
|
||||
response = client.post(
|
||||
"/api/setup/platforms",
|
||||
json=platform_slugs,
|
||||
headers={"Authorization": f"Bearer {access_token}"},
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_201_CREATED
|
||||
data = response.json()
|
||||
|
||||
assert data["success"] is True
|
||||
# Should only count 2 created (psx and gba)
|
||||
assert data["created_count"] == 2
|
||||
|
||||
|
||||
def test_create_setup_platforms_handles_permission_errors(
|
||||
self, client, admin_user, access_token
|
||||
):
|
||||
"""Test create_setup_platforms handles permission errors"""
|
||||
platform_slugs = ["n64"]
|
||||
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.detect_library_structure"
|
||||
) as mock_detect:
|
||||
mock_detect.return_value = "A"
|
||||
|
||||
with patch(
|
||||
"endpoints.heartbeat.fs_platform_handler.add_platform"
|
||||
) as mock_add_platform:
|
||||
mock_add_platform.side_effect = PermissionError("Permission denied")
|
||||
|
||||
response = client.post(
|
||||
"/api/setup/platforms",
|
||||
json=platform_slugs,
|
||||
headers={"Authorization": f"Bearer {access_token}"},
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_500_INTERNAL_SERVER_ERROR
|
||||
assert "Failed to create some platform folders" in response.json()["detail"]
|
||||
|
||||
@@ -311,3 +311,85 @@ class TestFSPlatformsHandler:
|
||||
for platform in expected_filtered:
|
||||
structure = handler.get_platform_fs_structure(platform)
|
||||
assert structure == f"{platform}/{config.ROMS_FOLDER_NAME}"
|
||||
|
||||
def test_detect_library_structure_structure_a(
|
||||
self, handler: FSPlatformsHandler, config
|
||||
):
|
||||
"""Test detect_library_structure detects Structure A (roms/{platform})"""
|
||||
roms_path = f"{LIBRARY_BASE_PATH}/{config.ROMS_FOLDER_NAME}"
|
||||
|
||||
with patch(
|
||||
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
|
||||
):
|
||||
with patch("os.path.exists") as mock_exists:
|
||||
mock_exists.return_value = True
|
||||
|
||||
result = handler.detect_library_structure()
|
||||
assert result == "A"
|
||||
mock_exists.assert_called_once_with(roms_path)
|
||||
|
||||
def test_detect_library_structure_structure_b(
|
||||
self, handler: FSPlatformsHandler, config
|
||||
):
|
||||
"""Test detect_library_structure detects Structure B ({platform}/roms)"""
|
||||
with patch(
|
||||
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
|
||||
):
|
||||
with patch("os.path.exists") as mock_exists:
|
||||
# Roms folder doesn't exist at base level
|
||||
mock_exists.return_value = False
|
||||
|
||||
with patch("os.listdir") as mock_listdir:
|
||||
mock_listdir.return_value = ["n64", "psx", "other_folder"]
|
||||
|
||||
with patch("os.path.isdir") as mock_isdir:
|
||||
# n64 and psx are directories with roms subfolders
|
||||
def isdir_side_effect(path):
|
||||
return "n64" in path or "psx" in path
|
||||
|
||||
def exists_side_effect(path):
|
||||
# n64/roms and psx/roms exist
|
||||
return (
|
||||
f"n64/{config.ROMS_FOLDER_NAME}" in path
|
||||
or f"psx/{config.ROMS_FOLDER_NAME}" in path
|
||||
)
|
||||
|
||||
mock_isdir.side_effect = isdir_side_effect
|
||||
mock_exists.side_effect = exists_side_effect
|
||||
|
||||
result = handler.detect_library_structure()
|
||||
assert result == "B"
|
||||
|
||||
def test_detect_library_structure_none(self, handler: FSPlatformsHandler, config):
|
||||
"""Test detect_library_structure returns None when no structure detected"""
|
||||
with patch(
|
||||
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
|
||||
):
|
||||
with patch("os.path.exists", return_value=False):
|
||||
with patch("os.listdir", return_value=[]):
|
||||
result = handler.detect_library_structure()
|
||||
assert result is None
|
||||
|
||||
def test_detect_library_structure_handles_os_errors(
|
||||
self, handler: FSPlatformsHandler, config
|
||||
):
|
||||
"""Test detect_library_structure handles OS errors gracefully"""
|
||||
with patch(
|
||||
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
|
||||
):
|
||||
with patch("os.path.exists", return_value=False):
|
||||
with patch("os.listdir", side_effect=OSError("Permission denied")):
|
||||
result = handler.detect_library_structure()
|
||||
assert result is None
|
||||
|
||||
def test_detect_library_structure_empty_library(
|
||||
self, handler: FSPlatformsHandler, config
|
||||
):
|
||||
"""Test detect_library_structure with empty library directory"""
|
||||
with patch(
|
||||
"handler.filesystem.platforms_handler.cm.get_config", return_value=config
|
||||
):
|
||||
with patch("os.path.exists", return_value=False):
|
||||
with patch("os.listdir", return_value=[]):
|
||||
result = handler.detect_library_structure()
|
||||
assert result is None
|
||||
|
||||
Reference in New Issue
Block a user