Skip to content

Commit a7f24c1

Browse files
committed
Fixed and added more test
1 parent cd1befa commit a7f24c1

File tree

7 files changed

+56
-80
lines changed

7 files changed

+56
-80
lines changed

tests/test_application/test_application_functions.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import os
22
import typing as t
33

4-
import pytest
54
from starlette.responses import JSONResponse, PlainTextResponse, Response
65

76
from ellar.common import Module, get, template_filter, template_global
@@ -15,7 +14,7 @@
1514
TestClientFactory,
1615
)
1716
from ellar.core.connection import Request
18-
from ellar.core.context import IExecutionContext, IHostContext
17+
from ellar.core.context import IExecutionContext
1918
from ellar.core.events import EventHandler
2019
from ellar.core.exceptions.interfaces import IExceptionHandler
2120
from ellar.core.modules import ModuleTemplateRef
@@ -292,14 +291,6 @@ def test_app_initialization_completion(self):
292291
assert injector.get(Reflector)
293292
assert injector.get(Config) is config
294293
assert injector.get(Environment) is app.jinja_environment
295-
with pytest.raises(
296-
Exception, match="Service Unavailable at the current context."
297-
):
298-
injector.get(IExecutionContext)
299-
with pytest.raises(
300-
Exception, match="Service Unavailable at the current context."
301-
):
302-
injector.get(IHostContext)
303294

304295
def test_app_exception_handler(self):
305296
class CustomException(Exception):

tests/test_application/test_replacing_app_services.py

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
from starlette.responses import PlainTextResponse
33

