Skip to content

Commit 4ed96d3

Browse files
committed
refactor test fixtures and expand test coverage
1 parent 2ae43a5 commit 4ed96d3

3 files changed

Lines changed: 56 additions & 31 deletions

File tree

src/tests/conftest.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
from collections.abc import AsyncGenerator
2+
13
import pytest
24

5+
from bubble_data_api_client import configure
6+
from bubble_data_api_client.pool import close_clients
7+
38

49
@pytest.fixture
510
def test_url() -> str:
@@ -9,3 +14,21 @@ def test_url() -> str:
914
@pytest.fixture
1015
def test_api_key() -> str:
1116
return "123"
17+
18+
19+
@pytest.fixture
20+
async def clean_client_pool() -> AsyncGenerator[None]:
21+
"""Ensure client pool is clean before and after each test."""
22+
await close_clients()
23+
yield
24+
await close_clients()
25+
26+
27+
@pytest.fixture
28+
def configured_client(clean_client_pool: None, test_url: str, test_api_key: str) -> None:
29+
"""Configure the client for testing."""
30+
configure(
31+
data_api_root_url=test_url,
32+
api_key=test_api_key,
33+
retry=None,
34+
)

src/tests/unit/client/test_orm.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
import json
2+
3+
import httpx
4+
import respx
5+
from pydantic import Field
6+
17
from bubble_data_api_client.client.orm import BubbleBaseModel
28

39

@@ -12,3 +18,21 @@ class User(BubbleBaseModel, typename="user"):
1218

1319
assert user.uid == "12345"
1420
assert user.name == "testuser"
21+
22+
23+
@respx.mock
24+
async def test_save_uses_field_aliases(configured_client: None) -> None:
25+
"""Verify save() sends Bubble aliases, not Python field names."""
26+
27+
class Order(BubbleBaseModel, typename="order"):
28+
company: str = Field(alias="Buying company")
29+
30+
order = Order(**{"Buying company": "Acme Corp", "_id": "abc123"})
31+
32+
route = respx.patch("https://example.com/order/abc123").mock(return_value=httpx.Response(204))
33+
34+
await order.save()
35+
36+
assert route.call_count == 1
37+
request_body = json.loads(route.calls[0].request.content)
38+
assert request_body == {"Buying company": "Acme Corp"}

src/tests/unit/client/test_raw_client.py

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,8 @@
1-
from collections.abc import AsyncGenerator
2-
31
import httpx
42
import pytest
53
import respx
64

7-
from bubble_data_api_client import configure
85
from bubble_data_api_client.client import raw_client
9-
from bubble_data_api_client.pool import close_clients
10-
11-
12-
@pytest.fixture
13-
async def clean_client_pool() -> AsyncGenerator[None]:
14-
"""Ensure client pool is clean before and after each test."""
15-
await close_clients()
16-
yield
17-
await close_clients()
18-
19-
20-
@pytest.fixture
21-
def configured_client(clean_client_pool: None) -> None:
22-
"""Configure the client for testing."""
23-
configure(
24-
data_api_root_url="https://test.example.com",
25-
api_key="test-key",
26-
retry=None,
27-
)
286

297

308
async def test_raw_client_init() -> None:
@@ -45,7 +23,7 @@ async def test_raw_client_init() -> None:
4523
@respx.mock
4624
async def test_replace(configured_client: None) -> None:
4725
"""Test that replace uses PUT to fully replace a thing."""
48-
route = respx.put("https://test.example.com/customer/123x456").mock(return_value=httpx.Response(204))
26+
route = respx.put("https://example.com/customer/123x456").mock(return_value=httpx.Response(204))
4927

5028
async with raw_client.RawClient() as client:
5129
response = await client.replace(
@@ -61,7 +39,7 @@ async def test_replace(configured_client: None) -> None:
6139
@respx.mock
6240
async def test_bulk_create(configured_client: None) -> None:
6341
"""Test that bulk_create posts newline-delimited JSON."""
64-
route = respx.post("https://test.example.com/customer/bulk").mock(
42+
route = respx.post("https://example.com/customer/bulk").mock(
6543
return_value=httpx.Response(200, json={"status": "success", "count": 2})
6644
)
6745

@@ -81,7 +59,7 @@ async def test_bulk_create(configured_client: None) -> None:
8159
@respx.mock
8260
async def test_find_with_parameters(configured_client: None) -> None:
8361
"""Test that find passes optional parameters correctly."""
84-
route = respx.get("https://test.example.com/customer").mock(
62+
route = respx.get("https://example.com/customer").mock(
8563
return_value=httpx.Response(200, json={"response": {"results": [], "count": 0, "remaining": 0}})
8664
)
8765

@@ -107,7 +85,7 @@ async def test_find_with_parameters(configured_client: None) -> None:
10785
@respx.mock
10886
async def test_find_with_additional_sort_fields(configured_client: None) -> None:
10987
"""Test that find passes additional_sort_fields correctly."""
110-
route = respx.get("https://test.example.com/customer").mock(
88+
route = respx.get("https://example.com/customer").mock(
11189
return_value=httpx.Response(200, json={"response": {"results": [], "count": 0, "remaining": 0}})
11290
)
11391

@@ -125,7 +103,7 @@ async def test_find_with_additional_sort_fields(configured_client: None) -> None
125103
@respx.mock
126104
async def test_count(configured_client: None) -> None:
127105
"""Test that count returns total from count + remaining."""
128-
respx.get("https://test.example.com/customer").mock(
106+
respx.get("https://example.com/customer").mock(
129107
return_value=httpx.Response(200, json={"response": {"results": [], "count": 5, "remaining": 95}})
130108
)
131109

@@ -138,7 +116,7 @@ async def test_count(configured_client: None) -> None:
138116
@respx.mock
139117
async def test_exists_by_uid_found(configured_client: None) -> None:
140118
"""Test exists returns True when record found by uid."""
141-
respx.get("https://test.example.com/customer/123x456").mock(
119+
respx.get("https://example.com/customer/123x456").mock(
142120
return_value=httpx.Response(200, json={"response": {"_id": "123x456"}})
143121
)
144122

@@ -151,7 +129,7 @@ async def test_exists_by_uid_found(configured_client: None) -> None:
151129
@respx.mock
152130
async def test_exists_by_uid_not_found(configured_client: None) -> None:
153131
"""Test exists returns False when record not found by uid."""
154-
respx.get("https://test.example.com/customer/123x456").mock(
132+
respx.get("https://example.com/customer/123x456").mock(
155133
return_value=httpx.Response(404, json={"status": "NOT_FOUND"})
156134
)
157135

@@ -164,7 +142,7 @@ async def test_exists_by_uid_not_found(configured_client: None) -> None:
164142
@respx.mock
165143
async def test_exists_by_uid_error_reraises(configured_client: None) -> None:
166144
"""Test exists re-raises non-404 HTTP errors."""
167-
respx.get("https://test.example.com/customer/123x456").mock(
145+
respx.get("https://example.com/customer/123x456").mock(
168146
return_value=httpx.Response(500, json={"error": "server error"})
169147
)
170148

@@ -178,7 +156,7 @@ async def test_exists_by_uid_error_reraises(configured_client: None) -> None:
178156
@respx.mock
179157
async def test_exists_by_constraints(configured_client: None) -> None:
180158
"""Test exists with constraints uses find."""
181-
respx.get("https://test.example.com/customer").mock(
159+
respx.get("https://example.com/customer").mock(
182160
return_value=httpx.Response(200, json={"response": {"results": [{"_id": "1x1"}], "count": 1, "remaining": 0}})
183161
)
184162

0 commit comments

Comments
 (0)