diff --git a/lib/playwright/api_request_context.ex b/lib/playwright/api_request_context.ex index fd8b7d7..e29d740 100644 --- a/lib/playwright/api_request_context.ex +++ b/lib/playwright/api_request_context.ex @@ -93,16 +93,53 @@ defmodule Playwright.APIRequestContext do # API # ---------------------------------------------------------------------------- - # @spec delete(t(), binary(), options()) :: APIResponse.t() - # def delete(context, url, options \\ %{}) + @doc """ + Sends an HTTP(S) [`DELETE`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE) + request and returns its response. + + Function invocation will populate request cookies from the context, and update + context cookies from the response. Calls automatically follow redirects. + + ## Usage + + request = Playwright.request(session) + context = APIRequest.new_context(request) + + APIRequest.delete(context, "https://example.com/api/books") + + ## Arguments + + | name | | description | + | ---------------- | ---------- | --------------------------------- | + | `context` | | The "subject" `APIRequestContext` | + | `url` | | Target URL | + | `options` | (optional) | `APIRequestContext.options()` | + + ## Options + + See "Shared options" above. + + ## Returns + + - `Playwright.APIResponse.t()` + - `{:error, Error.t()}` + """ + @spec delete(t(), binary(), options()) :: t() | {:error, Error.t()} + def delete(context, url, options \\ %{}) + + def delete(%APIRequestContext{} = context, url, options) do + fetch(context, url, Map.merge(options, %{method: "DELETE"})) + end # @spec dispose(t()) :: t() # def dispose(api_request_context) + # --- + @doc """ Sends an HTTP(S) request and returns the response (`Playwright.APIResponse`). - The function will populate request cookies from the context, and update + Function invocation will populate request cookies from the context, and update context cookies from the response. ## Usage @@ -138,14 +175,20 @@ defmodule Playwright.APIRequestContext do ## Arguments - | name | | description | - | ---------------- | ---------- | ----------------------------- | - | `url_or_request` | | The "subject" `APIRequest` | - | `options` | (optional) | `APIRequestContext.options()` | + | name | | description | + | ---------------- | ---------- | --------------------------------- | + | `context` | | The "subject" `APIRequestContext` | + | `url` | | Target URL | + | `options` | (optional) | `APIRequestContext.options()` | ## Options See "Shared options" above. + + ## Returns + + - `Playwright.APIResponse.t()` + - `{:error, Error.t()}` """ @spec fetch(t(), binary() | Request.t(), options()) :: APIResponse.t() | {:error, Error.t()} def fetch(context, url_or_request, options \\ %{}) @@ -160,22 +203,204 @@ defmodule Playwright.APIRequestContext do end end - # @spec get(t(), binary(), options()) :: APIResponse.t() - # def get(context, url, options \\ %{}) + @doc """ + Sends an HTTP(S) [`GET`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/GET) + request and returns its response. + + Function invocation will populate request cookies from the context, and update + context cookies from the response. Calls automatically follow redirects. + + ## Usage + + request = Playwright.request(session) + context = APIRequest.new_context(request) + + APIRequest.get(context, "https://example.com/api/books", %{ + params: %{isbn: "1234", page: "23"} + }) + + ## Arguments + + | name | | description | + | ---------------- | ---------- | --------------------------------- | + | `context` | | The "subject" `APIRequestContext` | + | `url` | | Target URL | + | `options` | (optional) | `APIRequestContext.options()` | + + ## Options + + See "Shared options" above. + + ## Returns + + - `Playwright.APIResponse.t()` + - `{:error, Error.t()}` + """ + @spec get(t(), binary(), options()) :: t() | {:error, Error.t()} + def get(context, url, options \\ %{}) + + def get(%APIRequestContext{} = context, url, options) do + fetch(context, url, Map.merge(options, %{method: "GET"})) + end + + @doc """ + Sends an HTTP(S) [`HEAD`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEAD) + request and returns its response. + + Function invocation will populate request cookies from the context, and update + context cookies from the response. Calls automatically follow redirects. + + ## Usage + + request = Playwright.request(session) + context = APIRequest.new_context(request) + + APIRequest.head(context, "https://example.com/api/books") + + ## Arguments + + | name | | description | + | ---------------- | ---------- | --------------------------------- | + | `context` | | The "subject" `APIRequestContext` | + | `url` | | Target URL | + | `options` | (optional) | `APIRequestContext.options()` | - # @spec head(t(), binary(), options()) :: APIResponse.t() - # def head(context, url, options \\ %{}) + ## Options + + See "Shared options" above. + + ## Returns - # @spec patch(t(), binary(), options()) :: APIResponse.t() - # def patch(context, url, options \\ %{}) + - `Playwright.APIResponse.t()` + - `{:error, Error.t()}` + """ + @spec head(t(), binary(), options()) :: t() | {:error, Error.t()} + def head(context, url, options \\ %{}) + + def head(%APIRequestContext{} = context, url, options) do + fetch(context, url, Map.merge(options, %{method: "HEAD"})) + end - # @spec post(t(), binary(), options()) :: Playwright.APIResponse.t() - # def post(%APIRequestContext{} = context, url, options \\ %{}) do - # Channel.post({context, :fetch}, %{url: url, method: "POST"}, options) - # end + @doc """ + Sends an HTTP(S) [`PATCH`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH) + request and returns its response. - # @spec put(t(), binary(), options()) :: APIResponse.t() - # def put(context, url, options \\ %{}) + Function invocation will populate request cookies from the context, and update + context cookies from the response. Calls automatically follow redirects. + + ## Usage + + request = Playwright.request(session) + context = APIRequest.new_context(request) + + APIRequest.patch(context, "https://example.com/api/books", %{ + data: %{title: "Updated"}, + params: %{isbn: "1234"} + }) + + ## Arguments + + | name | | description | + | ---------------- | ---------- | --------------------------------- | + | `context` | | The "subject" `APIRequestContext` | + | `url` | | Target URL | + | `options` | (optional) | `APIRequestContext.options()` | + + ## Options + + See "Shared options" above. + + ## Returns + + - `Playwright.APIResponse.t()` + - `{:error, Error.t()}` + """ + @spec patch(t(), binary(), options()) :: t() | {:error, Error.t()} + def patch(context, url, options \\ %{}) + + def patch(%APIRequestContext{} = context, url, options) do + fetch(context, url, Map.merge(options, %{method: "PATCH"})) + end + + @doc """ + Sends an HTTP(S) [`POST`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) + request and returns its response. + + Function invocation will populate request cookies from the context, and update + context cookies from the response. Calls automatically follow redirects. + + ## Usage + + request = Playwright.request(session) + context = APIRequest.new_context(request) + + APIRequest.post(context, "https://example.com/api/books", %{ + data: %{title: "Updated"} + }) + + ## Arguments + + | name | | description | + | ---------------- | ---------- | --------------------------------- | + | `context` | | The "subject" `APIRequestContext` | + | `url` | | Target URL | + | `options` | (optional) | `APIRequestContext.options()` | + + ## Options + + See "Shared options" above. + + ## Returns + + - `Playwright.APIResponse.t()` + - `{:error, Error.t()}` + """ + @spec post(t(), binary(), options()) :: t() | {:error, Error.t()} + def post(context, url, options \\ %{}) + + def post(%APIRequestContext{} = context, url, options) do + fetch(context, url, Map.merge(options, %{method: "POST"})) + end + + @doc """ + Sends an HTTP(S) [`PUT`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PUT) + request and returns its response. + + Function invocation will populate request cookies from the context, and update + context cookies from the response. Calls automatically follow redirects. + + ## Arguments + + | name | | description | + | ---------------- | ---------- | --------------------------------- | + | `context` | | The "subject" `APIRequestContext` | + | `url` | | Target URL | + | `options` | (optional) | `APIRequestContext.options()` | + + ## Usage + + request = Playwright.request(session) + context = APIRequest.new_context(request) + + APIRequest.put(context, "https://example.com/api/books", %{ + data: %{title: "Updated"} + }) + + ## Options + + See "Shared options" above. + + ## Returns + + - `Playwright.APIResponse.t()` + - `{:error, Error.t()}` + """ + @spec put(t(), binary(), options()) :: t() | {:error, Error.t()} + def put(context, url, options \\ %{}) + + def put(%APIRequestContext{} = context, url, options) do + fetch(context, url, Map.merge(options, %{method: "PUT"})) + end # @spec storage_state(t(), options()) :: StorageState.t() # def storage_state(context, options \\ %{}) diff --git a/mix.exs b/mix.exs index bde17ae..075ffbf 100644 --- a/mix.exs +++ b/mix.exs @@ -54,7 +54,7 @@ defmodule Playwright.MixProject do {:gun, "~> 1.3.3"}, {:jason, "~> 1.4"}, {:mix_audit, "~> 1.0", only: [:dev, :test], runtime: false}, - {:playwright_assets, "1.44.0", only: [:test]}, + {:playwright_assets, "1.44.1", only: [:test]}, {:recase, "~> 0.7"}, {:uuid, "~> 1.1"} ] diff --git a/mix.lock b/mix.lock index 6a3aed6..8ce51f9 100644 --- a/mix.lock +++ b/mix.lock @@ -15,16 +15,16 @@ "makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"}, "makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"}, "makeup_erlang": {:hex, :makeup_erlang, "1.0.0", "6f0eff9c9c489f26b69b61440bf1b238d95badae49adac77973cbacae87e3c2e", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "ea7a9307de9d1548d2a72d299058d1fd2339e3d398560a0e46c27dab4891e4d2"}, - "mime": {:hex, :mime, "2.0.5", "dc34c8efd439abe6ae0343edbb8556f4d63f178594894720607772a041b04b02", [:mix], [], "hexpm", "da0d64a365c45bc9935cc5c8a7fc5e49a0e0f9932a761c55d6c52b142780a05c"}, + "mime": {:hex, :mime, "2.0.6", "8f18486773d9b15f95f4f4f1e39b710045fa1de891fada4516559967276e4dc2", [:mix], [], "hexpm", "c9945363a6b26d747389aac3643f8e0e09d30499a138ad64fe8fd1d13d9b153e"}, "mix_audit": {:hex, :mix_audit, "1.0.1", "9dd114408961b8db214f42fee40b2f632ecd7e4fd29500403068c82c77db8361", [:make, :mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:yaml_elixir, "~> 2.8.0", [hex: :yaml_elixir, repo: "hexpm", optional: false]}], "hexpm", "65066bb7757078aa49faaa2f7c1e2d52f56ff6fe6cff01723dbaf5be2a75771b"}, "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, - "playwright_assets": {:hex, :playwright_assets, "1.44.0", "87276d2cf800c921fa475684699aa42df64d5df09fc3098ac81485be0feb8264", [:mix], [{:cowlib, "~> 2.7.3", [hex: :cowlib, repo: "hexpm", optional: false]}, {:plug, "~> 1.12", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.1.3", [hex: :plug_cowboy, repo: "hexpm", optional: false]}], "hexpm", "0e7788596f247db2c312992b70613a53a24b9f20d7dedeb76e37549f780066e8"}, - "plug": {:hex, :plug, "1.16.0", "1d07d50cb9bb05097fdf187b31cf087c7297aafc3fed8299aac79c128a707e47", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "cbf53aa1f5c4d758a7559c0bd6d59e286c2be0c6a1fac8cc3eee2f638243b93e"}, + "playwright_assets": {:hex, :playwright_assets, "1.44.1", "61f1d0a0f0e6cccfa25cc84afda8ccaba3a472cfe73a30fd8c44dba7ca6102b8", [:mix], [{:cowlib, "~> 2.7.3", [hex: :cowlib, repo: "hexpm", optional: false]}, {:plug, "~> 1.12", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.1.3", [hex: :plug_cowboy, repo: "hexpm", optional: false]}], "hexpm", "be655593929e8ab5dba4be8e44c84f49a35a58c4ced162414494b090328fff2e"}, + "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"}, "plug_cowboy": {:hex, :plug_cowboy, "2.1.3", "38999a3e85e39f0e6bdfdf820761abac61edde1632cfebbacc445cdcb6ae1333", [:mix], [{:cowboy, "~> 2.5", [hex: :cowboy, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "056f41f814dbb38ea44613e0f613b3b2b2f2c6afce64126e252837669eba84db"}, "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"}, "ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"}, "recase": {:hex, :recase, "0.8.0", "ec9500abee5d493d41e3cbfd7d51a4e10957a164570be0c805d5c6661b8cdbae", [:mix], [], "hexpm", "0d4b67b81e7897af77552bd1e6d6148717a4b45ec5c7b014a48b0ba9a28946b5"}, - "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, + "telemetry": {:hex, :telemetry, "1.3.0", "fedebbae410d715cf8e7062c96a1ef32ec22e764197f70cda73d82778d61e7a2", [:rebar3], [], "hexpm", "7015fc8919dbe63764f4b4b87a95b7c0996bd539e0d499be6ec9d7f3875b79e6"}, "uuid": {:hex, :uuid, "1.1.8", "e22fc04499de0de3ed1116b770c7737779f226ceefa0badb3592e64d5cfb4eb9", [:mix], [], "hexpm", "c790593b4c3b601f5dc2378baae7efaf5b3d73c4c6456ba85759905be792f2ac"}, "yamerl": {:hex, :yamerl, "0.10.0", "4ff81fee2f1f6a46f1700c0d880b24d193ddb74bd14ef42cb0bcf46e81ef2f8e", [:rebar3], [], "hexpm", "346adb2963f1051dc837a2364e4acf6eb7d80097c0f53cbdc3046ec8ec4b4e6e"}, "yaml_elixir": {:hex, :yaml_elixir, "2.8.0", "c7ff0034daf57279c2ce902788ce6fdb2445532eb4317e8df4b044209fae6832", [:mix], [{:yamerl, "~> 0.8", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "4b674bd881e373d1ac6a790c64b2ecb69d1fd612c2af3b22de1619c15473830b"}, diff --git a/test/api/api_request_context_test.exs b/test/api/api_request_context_test.exs index 07d127d..175071a 100644 --- a/test/api/api_request_context_test.exs +++ b/test/api/api_request_context_test.exs @@ -5,6 +5,11 @@ defmodule Playwright.APIRequestContextTest do alias Playwright.APIRequestContext describe "APIRequestContext.delete/3" do + test "on success, returns `APIResponse`", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.delete(request, assets.prefix <> "/simple.json") + assert APIResponse.ok(response) + end end describe "APIRequestContext.dispose/2" do @@ -16,9 +21,10 @@ defmodule Playwright.APIRequestContextTest do Enum.map(methods, fn method -> request = Playwright.request(session) |> APIRequest.new_context() - response = APIRequestContext.fetch(request, assets.prefix <> "/simple.json") + response = APIRequestContext.fetch(request, assets.prefix <> "/simple.json", %{method: method}) assert APIResponse.ok(response) + assert APIResponse.header(response, "x-playwright-request-method") == String.upcase(Atom.to_string(method)) assert APIResponse.header(response, "content-type") == "application/json" assert APIResponse.header(response, :"content-type") == "application/json" @@ -35,18 +41,43 @@ defmodule Playwright.APIRequestContextTest do end describe "APIRequestContext.get/3" do + test "on success, returns `APIResponse`", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.get(request, assets.prefix <> "/simple.json") + assert APIResponse.ok(response) + end end describe "APIRequestContext.head/3" do + test "on success, returns `APIResponse`", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.head(request, assets.prefix <> "/simple.json") + assert APIResponse.ok(response) + end end describe "APIRequestContext.patch/3" do + test "on success, returns `APIResponse`", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.patch(request, assets.prefix <> "/simple.json") + assert APIResponse.ok(response) + end end describe "APIRequestContext.post/3" do + test "on success, returns `APIResponse`", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.post(request, assets.prefix <> "/simple.json") + assert APIResponse.ok(response) + end end describe "APIRequestContext.put/3" do + test "on success, returns `APIResponse`", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.put(request, assets.prefix <> "/simple.json") + assert APIResponse.ok(response) + end end describe "APIRequestContext.storage_state/2" do