diff --git a/lib/src/test/java/com/microsoft/playwright/TestPageFill.java b/lib/src/test/java/com/microsoft/playwright/TestPageFill.java
new file mode 100644
index 00000000..ad018e17
--- /dev/null
+++ b/lib/src/test/java/com/microsoft/playwright/TestPageFill.java
@@ -0,0 +1,281 @@
+/**
+ * Copyright (c) Microsoft Corporation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.microsoft.playwright;
+
+import org.junit.jupiter.api.*;
+
+import java.io.IOException;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class TestPageFill {
+ private static Server server;
+ private static Browser browser;
+ private static boolean isChromium;
+ private static boolean isWebKit;
+ private static boolean isFirefox;
+ private BrowserContext context;
+ private Page page;
+
+ @BeforeAll
+ static void launchBrowser() {
+ Playwright playwright = Playwright.create();
+ BrowserType.LaunchOptions options = new BrowserType.LaunchOptions();
+ browser = playwright.chromium().launch(options);
+ isChromium = true;
+
+ }
+
+ @BeforeAll
+ static void startServer() throws IOException {
+ server = new Server(8907);
+ }
+
+ @AfterAll
+ static void stopServer() throws IOException {
+ browser.close();
+ server.stop();
+ server = null;
+ }
+
+ @BeforeEach
+ void setUp() {
+ context = browser.newContext();
+ page = context.newPage();
+ }
+
+ @AfterEach
+ void tearDown() {
+ context.close();
+ context = null;
+ page = null;
+ }
+
+ @Test
+ void shouldFillTextarea() {
+ page.navigate(server.PREFIX + "/input/textarea.html");
+ page.fill("textarea", "some value");
+ assertEquals("some value", page.evaluate("() => window['result']"));
+ }
+
+ @Test
+ void shouldFillInput() {
+ page.navigate(server.PREFIX + "/input/textarea.html");
+ page.fill("input", "some value");
+ assertEquals("some value", page.evaluate("() => window['result']"));
+ }
+
+ @Test
+ void shouldThrowOnUnsupportedInputs() {
+ page.navigate(server.PREFIX + "/input/textarea.html");
+ for (String type : new String[]{"color", "file"}) {
+ page.evalOnSelector("input", "(input, type) => input.setAttribute('type', type)", type);
+ try {
+ page.fill("input", "");
+ fail("fill should throw");
+ } catch (RuntimeException e) {
+ assertTrue(e.getMessage().contains("input of type \"" + type + "\" cannot be filled"), e.getMessage());
+ }
+ }
+ }
+
+ @Test
+ void shouldFillDifferentInputTypes() {
+ page.navigate(server.PREFIX + "/input/textarea.html");
+ for (String type : new String[]{"password", "search", "tel", "text", "url"}) {
+ page.evalOnSelector("input", "(input, type) => input.setAttribute('type', type)", type);
+ page.fill("input", "text " + type);
+ assertEquals("text " + type, page.evaluate("() => window['result']"));
+ }
+ }
+
+ @Test
+ void shouldFillDateInputAfterClicking() {
+ page.setContent("");
+ page.click("input");
+ page.fill("input", "2020-03-02");
+ assertEquals("2020-03-02", page.evalOnSelector("input", "input => input.value"));
+ }
+
+ @Test
+ void shouldThrowOnIncorrectDate() {
+ // TODO: test.skip(browserName === "webkit");
+ page.setContent("");
+ try {
+ page.fill("input", "2020-13-05");
+ fail("did not throw");
+ } catch (RuntimeException e) {
+ assertTrue(e.getMessage().contains("Malformed value"));
+ }
+ }
+
+ @Test
+ void shouldFillTimeInput() {
+ page.setContent("");
+ page.fill("input", "13:15");
+ assertEquals("13:15", page.evalOnSelector("input", "input => input.value"));
+ }
+
+ @Test
+ void shouldThrowOnIncorrectTime() {
+ // TODO: test.skip(browserName === "webkit");
+ page.setContent("");
+ try {
+ page.fill("input", "25:05");
+ fail("did not throw");
+ } catch (RuntimeException e) {
+ assertTrue(e.getMessage().contains("Malformed value"));
+ }
+ }
+
+ @Test
+ void shouldFillDatetimeLocalInput() {
+ page.setContent("");
+ page.fill("input", "2020-03-02T05:15");
+ assertEquals(page.evalOnSelector("input", "input => input.value"), "2020-03-02T05:15");
+ }
+
+ @Test
+ void shouldThrowOnIncorrectDatetimeLocal() {
+ // TODO: test.skip(browserName === "webkit" || browserName === "firefox");
+ page.setContent("");
+ try {
+ page.fill("input", "abc");
+ fail("did not throw");
+ } catch (RuntimeException e) {
+ assertTrue(e.getMessage().contains("Malformed value"));
+ }
+ }
+
+ @Test
+ void shouldFillContenteditable() {
+ page.navigate(server.PREFIX + "/input/textarea.html");
+ page.fill("div[contenteditable]", "some value");
+ assertEquals(page.evalOnSelector("div[contenteditable]", "div => div.textContent"), "some value");
+ }
+
+ @Test
+ void shouldFillElementsWithExistingValueAndSelection() {
+ page.navigate(server.PREFIX + "/input/textarea.html");
+
+ page.evalOnSelector("input", "input => input.value = 'value one'");
+ page.fill("input", "another value");
+ assertEquals("another value", page.evaluate("() => window['result']"));
+
+ page.evalOnSelector("input", "input => {\n" +
+ " input.selectionStart = 1;\n" +
+ " input.selectionEnd = 2;\n" +
+ "}");
+ page.fill("input", "maybe this one");
+ assertEquals("maybe this one", page.evaluate("() => window['result']"));
+
+ page.evalOnSelector("div[contenteditable]", "div => {\n" +
+ " div.innerHTML = 'some text some more text and even more text';\n" +
+ " const range = document.createRange();\n" +
+ " range.selectNodeContents(div.querySelector('span'));\n" +
+ " const selection = window.getSelection();\n" +
+ " selection.removeAllRanges();\n" +
+ " selection.addRange(range);\n" +
+ "}");
+ page.fill("div[contenteditable]", "replace with this");
+ assertEquals("replace with this", page.evalOnSelector("div[contenteditable]", "div => div.textContent"));
+ }
+
+ @Test
+ void shouldThrowWhenElementIsNotAnInputTextareaOrContenteditable() {
+ page.navigate(server.PREFIX + "/input/textarea.html");
+ try {
+ page.fill("body", "");
+ fail("did not throw");
+ } catch (RuntimeException e) {
+ assertTrue(e.getMessage().contains("Element is not an "));
+ }
+ }
+
+ void shouldThrowIfPassedANonStringValue() {
+ // Doesn't make sense in a strongly typed language
+ }
+
+ // TODO: not supported in sync api, tests internals
+ void shouldRetryOnDisabledElement() {
+ }
+ void shouldRetryOnInvisibleElement() {
+ }
+ @Test
+ void shouldBeAbleToFillTheBody() {
+ page.setContent("");
+ page.fill("body", "some value");
+ assertEquals("some value", page.evaluate("() => document.body.textContent"));
+ }
+
+ @Test
+ void shouldFillFixedPositionInput() {
+ page.setContent("");
+ page.fill("input", "some value");
+ assertEquals("some value", page.evaluate("() => document.querySelector('input').value"));
+ }
+
+ @Test
+ void shouldBeAbleToFillWhenFocusIsInTheWrongFrame() {
+ page.setContent("\n" +
+ "");
+ page.focus("iframe");
+ page.fill("div", "some value");
+ assertEquals("some value", page.evalOnSelector("div", "d => d.textContent"));
+ }
+
+ @Test
+ void shouldBeAbleToFillTheInputTypeNumber() {
+ page.setContent("");
+ page.fill("input", "42");
+ assertEquals("42", page.evaluate("() => window['input'].value"));
+ }
+
+ @Test
+ void shouldBeAbleToFillExponentIntoTheInputTypeNumber() {
+ page.setContent("");
+ page.fill("input", "-10e5");
+ assertEquals("-10e5", page.evaluate("() => window['input'].value"));
+ }
+
+ @Test
+ void shouldBeAbleToFillInputTypeNumberWithEmptyString() {
+ page.setContent("");
+ page.fill("input", "");
+ assertEquals("", page.evaluate("() => window['input'].value"));
+ }
+
+ @Test
+ void shouldNotBeAbleToFillTextIntoTheInputTypeNumber() {
+ page.setContent("");
+ try {
+ page.fill("input", "abc");
+ fail("did not throw");
+ } catch (RuntimeException e) {
+ assertTrue(e.getMessage().contains("Cannot type text into input[type=number]"));
+ }
+ }
+
+ @Test
+ void shouldBeAbleToClear() {
+ page.navigate(server.PREFIX + "/input/textarea.html");
+ page.fill("input", "some value");
+ assertEquals("some value", page.evaluate("() => window['result']"));
+ page.fill("input", "");
+ assertEquals("", page.evaluate("() => window['result']"));
+ }
+}