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