def test_sessions_enabled_secret_key_empty(raw_app, from_env): if from_env: with override_env("SECRET_KEY", ""): with pytest.raises(SettingsError): configure(raw_app, sessions=True) else: with pytest.raises(SettingsError): configure(raw_app, sessions={"secret_key": ""})
def test_conditional_plugin(raw_app, should_use): used = False def use_hello(_): nonlocal used used = True configure(raw_app, plugins=[{use_hello: should_use}]) assert used is should_use
def test_if_origin_not_in_allow_origins_then_400(raw_app): app = configure(raw_app, cors={"allow_origins": ["foobar.com"]}) @app.route("/") async def index(req, res): pass client = create_client(app) response = client.options( "/", headers={ "origin": "foobar.com", "access-control-request-method": "GET", }, ) assert response.status_code == 200 response = client.options( "/", headers={ "origin": "example.com", "access-control-request-method": "GET", }, ) assert response.status_code == 400
def test_whitenoise_config(raw_app): app = configure(raw_app, static_root="static", static_config={"max_age": 30}) whitenoise = next(route.app for route in app.router.routes if hasattr(route, "path") and route.path == "/static") assert whitenoise.max_age == 30
def test_middleware_called_if_routed_to_sub_app( raw_app, route: str, origin: str, expected: str, expected_body: str ): app = configure( raw_app, cors={"allow_origins": ["example.com", "localhost:8001", "ietf.org"]}, ) @app.route("/") async def index(req, res): res.text = "Hello" sub = App() @sub.route("/") class SubApp: async def get(self, req, res): res.text = "OK" app.mount("/sub", sub) client = create_client(app) res = client.get(route, headers={"origin": origin}) assert res.text == expected_body if not expected: # unknown origin -> no allow-origin header assert "access-control-allow-origin" not in res.headers else: # allowed origin -> allow-origin header" assert "access-control-allow-origin" in res.headers assert res.headers.get("access-control-allow-origin") == expected
def test_if_static_dir_is_none_then_no_assets_served(raw_app, tmpdir_factory): static_dir = tmpdir_factory.mktemp("static") _create_asset(static_dir) app = configure(raw_app, static_dir=None) client = create_client(app) assert client.get(f"/static/{FILE_DIR}/{FILE_NAME}").status_code == 404
def test_assets_are_served_at_static_by_default(raw_app, tmpdir_factory): static_dir = tmpdir_factory.mktemp("static") _create_asset(static_dir) app = configure(raw_app, static_dir=str(static_dir)) client = create_client(app) response = client.get(f"/static/{FILE_DIR}/{FILE_NAME}") assert response.status_code == 200 assert response.text == FILE_CONTENTS
def test_if_host_not_allowed_then_400(raw_app): app = configure(raw_app, allowed_hosts=["example.com"]) client = create_client(app) @app.route("/") async def index(req, res): pass response = client.get("/") assert response.status_code == 400
def test_settings(raw_app, positional: bool): class Settings: ONE = "one" _IGNORED = "ignored" ignored_too = "ignored too" args = [raw_app] kwargs = {"two": "two", "settings": Settings()} if positional: args.append(kwargs.pop("settings")) configure(*args, **kwargs) assert settings.ONE == "one" assert settings.TWO == "two" for name in "two", "three", "_IGNORED", "ignored_too", "IGNORED_TOO": assert name not in settings settings.ONE = 1 assert settings.ONE == 1
def test_customize_static_root(raw_app, tmpdir_factory): static_dir = tmpdir_factory.mktemp("static") _create_asset(static_dir) app = configure(raw_app, static_dir=str(static_dir), static_root="assets") client = create_client(app) assert client.get(f"/static/{FILE_DIR}/{FILE_NAME}").status_code == 404 response = client.get(f"/assets/{FILE_DIR}/{FILE_NAME}") assert response.status_code == 200 assert response.text == FILE_CONTENTS
def test_mount_extra_static_files_dirs(raw_app, tmpdir_factory): static_dir = tmpdir_factory.mktemp("staticfiles") _create_asset(static_dir) app = configure(raw_app, static_dir=None) app.mount("assets", static(str(static_dir))) client = create_client(app) response = client.get(f"/assets/{FILE_DIR}/{FILE_NAME}") assert response.status_code == 200 assert response.text == FILE_CONTENTS
def test_if_gzip_enabled_then_response_is_compressed(raw_app): app = configure(raw_app, gzip=True, gzip_min_size=0) @app.route("/") async def index(req, res): pass client = create_client(app) response = client.get("/", headers={"Accept-Encoding": "gzip"}) assert response.status_code == 200 assert response.headers["content-encoding"] == "gzip"
def test_basic(raw_app): def use_foo(app): @app.route("/foo") async def foo(req, res): res.text = "Foo" app = configure(raw_app, plugins=[use_foo]) client = create_client(app) r = client.get("/foo") assert r.status_code == 200 assert r.text == "Foo"
def test_disable_validation_error_handling(raw_app): app = configure(raw_app, handle_typesystem_validation_errors=False) client = create_client(app) @app.route("/todos") class TodoList: async def post(self, req, res): todo = Todo.validate(await req.json()) res.json = dict(todo) with pytest.raises(typesystem.ValidationError): client.post("/todos", json={"title": "Very long string" * 10})
def test_if_hsts_enabled_and_request_is_on_http_then_redirects_to_https( raw_app): app = configure(raw_app, hsts=True) @app.route("/") async def index(req, res): pass client = create_client(app) response = client.get("/", allow_redirects=False) assert 301 <= response.status_code <= 308 assert response.headers["location"] == "https://testserver/"
def test_sessions_enabled_secret_key_present(raw_app, from_env): if from_env: with override_env("SECRET_KEY", "not-so-secret"): app = configure(raw_app, sessions=True) else: app = configure(raw_app, sessions={"secret_key": "not-so-secret"}) @app.route("/set", methods=["post"]) async def set_session(req, res): req.session["data"] = "something" res.text = "Saved" @app.route("/") async def index(req, res): data = req.session["data"] res.text = f"Hello {data}" client = create_client(app) client.post("/set") response = client.get("/") assert "something" in response.text assert "session" in response.cookies
def test_use_settings(raw_app): @plugin def use_hello(app): hello_message = getattr(settings, "HELLO_MESSAGE") @app.route("/hello") async def foo(req, res): res.text = hello_message app = configure(raw_app, hello_message="Hello, plugins!") client = create_client(app) r = client.get("/hello") assert r.status_code == 200 assert r.text == "Hello, plugins!"
def test_no_allowed_origins_by_default(raw_app): app = configure(raw_app, cors=True) @app.route("/") async def index(req, res): pass client = create_client(app) response = client.options( "/", headers={ "origin": "foobar.com", "access-control-request-method": "GET", }, ) assert response.status_code == 400
def test_redirect_trailing_slash(raw_app, redirect): settings = {} if redirect is not None: settings["redirect_trailing_slash"] = redirect app = configure(raw_app, **settings) client = create_client(app) @app.route("/foo/") async def foo(req, res): pass r = client.get("/foo", allow_redirects=False) if redirect or redirect is None: assert r.status_code == 302 else: assert r.status_code == 404
def test_allow_origin(raw_app, origin: str, allowed: bool): app = configure(raw_app, cors={"allow_origins": ["example.com", "localhost:8001"]}) @app.route("/") async def index(req, res): res.text = "OK" client = create_client(app) r = client.get("/", headers={"origin": origin}) assert r.text == "OK" assert r.status_code == 200 if allowed else 400 if allowed: # allowed origin -> allow-origin header assert "access-control-allow-origin" in r.headers assert r.headers["access-control-allow-origin"] == origin else: # unknown origin -> no allow-origin header assert "access-control-allow-origin" not in r.headers
def test_allow_method(raw_app, method, allowed): app = configure( raw_app, cors={ "allow_origins": ["foobar.com"], "allow_methods": ["GET"] }, ) @app.route("/") async def index(req, res): pass client = create_client(app) r = client.options( "/", headers={ "origin": "foobar.com", "access-control-request-method": method, }, ) assert r.status_code == 200 if allowed else 400
from bocadillo import App, configure app = App() configure(app) @app.route("/") async def index(req, res): res.text = "" @app.route("/user", methods=["post"]) async def create_user(req, res): res.text = "" @app.route("/user/{pk}") async def get_user(req, res, pk: int): res.text = pk
def app(raw_app: App) -> App: return configure(raw_app, provider_modules=["tests.data.providerconf"])
def test_if_static_dir_does_not_exist_then_no_files_mounted(raw_app): with pytest.warns(None) as record: configure(raw_app, static_dir="foo") assert len(record) == 0
def fixture_app() -> App: from blogapi.app import app return configure(app, settings)
def test_sessions_enabled_no_secret_key(raw_app): with pytest.raises(SettingsError): configure(raw_app, sessions=True)
"""ASGI server entry point.""" from bocadillo import configure from .app import app from . import settings configure(app, settings)
def test_cannot_reconfigure(app): with pytest.raises(RuntimeError): configure(app)
def test_whitenoise_config(raw_app): app = configure(raw_app, static_root="static", static_config={"max_age": 30}) whitenoise = app._children["/static"] assert whitenoise.max_age == 30
def fixture_app(raw_app: App) -> App: configure(raw_app) return raw_app