diff --git a/tests/endpoints/test_assets.py b/tests/endpoints/test_assets.py index 0ec29dd..d1ba662 100644 --- a/tests/endpoints/test_assets.py +++ b/tests/endpoints/test_assets.py @@ -161,3 +161,347 @@ class TestAssetsEndpoint: with pytest.raises(ValidationError): endpoint.rename(1, "") + + # Move operations + def test_move_asset(self, endpoint): + """Test moving an asset to a different folder.""" + mock_response = { + "data": { + "assets": { + "moveAsset": { + "responseResult": {"succeeded": True}, + "asset": { + "id": 1, + "filename": "test.png", + "ext": "png", + "kind": "image", + "mime": "image/png", + "fileSize": 1024, + "folderId": 5, + "authorId": 1, + "authorName": "Admin", + "createdAt": "2024-01-01T00:00:00Z", + "updatedAt": "2024-01-01T00:00:00Z", + }, + } + } + } + } + endpoint._post = Mock(return_value=mock_response) + + asset = endpoint.move(1, 5) + + assert asset.folder_id == 5 + + def test_move_asset_validation_error(self, endpoint): + """Test move asset with invalid inputs.""" + with pytest.raises(ValidationError): + endpoint.move(0, 1) # Invalid asset ID + + with pytest.raises(ValidationError): + endpoint.move(1, -1) # Invalid folder ID + + # Folder operations + def test_create_folder(self, endpoint): + """Test creating a folder.""" + mock_response = { + "data": { + "assets": { + "createFolder": { + "responseResult": {"succeeded": True}, + "folder": {"id": 1, "slug": "documents", "name": "Documents"}, + } + } + } + } + endpoint._post = Mock(return_value=mock_response) + + folder = endpoint.create_folder("documents", "Documents") + + assert isinstance(folder, AssetFolder) + assert folder.slug == "documents" + assert folder.name == "Documents" + + def test_create_folder_minimal(self, endpoint): + """Test creating a folder with minimal parameters.""" + mock_response = { + "data": { + "assets": { + "createFolder": { + "responseResult": {"succeeded": True}, + "folder": {"id": 2, "slug": "images", "name": None}, + } + } + } + } + endpoint._post = Mock(return_value=mock_response) + + folder = endpoint.create_folder("images") + + assert folder.slug == "images" + assert folder.name is None + + def test_create_folder_validation_error(self, endpoint): + """Test create folder with invalid slug.""" + with pytest.raises(ValidationError): + endpoint.create_folder("") # Empty slug + + with pytest.raises(ValidationError): + endpoint.create_folder("///") # Just slashes + + def test_delete_folder(self, endpoint): + """Test deleting a folder.""" + mock_response = { + "data": { + "assets": { + "deleteFolder": { + "responseResult": {"succeeded": True} + } + } + } + } + endpoint._post = Mock(return_value=mock_response) + + result = endpoint.delete_folder(1) + + assert result is True + + def test_delete_folder_validation_error(self, endpoint): + """Test delete folder with invalid ID.""" + with pytest.raises(ValidationError): + endpoint.delete_folder(0) + + with pytest.raises(ValidationError): + endpoint.delete_folder(-1) + + # List operations with filters + def test_list_assets_with_folder_filter(self, endpoint): + """Test listing assets filtered by folder.""" + mock_response = { + "data": { + "assets": { + "list": [ + { + "id": 1, + "filename": "doc.pdf", + "ext": "pdf", + "kind": "binary", + "mime": "application/pdf", + "fileSize": 2048, + "folderId": 1, + "folder": {"id": 1, "slug": "documents", "name": "Documents"}, + "authorId": 1, + "authorName": "Admin", + "createdAt": "2024-01-01T00:00:00Z", + "updatedAt": "2024-01-01T00:00:00Z", + } + ] + } + } + } + endpoint._post = Mock(return_value=mock_response) + + assets = endpoint.list(folder_id=1) + + assert len(assets) == 1 + assert assets[0].folder_id == 1 + + def test_list_assets_with_kind_filter(self, endpoint): + """Test listing assets filtered by kind.""" + mock_response = { + "data": { + "assets": { + "list": [ + { + "id": 1, + "filename": "photo.jpg", + "ext": "jpg", + "kind": "image", + "mime": "image/jpeg", + "fileSize": 5120, + "folderId": 0, + "authorId": 1, + "authorName": "Admin", + "createdAt": "2024-01-01T00:00:00Z", + "updatedAt": "2024-01-01T00:00:00Z", + } + ] + } + } + } + endpoint._post = Mock(return_value=mock_response) + + assets = endpoint.list(kind="image") + + assert len(assets) == 1 + assert assets[0].kind == "image" + + def test_list_assets_empty(self, endpoint): + """Test listing assets when none exist.""" + mock_response = {"data": {"assets": {"list": []}}} + endpoint._post = Mock(return_value=mock_response) + + assets = endpoint.list() + + assert len(assets) == 0 + + # Error handling + def test_get_asset_not_found(self, endpoint): + """Test getting non-existent asset.""" + mock_response = { + "data": {"assets": {"single": None}}, + "errors": [{"message": "Asset not found"}], + } + endpoint._post = Mock(return_value=mock_response) + + with pytest.raises(APIError, match="Asset not found"): + endpoint.get(999) + + def test_delete_asset_failure(self, endpoint): + """Test delete asset API failure.""" + mock_response = { + "data": { + "assets": { + "deleteAsset": { + "responseResult": {"succeeded": False, "message": "Permission denied"} + } + } + } + } + endpoint._post = Mock(return_value=mock_response) + + with pytest.raises(APIError, match="Permission denied"): + endpoint.delete(1) + + def test_rename_asset_failure(self, endpoint): + """Test rename asset API failure.""" + mock_response = { + "data": { + "assets": { + "renameAsset": { + "responseResult": {"succeeded": False, "message": "Name already exists"} + } + } + } + } + endpoint._post = Mock(return_value=mock_response) + + with pytest.raises(APIError, match="Name already exists"): + endpoint.rename(1, "duplicate.png") + + def test_move_asset_failure(self, endpoint): + """Test move asset API failure.""" + mock_response = { + "data": { + "assets": { + "moveAsset": { + "responseResult": {"succeeded": False, "message": "Folder not found"} + } + } + } + } + endpoint._post = Mock(return_value=mock_response) + + with pytest.raises(APIError, match="Folder not found"): + endpoint.move(1, 999) + + def test_create_folder_failure(self, endpoint): + """Test create folder API failure.""" + mock_response = { + "data": { + "assets": { + "createFolder": { + "responseResult": {"succeeded": False, "message": "Folder already exists"} + } + } + } + } + endpoint._post = Mock(return_value=mock_response) + + with pytest.raises(APIError, match="Folder already exists"): + endpoint.create_folder("existing") + + def test_delete_folder_failure(self, endpoint): + """Test delete folder API failure.""" + mock_response = { + "data": { + "assets": { + "deleteFolder": { + "responseResult": {"succeeded": False, "message": "Folder not empty"} + } + } + } + } + endpoint._post = Mock(return_value=mock_response) + + with pytest.raises(APIError, match="Folder not empty"): + endpoint.delete_folder(1) + + # Pagination + def test_iter_all_assets(self, endpoint): + """Test iterating over all assets with pagination.""" + # First page (smaller batch to ensure pagination works) + mock_response_page1 = { + "data": { + "assets": { + "list": [ + { + "id": i, + "filename": f"file{i}.png", + "ext": "png", + "kind": "image", + "mime": "image/png", + "fileSize": 1024, + "folderId": 0, + "authorId": 1, + "authorName": "Admin", + "createdAt": "2024-01-01T00:00:00Z", + "updatedAt": "2024-01-01T00:00:00Z", + } + for i in range(1, 6) # 5 items + ] + } + } + } + + # Second page (empty - pagination stops) + mock_response_page2 = {"data": {"assets": {"list": []}}} + + endpoint._post = Mock( + side_effect=[mock_response_page1, mock_response_page2] + ) + + all_assets = list(endpoint.iter_all(batch_size=5)) + + assert len(all_assets) == 5 + assert all_assets[0].id == 1 + assert all_assets[4].id == 5 + + # Normalization edge cases + def test_normalize_asset_data_minimal(self, endpoint): + """Test normalizing asset data with minimal fields.""" + data = { + "id": 1, + "filename": "test.png", + "ext": "png", + "kind": "image", + "mime": "image/png", + "fileSize": 1024, + } + + normalized = endpoint._normalize_asset_data(data) + + assert normalized["id"] == 1 + assert normalized["filename"] == "test.png" + # Check that snake_case fields are present + assert "file_size" in normalized + assert normalized["file_size"] == 1024 + + def test_list_folders_empty(self, endpoint): + """Test listing folders when none exist.""" + mock_response = {"data": {"assets": {"folders": []}}} + endpoint._post = Mock(return_value=mock_response) + + folders = endpoint.list_folders() + + assert len(folders) == 0