diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9eb5790..83fe3740 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,11 @@ jobs: otp-version: '26.2.5' - name: Install Elixir dependencies run: mix deps.get - - name: Install Node dependencies - run: npm install --prefix assets + - name: Install Playwright dependencies (e.g., browsers) + run: mix playwright.install + # NOTE: not needed for now, while assets are + # directly installed to `priv/static`. + # - name: Install Node dependencies + # run: npm install --prefix assets - name: Run tests run: mix test diff --git a/lib/playwright/page/keyboard.ex b/lib/playwright/page/keyboard.ex index bb0c6ddb..940f23a9 100644 --- a/lib/playwright/page/keyboard.ex +++ b/lib/playwright/page/keyboard.ex @@ -1,19 +1,41 @@ -defmodule Playwright.Keyboard do +defmodule Playwright.Page.Keyboard do @moduledoc false - # @spec down(t(), binary()) :: :ok - # def down(keyboard, key) + use Playwright.SDK.ChannelOwner + alias Playwright.Page - # @spec insert_text(t(), binary()) :: :ok - # def insert_text(keyboard, text) + # API + # --------------------------------------------------------------------------- - # @spec press(t(), binary(), options()) :: :ok - # def press(keyboard, key, options \\ %{}) + @spec down(Page.t(), binary()) :: :ok + def down(page, key) do + channel_post(page, :keyboard_down, %{key: key}) + end - # @spec type(t(), binary(), options()) :: :ok - # def type(keyboard, text, options \\ %{}) + @spec insert_text(Page.t(), binary()) :: :ok + def insert_text(page, text) do + channel_post(page, :keyboard_type, %{text: text}) + end - # @spec up(t(), binary()) :: :ok - # def up(keyboard, key) + @spec press(Page.t(), binary()) :: :ok + def press(page, key) do + channel_post(page, :keyboard_press, %{key: key}) + end + @spec type(Page.t(), binary()) :: :ok + def type(page, text) do + channel_post(page, :keyboard_type, %{text: text}) + end + + @spec up(Page.t(), binary()) :: :ok + def up(page, key) do + channel_post(page, :keyboard_up, %{key: key}) + end + + # private + # --------------------------------------------------------------------------- + + defp channel_post(%Page{} = page, action, data) do + Channel.post(page.session, {:guid, page.guid}, action, data) + end end diff --git a/lib/playwright/sdk/cli.ex b/lib/playwright/sdk/cli.ex index 7a1c2e41..c80881b2 100644 --- a/lib/playwright/sdk/cli.ex +++ b/lib/playwright/sdk/cli.ex @@ -6,21 +6,13 @@ defmodule Playwright.SDK.CLI do require Logger def install do - Logger.info("Installing playwright browsers") + Logger.info("Installing playwright browsers and dependencies") cli_path = config_cli() || default_cli() - {result, exit_status} = System.cmd(cli_path, ["install"]) + {result, exit_status} = System.cmd(cli_path, ["install", "--with-deps"]) Logger.info(result) if exit_status != 0, do: raise("Failed to install playwright browsers") end - def install_deps do - Logger.info("Installing playwright deps") - cli_path = config_cli() || default_cli() - {result, exit_status} = System.cmd(cli_path, ["installdeps"]) - Logger.info(result) - if exit_status != 0, do: raise("Failed to install playwright deps") - end - # private # ---------------------------------------------------------------------------- diff --git a/test/integration/locator_test.exs b/test/integration/locator_test.exs index 36fff140..8b5da1ca 100644 --- a/test/integration/locator_test.exs +++ b/test/integration/locator_test.exs @@ -40,7 +40,7 @@ defmodule Playwright.LocatorTest do describe "Locator.check/2" do setup(%{assets: assets, page: page}) do - options = %{timeout: 200} + options = %{timeout: 500} page |> Page.goto(assets.prefix <> "/empty.html") page |> Page.set_content("") @@ -59,13 +59,13 @@ defmodule Playwright.LocatorTest do frame = Page.main_frame(page) locator = Locator.new(frame, "input#bogus") - assert {:error, %Error{message: "Timeout 200ms exceeded."}} = Locator.check(locator, options) + assert {:error, %Error{message: "Timeout 500ms exceeded."}} = Locator.check(locator, options) end end describe "Locator.click/2" do setup(%{assets: assets, page: page}) do - options = %{timeout: 200} + options = %{timeout: 500} page |> Page.goto(assets.prefix <> "/empty.html") page |> Page.set_content("yo") @@ -84,14 +84,14 @@ defmodule Playwright.LocatorTest do frame = Page.main_frame(page) locator = Locator.new(frame, "a#bogus") - assert {:error, %Error{message: "Timeout 200ms exceeded."}} = Locator.click(locator, options) + assert {:error, %Error{message: "Timeout 500ms exceeded."}} = Locator.click(locator, options) end test "clicking a button", %{assets: assets, page: page} do locator = Page.locator(page, "button") page |> Page.goto(assets.prefix <> "/input/button.html") - Locator.click(locator, %{timeout: 200}) + Locator.click(locator, %{timeout: 500}) assert Page.evaluate(page, "window['result']") == "Clicked" end end @@ -112,7 +112,7 @@ defmodule Playwright.LocatorTest do } """) - Locator.dblclick(locator, %{timeout: 200}) + Locator.dblclick(locator, %{timeout: 500}) assert Page.evaluate(page, "window['double']") == true assert Page.evaluate(page, "window['result']") == "Clicked" end @@ -694,7 +694,7 @@ defmodule Playwright.LocatorTest do describe "Locator.uncheck/2" do setup(%{assets: assets, page: page}) do - options = %{timeout: 200} + options = %{timeout: 500} page |> Page.goto(assets.prefix <> "/empty.html") page |> Page.set_content("") @@ -712,13 +712,13 @@ defmodule Playwright.LocatorTest do test "returns a timeout error when unable to 'uncheck'", %{options: options, page: page} do locator = Page.locator(page, "input#bogus") - assert {:error, %Error{message: "Timeout 200ms exceeded."}} = Locator.uncheck(locator, options) + assert {:error, %Error{message: "Timeout 500ms exceeded."}} = Locator.uncheck(locator, options) end end describe "Locator.wait_for/2" do setup(%{assets: assets, page: page}) do - options = %{timeout: 200} + options = %{timeout: 500} page |> Page.goto(assets.prefix <> "/empty.html") diff --git a/test/integration/page/expect_test.exs b/test/integration/page/expect_test.exs index 79068cd0..c8a3405b 100644 --- a/test/integration/page/expect_test.exs +++ b/test/integration/page/expect_test.exs @@ -37,10 +37,10 @@ defmodule Playwright.Page.NetworkTest do test "w/ an event and a timeout", %{page: page} do {:error, %Error{message: message}} = Page.expect_event(page, :request_finished, %{ - timeout: 200 + timeout: 500 }) - assert message == "Timeout 200ms exceeded." + assert message == "Timeout 500ms exceeded." end test "w/ an event, a (truthy) predicate, and a timeout", %{assets: assets, page: page} do @@ -51,7 +51,7 @@ defmodule Playwright.Page.NetworkTest do predicate: fn _, _ -> true end, - timeout: 200 + timeout: 500 }) assert event.type == :request_finished @@ -65,10 +65,10 @@ defmodule Playwright.Page.NetworkTest do predicate: fn _, _ -> false end, - timeout: 200 + timeout: 500 }) - assert message == "Timeout 200ms exceeded." + assert message == "Timeout 500ms exceeded." end end @@ -115,14 +115,14 @@ defmodule Playwright.Page.NetworkTest do predicate: fn _, _ -> false end, - timeout: 200 + timeout: 500 }, fn -> Page.goto(page, assets.empty) end ) - assert message == "Timeout 200ms exceeded." + assert message == "Timeout 500ms exceeded." end test "w/ an event and a timeout", %{assets: assets, page: page} do @@ -131,7 +131,7 @@ defmodule Playwright.Page.NetworkTest do page, :request_finished, %{ - timeout: 200 + timeout: 500 }, fn -> Page.goto(page, assets.empty) diff --git a/test/integration/page/keyboard_test.exs b/test/integration/page/keyboard_test.exs new file mode 100644 index 00000000..fdd89512 --- /dev/null +++ b/test/integration/page/keyboard_test.exs @@ -0,0 +1,78 @@ +defmodule Playwright.Page.KeyboardTest do + use Playwright.TestCase, async: true + + alias Playwright.Page + alias Playwright.Page.Keyboard + + describe "type" do + test "keyboard type into a textbox", %{page: page} do + Page.evaluate(page, """ + const textarea = document.createElement('textarea'); + document.body.appendChild(textarea); + textarea.focus(); + """) + + text = "Hello world. I am the text that was typed!" + + Keyboard.type(page, text) + + assert Page.evaluate(page, ~s[document.querySelector("textarea").value]) == text + end + end + + describe "insert_text" do + test "should send characters inserted", %{page: page} do + Page.evaluate(page, """ + const textarea = document.createElement('textarea'); + document.body.appendChild(textarea); + textarea.focus(); + """) + + text = "Hello world. I am the text that was typed!" + + Keyboard.insert_text(page, text) + + assert Page.evaluate(page, ~s[document.querySelector("textarea").value]) == text + end + end + + describe "up" do + test "sends proper code", %{page: page, assets: assets} do + Page.goto(page, assets.prefix <> "/input/keyboard.html") + + Keyboard.up(page, ";") + + assert Page.evaluate(page, "() => getResult()") == + "Keyup: ; Semicolon 186 []" + end + end + + describe "down" do + test "sends proper code", %{page: page, assets: assets} do + Page.goto(page, assets.prefix <> "/input/keyboard.html") + + Keyboard.down(page, "Control") + + assert Page.evaluate(page, "() => getResult()") == + "Keydown: Control ControlLeft 17 [Control]" + end + end + + describe "press" do + test "test should press plus", %{page: page, assets: assets} do + Page.goto(page, assets.prefix <> "/input/keyboard.html") + + Keyboard.press(page, "+") + + assert Page.evaluate(page, "() => getResult()") == + [ + # 192 is ` keyCode + "Keydown: + Equal 187 []", + # 126 is ~ charCode + "Keypress: + Equal 43 43 []", + "Keyup: + Equal 187 []" + ] + |> Enum.join("\n") + end + end +end diff --git a/test/integration/page_test.exs b/test/integration/page_test.exs index 01635d4c..f417ed8f 100644 --- a/test/integration/page_test.exs +++ b/test/integration/page_test.exs @@ -220,8 +220,8 @@ defmodule Playwright.PageTest do test "with a single option given mismatched attributes, returns a timeout", %{assets: assets, page: page} do page |> Page.goto(assets.prefix <> "/input/select.html") - assert {:error, %Error{message: "Timeout 200ms exceeded."}} = - Page.select_option(page, "select", %{value: "green", label: "Brown"}, %{timeout: 200}) + assert {:error, %Error{message: "Timeout 500ms exceeded."}} = + Page.select_option(page, "select", %{value: "green", label: "Brown"}, %{timeout: 500}) end test "with multiple options and a single-option select, selects the first", %{assets: assets, page: page} do @@ -342,7 +342,7 @@ defmodule Playwright.PageTest do assert page |> Page.get_attribute("div#outer", "name") == "value" assert page |> Page.get_attribute("div#outer", "foo") == nil - assert({:error, %Error{}} = Page.get_attribute(page, "glorp", "foo", %{timeout: 200})) + assert({:error, %Error{}} = Page.get_attribute(page, "glorp", "foo", %{timeout: 500})) end end