Big-Link-Man/tests/unit/test_bunnynet_client.py

204 lines
8.2 KiB
Python

"""
Unit tests for bunny.net API client
"""
import pytest
from unittest.mock import Mock, patch
import requests
from src.deployment.bunnynet import (
BunnyNetClient,
BunnyNetAPIError,
BunnyNetAuthError,
BunnyNetResourceConflictError,
StorageZoneResult,
PullZoneResult
)
@pytest.fixture
def bunny_client():
"""Fixture to create a BunnyNetClient instance"""
return BunnyNetClient(api_key="test_api_key")
@pytest.fixture
def mock_response():
"""Fixture to create a mock response"""
mock = Mock(spec=requests.Response)
mock.status_code = 200
mock.json.return_value = {}
mock.content = b'{}'
return mock
class TestBunnyNetClient:
"""Tests for BunnyNetClient"""
def test_client_initialization(self):
"""Test client initializes with correct headers"""
client = BunnyNetClient("test_key")
assert client.api_key == "test_key"
assert client.session.headers["AccessKey"] == "test_key"
assert client.session.headers["Content-Type"] == "application/json"
def test_create_storage_zone_success(self, bunny_client, mock_response):
"""Test successful storage zone creation"""
mock_response.json.return_value = {
"Id": 12345,
"Name": "test-storage",
"Password": "test-password",
"Region": "DE"
}
with patch.object(bunny_client.session, 'request', return_value=mock_response):
result = bunny_client.create_storage_zone("test-storage", "DE")
assert isinstance(result, StorageZoneResult)
assert result.id == 12345
assert result.name == "test-storage"
assert result.password == "test-password"
assert result.region == "DE"
def test_create_storage_zone_auth_error(self, bunny_client, mock_response):
"""Test storage zone creation with auth error"""
mock_response.status_code = 401
with patch.object(bunny_client.session, 'request', return_value=mock_response):
with pytest.raises(BunnyNetAuthError):
bunny_client.create_storage_zone("test-storage", "DE")
def test_create_storage_zone_conflict(self, bunny_client, mock_response):
"""Test storage zone creation with name conflict"""
mock_response.status_code = 409
with patch.object(bunny_client.session, 'request', return_value=mock_response):
with pytest.raises(BunnyNetResourceConflictError):
bunny_client.create_storage_zone("existing-storage", "DE")
def test_get_storage_zones_success(self, bunny_client, mock_response):
"""Test successful retrieval of storage zones"""
mock_response.json.return_value = [
{"Id": 1, "Name": "zone1", "Region": "DE"},
{"Id": 2, "Name": "zone2", "Region": "NY"}
]
with patch.object(bunny_client.session, 'request', return_value=mock_response):
result = bunny_client.get_storage_zones()
assert len(result) == 2
assert result[0]["Name"] == "zone1"
assert result[1]["Name"] == "zone2"
def test_find_storage_zone_by_name_found(self, bunny_client, mock_response):
"""Test finding an existing storage zone by name"""
mock_response.json.return_value = [
{"Id": 1, "Name": "zone1", "Region": "DE", "Password": "pass1"},
{"Id": 2, "Name": "zone2", "Region": "NY", "Password": "pass2"}
]
with patch.object(bunny_client.session, 'request', return_value=mock_response):
result = bunny_client.find_storage_zone_by_name("zone2")
assert result is not None
assert result.id == 2
assert result.name == "zone2"
assert result.region == "NY"
assert result.password == "pass2"
def test_find_storage_zone_by_name_not_found(self, bunny_client, mock_response):
"""Test finding a non-existent storage zone"""
mock_response.json.return_value = [
{"Id": 1, "Name": "zone1", "Region": "DE", "Password": "pass1"}
]
with patch.object(bunny_client.session, 'request', return_value=mock_response):
result = bunny_client.find_storage_zone_by_name("nonexistent")
assert result is None
def test_create_pull_zone_success(self, bunny_client, mock_response):
"""Test successful pull zone creation"""
mock_response.json.return_value = {
"Id": 67890,
"Name": "test-cdn",
"Hostnames": [{"Value": "test-cdn.b-cdn.net"}]
}
with patch.object(bunny_client.session, 'request', return_value=mock_response):
result = bunny_client.create_pull_zone("test-cdn", 12345)
assert isinstance(result, PullZoneResult)
assert result.id == 67890
assert result.name == "test-cdn"
assert result.hostname == "test-cdn.b-cdn.net"
def test_create_pull_zone_no_hostnames(self, bunny_client, mock_response):
"""Test pull zone creation with no hostnames in response"""
mock_response.json.return_value = {
"Id": 67890,
"Name": "test-cdn"
}
with patch.object(bunny_client.session, 'request', return_value=mock_response):
result = bunny_client.create_pull_zone("test-cdn", 12345)
assert result.hostname == "test-cdn.b-cdn.net"
def test_create_pull_zone_conflict(self, bunny_client, mock_response):
"""Test pull zone creation with name conflict"""
mock_response.status_code = 409
with patch.object(bunny_client.session, 'request', return_value=mock_response):
with pytest.raises(BunnyNetResourceConflictError):
bunny_client.create_pull_zone("existing-cdn", 12345)
def test_add_custom_hostname_success(self, bunny_client, mock_response):
"""Test successful custom hostname addition"""
mock_response.status_code = 200
with patch.object(bunny_client.session, 'request', return_value=mock_response):
result = bunny_client.add_custom_hostname(67890, "www.example.com")
assert result is True
def test_add_custom_hostname_error(self, bunny_client, mock_response):
"""Test custom hostname addition with error"""
mock_response.status_code = 400
mock_response.json.return_value = {"Message": "Invalid hostname"}
with patch.object(bunny_client.session, 'request', return_value=mock_response):
with pytest.raises(BunnyNetAPIError):
bunny_client.add_custom_hostname(67890, "invalid")
def test_request_timeout(self, bunny_client):
"""Test handling of request timeout"""
with patch.object(bunny_client.session, 'request', side_effect=requests.exceptions.Timeout):
with pytest.raises(BunnyNetAPIError, match="timeout"):
bunny_client.create_storage_zone("test", "DE")
def test_request_connection_error(self, bunny_client):
"""Test handling of connection error"""
with patch.object(bunny_client.session, 'request', side_effect=requests.exceptions.ConnectionError):
with pytest.raises(BunnyNetAPIError, match="Connection error"):
bunny_client.create_storage_zone("test", "DE")
def test_api_error_with_message(self, bunny_client, mock_response):
"""Test API error handling with message in response"""
mock_response.status_code = 500
mock_response.json.return_value = {"Message": "Internal server error"}
with patch.object(bunny_client.session, 'request', return_value=mock_response):
with pytest.raises(BunnyNetAPIError, match="Internal server error"):
bunny_client.create_storage_zone("test", "DE")
def test_empty_response_handling(self, bunny_client, mock_response):
"""Test handling of empty response"""
mock_response.status_code = 204
mock_response.content = b''
with patch.object(bunny_client.session, 'request', return_value=mock_response):
result = bunny_client._make_request("POST", "/test")
assert result == {}