44
from ellar.common import Controller, Module, exception_handler, get
5-
from ellar.constants import ASGI_CONTEXT_VAR
65
from ellar.core import TestClientFactory
76
from ellar.core.context import (
87
ExecutionContext,
@@ -15,7 +14,6 @@
1514
from ellar.core.exceptions import IExceptionMiddlewareService
1615
from ellar.core.exceptions.service import ExceptionMiddlewareService
1716
from ellar.di import ProviderConfig, injectable
18-
from ellar.di.exceptions import ServiceUnavailable
1917
from ellar.services import Reflector
2018

2119

@@ -42,35 +40,23 @@ class NewExecutionHostFactory(IExecutionContextFactory):
4240
def __init__(self, reflector: Reflector):
4341
self.reflector = reflector
4442

45-
def create_context(self, operation, scope, receive, send) -> IExecutionContext:
46-
scoped_request_args = ASGI_CONTEXT_VAR.get()
47-
48-
if not scoped_request_args:
49-
raise ServiceUnavailable()
50-
43+
def create_context(
44+
self, operation, scope, receive=None, send=None
45+
) -> IExecutionContext:
5146
i_execution_context = NewExecutionContext(
5247
scope=scope,
5348
receive=receive,
5449
send=send,
5550
operation_handler=operation.endpoint,
5651
reflector=self.reflector,
5752
)
58-
i_execution_context.get_service_provider().update_scoped_context(
59-
IExecutionContext, i_execution_context
60-
)
6153

6254
return i_execution_context
6355

6456

6557
@injectable()
6658
class NewHostContextFactory(IHostContextFactory):
67-
def create_context(self) -> IHostContext:
68-
scoped_request_args = ASGI_CONTEXT_VAR.get()
69-
70-
if not scoped_request_args:
71-
raise ServiceUnavailable()
72-
73-
scope, receive, send = scoped_request_args.get_args()
59+
def create_context(self, scope, receive=None, send=None) -> IHostContext:
7460
host_context = NewHostContext(scope=scope, receive=receive, send=send)
7561
host_context.get_service_provider().update_scoped_context(
7662
IHostContext, host_context
@@ -98,9 +84,8 @@ def test_can_replace_host_context():
9884

9985
assert hasattr(NewHostContext, "worked") is False
10086
client = tm.get_client()
101-
res = client.get("/example/")
102-
assert res.status_code == 200
103-
assert res.text == '"ExecutionContext"'
87+
res = client.get("/example/exception")
88+
assert res.json() == {"detail": "Bad Request", "status_code": 400}
10489

10590
assert hasattr(NewHostContext, "worked") is True
10691
assert NewHostContext.worked is True

tests/test_di/test_injector.py

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from injector import Binder, Injector, UnsatisfiedRequirement
55

66
from ellar.common import Module
7-
from ellar.constants import ASGI_CONTEXT_VAR, MODULE_REF_TYPES
7+
from ellar.constants import MODULE_REF_TYPES, SCOPED_CONTEXT_VAR
88
from ellar.core import Config, ModuleBase
99
from ellar.core.modules.ref import create_module_ref_factor
1010
from ellar.di import Container, EllarInjector
@@ -67,16 +67,8 @@ async def test_request_service_context():
6767
injector.container.register_scoped(Foo1)
6868
injector.container.register_exact_transient(Foo2)
6969

70-
def assert_attributes():
71-
asgi_context_var = ASGI_CONTEXT_VAR.get()
72-
assert len(asgi_context_var.context) == 0
73-
assert len(asgi_context_var.scope) == 0
74-
assert asgi_context_var.receive is None
75-
assert asgi_context_var.send is None
76-
77-
async with injector.create_asgi_args({}, None, None):
78-
assert_attributes()
79-
asgi_context = ASGI_CONTEXT_VAR.get()
70+
async with injector.create_asgi_args():
71+
asgi_context = SCOPED_CONTEXT_VAR.get()
8072

8173
foo1 = injector.get(Foo1) # result will be tracked by asgi_context
8274
injector.get(Foo2) # registered as transient scoped
@@ -101,8 +93,8 @@ def assert_attributes():
10193
async def test_injector_update_scoped_context():
10294
injector = EllarInjector(auto_bind=False)
10395

104-
async with injector.create_asgi_args({}, None, None):
105-
asgi_context = ASGI_CONTEXT_VAR.get()
96+
async with injector.create_asgi_args():
97+
asgi_context = SCOPED_CONTEXT_VAR.get()
10698

10799
injector.update_scoped_context(Foo1, Foo1())
108100
injector.update_scoped_context(Foo, ClassProvider(Foo))
@@ -111,7 +103,7 @@ async def test_injector_update_scoped_context():
111103
assert isinstance(asgi_context.context[Foo], ClassProvider)
112104

113105
injector.update_scoped_context(Foo1, Foo1())
114-
assert ASGI_CONTEXT_VAR.get() is None
106+
assert SCOPED_CONTEXT_VAR.get() is None
115107

116108

117109
class TestInjectorModuleFunctions:

tests/test_di/test_middleware.py

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33
import pytest
44

55
from ellar.constants import SCOPE_SERVICE_PROVIDER
6-
from ellar.core.connection import HTTPConnection, Request, WebSocket
7-
from ellar.core.context import HostContextException, IHostContext
6+
from ellar.core.context import HostContextException, IHostContextFactory
87
from ellar.core.middleware import RequestServiceProviderMiddleware
9-
from ellar.core.response import Response
108
from ellar.core.services import CoreServiceRegistration
119
from ellar.di import EllarInjector
1210

@@ -40,27 +38,14 @@ async def assert_iexecute_context_app(scope, receive, send):
4038
assert scope[SCOPE_SERVICE_PROVIDER]
4139

4240
service_provider = scope[SCOPE_SERVICE_PROVIDER]
43-
host_context: IHostContext = service_provider.get(IHostContext)
44-
assert (
45-
service_provider.get(HTTPConnection)
46-
is host_context.switch_to_http_connection().get_client()
41+
host_context_factory: IHostContextFactory = service_provider.get(
42+
IHostContextFactory
4743
)
48-
assert (
49-
service_provider.get(Request)
50-
is host_context.switch_to_http_connection().get_request()
51-
)
52-
assert (
53-
service_provider.get(Response)
54-
is host_context.switch_to_http_connection().get_response()
55-
)
56-
assert service_provider is host_context.get_service_provider()
44+
host_context = host_context_factory.create_context(scope, receive, send)
5745

5846
with pytest.raises(HostContextException):
5947
host_context.switch_to_websocket()
6048

61-
with pytest.raises(HostContextException):
62-
service_provider.get(WebSocket)
63-
6449
await send(
6550
{
6651
"type": "http.response.start",
@@ -80,22 +65,19 @@ async def assert_iexecute_context_app_websocket(scope, receive, send):
8065
assert scope[SCOPE_SERVICE_PROVIDER]
8166

8267
service_provider = scope[SCOPE_SERVICE_PROVIDER]
83-
host_context: IHostContext = service_provider.get(IHostContext)
68+
host_context_factory: IHostContextFactory = service_provider.get(
69+
IHostContextFactory
70+
)
71+
host_context = host_context_factory.create_context(scope, receive, send)
8472

8573
websocket = host_context.switch_to_websocket().get_client()
86-
assert service_provider.get(WebSocket) is websocket
8774
assert service_provider is host_context.get_service_provider()
8875

89-
assert (
90-
service_provider.get(HTTPConnection)
91-
is host_context.switch_to_http_connection().get_client()
92-
)
93-
9476
with pytest.raises(HostContextException):
95-
service_provider.get(Request)
77+
host_context.switch_to_http_connection().get_request()
9678

9779
with pytest.raises(HostContextException):
98-
service_provider.get(Response)
80+
host_context.switch_to_http_connection().get_response()
9981

10082
await websocket.accept()
10183
await websocket.send_text("Hello, world!")

tests/test_di/test_provider_scopes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,6 @@ async def test_request_scope_instance():
4141
# resolving RequestScope Providers outside RequestServiceProvider will behave like TransientScope
4242
assert injector.get(IContext) != injector.get(IContext)
4343
assert isinstance(injector.get(IContext), AnyContext)
44-
async with injector.create_asgi_args({}, None, None) as request_provider:
44+
async with injector.create_asgi_args() as request_provider:
4545
# resolving RequestScope during request will behave like singleton
4646
assert request_provider.get(IContext) == request_provider.get(IContext)

tests/test_exceptions/test_validation_exception.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import pytest
22
from pydantic.error_wrappers import ErrorWrapper
33

4-
from ellar.common import Ws, get, ws_route
4+
from ellar.common import Ws, WsBody, get, ws_route
55
from ellar.core import TestClientFactory
66
from ellar.core.exceptions.validation import (
77
RequestValidationError,
@@ -20,12 +20,18 @@ def exception_http():
2020
_exception_runner.run()
2121

2222

23-
@ws_route("/exception-Ws", use_extra_handler=True)
23+
@ws_route("/exception-Ws", use_extra_handler=False)
2424
async def exception_ws(websocket=Ws()):
2525
_exception_runner.run()
2626

2727

28-
test_module.app.router.extend([exception_http, exception_ws])
28+
@ws_route("/exception-Ws-2", use_extra_handler=True)
29+
async def exception_ws_2(*, websocket=Ws(), data: dict = WsBody()):
30+
assert data == {"hello": "world"}
31+
_exception_runner.run()
32+
33+
34+
test_module.app.router.extend([exception_http, exception_ws_2, exception_ws])
2935
client = test_module.get_client()
3036

3137

@@ -81,3 +87,23 @@ def test_websocket_validation_error():
8187
{"loc": ("form",), "msg": "Invalid Request", "type": "value_error.exception"},
8288
{"loc": ("model",), "msg": "Invalid Request", "type": "value_error.exception"},
8389
]
90+
91+
92+
def test_websocket_validation_error_2():
93+
global _exception_runner
94+
_exception_runner = ExceptionRunner(
95+
WebSocketRequestValidationError,
96+
errors=[
97+
ErrorWrapper(Exception("Invalid Request"), loc="body"),
98+
ErrorWrapper(Exception("Invalid Request"), loc="form"),
99+
ErrorWrapper(Exception("Invalid Request"), loc="model"),
100+
],
101+
)
102+
with pytest.raises(WebSocketRequestValidationError) as wex:
103+
with client.websocket_connect("/exception-Ws-2") as websocket:
104+
websocket.send_json({"hello": "world"})
105+
assert wex.value.errors() == [
106+
{"loc": ("body",), "msg": "Invalid Request", "type": "value_error.exception"},
107+
{"loc": ("form",), "msg": "Invalid Request", "type": "value_error.exception"},
108+
{"loc": ("model",), "msg": "Invalid Request", "type": "value_error.exception"},
109+
]

tests/test_routing/test_extra_args.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from starlette.responses import Response
44

5-
from ellar.common import Provide, Query, get, set_metadata
5+
from ellar.common import Context, Query, Res, get, set_metadata
66
from ellar.constants import EXTRA_ROUTE_ARGS_KEY
77
from ellar.core import TestClientFactory
88
from ellar.core.connection import Request
@@ -41,10 +41,10 @@ def _wrapper(*args, **kwargs):
4141
def add_extra_non_field_extra_args(func):
4242
# EXTRA ARGS SETUP
4343
context = ExtraEndpointArg(
44-
name="context", annotation=IExecutionContext, default_value=Provide()
44+
name="context", annotation=IExecutionContext, default_value=Context()
4545
)
4646
response = ExtraEndpointArg(
47-
name="response", annotation=Response, default_value=Provide()
47+
name="response", annotation=Response, default_value=Res()
4848
)
4949

5050
set_metadata(EXTRA_ROUTE_ARGS_KEY, response)(func)

0 commit comments

Comments
 (0)