async def test_error_middleware( path: str, method: str, body: str, expected_response_body: str, expected_response_status_code: int, ): app = Baguette(error_include_description=False) @app.route("/") async def index(request): return await request.body() @app.route("/user/<user_id:int>") async def user(user_id: int): return str(user_id) @app.route("/notimplemented") async def notimplemented(): raise NotImplemented() # noqa: F901 @app.route("/error") async def error(): raise Exception() request = create_test_request(path=path, method=method, body=body) response = await app.handle_request(request) assert response.body == expected_response_body assert response.status_code == expected_response_status_code
def test_app_run(): app = Baguette() running = threading.Event() async def set_running(): running.set() def do_request(): if not running.wait(10.0): raise TimeoutError("App hasn't started after 10s") requests.get("http://127.0.0.1:8080") request_thread = threading.Thread(target=do_request) request_thread.start() app.run( host="127.0.0.1", port=8080, debug=True, limit_max_requests=1, # end after one request callback_notify=set_running, timeout_notify=1, # set the running event every second ) request_thread.join()
def create_test_request( path: str = "/", method: str = "GET", headers={ "server": "baguette", "content-type": "text/plain; charset=utf-8" }, querystring: str = "a=b", body: str = "", json=None, ): request = Request( Baguette(), create_http_scope( path=path, method=method, headers=headers, querystring=querystring, ), Receive(), ) request._body = body if json is not None: request._json = json return request
async def test_app_add_remove_middleware(): app = Baguette() @app.route("/short") async def short(): return "" @app.route("/long") async def long(): await asyncio.sleep(0.2) return "" assert len(app.middlewares) == 2 app.add_middleware(TimingMiddleware) assert len(app.middlewares) == 3 request = create_test_request(path="/short") response = await app.handle_request(request) assert "X-time" in response.headers short_time = float(response.headers["X-time"]) request = create_test_request(path="/long") response = await app.handle_request(request) assert "X-time" in response.headers long_time = float(response.headers["X-time"]) assert short_time < long_time app.remove_middleware(TimingMiddleware) assert len(app.middlewares) == 2
async def test_app_call_error(): app = Baguette() scope = {"type": "nonexistent"} receive = Receive() send = Send() with pytest.raises(NotImplementedError): await app(scope, receive, send)
async def test_default_headers_middleware(headers, expected_headers): app = Baguette(default_headers={"server": "baguette"}) @app.route("/") async def index(request): return Response(body="", headers=request.headers) request = create_test_request(headers=headers) response = await app.handle_request(request) assert response.headers == expected_headers
async def test_app_call(scope, receive: Receive, expected_sent_values: list): app = Baguette() @app.route("/") async def index(request): return PlainTextResponse(await request.body()) send = Send() await app(scope, receive, send) assert len(expected_sent_values) == len(send.values) for message in send.values: assert message == expected_sent_values.pop(0)
def test_app_route(setup, expected_attributes: dict): app = Baguette() handler = setup(app) router = app.router.routes.pop() while (not router.handler_is_class and router.handler != handler) or ( router.handler_is_class and not isinstance(router.handler, handler)): router = app.router.routes.pop() for name, value in expected_attributes.items(): assert getattr(router, name) == value
async def test_app_render(): app = Baguette(templates_directory="tests/templates") @app.route("/template") async def template(): return await render( "index.html", paragraphs=["1st paragraph", "2nd paragraph"], ) app = TestClient(app) response: HTMLResponse = await app.get("/template") assert strip(response.body) == strip(expected_html)
def test_create_app(): app = Baguette() assert app.debug is False assert isinstance(app.router, Router) assert isinstance(app.default_headers, Headers) assert app.error_response_type == "plain" assert app.error_include_description is True app = Baguette( debug=True, default_headers={"server": "baguette"}, error_response_type="json", error_include_description=False, ) assert app.debug is True assert isinstance(app.router, Router) assert isinstance(app.default_headers, Headers) assert app.default_headers["server"] == "baguette" assert app.error_response_type == "json" assert app.error_include_description is True # True because debug=True with pytest.raises(ValueError): Baguette(error_response_type="nonexistent")
async def test_app_middleware(): app = Baguette() @app.route("/short") async def short(): return "" @app.route("/long") async def long(): await asyncio.sleep(0.2) return "" assert len(app.middlewares) == 2 @app.middleware() class TimingMiddleware(Middleware): async def __call__(self, request: Request): start_time = time.perf_counter() response = await self.next(request) response.headers["X-time"] = str(time.perf_counter() - start_time) return response assert len(app.middlewares) == 3 @app.middleware() async def timing_middleware(next_middleware, request: Request): start_time = time.time() response = await next_middleware(request) process_time = time.time() - start_time response.headers["X-time"] = str(process_time) return response assert len(app.middlewares) == 4 request = create_test_request(path="/short") response = await app.handle_request(request) assert "X-time" in response.headers short_time = float(response.headers["X-time"]) request = create_test_request(path="/long") response = await app.handle_request(request) assert "X-time" in response.headers long_time = float(response.headers["X-time"]) assert short_time < long_time app.remove_middleware(timing_middleware) app.remove_middleware(TimingMiddleware) assert len(app.middlewares) == 2
def create_view(): class TestView(View): async def get(self, request): return "GET" async def post(self, request): return "POST" async def put(self, request): return "PUT" async def delete(self, request): return "DELETE" return TestView(Baguette())
async def test_app_static(path, file_path, mimetype): app = TestClient(Baguette(static_directory="tests/static")) response: FileResponse = await app.get(path) path = pathlib.Path(file_path).resolve(strict=True) async with aiofiles.open(path, "rb") as f: content_length = len(await f.read()) assert isinstance(response, FileResponse) assert response.file_path == path assert response.mimetype == mimetype assert response.headers["content-type"] == mimetype assert response.file_size == content_length assert int(response.headers["content-length"]) == content_length
async def test_view_create(): class TestView(View): async def get(self, request): return "GET" async def post(self, request): return "POST" async def put(self, request): return "PUT" async def delete(self, request): return "DELETE" async def nonexistent_method(self, request): return "NONEXISTENT" view = TestView(Baguette()) assert view.methods == ["GET", "POST", "PUT", "DELETE"] assert await view.get(None) == "GET" assert await view.post(None) == "POST" assert await view.put(None) == "PUT" assert await view.delete(None) == "DELETE" assert await view.nonexistent_method(None) == "NONEXISTENT"