204 lines
8.2 KiB
Python
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 == {}
|
|
|