feat: implement ElementHandle.click
This commit is contained in:
@@ -464,6 +464,8 @@ class Interface extends TypeDefinition {
|
||||
"\n" +
|
||||
"package com.microsoft.playwright;\n";
|
||||
|
||||
private static Set<String> allowedBaseInterfaces = new HashSet<>(Arrays.asList("Browser", "JSHandle"));
|
||||
|
||||
Interface(JsonObject jsonElement) {
|
||||
super(null, jsonElement);
|
||||
|
||||
@@ -489,7 +491,16 @@ class Interface extends TypeDefinition {
|
||||
output.add("import java.util.*;");
|
||||
output.add("import java.util.function.BiConsumer;");
|
||||
output.add("");
|
||||
output.add("public interface " + jsonName + " {");
|
||||
|
||||
String implementsClause = "";
|
||||
if (jsonElement.getAsJsonObject().has("extends")) {
|
||||
String base = jsonElement.getAsJsonObject().get("extends").getAsString();
|
||||
if (allowedBaseInterfaces.contains(base)) {
|
||||
implementsClause = " extends " + base;
|
||||
}
|
||||
}
|
||||
|
||||
output.add("public interface " + jsonName + implementsClause + " {");
|
||||
offset = " ";
|
||||
writeSharedTypes(output, offset);
|
||||
super.writeTo(output, offset);
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.microsoft.playwright;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public interface ChromiumBrowser {
|
||||
public interface ChromiumBrowser extends Browser {
|
||||
class StartTracingOptions {
|
||||
public String path;
|
||||
public Boolean screenshots;
|
||||
|
||||
@@ -19,7 +19,7 @@ package com.microsoft.playwright;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public interface ElementHandle {
|
||||
public interface ElementHandle extends JSHandle {
|
||||
enum ElementState { DISABLED, ENABLED, HIDDEN, STABLE, VISIBLE }
|
||||
class CheckOptions {
|
||||
public Boolean force;
|
||||
|
||||
@@ -19,6 +19,6 @@ package com.microsoft.playwright;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public interface FirefoxBrowser {
|
||||
public interface FirefoxBrowser extends Browser {
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,6 @@ package com.microsoft.playwright;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
public interface WebKitBrowser {
|
||||
public interface WebKitBrowser extends Browser {
|
||||
}
|
||||
|
||||
|
||||
@@ -198,11 +198,14 @@ public class Connection {
|
||||
case "Electron":
|
||||
// result = new Playwright(parent, type, guid, initializer);
|
||||
break;
|
||||
case "ElementHandle":
|
||||
result = new ElementHandleImpl(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Frame":
|
||||
result = new FrameImpl(parent, type, guid, initializer);
|
||||
break;
|
||||
case "JSHandle":
|
||||
// result = new JSHandle(parent, type, guid, initializer);
|
||||
result = new JSHandleImpl(parent, type, guid, initializer);
|
||||
break;
|
||||
case "Page":
|
||||
result = new PageImpl(parent, type, guid, initializer);
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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.impl;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.microsoft.playwright.ElementHandle;
|
||||
import com.microsoft.playwright.Frame;
|
||||
import com.microsoft.playwright.JSHandle;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.microsoft.playwright.impl.Serialization.toProtocol;
|
||||
|
||||
public class ElementHandleImpl extends JSHandleImpl implements ElementHandle {
|
||||
public ElementHandleImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementHandle asElement() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementHandle querySelector(String selector) {
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("selector", selector);
|
||||
JsonElement json = sendMessage("querySelector", params);
|
||||
JsonObject element = json.getAsJsonObject().getAsJsonObject("element");
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
return connection.getExistingObject(element.get("guid").getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ElementHandle> querySelectorAll(String selector) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evalOnSelector(String selector, String pageFunction, Object arg) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evalOnSelectorAll(String selector, String pageFunction, Object arg) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object boundingBox() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void check(CheckOptions options) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(ClickOptions options) {
|
||||
if (options == null) {
|
||||
options = new ClickOptions();
|
||||
}
|
||||
JsonObject params = new Gson().toJsonTree(options).getAsJsonObject();
|
||||
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));
|
||||
}
|
||||
|
||||
sendMessage("click", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Frame contentFrame() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dblclick(DblclickOptions options) {
|
||||
if (options == null) {
|
||||
options = new DblclickOptions();
|
||||
}
|
||||
JsonObject params = new Gson().toJsonTree(options).getAsJsonObject();
|
||||
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));
|
||||
}
|
||||
|
||||
sendMessage("dblclick", params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchEvent(String type, Object eventInit) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fill(String value, FillOptions options) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focus() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAttribute(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hover(HoverOptions options) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String innerHTML() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String innerText() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Frame ownerFrame() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void press(String key, PressOptions options) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] screenshot(ScreenshotOptions options) {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scrollIntoViewIfNeeded(ScrollIntoViewIfNeededOptions options) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> selectOption(String values, SelectOptionOptions options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void selectText(SelectTextOptions options) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInputFiles(String files, SetInputFilesOptions options) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String textContent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void type(String text, TypeOptions options) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uncheck(UncheckOptions options) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void waitForElementState(ElementState state, WaitForElementStateOptions options) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementHandle waitForSelector(String selector, WaitForSelectorOptions options) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,6 @@
|
||||
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.*;
|
||||
@@ -70,7 +69,14 @@ public class FrameImpl extends ChannelOwner implements Frame {
|
||||
|
||||
@Override
|
||||
public ElementHandle querySelector(String selector) {
|
||||
return null;
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("selector", selector);
|
||||
JsonElement json = sendMessage("querySelector", params);
|
||||
JsonObject element = json.getAsJsonObject().getAsJsonObject("element");
|
||||
if (element == null) {
|
||||
return null;
|
||||
}
|
||||
return connection.getExistingObject(element.get("guid").getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -116,32 +122,6 @@ public class FrameImpl extends ChannelOwner implements Frame {
|
||||
}
|
||||
|
||||
|
||||
private static String toProtocol(Mouse.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<Keyboard.Modifier> modifiers) {
|
||||
JsonArray result = new JsonArray();
|
||||
if (modifiers.contains(Keyboard.Modifier.ALT)) {
|
||||
result.add("Alt");
|
||||
}
|
||||
if (modifiers.contains(Keyboard.Modifier.CONTROL)) {
|
||||
result.add("Control");
|
||||
}
|
||||
if (modifiers.contains(Keyboard.Modifier.META)) {
|
||||
result.add("Meta");
|
||||
}
|
||||
if (modifiers.contains(Keyboard.Modifier.SHIFT)) {
|
||||
result.add("Shift");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(String selector, ClickOptions options) {
|
||||
if (options == null) {
|
||||
@@ -152,12 +132,12 @@ public class FrameImpl extends ChannelOwner implements Frame {
|
||||
|
||||
params.remove("button");
|
||||
if (options.button != null) {
|
||||
params.addProperty("button", toProtocol(options.button));
|
||||
params.addProperty("button", Serialization.toProtocol(options.button));
|
||||
}
|
||||
|
||||
params.remove("modifiers");
|
||||
if (options.modifiers != null) {
|
||||
params.add("modifiers", toProtocol(options.modifiers));
|
||||
params.add("modifiers", Serialization.toProtocol(options.modifiers));
|
||||
}
|
||||
|
||||
sendMessage("click", params);
|
||||
@@ -178,12 +158,12 @@ public class FrameImpl extends ChannelOwner implements Frame {
|
||||
|
||||
params.remove("button");
|
||||
if (options.button != null) {
|
||||
params.addProperty("button", toProtocol(options.button));
|
||||
params.addProperty("button", Serialization.toProtocol(options.button));
|
||||
}
|
||||
|
||||
params.remove("modifiers");
|
||||
if (options.modifiers != null) {
|
||||
params.add("modifiers", toProtocol(options.modifiers));
|
||||
params.add("modifiers", Serialization.toProtocol(options.modifiers));
|
||||
}
|
||||
|
||||
sendMessage("dblclick", params);
|
||||
@@ -201,7 +181,13 @@ public class FrameImpl extends ChannelOwner implements Frame {
|
||||
|
||||
@Override
|
||||
public JSHandle evaluateHandle(String pageFunction, Object arg) {
|
||||
return null;
|
||||
JsonObject params = new JsonObject();
|
||||
params.addProperty("expression", pageFunction);
|
||||
params.addProperty("world", "main");
|
||||
params.addProperty("isFunction", isFunctionBody(pageFunction));
|
||||
params.add("arg", new Gson().toJsonTree(serializeArgument(arg)));
|
||||
JsonElement json = sendMessage("evaluateExpressionHandle", params);
|
||||
return connection.getExistingObject(json.getAsJsonObject().getAsJsonObject("handle").get("guid").getAsString());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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.impl;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.microsoft.playwright.ElementHandle;
|
||||
import com.microsoft.playwright.JSHandle;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class JSHandleImpl extends ChannelOwner implements JSHandle {
|
||||
public JSHandleImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementHandle asElement() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(String pageFunction, Object arg) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSHandle evaluateHandle(String pageFunction, Object arg) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, JSHandle> getProperties() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSHandle getProperty(String propertyName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonValue() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.microsoft.playwright.Mouse;
|
||||
|
||||
import static com.microsoft.playwright.impl.Serialization.toProtocol;
|
||||
import static com.microsoft.playwright.impl.Utils.convertViaJson;
|
||||
|
||||
class MouseImpl implements Mouse {
|
||||
@@ -29,15 +30,6 @@ class MouseImpl implements Mouse {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
private static String toProtocol(Mouse.Button button) {
|
||||
switch (button) {
|
||||
case LEFT: return "left";
|
||||
case RIGHT: return "right";
|
||||
case MIDDLE: return "middle";
|
||||
default: throw new RuntimeException("Unexpected value: " + button);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void click(int x, int y, ClickOptions options) {
|
||||
if (options == null) {
|
||||
|
||||
@@ -106,7 +106,7 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
|
||||
@Override
|
||||
public void close(CloseOptions options) {
|
||||
JsonObject params = options == null ? new JsonObject() : (JsonObject) new Gson().toJsonTree(options);
|
||||
JsonObject params = options == null ? new JsonObject() : new Gson().toJsonTree(options).getAsJsonObject();
|
||||
sendMessage("close", params);
|
||||
if (ownedContext != null) {
|
||||
ownedContext.close();
|
||||
@@ -205,7 +205,7 @@ public class PageImpl extends ChannelOwner implements Page {
|
||||
|
||||
@Override
|
||||
public JSHandle evaluateHandle(String pageFunction, Object arg) {
|
||||
return null;
|
||||
return mainFrame.evaluateHandle(pageFunction, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -22,6 +22,7 @@ class Binary {
|
||||
}
|
||||
|
||||
class Channel {
|
||||
String guid;
|
||||
}
|
||||
|
||||
class Metadata{
|
||||
|
||||
@@ -17,13 +17,14 @@
|
||||
package com.microsoft.playwright.impl;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.microsoft.playwright.JSHandle;
|
||||
import com.microsoft.playwright.Keyboard;
|
||||
import com.microsoft.playwright.Mouse;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
class Serialization {
|
||||
static SerializedError serializeError(Throwable e) {
|
||||
@@ -38,8 +39,16 @@ class Serialization {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static SerializedValue serializeValue(Object value) {
|
||||
private static SerializedValue serializeValue(Object value, List<JSHandleImpl> handles, int depth) {
|
||||
if (depth > 100) {
|
||||
throw new RuntimeException("Maximum argument depth exceeded");
|
||||
}
|
||||
SerializedValue result = new SerializedValue();
|
||||
if (value instanceof JSHandleImpl) {
|
||||
result.h = handles.size();
|
||||
handles.add((JSHandleImpl) value);
|
||||
return result;
|
||||
}
|
||||
if (value == null)
|
||||
result.v = "undefined";
|
||||
else if (value instanceof Double) {
|
||||
@@ -64,7 +73,7 @@ class Serialization {
|
||||
else if (value instanceof List) {
|
||||
List<SerializedValue> list = new ArrayList<>();
|
||||
for (Object o : (List) value)
|
||||
list.add(serializeValue(o));
|
||||
list.add(serializeValue(o, handles, depth + 1));
|
||||
result.a = list.toArray(new SerializedValue[0]);
|
||||
} else if (value instanceof Map) {
|
||||
List<SerializedValue.O> list = new ArrayList<>();
|
||||
@@ -72,7 +81,7 @@ class Serialization {
|
||||
for (Map.Entry<String, Object> e : map.entrySet()) {
|
||||
SerializedValue.O o = new SerializedValue.O();
|
||||
o.k = e.getKey();
|
||||
o.v = serializeValue(e.getValue());
|
||||
o.v = serializeValue(e.getValue(), handles, depth + 1);
|
||||
list.add(o);
|
||||
}
|
||||
result.o = list.toArray(new SerializedValue.O[0]);
|
||||
@@ -83,8 +92,15 @@ class Serialization {
|
||||
|
||||
static SerializedArgument serializeArgument(Object arg) {
|
||||
SerializedArgument result = new SerializedArgument();
|
||||
result.value = serializeValue(arg);
|
||||
result.handles = new Channel[0];
|
||||
List<JSHandleImpl> handles = new ArrayList<>();
|
||||
result.value = serializeValue(arg, handles, 0);
|
||||
result.handles = new Channel[handles.size()];
|
||||
int i = 0;
|
||||
for (JSHandleImpl handle : handles) {
|
||||
result.handles[i] = new Channel();
|
||||
result.handles[i].guid = handle.guid;
|
||||
++i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -129,4 +145,30 @@ class Serialization {
|
||||
}
|
||||
throw new RuntimeException("Unexpected result: " + new Gson().toJson(value));
|
||||
}
|
||||
|
||||
static String toProtocol(Mouse.Button button) {
|
||||
switch (button) {
|
||||
case LEFT: return "left";
|
||||
case RIGHT: return "right";
|
||||
case MIDDLE: return "middle";
|
||||
default: throw new RuntimeException("Unexpected value: " + button);
|
||||
}
|
||||
}
|
||||
|
||||
static JsonArray toProtocol(Set<Keyboard.Modifier> modifiers) {
|
||||
JsonArray result = new JsonArray();
|
||||
if (modifiers.contains(Keyboard.Modifier.ALT)) {
|
||||
result.add("Alt");
|
||||
}
|
||||
if (modifiers.contains(Keyboard.Modifier.CONTROL)) {
|
||||
result.add("Control");
|
||||
}
|
||||
if (modifiers.contains(Keyboard.Modifier.META)) {
|
||||
result.add("Meta");
|
||||
}
|
||||
if (modifiers.contains(Keyboard.Modifier.SHIFT)) {
|
||||
result.add("Shift");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,16 +31,21 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
public class TestClick {
|
||||
private static Playwright playwright;
|
||||
private static Server server;
|
||||
private Browser browser;
|
||||
private boolean isChromium;
|
||||
private boolean isWebKit;
|
||||
private boolean headful;
|
||||
private static Browser browser;
|
||||
private static boolean isChromium;
|
||||
private static boolean isWebKit;
|
||||
private static boolean headful;
|
||||
private BrowserContext context;
|
||||
private Page page;
|
||||
|
||||
@BeforeAll
|
||||
static void createPlaywright() {
|
||||
static void launchBrowser() {
|
||||
playwright = Playwright.create();
|
||||
BrowserType.LaunchOptions options = new BrowserType.LaunchOptions();
|
||||
browser = playwright.chromium().launch(options);
|
||||
isChromium = true;
|
||||
isWebKit = false;
|
||||
headful = false;
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
@@ -50,25 +55,22 @@ public class TestClick {
|
||||
|
||||
@AfterAll
|
||||
static void stopServer() throws IOException {
|
||||
browser.close();
|
||||
server.stop();
|
||||
server = null;
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
// BrowserType.LaunchOptions options = new BrowserType.LaunchOptions().withHeadless(false).withSlowMo(1000);
|
||||
BrowserType.LaunchOptions options = new BrowserType.LaunchOptions();
|
||||
browser = playwright.chromium().launch(options);
|
||||
isChromium = true;
|
||||
isWebKit = false;
|
||||
headful = false;
|
||||
context = browser.newContext();
|
||||
page = context.newPage();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
browser.close();
|
||||
context.close();
|
||||
context = null;
|
||||
page = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
* <p>
|
||||
* 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
|
||||
* <p>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p>
|
||||
* 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 TestElementHandleClick {
|
||||
private static Playwright playwright;
|
||||
private static Server server;
|
||||
private static Browser browser;
|
||||
private static boolean isChromium;
|
||||
private static boolean isWebKit;
|
||||
private static boolean headful;
|
||||
private BrowserContext context;
|
||||
private Page page;
|
||||
|
||||
@BeforeAll
|
||||
static void launchBrowser() {
|
||||
playwright = Playwright.create();
|
||||
BrowserType.LaunchOptions options = new BrowserType.LaunchOptions();
|
||||
browser = playwright.chromium().launch(options);
|
||||
isChromium = true;
|
||||
isWebKit = false;
|
||||
headful = false;
|
||||
}
|
||||
|
||||
@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 should_work() {
|
||||
page.navigate(server.PREFIX + "/input/button.html");
|
||||
ElementHandle button = page.querySelector("button");
|
||||
button.click();
|
||||
assertEquals("Clicked", page.evaluate("() => window['result']"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_work_with_Node_removed() {
|
||||
page.navigate(server.PREFIX + "/input/button.html");
|
||||
page.evaluate("() => delete window['Node']");
|
||||
ElementHandle button = page.querySelector("button");
|
||||
button.click();
|
||||
assertEquals("Clicked", page.evaluate("() => window['result']"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_work_for_Shadow_DOM_v1() {
|
||||
page.navigate(server.PREFIX + "/shadow.html");
|
||||
ElementHandle buttonHandle = page.evaluateHandle("() => window['button']").asElement();
|
||||
buttonHandle.click();
|
||||
assertEquals(true, page.evaluate("clicked"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_work_for_TextNodes() {
|
||||
page.navigate(server.PREFIX + "/input/button.html");
|
||||
ElementHandle buttonTextNode = page.evaluateHandle("() => document.querySelector('button').firstChild").asElement();
|
||||
buttonTextNode.click();
|
||||
assertEquals("Clicked", page.evaluate("() => window['result']"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_throw_for_detached_nodes() {
|
||||
page.navigate(server.PREFIX + "/input/button.html");
|
||||
ElementHandle button = page.querySelector("button");
|
||||
page.evaluate("button => button.remove()", button);
|
||||
try {
|
||||
button.click();
|
||||
fail("click should throw");
|
||||
} catch (RuntimeException e) {
|
||||
assertTrue(e.getMessage().contains("Element is not attached to the DOM"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_throw_for_hidden_nodes_with_force() {
|
||||
page.navigate(server.PREFIX + "/input/button.html");
|
||||
ElementHandle button = page.querySelector("button");
|
||||
page.evaluate("button => button.style.display = 'none'", button);
|
||||
try {
|
||||
button.click(new ElementHandle.ClickOptions().withForce(true));
|
||||
fail("click should throw");
|
||||
} catch (RuntimeException e) {
|
||||
assertTrue(e.getMessage().contains("Element is not visible"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_throw_for_recursively_hidden_nodes_with_force() {
|
||||
page.navigate(server.PREFIX + "/input/button.html");
|
||||
ElementHandle button = page.querySelector("button");
|
||||
page.evaluate("button => button.parentElement.style.display = 'none'", button);
|
||||
try {
|
||||
button.click(new ElementHandle.ClickOptions().withForce(true));
|
||||
fail("click should throw");
|
||||
} catch (RuntimeException e) {
|
||||
assertTrue(e.getMessage().contains("Element is not visible"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_throw_for__br__elements_with_force() {
|
||||
page.setContent("hello<br>goodbye");
|
||||
ElementHandle br = page.querySelector("br");
|
||||
try {
|
||||
br.click(new ElementHandle.ClickOptions().withForce(true));
|
||||
fail("click should throw");
|
||||
} catch (RuntimeException e) {
|
||||
assertTrue(e.getMessage().contains("Element is outside of the viewport"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_double_click_the_button() {
|
||||
page.navigate(server.PREFIX + "/input/button.html");
|
||||
page.evaluate("() => {\n" +
|
||||
" window['double'] = false;\n" +
|
||||
" const button = document.querySelector('button');\n" +
|
||||
" button.addEventListener('dblclick', event => {\n" +
|
||||
" window['double'] = true;\n" +
|
||||
" });\n" +
|
||||
"}");
|
||||
ElementHandle button = page.querySelector("button");
|
||||
button.dblclick();
|
||||
assertEquals(true, page.evaluate("double"));
|
||||
assertEquals("Clicked", page.evaluate("result"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user