Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 209 additions & 0 deletions tests/test_assets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
import unittest
from unittest.mock import patch, MagicMock
import requests
import os
import tempfile
from immich_lib.client import ImmichClient


# Create a test class that uses the actual client with mocked methods
class TestAssetsMixin(unittest.TestCase):
def setUp(self):
# Create a proper client instance that will be used for testing
self.server_url = "http://localhost:2283"
self.api_key = "test-api-key"
self.client = ImmichClient(self.server_url, self.api_key)

@patch("requests.Session.request")
def test_list_assets_success(self, mock_request):
"""Test successful list assets with various filter parameters"""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.headers = {"Content-Type": "application/json"}
mock_response.json.return_value = {
"assets": {
"items": [
{"id": "asset1", "originalFileName": "test1.jpg"},
{"id": "asset2", "originalFileName": "test2.jpg"},
]
}
}
mock_request.return_value = mock_response

# Test with no filters
result = self.client.list_assets()
self.assertEqual(len(result), 2)
self.assertEqual(result[0]["id"], "asset1")

# Test with filter parameters
result = self.client.list_assets(isFavorite=True, type="IMAGE")
self.assertEqual(len(result), 2)

@patch("requests.Session.request")
def test_list_assets_empty_response(self, mock_request):
"""Test list assets with empty response"""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.headers = {"Content-Type": "application/json"}
mock_response.json.return_value = {"assets": {"items": []}}
mock_request.return_value = mock_response

result = self.client.list_assets()
self.assertEqual(result, [])

@patch("requests.Session.request")
def test_list_assets_no_assets_key(self, mock_request):
"""Test list assets with missing assets key"""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.headers = {"Content-Type": "application/json"}
mock_response.json.return_value = {"other": "data"}
mock_request.return_value = mock_response

result = self.client.list_assets()
self.assertEqual(result, [])

@patch("requests.Session.request")
def test_get_asset_info_success(self, mock_request):
"""Test successful get asset info"""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.headers = {"Content-Type": "application/json"}
mock_response.json.return_value = {
"id": "test123",
"originalFileName": "test.jpg",
}
mock_request.return_value = mock_response

result = self.client.get_asset_info("test123")
self.assertEqual(result["id"], "test123")

@patch("requests.Session.request")
def test_get_asset_info_error(self, mock_request):
"""Test get asset info with error response"""
mock_response = MagicMock()
mock_response.status_code = 404
mock_response.headers = {"Content-Type": "application/json"}
mock_response.json.return_value = {"message": "Asset not found"}
mock_response.raise_for_status.side_effect = requests.exceptions.HTTPError(
"Not Found", response=mock_response
)
mock_request.return_value = mock_response

with self.assertRaises(requests.exceptions.HTTPError):
self.client.get_asset_info("nonexistent")

@patch("requests.Session.request")
def test_update_asset_success(self, mock_request):
"""Test successful asset update"""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.headers = {"Content-Type": "application/json"}
mock_response.json.return_value = {"id": "test123", "isFavorite": True}
mock_request.return_value = mock_response

result = self.client.update_asset("test123", isFavorite=True)
self.assertEqual(result["isFavorite"], True)

@patch("requests.Session.request")
def test_delete_assets_success(self, mock_request):
"""Test successful asset deletion"""
mock_response = MagicMock()
mock_response.status_code = 204
mock_request.return_value = mock_response

result = self.client.delete_assets(["asset1", "asset2"])
self.assertTrue(result)

@patch("requests.Session.request")
def test_delete_assets_error(self, mock_request):
"""Test asset deletion with error"""
mock_response = MagicMock()
mock_response.status_code = 500
mock_response.raise_for_status.side_effect = requests.exceptions.HTTPError(
"Internal Server Error", response=mock_response
)
mock_request.return_value = mock_response

with self.assertRaises(requests.exceptions.HTTPError):
self.client.delete_assets(["asset1"])

@patch("requests.Session.request")
def test_download_asset_success_with_path(self, mock_request):
"""Test successful asset download with file path"""
# Mock response for downloading the asset
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.headers = {"Content-Type": "image/jpeg", "content-length": "1024"}
mock_response.iter_content.return_value = [b"test data"]

# Mock file operations
with patch("builtins.open", MagicMock()) as mock_open:
# Mock tqdm class directly since it's imported in the client module
with patch("immich_lib.api.assets.tqdm") as mock_tqdm:
mock_tqdm_instance = MagicMock()
mock_tqdm.return_value.__enter__.return_value = mock_tqdm_instance

mock_request.return_value = mock_response

