Skip to content

Commit 6d257d0

Browse files
committed
unittest: add unit tests for auto generated apis and follow the idea of ninja-extra's new testing client
1 parent 28e3315 commit 6d257d0

File tree

3 files changed

+78
-28
lines changed

3 files changed

+78
-28
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fmt format: ## Run code formatters
2828
black easy tests
2929

3030
test: ## Run tests
31-
pytest
31+
pytest -s
3232

3333
test-cov: ## Run tests with coverage
3434
pytest --cov=easy --cov-report term

easy/testing/client.py

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,62 @@
1-
from typing import Any, Callable, Dict, Sequence, Type, Union
1+
from json import dumps as json_dumps
2+
from typing import Any, Callable, Dict, List, Sequence, Type, Union, cast
23
from unittest.mock import Mock
4+
from urllib.parse import urlencode
35

6+
from ninja import NinjaAPI, Router
47
from ninja.constants import NOT_SET, NOT_SET_TYPE
5-
from ninja.testing.client import NinjaResponse
8+
from ninja.testing.client import NinjaClientBase, NinjaResponse
69
from ninja_extra import ControllerBase
7-
from ninja_extra.testing.client import NinjaExtraClientBase
810

911
from easy.main import EasyAPI
1012

1113

12-
class EasyAPIClientBase(NinjaExtraClientBase):
14+
class EasyAPIClientBase(NinjaClientBase):
1315
def __init__(
1416
self,
15-
controller_class: Union[Type[ControllerBase], Type],
17+
router_or_app: Union[EasyAPI, Router, Type[ControllerBase]],
1618
auth: Union[
1719
Sequence[Callable[..., Any]], Callable[..., Any], NOT_SET_TYPE, None
1820
] = NOT_SET,
1921
api_cls: Union[Type[EasyAPI], Type] = EasyAPI,
2022
) -> None:
21-
api = api_cls(auth=auth)
22-
assert hasattr(controller_class, "get_api_controller"), "Not a valid object"
23-
controller_ninja_api_controller = controller_class.get_api_controller()
24-
assert controller_ninja_api_controller
25-
controller_ninja_api_controller.set_api_instance(api)
26-
self._urls_cache = list(controller_ninja_api_controller.urls_paths(""))
27-
super(NinjaExtraClientBase, self).__init__(api)
23+
if hasattr(router_or_app, "get_api_controller"):
24+
api = api_cls(auth=auth)
25+
controller_ninja_api_controller = router_or_app.get_api_controller() # type: ignore
26+
assert controller_ninja_api_controller
27+
controller_ninja_api_controller.set_api_instance(api)
28+
self._urls_cache = list(controller_ninja_api_controller.urls_paths(""))
29+
router_or_app = api
30+
super().__init__(cast(Union[NinjaAPI, Router], router_or_app))
31+
32+
def request(
33+
self,
34+
method: str,
35+
path: str,
36+
data: Dict = {},
37+
json: Any = None,
38+
**request_params: Any,
39+
) -> "NinjaResponse":
40+
if json is not None:
41+
request_params["body"] = json_dumps(json)
42+
if "query" in request_params and isinstance(request_params["query"], dict):
43+
query = request_params.pop("query")
44+
url_encode = urlencode(query)
45+
path = f"{path}?{url_encode}"
46+
func, request, kwargs = self._resolve(method, path, data, request_params)
47+
return self._call(func, request, kwargs) # type: ignore
48+
49+
@property
50+
def urls(self) -> List:
51+
if not hasattr(self, "_urls_cache"):
52+
self._urls_cache: List
53+
if isinstance(self.router_or_app, EasyAPI):
54+
self._urls_cache = self.router_or_app.urls[0] # pragma: no cover
55+
else:
56+
api = EasyAPI()
57+
self.router_or_app.set_api_instance(api) # type: ignore
58+
self._urls_cache = list(self.router_or_app.urls_paths("")) # type: ignore
59+
return self._urls_cache
2860

2961

3062
class EasyTestClient(EasyAPIClientBase):

tests/demo_app/test_auto_api_creation.py

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,49 @@
55
api_admin_v1 = EasyAPI()
66
api_admin_v1.auto_create_admin_controllers()
77

8+
path_names = []
9+
controllers = []
10+
controller_names = []
11+
12+
for path, rtr in api_admin_v1._routers:
13+
path_names.append(path)
14+
controllers.append(rtr)
15+
controller_names.append(str(rtr))
16+
for path_ops in rtr.path_operations.values():
17+
for op in path_ops.operations:
18+
assert isinstance(op, AsyncOperation)
19+
assert op.api is api_admin_v1
20+
821

922
def test_auto_generate_admin_api():
1023
assert len(api_admin_v1._routers) == 5 # default + 3 models
11-
path_names = []
12-
controllers = []
13-
for path, rtr in api_admin_v1._routers:
14-
path_names.append(path)
15-
controllers.append(str(rtr))
16-
for path_ops in rtr.path_operations.values():
17-
for op in path_ops.operations:
18-
assert isinstance(op, AsyncOperation)
19-
assert op.api is api_admin_v1
20-
2124
assert "/demo_app/category" in path_names
2225
assert "/demo_app/client" in path_names
2326
assert "/demo_app/event" in path_names
2427
assert "/demo_app/type" in path_names
2528

26-
assert "CategoryAdminAPIController" in controllers
27-
assert "EventAdminAPIController" in controllers
28-
assert "ClientAdminAPIController" in controllers
29-
assert "TypeAdminAPIController" in controllers
29+
assert "CategoryAdminAPIController" in controller_names
30+
assert "EventAdminAPIController" in controller_names
31+
assert "ClientAdminAPIController" in controller_names
32+
assert "TypeAdminAPIController" in controller_names
33+
34+
35+
async def test_auto_apis(transactional_db, easy_api_client):
36+
for controller_class in controllers:
37+
if not str(controller_class).endswith("AdminAPIController"):
38+
continue
39+
client = easy_api_client(controller_class)
40+
response = await client.get(
41+
"/get_all",
42+
query=dict(
43+
maximum=100,
44+
),
45+
)
46+
assert response.status_code == 200
47+
assert response.json()["data"] == []
3048

3149

32-
def test_auto_generation_settings(settings):
50+
async def test_auto_generation_settings(settings):
3351
settings.AUTO_ADMIN_EXCLUDE_APPS = ["tests.demo_app"]
3452
api_admin_v2 = EasyAPI()
3553
api_admin_v2.auto_create_admin_controllers()

0 commit comments

Comments
 (0)