diff --git a/lib/playwright/api_request.ex b/lib/playwright/api_request.ex index aff4f18..1be92de 100644 --- a/lib/playwright/api_request.ex +++ b/lib/playwright/api_request.ex @@ -15,6 +15,9 @@ defmodule Playwright.APIRequest do alias Playwright.APIRequestContext alias Playwright.SDK.Channel + # structs & types + # ---------------------------------------------------------------------------- + @enforce_keys [:guid, :session] defstruct [:guid, :session] @@ -101,6 +104,9 @@ defmodule Playwright.APIRequest do required(:value) => String.t() } + # API + # ---------------------------------------------------------------------------- + @doc """ Returns a new `Playwright.APIRequest`. diff --git a/lib/playwright/api_request_context.ex b/lib/playwright/api_request_context.ex index 60ad0d6..340e4c5 100644 --- a/lib/playwright/api_request_context.ex +++ b/lib/playwright/api_request_context.ex @@ -59,7 +59,7 @@ defmodule Playwright.APIRequestContext do alias Playwright.API.Error alias Playwright.SDK.Channel - # types + # structs & types # ---------------------------------------------------------------------------- @typedoc "Options for the various request types." diff --git a/lib/playwright/api_response.ex b/lib/playwright/api_response.ex index 92e35b8..28f4556 100644 --- a/lib/playwright/api_response.ex +++ b/lib/playwright/api_response.ex @@ -18,6 +18,9 @@ defmodule Playwright.APIResponse do alias Playwright.API.Error alias Playwright.SDK.Channel + # structs & types + # ---------------------------------------------------------------------------- + defstruct [:context, :fetchUid, :headers, :status, :statusText, :url] @typedoc """ @@ -35,6 +38,9 @@ defmodule Playwright.APIResponse do @typedoc "Data serializable as JSON." @type serializable() :: list() | map() + # API + # ---------------------------------------------------------------------------- + @doc """ Returns a `Playwright.APIResponse` hydrated from the provided `properties`. @@ -171,6 +177,10 @@ defmodule Playwright.APIResponse do Returns a boolean indicating whether the response was successful. Success means the response status code is within the range of `200-299`. + + ## Returns + + - `boolean()` """ @pipe {:ok, [:response]} @spec ok(t()) :: boolean() diff --git a/lib/playwright/sdk/channel.ex b/lib/playwright/sdk/channel.ex index 2a2196e..d51853f 100644 --- a/lib/playwright/sdk/channel.ex +++ b/lib/playwright/sdk/channel.ex @@ -52,7 +52,7 @@ defmodule Playwright.SDK.Channel do @spec post({resource(), atom() | String.t()}, map(), map()) :: any() | {:error, any()} def post({resource, action}, params \\ %{}, options \\ %{}) when is_struct(resource) - when is_atom(action) do + when is_atom(action) or is_binary(action) do {refresh?, params} = Map.pop(Map.merge(%{refresh: true}, Map.merge(params, options)), :refresh) connection = Session.connection(resource.session) message = Message.new(resource.guid, action, params) diff --git a/test/api/api_response_test.exs b/test/api/api_response_test.exs index 699e3cd..3d6c14b 100644 --- a/test/api/api_response_test.exs +++ b/test/api/api_response_test.exs @@ -1,10 +1,47 @@ defmodule Playwright.APIResponseTest do use Playwright.TestCase, async: true + alias Playwright.API.Error alias Playwright.APIRequest alias Playwright.APIResponse alias Playwright.APIRequestContext - describe "APIResponse.dispose/" do + describe "APIResponse.body/1" do + test "on success, returns response body", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/simple.json") + + assert "{\"foo\": \"bar\"}\n" = APIResponse.body(response) + end + + test "on failure, returns `{:error, error}`", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/simple.json") + response = %{response | fetchUid: "bogus"} + + assert {:error, %Error{type: "ResponseError"}} = APIResponse.body(response) + end + + test "on HTTP error, returns status code as the response body", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/bogus.json") + + assert "404" = APIResponse.body(response) + end + end + + describe "APIResponse.body!/1" do + test "on failure, raises", %{assets: assets, session: session} do + assert_raise RuntimeError, fn -> + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/simple.json") + response = %{response | fetchUid: "bogus"} + + APIResponse.body!(response) + end + end + end + + describe "APIResponse.dispose/1" do test "on success, causes subsequent usage of `APIResponse` to fail", %{assets: assets, session: session} do request = Playwright.request(session) |> APIRequest.new_context() response = APIRequestContext.fetch(request, assets.prefix <> "/simple.json") @@ -12,5 +49,161 @@ defmodule Playwright.APIResponseTest do assert :ok = APIResponse.dispose(response) assert {:error, %{type: "ResponseError", message: "Response has been disposed"}} = APIResponse.body(response) end + + test "on failure, returns `{:error, error}`", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/simple.json") + response = %{response | context: %{guid: "bogus", session: session}} + + assert {:error, %Error{type: "TargetClosedError"}} = APIResponse.dispose(response) + end + end + + describe "APIResponse.dispose!/1" do + test "on failure, raises", %{assets: assets, session: session} do + assert_raise RuntimeError, fn -> + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/simple.json") + response = %{response | context: %{guid: "bogus", session: session}} + + APIResponse.dispose!(response) + end + end + end + + describe "APIResponse.header/1" do + test "on success, returns the value of the HTTP header", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/simple.json") + + assert "application/json" = APIResponse.header(response, "content-type") + end + + test "when the HTTP header is not found, returns `nil`", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/simple.json") + + assert APIResponse.header(response, "bogus") == nil + end + end + + describe "APIResponse.header!/1" do + test "on success, returns the value of the HTTP header", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/simple.json") + + assert "application/json" = APIResponse.header(response, "content-type") + end + + # @tag :skip + # ...haven't found a way to fail + # test "on failure, raises", %{assets: assets, session: session} do + # end + end + + describe "APIResponse.headers/1" do + end + + describe "APIResponse.headers!/1" do + end + + describe "APIResponse.json/1" do + test "on success, returns response body", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/simple.json") + + assert %{"foo" => "bar"} = APIResponse.json(response) + end + + test "on failure, returns `{:error, error}`", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/simple.json") + response = %{response | fetchUid: "bogus"} + + assert {:error, %Error{type: "ResponseError"}} = APIResponse.json(response) + end + + test "on HTTP error, returns status code as the response body", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/bogus.json") + + assert 404 = APIResponse.json(response) + end + end + + describe "APIResponse.json!/1" do + test "on failure, raises", %{assets: assets, session: session} do + assert_raise RuntimeError, fn -> + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/simple.json") + response = %{response | fetchUid: "bogus"} + + APIResponse.json!(response) + end + end + end + + describe "APIResponse.ok/1" do + test "is true when the response status code is in the range, 200-299" do + range = 200..299 + + Enum.each(range, fn code -> + assert APIResponse.ok(%APIResponse{status: code}) + end) + end + + test "is true when the response status code is 0" do + assert APIResponse.ok(%APIResponse{status: 0}) + end + + test "is false otherwise" do + range = 1..199 + + Enum.each(range, fn code -> + refute APIResponse.ok(%APIResponse{status: code}) + end) + + range = 300..999 + + Enum.each(range, fn code -> + refute APIResponse.ok(%APIResponse{status: code}) + end) + end + end + + describe "APIResponse.text/1" do + test "on success, returns response body", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/empty.html") + + assert APIResponse.text(response) == "" + end + + test "on failure, returns `{:error, error}`", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/empty.html") + response = %{response | fetchUid: "bogus"} + + assert {:error, %Error{type: "ResponseError"}} = APIResponse.text(response) + end + + test "on HTTP error, returns status code as the response body", %{assets: assets, session: session} do + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/bogus.text") + + assert "404" = APIResponse.text(response) + end + end + + describe "APIResponse.text!/1" do + test "on failure, raises", %{assets: assets, session: session} do + assert_raise RuntimeError, fn -> + request = Playwright.request(session) |> APIRequest.new_context() + response = APIRequestContext.fetch(request, assets.prefix <> "/empty.html") + response = %{response | fetchUid: "bogus"} + + APIResponse.text!(response) + end + end end end