diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/JSHandleImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/JSHandleImpl.java
index dcf8ad2a..5020b111 100644
--- a/playwright/src/main/java/com/microsoft/playwright/impl/JSHandleImpl.java
+++ b/playwright/src/main/java/com/microsoft/playwright/impl/JSHandleImpl.java
@@ -28,8 +28,11 @@ import static com.microsoft.playwright.impl.Serialization.*;
import static com.microsoft.playwright.impl.Utils.isFunctionBody;
public class JSHandleImpl extends ChannelOwner implements JSHandle {
+ private String preview;
+
public JSHandleImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
super(parent, type, guid, initializer);
+ this.preview = initializer.get("preview").getAsString();
}
@Override
@@ -101,4 +104,17 @@ public class JSHandleImpl extends ChannelOwner implements JSHandle {
return deserialize(value);
});
}
+
+ @Override
+ void handleEvent(String event, JsonObject parameters) {
+ if ("previewUpdated".equals(event)) {
+ preview = parameters.get("preview").getAsString();
+ }
+ super.handleEvent(event, parameters);
+ }
+
+ @Override
+ public String toString() {
+ return preview;
+ }
}
diff --git a/playwright/src/test/java/com/microsoft/playwright/TestElementHandleConvenience.java b/playwright/src/test/java/com/microsoft/playwright/TestElementHandleConvenience.java
index 7fac9cec..97cb4cc9 100644
--- a/playwright/src/test/java/com/microsoft/playwright/TestElementHandleConvenience.java
+++ b/playwright/src/test/java/com/microsoft/playwright/TestElementHandleConvenience.java
@@ -21,6 +21,164 @@ import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
public class TestElementHandleConvenience extends TestBase {
+ @Test
+ void shouldHaveANicePreview() {
+ page.navigate(server.PREFIX + "/dom.html");
+ ElementHandle outer = page.querySelector("#outer");
+ ElementHandle inner = page.querySelector("#inner");
+ ElementHandle check = page.querySelector("#check");
+ JSHandle text = inner.evaluateHandle("e => e.firstChild");
+ page.evaluate("() => 1"); // Give them a chance to calculate the preview.
+ assertEquals("JSHandle@
…
", outer.toString());
+ assertEquals("JSHandle@Text,↵more text
", inner.toString());
+ assertEquals("JSHandle@#text=Text,↵more text", text.toString());
+ assertEquals("JSHandle@", check.toString());
+ }
+
+ @Test
+ void getAttributeShouldWork() {
+ page.navigate(server.PREFIX + "/dom.html");
+ ElementHandle handle = page.querySelector("#outer");
+ assertEquals("value", handle.getAttribute("name"));
+ assertNull(handle.getAttribute("foo"));
+ assertEquals("value", page.getAttribute("#outer", "name"));
+ assertNull(page.getAttribute("#outer", "foo"));
+ }
+
+ @Test
+ void innerHTMLShouldWork() {
+ page.navigate(server.PREFIX + "/dom.html");
+ ElementHandle handle = page.querySelector("#outer");
+ assertEquals("Text,\nmore text
", handle.innerHTML());
+ assertEquals("Text,\nmore text
", page.innerHTML("#outer"));
+ }
+
+ @Test
+ void innerTextShouldWork() {
+ page.navigate(server.PREFIX + "/dom.html");
+ ElementHandle handle = page.querySelector("#inner");
+ assertEquals("Text, more text", handle.innerText());
+ assertEquals("Text, more text", page.innerText("#inner"));
+ }
+
+ @Test
+ void innerTextShouldThrow() {
+ page.setContent("");
+ try {
+ page.innerText("svg");
+ fail("did not throw");
+ } catch (PlaywrightException e) {
+ assertTrue(e.getMessage().contains("Not an HTMLElement"));
+ }
+ ElementHandle handle = page.querySelector("svg");
+ try {
+ handle.innerText();
+ fail("did not throw");
+ } catch (PlaywrightException e) {
+ assertTrue(e.getMessage().contains("Not an HTMLElement"));
+ }
+ }
+
+ @Test
+ void textContentShouldWork() {
+ page.navigate(server.PREFIX + "/dom.html");
+ ElementHandle handle = page.querySelector("#inner");
+ assertEquals("Text,\nmore text", handle.textContent());
+ assertEquals("Text,\nmore text", page.textContent("#inner"));
+ }
+
+ @Test
+ void textContentShouldBeAtomic() {
+ String createDummySelector = "{\n" +
+ " query(root, selector) {\n" +
+ " const result = root.querySelector(selector);\n" +
+ " if (result)\n" +
+ " Promise.resolve().then(() => result.textContent = 'modified');\n" +
+ " return result;\n" +
+ " },\n" +
+ " queryAll(root, selector) {\n" +
+ " const result = Array.from(root.querySelectorAll(selector));\n" +
+ " for (const e of result)\n" +
+ " Promise.resolve().then(() => e.textContent = 'modified');\n" +
+ " return result;\n" +
+ " }\n" +
+ "}\n";
+ playwright.selectors().register("textContent", createDummySelector);
+ page.setContent("Hello
");
+ String tc = page.textContent("textContent=div");
+ assertEquals("Hello", tc);
+ assertEquals("modified", page.evaluate("() => document.querySelector('div').textContent"));
+ }
+
+ @Test
+ void innerTextShouldBeAtomic() {
+ String createDummySelector = "{\n" +
+ " query(root, selector) {\n" +
+ " const result = root.querySelector(selector);\n" +
+ " if (result)\n" +
+ " Promise.resolve().then(() => result.textContent = 'modified');\n" +
+ " return result;\n" +
+ " },\n" +
+ " queryAll(root, selector) {\n" +
+ " const result = Array.from(root.querySelectorAll(selector));\n" +
+ " for (const e of result)\n" +
+ " Promise.resolve().then(() => e.textContent = 'modified');\n" +
+ " return result;\n" +
+ " }\n" +
+ "}\n";
+ playwright.selectors().register("innerText", createDummySelector);
+ page.setContent("Hello
");
+ String tc = page.innerText("innerText=div");
+ assertEquals("Hello", tc);
+ assertEquals("modified", page.evaluate("() => document.querySelector('div').innerText"));
+ }
+
+ @Test
+ void innerHTMLShouldBeAtomic() {
+ String createDummySelector = "{\n" +
+ " query(root, selector) {\n" +
+ " const result = root.querySelector(selector);\n" +
+ " if (result)\n" +
+ " Promise.resolve().then(() => result.textContent = 'modified');\n" +
+ " return result;\n" +
+ " },\n" +
+ " queryAll(root, selector) {\n" +
+ " const result = Array.from(root.querySelectorAll(selector));\n" +
+ " for (const e of result)\n" +
+ " Promise.resolve().then(() => e.textContent = 'modified');\n" +
+ " return result;\n" +
+ " }\n" +
+ "}\n";
+ playwright.selectors().register("innerHTML", createDummySelector);
+ page.setContent("Helloworld
");
+ String tc = page.innerHTML("innerHTML=div");
+ assertEquals("Helloworld", tc);
+ assertEquals("modified", page.evaluate("() => document.querySelector('div').innerHTML"));
+ }
+
+ @Test
+ void getAttributeShouldBeAtomic() {
+ String createDummySelector = "{\n" +
+ " query(root, selector) {\n" +
+ " const result = root.querySelector(selector);\n" +
+ " if (result)\n" +
+ " Promise.resolve().then(() => result.setAttribute('foo', 'modified'));\n" +
+ " return result;\n" +
+ " },\n" +
+ " queryAll(root, selector) {\n" +
+ " const result = Array.from(root.querySelectorAll(selector));\n" +
+ " for (const e of result)\n" +
+ " Promise.resolve().then(() => e.setAttribute('foo', 'modified'));\n" +
+ " return result;\n" +
+ " }\n" +
+ "}\n";
+ playwright.selectors().register("getAttribute", createDummySelector);
+ page.setContent("");
+ String tc = page.getAttribute("getAttribute=div", "foo");
+ assertEquals("hello", tc);
+ assertEquals("modified", page.evaluate("() => document.querySelector('div').getAttribute('foo')"));
+ }
+
@Test
void isVisibleAndIsHiddenShouldWork() {
page.setContent("Hi
");