diff --git a/lib/playwright/api_request.ex b/lib/playwright/api_request.ex
index f0318cd..cfca650 100644
--- a/lib/playwright/api_request.ex
+++ b/lib/playwright/api_request.ex
@@ -25,29 +25,97 @@ defmodule Playwright.APIRequest do
}
@typedoc "Options for calls to `new_context/1`"
- @type options :: map()
- # %{
- # base_url: String.t(),
- # extra_http_headers: map(),
- # http_credentials: http_credentials(),
- # ignore_https_errors: boolean(),
- # proxy: proxy_settings(),
- # user_agent: String.t(),
- # timeout: float(),
- # storage_state: storage_state() | String.t() | Path.t(),
- # client_certificates: [client_certificate()]
- # }
+ @type options :: %{
+ optional(:base_url) => String.t(),
+ optional(:client_certificates) => [client_certificate()],
+ optional(:extra_http_headers) => http_headers(),
+ optional(:http_credentials) => http_credentials(),
+ optional(:ignore_https_errors) => boolean(),
+ optional(:proxy) => proxy_settings(),
+ optional(:storage_state) => storage_state() | Path.t() | String.t(),
+ optional(:timeout) => float(),
+ optional(:user_agent) => String.t()
+ }
+
+ @typedoc """
+ A client certificate to be used in requests.
+ """
+ @type client_certificate :: %{
+ required(:origin) => String.t(),
+ optional(:cert_path) => Path.t() | String.t(),
+ optional(:key_path) => Path.t() | String.t(),
+ optional(:pfx_path) => Path.t() | String.t(),
+ optional(:passphrase) => String.t()
+ }
+
+ @typedoc """
+ A `map` containing additional HTTP headers to be sent with every request.
+ """
+ @type http_headers :: %{required(String.t()) => String.t()}
+
+ @typedoc "HTTP authetication credentials."
+ @type http_credentials() :: %{
+ required(:username) => String.t(),
+ required(:password) => String.t(),
+ optional(:origin) => String.t(),
+ optional(:send) => :always | :unauthorized
+ }
+
+ @typedoc "Network proxy settings."
+ @type proxy_settings :: %{
+ required(:server) => String.t(),
+ optional(:bypass) => String.t(),
+ optional(:username) => String.t(),
+ optional(:password) => String.t()
+ }
+
+ @typedoc "Storage state settings."
+ @type storage_state :: %{
+ required(:cookies) => [cookie()],
+ required(:origins) => [
+ %{
+ required(:origin) => String.t(),
+ required(:local_storage) => [local_storage()]
+ }
+ ]
+ }
+
+ @typedoc "An HTTP cookie."
+ @type cookie :: %{
+ required(:name) => String.t(),
+ required(:value) => String.t(),
+ required(:domain) => String.t(),
+ required(:path) => String.t(),
+ required(:expires) => float(),
+ required(:http_only) => boolean(),
+ required(:secure) => boolean(),
+ required(:same_site) => :lax | :none | :strict
+ }
+
+ @typedoc "Local storage settings."
+ @type local_storage :: %{
+ required(:name) => String.t(),
+ required(:value) => String.t()
+ }
@doc """
Returns a new `Playwright.APIRequest`.
- ## Returns
+ See also `Playwright.request/1` which is a more likely entry-point.
- - `Playwright.APIRequest.t()`
+ ## Usage
+
+ request = APIRequest.new(session)
+
+ ## Arguments
- ## Parameters
+ | name | description |
+ | --------- | -------------------------------------------- |
+ | `session` | The `pid` for the current Playwright session |
+
+ ## Returns
- - session ...
+ - `Playwright.APIRequest.t()`
"""
@spec new(pid()) :: t()
def new(session) do
@@ -60,31 +128,26 @@ defmodule Playwright.APIRequest do
@doc """
Creates a new instance of `Playwright.APIRequestContext`.
- ## Returns
+ ## Usage
- - `Playwright.APIRequestContext.t()`
- - `{:error, Playwright.API.Error.t()}`
+ request = Playwright.request(session)
- ## Parameters
+ APIRequest.new_context(request)
+ APIRequest.new_context(request, options)
- - request ...
- - options
+ APIRequest.new_context!(request)
+ APIRequest.new_context!(request, options)
- ## Options
+ ## Arguments
+
+ | name | | description |
+ | --------- | ---------- | -------------------------- |
+ | `request` | | The "subject" `APIRequest` |
+ | `options` | (optional) | `APIRequest.options()` |
- | name | type |
- | ---------------------- | ------------------------ |
- | `:base_url` | `String.t()` |
- | `:extra_http_headers` | `map()` |
- | `:http_credentials` | `[http_credential()]` |
- | `:ignore_https_errors` | `boolean()` |
- | `:proxy` | `proxy()` |
- | `:user_agent` | `String.t()` |
- | `:timeout` | `float()` |
- | `:storage_state` | `storage_state()` |
- | `:client_certififates` | `[client_certificate()]` |
+ ## Options
- ---
+
⋯
### Option: `:base_url`
@@ -92,7 +155,7 @@ defmodule Playwright.APIRequest do
consideration by using the [`URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL)
constructor for building the corresponding require URL.
- Examples:
+ #### Examples
- With `base_url: http://localhost:3000`, sending a request to `/bar.html`
results in `http://localhost:3000/bar.html`.
@@ -101,59 +164,82 @@ defmodule Playwright.APIRequest do
- With `base_url: http://localhost:3000/foo` (without the trailing slash),
navigating to `./bar.html` results in `http://localhost:3000/bar.html`.
- ---
+ ⋯
+
+ ### Option: `:client_certificates`
+
+ A list of client certificates to be used. Each certificate instance must have
+ both `:cert_path` and `:key_path` or a single `:pfx_path` to load the client
+ certificate. Optionally, the `:passphrase` property should be provided if the
+ certficiate is encrypted. The `:origin` property should be provided with an
+ exact match to the request origin for which the certificate is valid.
+
+ TLS client authentication allows the server to request a client certificate
+ and verify it.
+
+ > #### NOTE {: .info}
+ >
+ > Using client certificates in combination with proxy servers is not supported.
+
+ > #### NOTE {: .info}
+ >
+ > When using WebKit on macOS, accessing `localhost` will not pick up client
+ > certificates. As a work-around: replace `localhost` with `local.playwright`.
+
+ #### Certificate details
+
+ | name | | description |
+ | ------------- | ---------- | --------------------------------- |
+ | `:origin` | | Exact origin that the certificate is valid for. Origin includes https protocol, a hostname and optionally a port. |
+ | `:cert_path` | (optional) | Path to the file with the certificate in PEM format. |
+ | `:key_path` | (optional) | Path to the file with the private key in PEM format. |
+ | `:pfx_path` | (optional) | Path to the PFX or PKCS12 encoded private key and certificate chain. |
+ | `:passphrase` | (optional) | Passphrase for the private key (PEM or PFX). |
+
+ ⋯
### Option: `:extra_http_headers`
A `map` containing additional HTTP headers to be sent with every request.
+ ⋯
+
### Option: `:http_credentials`
Credentials for [HTTP authentication](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication).
If no `:origin` is specified, the `:username` and `:password` are sent to any
servers upon unauthorized responses.
- | name | type |
- | ---------------------- | -------------------------------------- |
- | `:username` | `String.t()` |
- | `:password` | `String.t()` |
- | `:origin` | `String.t()` (optional) |
- | `:send` | `"always", "unauthorized"` (optional) |
+ #### Credential details
+
+ | name | | description |
+ | ----------- | ---------- | ----------- |
+ | `:username` | | |
+ | `:password` | | |
+ | `:origin` | (optional) | Restrain sending http credentials on specific origin (`scheme://host:port`). |
+ | `:send` | (optional) | This option only applies to the requests sent from corresponding `APIRequestContext` and does not affect requests sent from the browser. `:always` - `Authorization` header with basic authentication credentials will be sent with the each API request. `:unauthorized`- the credentials are only sent when 401 (Unauthorized) response with `WWW-Authenticate` header is received. Defaults to `:unauthorized`. |
- ---
+ ⋯
### Option: `:ignore_https_errors`
Whether to ignore HTTPS errors when sending network requests. Defaults to
`false`.
- ---
+ ⋯
### Option: `:proxy`
Network proxy settings.
- | name | type |
- | ----------- | ----------------------- |
- | `:server` | `String.t()` |
- | `:bypass` | `String.t()` (optional) |
- | `:username` | `String.t()` (optional) |
- | `:password` | `String.t()` (optional) |
-
- ---
-
- ### Option: `:user_agent`
-
- Specific user agent to use in this context.
-
- ---
-
- ### Option: `:timeout`
-
- Maximum time in milliseconds to wait for the response. Defaults to `30_000`
- (30 seconds). Pass `0` to disable the timeout.
+ | name | | description |
+ | ----------- | ---------- | ----------- |
+ | `:server` | | Proxy to be used for all requests. HTTP and SOCKS proxies are supported, for example `http://myproxy.com:3128` or `socks5://myproxy.com:3128`. Short form `myproxy.com:3128` is considered an HTTP proxy. |
+ | `:bypass` | (optional) | Optional comma-separated domains to bypass proxy, for example `".com, chromium.org, .domain.com"`. |
+ | `:username` | (optional) | Optional username to use if HTTP proxy requires authentication. |
+ | `:password` | (optional) | Optional password to use if HTTP proxy requires authentication. |
- ---
+ ⋯
### Option: `:storage_state`
@@ -164,51 +250,28 @@ defmodule Playwright.APIRequest do
returned by one of `BrowserContext.storage_state/2` or
`APIRequestContext.storage_state/2`.
- One of:
+ | name | | description |
+ | ----------- | ---------- | ----------- |
+ | `:cookies` | | `[APIRequest.cookie()]` |
+ | `:origins` | | `[APIRequest.origin()]` |
- - `String.t()`
- - `Path.t()`
- - Storage state
+ ⋯
- Where storage state has the following shape:
-
- | name | type |
- | ----------- | --------- |
- | `:cookies` | **TODO** |
- | `:origins` | **TODO** |
-
- ---
-
- ### Option: `:client_certificates`
-
- TLS client authentication allows the server to request a client certificate
- and verify it.
-
- **Details**
+ ### Option: `:timeout`
- An array of client certificates to be used. Each certificate object must have
- both `:cert_path` and `:key_path` or a single `:pfx_path` to load the client
- certificate.
+ Maximum time in milliseconds to wait for the response. Defaults to `30_000`
+ (30 seconds). Pass `0` to disable the timeout.
- Optionally, the `:passphrase` property should be provided if the certficiate
- is encrypted. The `:origin` property should be provided with an exact match to
- the request origin for which the certificate is valid.
+ ⋯
- **NOTES:**
+ ### Option: `:user_agent`
- - Using client certificates in combination with proxy servers is not supported.
- - When using WebKit on macOS, accessing `localhost` will not pick up client
- certificates. As a work-around: replace `localhost` with `local.playwright`.
+ Specific user agent to use in this context.
- Where each client certificate has the following shape:
+ ## Returns
- | name | type |
- | ------------- | --------------------------------- |
- | `:origin` | `String.t()` |
- | `:cert_path` | `Path.t(), String.t()` (optional) |
- | `:key_path` | `Path.t(), String.t()` (optional) |
- | `:pfx_path` | `Path.t(), String.t()` (optional) |
- | `:passphrase` | `String.t()` (optional) |
+ - `Playwright.APIRequestContext.t()`
+ - `{:error, Playwright.API.Error.t()}`
"""
@pipe {:new_context, [:request]}
@pipe {:new_context, [:request, :options]}
@@ -216,31 +279,4 @@ defmodule Playwright.APIRequest do
def new_context(request, options \\ %{}) do
Channel.post({request, :new_request}, options)
end
-
- # Storage State shape:
- # {
- # cookies: [
- # {
- # name: str,
- # value: str,
- # domain: str,
- # path: str,
- # expires: float,
- # httpOnly: bool,
- # secure: bool,
- # sameSite: Union["Lax", "None", "Strict"]
- # }
- # ],
- # origins: [
- # {
- # origin: str,
- # localStorage: [
- # {
- # name: str,
- # value: str
- # }
- # ]
- # }
- # ]
- # }
end
diff --git a/test/api/api_request_context_test.exs b/test/api/api_request_context_test.exs
new file mode 100644
index 0000000..64e571a
--- /dev/null
+++ b/test/api/api_request_context_test.exs
@@ -0,0 +1,300 @@
+# def test_should_work(playwright: Playwright, method: str, server: Server) -> None:
+# def test_should_dispose_global_request(playwright: Playwright, server: Server) -> None:
+# def test_should_support_global_user_agent_option(
+# def test_should_support_global_timeout_option(
+# def test_should_propagate_extra_http_headers_with_redirects(
+# def test_should_support_global_http_credentials_option(
+# def test_should_return_error_with_wrong_credentials(
+# def test_should_work_with_correct_credentials_and_matching_origin(
+# def test_should_work_with_correct_credentials_and_matching_origin_case_insensitive(
+# def test_should_return_error_with_correct_credentials_and_mismatching_scheme(
+# def test_should_return_error_with_correct_credentials_and_mismatching_hostname(
+# def test_should_return_error_with_correct_credentials_and_mismatching_port(
+# def test_should_support_global_ignore_https_errors_option(
+# def test_should_resolve_url_relative_to_global_base_url_option(
+# def test_should_use_playwright_as_a_user_agent(
+# def test_should_return_empty_body(playwright: Playwright, server: Server) -> None:
+# def test_storage_state_should_round_trip_through_file(
+# def test_should_throw_an_error_when_max_redirects_is_exceeded(
+# def test_should_not_follow_redirects_when_max_redirects_is_set_to_0(
+# def test_should_throw_an_error_when_max_redirects_is_less_than_0(
+# def test_should_serialize_null_values_in_json(
+
+# def test_should_work(playwright: Playwright, method: str, server: Server) -> None:
+# request = playwright.request.new_context()
+# response: APIResponse = getattr(request, method)(server.PREFIX + "/simple.json")
+# assert response.status == 200
+# assert response.status_text == "OK"
+# assert response.ok is True
+# assert response.url == server.PREFIX + "/simple.json"
+# assert response.headers["content-type"] == "application/json"
+# assert {
+# "name": "Content-Type",
+# "value": "application/json",
+# } in response.headers_array
+# assert response.text() == ("" if method == "head" else '{"foo": "bar"}\n')
+
+# def test_should_dispose_global_request(playwright: Playwright, server: Server) -> None:
+# request = playwright.request.new_context()
+# response = request.get(server.PREFIX + "/simple.json")
+# assert response.json() == {"foo": "bar"}
+# response.dispose()
+# with pytest.raises(Error, match="Response has been disposed"):
+# response.body()
+
+# def test_should_support_global_user_agent_option(
+# playwright: Playwright, server: Server
+# ) -> None:
+# request = playwright.request.new_context(user_agent="My Agent")
+# response = request.get(server.PREFIX + "/empty.html")
+# with server.expect_request("/empty.html") as server_req:
+# request.get(server.EMPTY_PAGE)
+# assert response.ok is True
+# assert response.url == server.EMPTY_PAGE
+
+# assert server_req.value.getHeader("user-agent") == "My Agent"
+
+# def test_should_support_global_timeout_option(
+# playwright: Playwright, server: Server
+# ) -> None:
+# request = playwright.request.new_context(timeout=100)
+# server.set_route("/empty.html", lambda req: None)
+# with pytest.raises(Error, match="Request timed out after 100ms"):
+# request.get(server.EMPTY_PAGE)
+
+# def test_should_propagate_extra_http_headers_with_redirects(
+# playwright: Playwright, server: Server
+# ) -> None:
+# server.set_redirect("/a/redirect1", "/b/c/redirect2")
+# server.set_redirect("/b/c/redirect2", "/simple.json")
+# request = playwright.request.new_context(extra_http_headers={"My-Secret": "Value"})
+# with server.expect_request("/a/redirect1") as server_req1:
+# with server.expect_request("/b/c/redirect2") as server_req2:
+# with server.expect_request("/simple.json") as server_req3:
+# request.get(f"{server.PREFIX}/a/redirect1")
+# assert server_req1.value.getHeader("my-secret") == "Value"
+# assert server_req2.value.getHeader("my-secret") == "Value"
+# assert server_req3.value.getHeader("my-secret") == "Value"
+
+# def test_should_support_global_http_credentials_option(
+# playwright: Playwright, server: Server
+# ) -> None:
+# server.set_auth("/empty.html", "user", "pass")
+# request1 = playwright.request.new_context()
+# response1 = request1.get(server.EMPTY_PAGE)
+# assert response1.status == 401
+# response1.dispose()
+
+# request2 = playwright.request.new_context(
+# http_credentials={"username": "user", "password": "pass"}
+# )
+# response2 = request2.get(server.EMPTY_PAGE)
+# assert response2.status == 200
+# assert response2.ok is True
+# response2.dispose()
+
+# def test_should_return_error_with_wrong_credentials(
+# playwright: Playwright, server: Server
+# ) -> None:
+# server.set_auth("/empty.html", "user", "pass")
+# request = playwright.request.new_context(
+# http_credentials={"username": "user", "password": "wrong"}
+# )
+# response = request.get(server.EMPTY_PAGE)
+# assert response.status == 401
+# assert response.ok is False
+
+# def test_should_work_with_correct_credentials_and_matching_origin(
+# playwright: Playwright, server: Server
+# ) -> None:
+# server.set_auth("/empty.html", "user", "pass")
+# request = playwright.request.new_context(
+# http_credentials={
+# "username": "user",
+# "password": "pass",
+# "origin": server.PREFIX,
+# }
+# )
+# response = request.get(server.EMPTY_PAGE)
+# assert response.status == 200
+# response.dispose()
+
+# def test_should_work_with_correct_credentials_and_matching_origin_case_insensitive(
+# playwright: Playwright, server: Server
+# ) -> None:
+# server.set_auth("/empty.html", "user", "pass")
+# request = playwright.request.new_context(
+# http_credentials={
+# "username": "user",
+# "password": "pass",
+# "origin": server.PREFIX.upper(),
+# }
+# )
+# response = request.get(server.EMPTY_PAGE)
+# assert response.status == 200
+# response.dispose()
+
+# def test_should_return_error_with_correct_credentials_and_mismatching_scheme(
+# playwright: Playwright, server: Server
+# ) -> None:
+# server.set_auth("/empty.html", "user", "pass")
+# request = playwright.request.new_context(
+# http_credentials={
+# "username": "user",
+# "password": "pass",
+# "origin": server.PREFIX.replace("http://", "https://"),
+# }
+# )
+# response = request.get(server.EMPTY_PAGE)
+# assert response.status == 401
+# response.dispose()
+
+# def test_should_return_error_with_correct_credentials_and_mismatching_hostname(
+# playwright: Playwright, server: Server
+# ) -> None:
+# server.set_auth("/empty.html", "user", "pass")
+# hostname = urlparse(server.PREFIX).hostname
+# assert hostname
+# origin = server.PREFIX.replace(hostname, "mismatching-hostname")
+# request = playwright.request.new_context(
+# http_credentials={"username": "user", "password": "pass", "origin": origin}
+# )
+# response = request.get(server.EMPTY_PAGE)
+# assert response.status == 401
+# response.dispose()
+
+# def test_should_return_error_with_correct_credentials_and_mismatching_port(
+# playwright: Playwright, server: Server
+# ) -> None:
+# server.set_auth("/empty.html", "user", "pass")
+# origin = server.PREFIX.replace(str(server.PORT), str(server.PORT + 1))
+# request = playwright.request.new_context(
+# http_credentials={"username": "user", "password": "pass", "origin": origin}
+# )
+# response = request.get(server.EMPTY_PAGE)
+# assert response.status == 401
+# response.dispose()
+
+# def test_should_support_global_ignore_https_errors_option(
+# playwright: Playwright, https_server: Server
+# ) -> None:
+# request = playwright.request.new_context(ignore_https_errors=True)
+# response = request.get(https_server.EMPTY_PAGE)
+# assert response.status == 200
+# assert response.ok is True
+# assert response.url == https_server.EMPTY_PAGE
+# response.dispose()
+
+# def test_should_resolve_url_relative_to_global_base_url_option(
+# playwright: Playwright, server: Server
+# ) -> None:
+# request = playwright.request.new_context(base_url=server.PREFIX)
+# response = request.get("/empty.html")
+# assert response.status == 200
+# assert response.ok is True
+# assert response.url == server.EMPTY_PAGE
+# response.dispose()
+
+# def test_should_use_playwright_as_a_user_agent(
+# playwright: Playwright, server: Server
+# ) -> None:
+# request = playwright.request.new_context()
+# with server.expect_request("/empty.html") as server_req:
+# request.get(server.EMPTY_PAGE)
+# assert str(server_req.value.getHeader("User-Agent")).startswith("Playwright/")
+# request.dispose()
+
+# def test_should_return_empty_body(playwright: Playwright, server: Server) -> None:
+# request = playwright.request.new_context()
+# response = request.get(server.EMPTY_PAGE)
+# body = response.body()
+# assert len(body) == 0
+# assert response.text() == ""
+# request.dispose()
+# with pytest.raises(Error, match="Response has been disposed"):
+# response.body()
+
+# def test_storage_state_should_round_trip_through_file(
+# playwright: Playwright, tmpdir: Path
+# ) -> None:
+# expected: StorageState = {
+# "cookies": [
+# {
+# "name": "a",
+# "value": "b",
+# "domain": "a.b.one.com",
+# "path": "/",
+# "expires": -1,
+# "httpOnly": False,
+# "secure": False,
+# "sameSite": "Lax",
+# }
+# ],
+# "origins": [],
+# }
+# request = playwright.request.new_context(storage_state=expected)
+# path = tmpdir / "storage-state.json"
+# actual = request.storage_state(path=path)
+# assert actual == expected
+
+# written = path.read_text("utf8")
+# assert json.loads(written) == expected
+
+# request2 = playwright.request.new_context(storage_state=path)
+# state2 = request2.storage_state()
+# assert state2 == expected
+
+# def test_should_throw_an_error_when_max_redirects_is_exceeded(
+# playwright: Playwright, server: Server
+# ) -> None:
+# server.set_redirect("/a/redirect1", "/b/c/redirect2")
+# server.set_redirect("/b/c/redirect2", "/b/c/redirect3")
+# server.set_redirect("/b/c/redirect3", "/b/c/redirect4")
+# server.set_redirect("/b/c/redirect4", "/simple.json")
+
+# request = playwright.request.new_context()
+# for method in ["GET", "PUT", "POST", "OPTIONS", "HEAD", "PATCH"]:
+# for max_redirects in [1, 2, 3]:
+# with pytest.raises(Error) as exc_info:
+# request.fetch(
+# server.PREFIX + "/a/redirect1",
+# method=method,
+# max_redirects=max_redirects,
+# )
+# assert "Max redirect count exceeded" in str(exc_info)
+
+# def test_should_not_follow_redirects_when_max_redirects_is_set_to_0(
+# playwright: Playwright, server: Server
+# ) -> None:
+# server.set_redirect("/a/redirect1", "/b/c/redirect2")
+# server.set_redirect("/b/c/redirect2", "/simple.json")
+
+# request = playwright.request.new_context()
+# for method in ["GET", "PUT", "POST", "OPTIONS", "HEAD", "PATCH"]:
+# response = request.fetch(
+# server.PREFIX + "/a/redirect1", method=method, max_redirects=0
+# )
+# assert response.headers["location"] == "/b/c/redirect2"
+# assert response.status == 302
+
+# def test_should_throw_an_error_when_max_redirects_is_less_than_0(
+# playwright: Playwright,
+# server: Server,
+# ) -> None:
+# request = playwright.request.new_context()
+# for method in ["GET", "PUT", "POST", "OPTIONS", "HEAD", "PATCH"]:
+# with pytest.raises(AssertionError) as exc_info:
+# request.fetch(
+# server.PREFIX + "/a/redirect1", method=method, max_redirects=-1
+# )
+# assert "'max_redirects' must be greater than or equal to '0'" in str(exc_info)
+
+# def test_should_serialize_null_values_in_json(
+# playwright: Playwright, server: Server
+# ) -> None:
+# request = playwright.request.new_context()
+# server.set_route("/echo", lambda req: (req.write(req.post_body), req.finish()))
+# response = request.post(server.PREFIX + "/echo", data={"foo": None})
+# assert response.status == 200
+# assert response.text() == '{"foo": null}'
+# request.dispose()
diff --git a/test/api/api_request_test.exs b/test/api/api_request_test.exs
index f5688a8..d916e93 100644
--- a/test/api/api_request_test.exs
+++ b/test/api/api_request_test.exs
@@ -49,304 +49,3 @@ defmodule Playwright.APIRequestTest do
end
end
end
-
-# def test_should_work(playwright: Playwright, method: str, server: Server) -> None:
-# def test_should_dispose_global_request(playwright: Playwright, server: Server) -> None:
-# def test_should_support_global_user_agent_option(
-# def test_should_support_global_timeout_option(
-# def test_should_propagate_extra_http_headers_with_redirects(
-# def test_should_support_global_http_credentials_option(
-# def test_should_return_error_with_wrong_credentials(
-# def test_should_work_with_correct_credentials_and_matching_origin(
-# def test_should_work_with_correct_credentials_and_matching_origin_case_insensitive(
-# def test_should_return_error_with_correct_credentials_and_mismatching_scheme(
-# def test_should_return_error_with_correct_credentials_and_mismatching_hostname(
-# def test_should_return_error_with_correct_credentials_and_mismatching_port(
-# def test_should_support_global_ignore_https_errors_option(
-# def test_should_resolve_url_relative_to_global_base_url_option(
-# def test_should_use_playwright_as_a_user_agent(
-# def test_should_return_empty_body(playwright: Playwright, server: Server) -> None:
-# def test_storage_state_should_round_trip_through_file(
-# def test_should_throw_an_error_when_max_redirects_is_exceeded(
-# def test_should_not_follow_redirects_when_max_redirects_is_set_to_0(
-# def test_should_throw_an_error_when_max_redirects_is_less_than_0(
-# def test_should_serialize_null_values_in_json(
-
-# def test_should_work(playwright: Playwright, method: str, server: Server) -> None:
-# request = playwright.request.new_context()
-# response: APIResponse = getattr(request, method)(server.PREFIX + "/simple.json")
-# assert response.status == 200
-# assert response.status_text == "OK"
-# assert response.ok is True
-# assert response.url == server.PREFIX + "/simple.json"
-# assert response.headers["content-type"] == "application/json"
-# assert {
-# "name": "Content-Type",
-# "value": "application/json",
-# } in response.headers_array
-# assert response.text() == ("" if method == "head" else '{"foo": "bar"}\n')
-
-# def test_should_dispose_global_request(playwright: Playwright, server: Server) -> None:
-# request = playwright.request.new_context()
-# response = request.get(server.PREFIX + "/simple.json")
-# assert response.json() == {"foo": "bar"}
-# response.dispose()
-# with pytest.raises(Error, match="Response has been disposed"):
-# response.body()
-
-# def test_should_support_global_user_agent_option(
-# playwright: Playwright, server: Server
-# ) -> None:
-# request = playwright.request.new_context(user_agent="My Agent")
-# response = request.get(server.PREFIX + "/empty.html")
-# with server.expect_request("/empty.html") as server_req:
-# request.get(server.EMPTY_PAGE)
-# assert response.ok is True
-# assert response.url == server.EMPTY_PAGE
-
-# assert server_req.value.getHeader("user-agent") == "My Agent"
-
-# def test_should_support_global_timeout_option(
-# playwright: Playwright, server: Server
-# ) -> None:
-# request = playwright.request.new_context(timeout=100)
-# server.set_route("/empty.html", lambda req: None)
-# with pytest.raises(Error, match="Request timed out after 100ms"):
-# request.get(server.EMPTY_PAGE)
-
-# def test_should_propagate_extra_http_headers_with_redirects(
-# playwright: Playwright, server: Server
-# ) -> None:
-# server.set_redirect("/a/redirect1", "/b/c/redirect2")
-# server.set_redirect("/b/c/redirect2", "/simple.json")
-# request = playwright.request.new_context(extra_http_headers={"My-Secret": "Value"})
-# with server.expect_request("/a/redirect1") as server_req1:
-# with server.expect_request("/b/c/redirect2") as server_req2:
-# with server.expect_request("/simple.json") as server_req3:
-# request.get(f"{server.PREFIX}/a/redirect1")
-# assert server_req1.value.getHeader("my-secret") == "Value"
-# assert server_req2.value.getHeader("my-secret") == "Value"
-# assert server_req3.value.getHeader("my-secret") == "Value"
-
-# def test_should_support_global_http_credentials_option(
-# playwright: Playwright, server: Server
-# ) -> None:
-# server.set_auth("/empty.html", "user", "pass")
-# request1 = playwright.request.new_context()
-# response1 = request1.get(server.EMPTY_PAGE)
-# assert response1.status == 401
-# response1.dispose()
-
-# request2 = playwright.request.new_context(
-# http_credentials={"username": "user", "password": "pass"}
-# )
-# response2 = request2.get(server.EMPTY_PAGE)
-# assert response2.status == 200
-# assert response2.ok is True
-# response2.dispose()
-
-# def test_should_return_error_with_wrong_credentials(
-# playwright: Playwright, server: Server
-# ) -> None:
-# server.set_auth("/empty.html", "user", "pass")
-# request = playwright.request.new_context(
-# http_credentials={"username": "user", "password": "wrong"}
-# )
-# response = request.get(server.EMPTY_PAGE)
-# assert response.status == 401
-# assert response.ok is False
-
-# def test_should_work_with_correct_credentials_and_matching_origin(
-# playwright: Playwright, server: Server
-# ) -> None:
-# server.set_auth("/empty.html", "user", "pass")
-# request = playwright.request.new_context(
-# http_credentials={
-# "username": "user",
-# "password": "pass",
-# "origin": server.PREFIX,
-# }
-# )
-# response = request.get(server.EMPTY_PAGE)
-# assert response.status == 200
-# response.dispose()
-
-# def test_should_work_with_correct_credentials_and_matching_origin_case_insensitive(
-# playwright: Playwright, server: Server
-# ) -> None:
-# server.set_auth("/empty.html", "user", "pass")
-# request = playwright.request.new_context(
-# http_credentials={
-# "username": "user",
-# "password": "pass",
-# "origin": server.PREFIX.upper(),
-# }
-# )
-# response = request.get(server.EMPTY_PAGE)
-# assert response.status == 200
-# response.dispose()
-
-# def test_should_return_error_with_correct_credentials_and_mismatching_scheme(
-# playwright: Playwright, server: Server
-# ) -> None:
-# server.set_auth("/empty.html", "user", "pass")
-# request = playwright.request.new_context(
-# http_credentials={
-# "username": "user",
-# "password": "pass",
-# "origin": server.PREFIX.replace("http://", "https://"),
-# }
-# )
-# response = request.get(server.EMPTY_PAGE)
-# assert response.status == 401
-# response.dispose()
-
-# def test_should_return_error_with_correct_credentials_and_mismatching_hostname(
-# playwright: Playwright, server: Server
-# ) -> None:
-# server.set_auth("/empty.html", "user", "pass")
-# hostname = urlparse(server.PREFIX).hostname
-# assert hostname
-# origin = server.PREFIX.replace(hostname, "mismatching-hostname")
-# request = playwright.request.new_context(
-# http_credentials={"username": "user", "password": "pass", "origin": origin}
-# )
-# response = request.get(server.EMPTY_PAGE)
-# assert response.status == 401
-# response.dispose()
-
-# def test_should_return_error_with_correct_credentials_and_mismatching_port(
-# playwright: Playwright, server: Server
-# ) -> None:
-# server.set_auth("/empty.html", "user", "pass")
-# origin = server.PREFIX.replace(str(server.PORT), str(server.PORT + 1))
-# request = playwright.request.new_context(
-# http_credentials={"username": "user", "password": "pass", "origin": origin}
-# )
-# response = request.get(server.EMPTY_PAGE)
-# assert response.status == 401
-# response.dispose()
-
-# def test_should_support_global_ignore_https_errors_option(
-# playwright: Playwright, https_server: Server
-# ) -> None:
-# request = playwright.request.new_context(ignore_https_errors=True)
-# response = request.get(https_server.EMPTY_PAGE)
-# assert response.status == 200
-# assert response.ok is True
-# assert response.url == https_server.EMPTY_PAGE
-# response.dispose()
-
-# def test_should_resolve_url_relative_to_global_base_url_option(
-# playwright: Playwright, server: Server
-# ) -> None:
-# request = playwright.request.new_context(base_url=server.PREFIX)
-# response = request.get("/empty.html")
-# assert response.status == 200
-# assert response.ok is True
-# assert response.url == server.EMPTY_PAGE
-# response.dispose()
-
-# def test_should_use_playwright_as_a_user_agent(
-# playwright: Playwright, server: Server
-# ) -> None:
-# request = playwright.request.new_context()
-# with server.expect_request("/empty.html") as server_req:
-# request.get(server.EMPTY_PAGE)
-# assert str(server_req.value.getHeader("User-Agent")).startswith("Playwright/")
-# request.dispose()
-
-# def test_should_return_empty_body(playwright: Playwright, server: Server) -> None:
-# request = playwright.request.new_context()
-# response = request.get(server.EMPTY_PAGE)
-# body = response.body()
-# assert len(body) == 0
-# assert response.text() == ""
-# request.dispose()
-# with pytest.raises(Error, match="Response has been disposed"):
-# response.body()
-
-# def test_storage_state_should_round_trip_through_file(
-# playwright: Playwright, tmpdir: Path
-# ) -> None:
-# expected: StorageState = {
-# "cookies": [
-# {
-# "name": "a",
-# "value": "b",
-# "domain": "a.b.one.com",
-# "path": "/",
-# "expires": -1,
-# "httpOnly": False,
-# "secure": False,
-# "sameSite": "Lax",
-# }
-# ],
-# "origins": [],
-# }
-# request = playwright.request.new_context(storage_state=expected)
-# path = tmpdir / "storage-state.json"
-# actual = request.storage_state(path=path)
-# assert actual == expected
-
-# written = path.read_text("utf8")
-# assert json.loads(written) == expected
-
-# request2 = playwright.request.new_context(storage_state=path)
-# state2 = request2.storage_state()
-# assert state2 == expected
-
-# def test_should_throw_an_error_when_max_redirects_is_exceeded(
-# playwright: Playwright, server: Server
-# ) -> None:
-# server.set_redirect("/a/redirect1", "/b/c/redirect2")
-# server.set_redirect("/b/c/redirect2", "/b/c/redirect3")
-# server.set_redirect("/b/c/redirect3", "/b/c/redirect4")
-# server.set_redirect("/b/c/redirect4", "/simple.json")
-
-# request = playwright.request.new_context()
-# for method in ["GET", "PUT", "POST", "OPTIONS", "HEAD", "PATCH"]:
-# for max_redirects in [1, 2, 3]:
-# with pytest.raises(Error) as exc_info:
-# request.fetch(
-# server.PREFIX + "/a/redirect1",
-# method=method,
-# max_redirects=max_redirects,
-# )
-# assert "Max redirect count exceeded" in str(exc_info)
-
-# def test_should_not_follow_redirects_when_max_redirects_is_set_to_0(
-# playwright: Playwright, server: Server
-# ) -> None:
-# server.set_redirect("/a/redirect1", "/b/c/redirect2")
-# server.set_redirect("/b/c/redirect2", "/simple.json")
-
-# request = playwright.request.new_context()
-# for method in ["GET", "PUT", "POST", "OPTIONS", "HEAD", "PATCH"]:
-# response = request.fetch(
-# server.PREFIX + "/a/redirect1", method=method, max_redirects=0
-# )
-# assert response.headers["location"] == "/b/c/redirect2"
-# assert response.status == 302
-
-# def test_should_throw_an_error_when_max_redirects_is_less_than_0(
-# playwright: Playwright,
-# server: Server,
-# ) -> None:
-# request = playwright.request.new_context()
-# for method in ["GET", "PUT", "POST", "OPTIONS", "HEAD", "PATCH"]:
-# with pytest.raises(AssertionError) as exc_info:
-# request.fetch(
-# server.PREFIX + "/a/redirect1", method=method, max_redirects=-1
-# )
-# assert "'max_redirects' must be greater than or equal to '0'" in str(exc_info)
-
-# def test_should_serialize_null_values_in_json(
-# playwright: Playwright, server: Server
-# ) -> None:
-# request = playwright.request.new_context()
-# server.set_route("/echo", lambda req: (req.write(req.post_body), req.finish()))
-# response = request.post(server.PREFIX + "/echo", data={"foo": None})
-# assert response.status == 200
-# assert response.text() == '{"foo": null}'
-# request.dispose()