# Create temporary directory and file
with tempfile.TemporaryDirectory() as tmpdir:
test_file = os.path.join(tmpdir, "test.jpg")
result = self.client.download_asset("asset123", test_file)

# Should return True to indicate success
self.assertTrue(result)

@patch("requests.Session.request")
def test_download_asset_success_no_path(self, mock_request):
"""Test asset download without file path (returns response)"""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.headers = {"Content-Type": "image/jpeg"}
mock_request.return_value = mock_response

result = self.client.download_asset("asset123")
self.assertEqual(result, mock_response)

@patch("requests.Session.request")
def test_view_asset_success(self, mock_request):
"""Test successful asset thumbnail view"""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.headers = {"Content-Type": "image/jpeg"}
mock_request.return_value = mock_response

result = self.client.view_asset("asset123")
self.assertEqual(result, mock_response)

@patch("requests.Session.request")
def test_upload_asset_success(self, mock_request):
"""Test successful asset upload"""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.headers = {"Content-Type": "application/json"}
mock_response.json.return_value = {
"id": "uploaded123",
"originalFileName": "new.jpg",
}
mock_request.return_value = mock_response

# Create a temporary file for testing
with tempfile.NamedTemporaryFile(mode="w", delete=False) as tmp_file:
tmp_file.write("test content")
tmp_file_path = tmp_file.name

try:
# Mock file open operation
with patch("builtins.open", MagicMock()):
mock_request.return_value = mock_response

result = self.client.upload_asset(tmp_file_path, isFavorite=True)
self.assertEqual(result["id"], "uploaded123")
finally:
# Clean up temp file
os.unlink(tmp_file_path)


if __name__ == "__main__":
unittest.main()
97 changes: 97 additions & 0 deletions tests/test_folders.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import unittest
from unittest.mock import patch, MagicMock
import requests
from immich_lib.client import ImmichClient


class TestFoldersMixin(unittest.TestCase):
def setUp(self):
# Create a proper client instance that will be used for testing
self.server_url = "http://localhost:2283"
self.api_key = "test-api-key"
self.client = ImmichClient(self.server_url, self.api_key)

@patch("requests.Session.request")
def test_list_folders_success(self, mock_request):
"""Test successful list folders"""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.headers = {"Content-Type": "application/json"}
mock_response.json.return_value = [
{"id": "folder1", "importPath": "/path/to/folder1"},
{"id": "folder2", "importPath": "/path/to/folder2"},
]
mock_request.return_value = mock_response

result = self.client.list_folders()
self.assertEqual(len(result), 2)
self.assertEqual(result[0]["id"], "folder1")

@patch("requests.Session.request")
def test_list_folders_empty_response(self, mock_request):
"""Test list folders with empty response"""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.headers = {"Content-Type": "application/json"}
mock_response.json.return_value = []
mock_request.return_value = mock_response

result = self.client.list_folders()
self.assertEqual(result, [])

@patch("requests.Session.request")
def test_create_folder_success(self, mock_request):
"""Test successful folder creation"""
mock_response = MagicMock()
mock_response.status_code = 200
mock_response.headers = {"Content-Type": "application/json"}
mock_response.json.return_value = {
"id": "newfolder123",
"importPath": "/new/path",
}
mock_request.return_value = mock_response

result = self.client.create_folder("/new/path")
self.assertEqual(result["id"], "newfolder123")

@patch("requests.Session.request")
def test_create_folder_error(self, mock_request):
"""Test folder creation with error response"""
mock_response = MagicMock()
mock_response.status_code = 400
mock_response.headers = {"Content-Type": "application/json"}
mock_response.json.return_value = {"message": "Invalid path"}
mock_response.raise_for_status.side_effect = requests.exceptions.HTTPError(
"Bad Request", response=mock_response
)
mock_request.return_value = mock_response

with self.assertRaises(requests.exceptions.HTTPError):
self.client.create_folder("/invalid/path")

@patch("requests.Session.request")
def test_delete_folder_success(self, mock_request):
"""Test successful folder deletion"""
mock_response = MagicMock()
mock_response.status_code = 204
mock_request.return_value = mock_response

result = self.client.delete_folder("folder123")
self.assertTrue(result)

@patch("requests.Session.request")
def test_delete_folder_error(self, mock_request):
"""Test folder deletion with error"""
mock_response = MagicMock()
mock_response.status_code = 500
mock_response.raise_for_status.side_effect = requests.exceptions.HTTPError(
"Internal Server Error", response=mock_response
)
mock_request.return_value = mock_response

with self.assertRaises(requests.exceptions.HTTPError):
self.client.delete_folder("folder123")


if __name__ == "__main__":
unittest.main()
Loading
Loading