async def test_controller_parameter_name_match(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Example(Controller): @get("/") async def from_query(self, example: str): assert isinstance(self, Example) assert isinstance(example, str) return text(example) @get("/{example}") async def from_route(self, example: str): assert isinstance(self, Example) assert isinstance(example, str) return text(example) app.setup_controllers() await app(get_example_scope("GET", "/"), MockReceive(), MockSend()) assert app.response.status == 400 body = await app.response.text() assert body == "Bad Request: Missing query parameter `example`" await app(get_example_scope("GET", "/foo"), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == "foo"
async def test_handler_through_controller_owned_text_method(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get # noinspection PyUnusedLocal class Home(Controller): def greet(self): return 'Hello World' @get('/') async def index(self, request: Request): assert isinstance(self, Home) return self.text(self.greet()) @get('/foo') async def foo(self): assert isinstance(self, Home) return self.text('foo') app.setup_controllers() await app(get_example_scope('GET', '/'), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == 'Hello World' await app(get_example_scope('GET', '/foo'), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == 'foo'
async def test_controller_with_base_route_as_string_attribute(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Home(Controller): route = "/home" def greet(self): return "Hello World" @get() async def index(self, request: Request): assert isinstance(self, Home) return text(self.greet()) app.setup_controllers() await app(get_example_scope("GET", "/"), MockReceive(), MockSend()) assert app.response.status == 404 await app(get_example_scope("GET", "/home"), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == "Hello World" await app(get_example_scope("GET", "/home/"), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == "Hello World"
async def test_many_controllers(value): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Settings: def __init__(self, greetings: str): self.greetings = greetings class Home(Controller): def __init__(self, settings: Settings): self.settings = settings def greet(self): return self.settings.greetings @get("/") async def index(self, request: Request): return text(self.greet()) class Foo(Controller): @get("/foo") async def foo(self, request: Request): return text("foo") app.services.add_instance(Settings(value)) app.setup_controllers() await app(get_example_scope("GET", "/"), MockReceive(), MockSend()) body = await app.response.text() assert body == value assert app.response.status == 200
async def test_controllers_with_duplicate_routes_throw(first_pattern, second_pattern): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get class A(Controller): @get(first_pattern) async def index(self, request: Request): ... class B(Controller): @get(second_pattern) async def index(self, request: Request): ... with pytest.raises(RouteDuplicate) as context: app.use_controllers() error = context.value assert "Cannot register route pattern `" + ensure_str( first_pattern) + "` for `GET` more than once." in str(error) assert ("This pattern is already registered for handler " "test_controllers_with_duplicate_routes_throw.<locals>.A.index." in str(error))
async def test_controller_with_base_route_as_string_attribute(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get # noinspection PyUnusedLocal class Home(Controller): route = '/home' def greet(self): return 'Hello World' @get() async def index(self, request: Request): assert isinstance(self, Home) return text(self.greet()) app.setup_controllers() await app(get_example_scope('GET', '/'), MockReceive(), MockSend()) assert app.response.status == 404 await app(get_example_scope('GET', '/home'), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == 'Hello World' await app(get_example_scope('GET', '/home/'), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == 'Hello World'
async def test_controller_return_file(): file_path = get_file_path("example.config", "files2") app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Example(Controller): @get("/") async def home(self): return self.file(file_path, "text/plain; charset=utf-8") app.setup_controllers() await app( get_example_scope("GET", "/", []), MockReceive(), MockSend(), ) response = app.response assert response.status == 200 assert response.headers.get_single( b"content-type") == b"text/plain; charset=utf-8" assert response.headers.get_single(b"content-disposition") == b"attachment" text = await response.text() with open(file_path, mode="rt", encoding="utf8") as f: contents = f.read() assert contents == text
async def test_handler_through_controller_owned_text_method(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Home(Controller): def greet(self): return "Hello World" @get("/") async def index(self, request: Request): assert isinstance(self, Home) return self.text(self.greet()) @get("/foo") async def foo(self): assert isinstance(self, Home) return self.text("foo") app.setup_controllers() await app(get_example_scope("GET", "/"), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == "Hello World" await app(get_example_scope("GET", "/foo"), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == "foo"
async def test_controller_with_base_route_as_class_method_fragments(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Api(Controller): @classmethod def route(cls): return "/api/" + cls.__name__.lower() class Home(Api): def greet(self): return "Hello World" @get() async def index(self, request: Request): assert isinstance(self, Home) return text(self.greet()) class Health(Api): @get() def alive(self): return text("Good") app.setup_controllers() await app(get_example_scope("GET", "/api/home"), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == "Hello World" for value in {"/api/Health", "/api/health"}: await app(get_example_scope("GET", value), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == "Good"
async def test_controller_with_dependency(value): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Settings: def __init__(self, greetings: str): self.greetings = greetings # noinspection PyUnusedLocal class Home(Controller): def __init__(self, settings: Settings): assert isinstance(settings, Settings) self.settings = settings def greet(self): return self.settings.greetings @get('/') async def index(self, request: Request): return text(self.greet()) app.services.add_instance(Settings(value)) app.setup_controllers() await app(get_example_scope('GET', '/'), MockReceive(), MockSend()) body = await app.response.text() assert body == value assert app.response.status == 200
async def test_controller_specific_view_name_async_no_model(): app, _ = get_app(True) app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Lorem(Controller): @get() async def index(self): return await self.view_async("nomodel") app.setup_controllers() await _home_scenario(app, expected_text=nomodel_text)
async def test_controller_conventional_view_name_async(home_model): app, _ = get_app(True) app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Lorem(Controller): @get() async def index(self): return await self.view_async(model=home_model) app.setup_controllers() await _home_scenario(app)
async def test_handler_catch_all_through_controller(path_one, path_two): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Home(Controller): def greet(self): return "Hello World" @get(path_one) async def catch_all(self, filepath: str): assert isinstance(self, Home) assert isinstance(filepath, str) return text(filepath) @get(path_two) async def catch_all_under_example(self, filepath: str): assert isinstance(self, Home) assert isinstance(filepath, str) return text(f"Example: {filepath}") @get("/foo") async def foo(self): assert isinstance(self, Home) return text("foo") app.setup_controllers() await app(get_example_scope("GET", "/hello.js"), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == "hello.js" await app(get_example_scope("GET", "/scripts/a/b/c/hello.js"), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == "scripts/a/b/c/hello.js" await app(get_example_scope("GET", "/example/a/b/c/hello.js"), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == "Example: a/b/c/hello.js" await app(get_example_scope("GET", "/foo"), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == "foo"
async def test_controller_specific_view_name(home_model, specific_text): app, _ = get_app(False) app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Lorem(Controller): @get() def index(self): return self.view("specific", home_model) app.setup_controllers() await _home_scenario(app, expected_text=specific_text)
async def test_controller_specific_view_name_async(home_model, specific_text): app, _ = get_app(True) app.controllers_router = RoutesRegistry() get = app.controllers_router.get # noinspection PyUnusedLocal class Lorem(Controller): @get() async def index(self): return await self.view_async('specific', model=home_model) app.setup_controllers() await _home_scenario(app, expected_text=specific_text)
async def test_controller_conventional_view_name_no_model(home_model): app, _ = get_app(False) app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Lorem(Controller): @get(...) def nomodel(self): return self.view() app.setup_controllers() await _home_scenario(app, "/nomodel", expected_text=nomodel_text)
async def test_controller_conventional_view_name_no_model(home_model): app, _ = get_app(False) app.controllers_router = RoutesRegistry() get = app.controllers_router.get # noinspection PyUnusedLocal class Lorem(Controller): @get(...) def nomodel(self): return self.view() app.setup_controllers() await _home_scenario(app, '/nomodel')
async def test_handler_through_controller_default_type(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Home(Controller): @get("/") async def index(self) -> Foo: return Foo("Hello", 5.5) app.setup_controllers() await app(get_example_scope("GET", "/"), MockReceive(), MockSend()) assert app.response.status == 200 data = await app.response.json() assert data == {"name": "Hello", "value": 5.5}
async def test_application_raises_for_controllers_for_invalid_services(): app = FakeApplication(services=Services()) app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Home(Controller): def greet(self): return "Hello World" @get() async def index(self, request: Request): assert isinstance(self, Home) return text(self.greet()) with pytest.raises(RequiresServiceContainerError): app.setup_controllers()
async def test_handler_through_controller_default_str(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Home(Controller): @get("/") async def index(self) -> str: return "Hello World" app.setup_controllers() await app(get_example_scope("GET", "/"), MockReceive(), MockSend()) assert app.response.status == 200 data = await app.response.text() assert data == "Hello World"
async def test_api_controller_with_version(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get post = app.controllers_router.post delete = app.controllers_router.delete patch = app.controllers_router.patch class Cat(ApiController): @classmethod def version(cls) -> Optional[str]: return "v1" @get(":cat_id") def get_cat(self, cat_id: str): return text("1") @patch() def update_cat(self): return text("2") @post() def create_cat(self): return text("3") @delete(":cat_id") def delete_cat(self): return text("4") app.setup_controllers() expected_result = { ("GET", "/api/v1/cat/100"): "1", ("PATCH", "/api/v1/cat"): "2", ("POST", "/api/v1/cat"): "3", ("DELETE", "/api/v1/cat/100"): "4", } for key, value in expected_result.items(): method, pattern = key await app(get_example_scope(method, pattern), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == value
async def test_controller_model_interop(model_fixture): app, _ = get_app(False) app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Lorem(Controller): @get() def index(self): return self.view("hello", model_fixture()) app.setup_controllers() await _view_scenario( app, expected_text='<div style="margin: 10em 2em;">\n <h1>Hello, World!!</h1>\n\n' + ' <ul>\n \n <li><a href="https://github.com/Neoteroi/' + 'BlackSheep">Check this out!</a></li>\n \n </ul>\n</div>', )
async def test_controller_supports_on_response(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get k = 0 # noinspection PyUnusedLocal class Home(Controller): def greet(self): return 'Hello World' async def on_response(self, response: Response): nonlocal k k += 1 assert isinstance(response, Response) if response.content.body == b'Hello World': assert k < 10 else: assert k >= 10 return await super().on_response(response) @get('/') async def index(self, request: Request): assert isinstance(self, Home) return text(self.greet()) @get('/foo') async def foo(self): assert isinstance(self, Home) return text('foo') app.setup_controllers() for j in range(1, 10): await app(get_example_scope('GET', '/'), MockReceive(), MockSend()) assert app.response.status == 200 assert k == j for j in range(10, 20): await app(get_example_scope('GET', '/foo'), MockReceive(), MockSend()) assert app.response.status == 200 assert k == j
async def test_api_controller_with_version(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get post = app.controllers_router.post delete = app.controllers_router.delete patch = app.controllers_router.patch # noinspection PyUnusedLocal class Cat(ApiController): @classmethod def version(cls) -> Optional[str]: return 'v1' @get(':cat_id') def get_cat(self, cat_id: str): return text('1') @patch() def update_cat(self): return text('2') @post() def create_cat(self): return text('3') @delete(':cat_id') def delete_cat(self): return text('4') app.setup_controllers() expected_result = { ('GET', '/api/v1/cat/100'): '1', ('PATCH', '/api/v1/cat'): '2', ('POST', '/api/v1/cat'): '3', ('DELETE', '/api/v1/cat/100'): '4', } for key, value in expected_result.items(): method, pattern = key await app(get_example_scope(method, pattern), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == value
async def test_application_raises_for_invalid_route_class_attribute(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Home(Controller): route = False def greet(self): return "Hello World" @get() async def index(self, request: Request): assert isinstance(self, Home) return text(self.greet()) with pytest.raises(RuntimeError): app.setup_controllers()
async def test_controller_conventional_view_name_sub_function(home_model): app, _ = get_app(False) app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Lorem(Controller): def ufo(self, model): return self.foo(model) def foo(self, model): return self.view(model=model) @get() def index(self): return self.ufo(home_model) app.setup_controllers() await _home_scenario(app)
async def test_controller_with_duplicate_route_with_base_route_throw(first_pattern, second_pattern): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get # NB: this test creates ambiguity between the full route of a controller handler, # and another handler # noinspection PyUnusedLocal class A(Controller): route = 'home' @get(first_pattern) async def index(self, request: Request): ... @app.route(second_pattern) async def home(): ... with pytest.raises(RouteDuplicate): app.use_controllers()
async def test_controller_with_base_route_as_class_method_fragments(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Api(Controller): @classmethod def route(cls): return '/api/' + cls.__name__.lower() # noinspection PyUnusedLocal class Home(Api): def greet(self): return 'Hello World' @get() async def index(self, request: Request): assert isinstance(self, Home) return text(self.greet()) # noinspection PyUnusedLocal class Health(Api): @get() def alive(self): return text('Good') app.setup_controllers() await app(get_example_scope('GET', '/api/home'), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == 'Hello World' for value in {'/api/Health', '/api/health'}: await app(get_example_scope('GET', value), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert body == 'Good'
async def test_controller_supports_on_request(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get k = 0 class Home(Controller): def greet(self): return "Hello World" async def on_request(self, request: Request): nonlocal k k += 1 assert isinstance(request, Request) assert request.url.path == b"/" if k < 10 else b"/foo" return await super().on_request(request) @get("/") async def index(self, request: Request): assert isinstance(self, Home) return text(self.greet()) @get("/foo") async def foo(self): assert isinstance(self, Home) return text("foo") app.setup_controllers() for j in range(1, 10): await app(get_example_scope("GET", "/"), MockReceive(), MockSend()) assert app.response.status == 200 assert k == j for j in range(10, 20): await app(get_example_scope("GET", "/foo"), MockReceive(), MockSend()) assert app.response.status == 200 assert k == j
async def test_handler_through_controller_owned_html_method(): app = FakeApplication() app.controllers_router = RoutesRegistry() get = app.controllers_router.get class Home(Controller): @get("/") async def index(self): assert isinstance(self, Home) return self.html(""" <h1>Title</h1> <p>Lorem ipsum</p> """) app.setup_controllers() await app(get_example_scope("GET", "/"), MockReceive(), MockSend()) assert app.response.status == 200 body = await app.response.text() assert "<h1>Title</h1>" in body assert "<p>Lorem ipsum</p>" in body assert app.response.content_type() == b"text/html; charset=utf-8"