def test_content_type(): app = Application() testapp = webtest.TestApp(app) @app.route("/") def get(): return "The Root" @app.text("/user") def get(): return "The User" @app.json("/user") def post(): return dict(id="bla") resp = testapp.get("/") assert resp.text == "The Root" assert resp.headers["content-type"] == "text/plain; charset=utf-8" resp = testapp.get("/user") assert resp.text == "The User" assert resp.headers["content-type"] == "text/plain; charset=utf-8" resp = testapp.post("/user") assert resp.json == dict(id="bla") assert resp.headers["content-type"] == "application/json; charset=utf-8"
def test_racing(): app = Application() @app.route("/") def get(): return f"Hello {app.request.query['username']}" @app.route("/lazy-route") def get(): time.sleep(1) return f"Hello lazy {app.request.query['username']}" testapp = webtest.TestApp(app) lazy_resp = dict(text=None) def do_lazyrequest(): lazy_resp["text"] = testapp.get("/lazy-route?username=bohlul").text t = threading.Thread(target=do_lazyrequest) t.start() resp = testapp.get("/?username=javid") assert resp.text == "Hello javid" t.join() assert lazy_resp["text"] == "Hello lazy bohlul"
def test_exception_on_production(): app = Application() app.config.debug = False @app.route("/") def get(): raise HTTPNotFound("im not here") @app.route("/empty") def get(): raise HTTPNoContent("im empty") testapp = webtest.TestApp(app) resp = testapp.get("/", status=HTTPNotFound.code) assert resp.status == "404 im not here" assert resp.body == b"404 im not here" resp = testapp.get("/empty", status=HTTPNoContent.code) assert resp.status == "204 im empty" assert resp.body == b"" assert "content-type" not in resp.headers app.config.debug = True resp = testapp.get("/", status=HTTPNotFound.code) assert resp.status == "404 im not here" assert resp.body.decode().startswith("Traceback (") resp = testapp.get("/empty", status=HTTPNoContent.code) assert resp.status == "204 im empty" assert resp.body == b"" assert "content-type" not in resp.headers
def test_simple_route(): app = Application() @app.text("/cookies") def get(): cookies = app.request.cookies counter = cookies["counter"] cookies["counter"] = str(int(counter.value) + 1) cookies["counter"]["max-age"] = 1 cookies["counter"]["path"] = "/a" cookies["counter"]["domain"] = "example.com" return "Cookies" testapp = webtest.TestApp(app) resp = testapp.get("/cookies", headers={"cookie": "counter=1;"}) assert resp.text == "Cookies" assert "Set-cookie" in resp.headers cookie = cookies.SimpleCookie(resp.headers["Set-cookie"]) counter = cookie["counter"] assert counter.value == "2" assert counter["path"] == "/a" assert counter["domain"] == "example.com" assert counter["max-age"] == "1"
def test_http_status(): app = Application() @app.route("/no_content") def get(): app.response.headers["custom-one"] = "yes" raise HTTPNoContent @app.route("/old_page") def get(): raise HTTPFound("https://localhost/new_page") @app.route("/old_user") def get(): # noqa: F811 raise HTTPMovedPermanently("https://localhost/new_user") @app.route("/oops") def get(): app.response.headers["custom-one"] = "false" return 12 / 0 testapp = webtest.TestApp(app) resp = testapp.get("/no_content", status=HTTPNoContent.code) assert resp.headers["custom-one"] == "yes" assert "content-type" not in resp.headers resp = testapp.get("/old_page", status=HTTPFound.code) assert resp.headers["location"] == "https://localhost/new_page" assert "content-type" not in resp.headers resp = testapp.get("/old_user", status=HTTPMovedPermanently.code) assert resp.headers["location"] == "https://localhost/new_user" assert "content-type" not in resp.headers resp = testapp.get("/oops", status=HTTPInternalServerError.code) assert resp.status == HTTPInternalServerError().status assert resp.headers["content-type"] == "text/plain; charset=utf-8" assert "custom-one" not in resp.headers # Custom exception class InvalidEmail(HTTPKnownStatus): code, text = (700, "Invalid Email") @app.route("/user") def post(): raise InvalidEmail resp = testapp.post("/user", status=InvalidEmail.code) assert resp.status == "700 Invalid Email"
def test_configuration(): app = Application() config = """ debug: False site_url: http://localhost """ tempdir = tempfile.gettempdir() config_filename = join(tempdir, "tempconfig.yaml") with open(config_filename, "w") as f: f.write(config) app.configure(config_filename) assert app.config.site_url == "http://localhost"
def test_multiple_verbs(): app = Application() @app.route("/", verbs=("get", "post", "delete")) def resource(): return f"The Root {app.request.verb}" testapp = webtest.TestApp(app) resp = testapp.get("/") assert resp.text == "The Root get" assert resp.status == "200 OK" resp = testapp.post("/") assert resp.text == "The Root post" assert resp.status == "200 OK" testapp.put("/", status=404)
def test_static(stuff_dir): app = Application() app.add_static("/public", stuff_dir) app.add_static("/lost", join(stuff_dir, "lost")) os.utime(join(stuff_dir, "index.html"), (1602179630, 1602179635)) os.utime(join(stuff_dir, "img1.png"), (1602179640, 1602179645)) @app.route("/") def get(): return "The Root" testapp = webtest.TestApp(app) resp = testapp.get("/") assert resp.text == "The Root" assert resp.status == "200 OK" resp = testapp.get("/public") assert resp.text == "<h1>Hi!</h1>" assert resp.headers["content-type"] == "text/html" assert resp.status == "200 OK" resp = testapp.get("/public/index.html") assert resp.text == "<h1>Hi!</h1>" assert resp.headers["content-type"] == "text/html" assert resp.headers["last-modified"] == "Thu, 08 Oct 2020 17:53:55 GMT" resp = testapp.get("/public/img1.png") assert len(resp.body) == 72332 assert resp.headers["content-type"] == "image/png" assert resp.headers["last-modified"] == "Thu, 08 Oct 2020 17:54:05 GMT" testapp.get("/lost", status=404) testapp.get("/public/img1.jpg", status=404) testapp.get("/public/subdir", status=404) testapp.get("/public/../conftest.py", status=403) testapp.get("/public/../../setup.py", status=403)
def test_forms(): app = Application() @app.json("/user") def post(): return {"headers": dict(app.request.headers), "form": app.request.form} @app.json("/user/avatar") def put(): return { "headers": dict(app.request.headers), "avatar": app.request.form.avatar.filename, } testapp = webtest.TestApp(app) # URL Encoded form data resp = testapp.post("/user", params={"firstname": "John", "age": 18}) assert (resp.json["headers"]["content-type"] == "application/x-www-form-urlencoded") assert resp.json["form"] == {"firstname": "John", "age": "18"} # JSON form data resp = testapp.post_json("/user", params={"firstname": "John", "age": 18}) assert resp.json["headers"]["content-type"] == "application/json" assert resp.json["form"] == {"firstname": "John", "age": 18} # Multipart form data resp = testapp.put("/user/avatar", upload_files=[("avatar", "avatar.png", b"BlaBla!")]) assert resp.json["headers"]["content-type"].startswith( "multipart/form-data") assert resp.json["avatar"] == "avatar.png" # Bad wsgi.input with pytest.raises(HTTPBadRequest): RequestForm( { "REQUEST_METHOD": "POST", "wsgi.input": [] }, "multipart/form-data", 0, ) # No content-length with pytest.raises(HTTPBadRequest): RequestForm( { "REQUEST_METHOD": "GET", "wsgi.input": "" }, "application/json", None, ) # Invalid JSON with pytest.raises(HTTPBadRequest): RequestForm( { "REQUEST_METHOD": "GET", "wsgi.input": b"{" }, "application/json", 0, ) # Absent query string RequestForm( { "REQUEST_METHOD": "GET", "wsgi.input": "" }, "application/x-www-form-urlencoded", 0, ) # Array field assert (RequestForm( { "REQUEST_METHOD": "GET", "QUERY_STRING": "foo=bar&foo=baz", "wsgi.input": "", }, "application/x-www-form-urlencoded", 0, ).foo == ["bar", "baz"]) # Form attribute existence assert (RequestForm( { "REQUEST_METHOD": "GET", "QUERY_STRING": "foo=bar&foo=baz", "wsgi.input": "", }, "application/x-www-form-urlencoded", 0, ).bar is None)
def test_simple_route(): app = Application() @app.route("/") def get(): return "The Root" @app.route("/user") def GET(): return "User Route" @app.route("/user/me") def get(): return "Its me" @app.route("/user") def POST(): return "User Route Post" @app.route("/user/:userid") def delete(userid: int): return f"Delete User {userid}" @app.route("/user/email/:email/book") def get(email: str): return f"Get user {email} books" @app.route("/user/:userid/book") def get(userid: str): return f"Get user {userid} books" @app.route("/user/:userid/book/year/:year") def get(userid: str, year: int): return f"Get user {userid} books for year {year}" @app.json("/request") def get(): return { "fullpath": app.request.fullpath, "contenttype": app.request.contenttype, "query": app.request.query, "cookies": app.request.cookies, "scheme": app.request.scheme, "response_type": app.response.type, "response_charset": app.response.charset, } @app.binary("/binary") def get(): return b"TheMachine!" @app.text("/no_annotation/:name") def get(name): return name @app.json("/wildcard1/*") def get(*args): return args @app.json("/wildcard1/*") def post(*args): return args @app.json("/wildcard1/wildcardinner/*") def get(*args): return args @app.json("/wildcard2/wildcardinner/*") def get(*args): return args testapp = webtest.TestApp(app) resp = testapp.get("/") assert resp.text == "The Root" assert resp.status == "200 OK" resp = testapp.get("/user") assert resp.text == "User Route" assert resp.status == "200 OK" resp = testapp.post("/user") assert resp.text == "User Route Post" assert resp.status == "200 OK" resp = testapp.delete("/user/4") assert resp.text == "Delete User 4" assert resp.status == "200 OK" resp = testapp.delete("/user/me", status=400) assert resp.status == "400 Invalid Parameter `userid`" resp = testapp.delete("/user/13") assert resp.text == "Delete User 13" assert resp.status == "200 OK" resp = testapp.get("/user/me") assert resp.text == "Its me" assert resp.status == "200 OK" resp = testapp.get("/user/email/[email protected]/book") assert resp.text == "Get user [email protected] books" assert resp.status == "200 OK" resp = testapp.get("/user/5/book/year/2001") assert resp.text == "Get user 5 books for year 2001" assert resp.status == "200 OK" resp = testapp.get("/request") assert resp.json == { "fullpath": "http://localhost:80/request", "contenttype": None, "query": {}, "cookies": {}, "scheme": "http", "response_type": None, "response_charset": None, } resp = testapp.get("/binary") assert resp.body == b"TheMachine!" resp = testapp.get("/no_annotation/john") assert resp.text == "john" resp = testapp.get("/wildcard1/first") assert resp.json == ["first"] resp = testapp.get("/wildcard2/wildcardinner/first") assert resp.json == ["first"] resp = testapp.get("/wildcard1/wildcardinner/a/b/c/d/e/f/g/h") assert resp.json == "a/b/c/d/e/f/g/h".split("/") resp = testapp.get("/wildcard2/wildcardinner/a/b/c/d/e/f/g/h") assert resp.json == "a/b/c/d/e/f/g/h".split("/") resp = testapp.get("/wildcard1/a/b/c/d/e/f/g/h") assert resp.json == "a/b/c/d/e/f/g/h".split("/") resp = testapp.post_json("/wildcard1/first") assert resp.json == ["first"] resp = testapp.post_json("/wildcard1/a/b/c/d/e/f/g/h") assert resp.json == "a/b/c/d/e/f/g/h".split("/") # Query string not existed assert Request({"REQUEST_METHOD": "GET"}).query == {}
def test_stream(): app = Application() testapp = webtest.TestApp(app) @app.route("/") def get(): yield "Foo" yield "Bar" @app.route("/haslength") def get(): app.response.length = 6 yield "Foo" yield "Bar" @app.binary("/binary") def get(): yield b"Foo" yield b"Bar" @app.route("/bad") def get(): yield "Foo" raise ValueError("something wrong") @app.route("/chunked") @app.chunked def get(): yield "first" yield "second" @app.route("/chunked_trailer") @app.chunked("trailer1", "end") def get(): yield "first" yield "second" @app.route("/bad_chunked") @app.chunked def get(): yield "first" raise Exception("error in streaming") resp = testapp.get("/") assert resp.text == "FooBar" assert resp.headers["content-type"] == "text/plain; charset=utf-8" resp = testapp.get("/haslength") assert resp.text == "FooBar" assert resp.headers["content-type"] == "text/plain; charset=utf-8" assert resp.headers["content-length"] == "6" resp = testapp.get("/binary") assert resp.body == b"FooBar" assert resp.headers["content-type"] == "application/octet-stream" # Headers already sent and cannot handle exception in HTTP with pytest.raises(ValueError): testapp.get("/bad") resp = testapp.get("/chunked") assert resp.headers["transfer-encoding"] == "chunked" assert "trailer" not in resp.headers assert resp.text == "5\r\nfirst\r\n6\r\nsecond\r\n0\r\n\r\n" resp = testapp.get("/chunked_trailer") assert resp.headers["transfer-encoding"] == "chunked" assert resp.headers["trailer"] == "trailer1" assert ( resp.text == "5\r\nfirst\r\n6\r\nsecond\r\n0\r\ntrailer1: end\r\n\r\n" ) resp = testapp.get("/bad_chunked") assert resp.headers["transfer-encoding"] == "chunked" assert "trailer" not in resp.headers assert resp.text == "5\r\nfirst\r\n18\r\nerror in streaming0\r\n\r\n"