Skip to content

Commit

Permalink
Implement basic versions of Page.Keyboard
Browse files Browse the repository at this point in the history
What changed?
=============

We implement a basic version of `Page.Keyboard` functions whose specs
were commented out in the module.

The test cases are the simplest versions I could come up with (having
borrowed heavily from [Python's keyboard tests])

The implementation also follows [Python's implementations].

[Python's keyboard tests]: https://github.com/microsoft/playwright-python/blob/2402e1283de6049cb66ea8ec6f303ba681890d2a/tests/async/test_keyboard.py#L1
[Python's implementations]: https://github.com/microsoft/playwright-python/blob/2402e1283de6049cb66ea8ec6f303ba681890d2a/playwright/_impl/_input.py#L25-L38

Noteworthy Highlights
----------------------

1. Our implementation takes a `%Page{}` struct rather than what the
   specs suggested (a `Keyboard.t()`). I don't know if it's possible to
   pass down a narrower type, but as far as I could tell `Page` had both
   the `session` and `guid` (which are needed for the `Channel.post`
   call).

2. We namespace `Playwright.Keyboard` under `Page` (i.e.
   `Playwright.Page.Keyboard`)  to match the directory structure and
   since that seems to match the Playwright documentation as well.

3. Finally, we add a new `test/assets/` directory where we include a new
   `inputs/keyboard.html` page. That page is [copied directly from
   Python][keyboard.html], so it follows Python's style of testing. In
   particular, our tests needed the `getResult()` function to get the
   values back for our test assertions.

[keyboard.html]: https://github.com/microsoft/playwright-python/blob/2402e1283de6049cb66ea8ec6f303ba681890d2a/tests/assets/input/keyboard.html#L1
  • Loading branch information
germsvel committed May 30, 2024
1 parent fab2462 commit e4ffe54
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 11 deletions.
38 changes: 27 additions & 11 deletions lib/playwright/page/keyboard.ex
Original file line number Diff line number Diff line change
@@ -1,19 +1,35 @@
defmodule Playwright.Keyboard do
defmodule Playwright.Page.Keyboard do
@moduledoc false

# @spec down(t(), binary()) :: :ok
# def down(keyboard, key)
alias Playwright.Channel
alias Playwright.Page

# @spec insert_text(t(), binary()) :: :ok
# def insert_text(keyboard, text)
@spec type(Page.t(), binary()) :: :ok
def type(page, text) do
channel_post(page, :keyboard_type, %{text: text})
end

# @spec press(t(), binary(), options()) :: :ok
# def press(keyboard, key, options \\ %{})
@spec insert_text(Page.t(), binary()) :: :ok
def insert_text(page, text) do
channel_post(page, :keyboard_type, %{text: text})
end

# @spec type(t(), binary(), options()) :: :ok
# def type(keyboard, text, options \\ %{})
@spec up(Page.t(), binary()) :: :ok
def up(page, key) do
channel_post(page, :keyboard_up, %{key: key})
end

# @spec up(t(), binary()) :: :ok
# def up(keyboard, key)
@spec down(Page.t(), binary()) :: :ok
def down(page, key) do
channel_post(page, :keyboard_down, %{key: key})
end

@spec press(Page.t(), binary()) :: :ok
def press(page, key) do
channel_post(page, :keyboard_press, %{key: key})
end

defp channel_post(%Page{} = page, action, data) do
Channel.post(page.session, {:guid, page.guid}, action, data)
end
end
42 changes: 42 additions & 0 deletions test/assets/input/keyboard.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<title>Keyboard test</title>
</head>
<body>
<textarea></textarea>
<script>
window.result = "";
let textarea = document.querySelector('textarea');
textarea.focus();
textarea.addEventListener('keydown', event => {
log('Keydown:', event.key, event.code, event.which, modifiers(event));
});
textarea.addEventListener('keypress', event => {
log('Keypress:', event.key, event.code, event.which, event.charCode, modifiers(event));
});
textarea.addEventListener('keyup', event => {
log('Keyup:', event.key, event.code, event.which, modifiers(event));
});
function modifiers(event) {
let m = [];
if (event.altKey)
m.push('Alt')
if (event.ctrlKey)
m.push('Control');
if (event.shiftKey)
m.push('Shift')
return '[' + m.join(' ') + ']';
}
function log(...args) {
console.log.apply(console, args);
result += args.join(' ') + '\n';
}
function getResult() {
let temp = result.trim();
result = "";
return temp;
}
</script>
</body>
</html>
78 changes: 78 additions & 0 deletions test/integration/page/keyboard_test.exs
Original file line number Diff line number Diff line change
@@ -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

Check failure on line 8 in test/integration/page/keyboard_test.exs

View workflow job for this annotation

GitHub Actions / Build & Test

test type keyboard type into a textbox (Playwright.Page.KeyboardTest)
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

Check failure on line 24 in test/integration/page/keyboard_test.exs

View workflow job for this annotation

GitHub Actions / Build & Test

test insert_text should send characters inserted (Playwright.Page.KeyboardTest)
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

Check failure on line 40 in test/integration/page/keyboard_test.exs

View workflow job for this annotation

GitHub Actions / Build & Test

test up sends proper code (Playwright.Page.KeyboardTest)
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

Check failure on line 51 in test/integration/page/keyboard_test.exs

View workflow job for this annotation

GitHub Actions / Build & Test

test down sends proper code (Playwright.Page.KeyboardTest)
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

Check failure on line 62 in test/integration/page/keyboard_test.exs

View workflow job for this annotation

GitHub Actions / Build & Test

test press test should press plus (Playwright.Page.KeyboardTest)
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

0 comments on commit e4ffe54

Please sign in to comment.