diff --git a/lib/src/main/java/com/microsoft/playwright/impl/FrameImpl.java b/lib/src/main/java/com/microsoft/playwright/impl/FrameImpl.java index 4e2cfc3a..643d41a0 100644 --- a/lib/src/main/java/com/microsoft/playwright/impl/FrameImpl.java +++ b/lib/src/main/java/com/microsoft/playwright/impl/FrameImpl.java @@ -17,6 +17,7 @@ package com.microsoft.playwright.impl; import com.google.gson.Gson; +import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.microsoft.playwright.*; @@ -182,14 +183,54 @@ public class FrameImpl extends ChannelOwner implements Frame { return null; } + + private static String toProtocol(ClickOptions.Button button) { + switch (button) { + case LEFT: return "left"; + case RIGHT: return "right"; + case MIDDLE: return "middle"; + default: throw new RuntimeException("Unexpected value: " + button); + } + } + + private static JsonArray toProtocol(Set modifiers) { + JsonArray result = new JsonArray(); + if (modifiers.contains(ClickOptions.Modifier.ALT)) { + result.add("Alt"); + } + if (modifiers.contains(ClickOptions.Modifier.CONTROL)) { + result.add("Control"); + } + if (modifiers.contains(ClickOptions.Modifier.META)) { + result.add("Meta"); + } + if (modifiers.contains(ClickOptions.Modifier.SHIFT)) { + result.add("Shift"); + } + return result; + } + @Override public void click(String selector, ClickOptions options) { if (options == null) { options = new ClickOptions(); } - JsonObject params = new JsonObject(); + JsonObject params = new Gson().toJsonTree(options).getAsJsonObject(); params.addProperty("selector", selector); - JsonElement result = sendMessage("click", params); + + params.remove("button"); + if (options.button != null) { + params.addProperty("button", toProtocol(options.button)); + } + + params.remove("modifiers"); + if (options.modifiers != null) { + params.add("modifiers", toProtocol(options.modifiers)); + } + +// System.err.println(new Gson().toJson(params)); + + sendMessage("click", params); } @Override @@ -219,7 +260,13 @@ public class FrameImpl extends ChannelOwner implements Frame { @Override public void fill(String selector, String value, FillOptions options) { - + if (options == null) { + options = new FillOptions(); + } + JsonObject params = new Gson().toJsonTree(options).getAsJsonObject(); + params.addProperty("selector", selector); + params.addProperty("value", value); + sendMessage("fill", params); } @Override @@ -245,7 +292,6 @@ public class FrameImpl extends ChannelOwner implements Frame { JsonObject params = new Gson().toJsonTree(options).getAsJsonObject(); params.addProperty("url", url); JsonElement result = sendMessage("goto", params); - System.out.println("result = " + new Gson().toJson(result)); return connection.getExistingObject(result.getAsJsonObject().getAsJsonObject("response").get("guid").getAsString()); } diff --git a/lib/src/main/java/com/microsoft/playwright/impl/PageImpl.java b/lib/src/main/java/com/microsoft/playwright/impl/PageImpl.java index 82a595d1..cc0e31ae 100644 --- a/lib/src/main/java/com/microsoft/playwright/impl/PageImpl.java +++ b/lib/src/main/java/com/microsoft/playwright/impl/PageImpl.java @@ -145,7 +145,7 @@ public class PageImpl extends ChannelOwner implements Page { @Override public void click(String selector, ClickOptions options) { - mainFrame.click(selector); + mainFrame.click(selector, convertViaJson(options, Frame.ClickOptions.class)); } @Override @@ -195,7 +195,7 @@ public class PageImpl extends ChannelOwner implements Page { @Override public void fill(String selector, String value, FillOptions options) { - + mainFrame.fill(selector, value, convertViaJson(options, Frame.FillOptions.class)); } @Override @@ -406,4 +406,9 @@ public class PageImpl extends ChannelOwner implements Page { public List workers() { return null; } + + private static T convertViaJson(F f, Class t) { + String json = new Gson().toJson(f); + return new Gson().fromJson(json, t); + } } diff --git a/lib/src/test/java/com/microsoft/playwright/TestClick.java b/lib/src/test/java/com/microsoft/playwright/TestClick.java index 8c620dd9..344315b1 100644 --- a/lib/src/test/java/com/microsoft/playwright/TestClick.java +++ b/lib/src/test/java/com/microsoft/playwright/TestClick.java @@ -21,6 +21,7 @@ import org.junit.jupiter.api.*; import java.io.IOException; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; public class TestClick { private static Playwright playwright; @@ -48,7 +49,8 @@ public class TestClick { @BeforeEach void setUp() { - BrowserType.LaunchOptions options = new BrowserType.LaunchOptions().withHeadless(false); +// BrowserType.LaunchOptions options = new BrowserType.LaunchOptions().withHeadless(false).withSlowMo(1000); + BrowserType.LaunchOptions options = new BrowserType.LaunchOptions(); browser = playwright.chromium().launch(options); isChromium = true; context = browser.newContext(); @@ -76,4 +78,81 @@ public class TestClick { page.click("circle"); assertEquals(42, page.evaluate("__CLICKED")); } + + @Test + void should_click_the_button_if_window_Node_is_removed() { + page.navigate(server.PREFIX + "/input/button.html"); + page.evaluate("() => delete window.Node"); + page.click("button"); + assertEquals("Clicked", page.evaluate("result")); + } + + // @see https://github.com/GoogleChrome/puppeteer/issues/4281 + @Test + void should_click_on_a_span_with_an_inline_element_inside() { + page.setContent( + "\n" + + "\n"); + page.click("span"); + assertEquals(42, page.evaluate("CLICKED")); + } + + // TODO: it('should not throw UnhandledPromiseRejection when page closes' + + @Test + void should_click_the_1x1_div() { + page.setContent("
"); + page.click("div"); + assertTrue((Boolean) page.evaluate("window.__clicked")); + } + + @Test + void should_click_the_button_after_navigation() { + page.navigate(server.PREFIX + "/input/button.html"); + page.click("button"); + page.navigate(server.PREFIX + "/input/button.html"); + page.click("button"); + assertEquals("Clicked", page.evaluate("result")); + } + + @Test + void should_click_the_button_after_a_cross_origin_navigation() { + page.navigate(server.PREFIX + "/input/button.html"); + page.click("button"); + page.navigate(server.CROSS_PROCESS_PREFIX + "/input/button.html"); + page.click("button"); + assertEquals("Clicked", page.evaluate("result")); + } + + // TODO: it('should click with disabled javascript' + + @Test + void should_click_when_one_of_inline_box_children_is_outside_of_viewport() { + page.setContent( + "\n" + + "woofdoggo\n"); + page.click("span"); + assertEquals(42, page.evaluate("CLICKED")); + } + + @Test + void should_select_the_text_by_triple_clicking() { + page.navigate(server.PREFIX + "/input/textarea.html"); + String text = "This is the text that we are going to try to select. Let's see how it goes."; + page.fill("textarea", text); + page.click("textarea", new Page.ClickOptions().withClickCount(3)); + assertEquals(text, page.evaluate("() => {\n" + + " const textarea = document.querySelector('textarea');\n" + + " return textarea.value.substring(textarea.selectionStart, textarea.selectionEnd);\n" + + "}")); + }; }