1
0
mirror of synced 2026-05-22 18:53:15 +00:00

feat: roll driver, add dnd tests (#540)

This commit is contained in:
Yury Semikhatsky
2021-08-06 16:06:52 -07:00
committed by GitHub
parent 476e222c93
commit fcac298050
13 changed files with 458 additions and 41 deletions
@@ -24,21 +24,8 @@ import java.util.*;
* ElementHandle represents an in-page DOM element. ElementHandles can be created with the {@link Page#querySelector
* Page.querySelector()} method.
* <pre>{@code
* import com.microsoft.playwright.*;
*
* public class Example {
* public static void main(String[] args) {
* try (Playwright playwright = Playwright.create()) {
* BrowserType chromium = playwright.chromium();
* Browser browser = chromium.launch();
* Page page = browser.newPage();
* page.navigate("https://example.com");
* ElementHandle hrefElement = page.querySelector("a");
* hrefElement.click();
* // ...
* }
* }
* }
* ElementHandle hrefElement = page.querySelector("a");
* hrefElement.click();
* }</pre>
*
* <p> ElementHandle prevents DOM element from garbage collection unless the handle is disposed with {@link JSHandle#dispose
@@ -46,6 +33,30 @@ import java.util.*;
*
* <p> ElementHandle instances can be used as an argument in {@link Page#evalOnSelector Page.evalOnSelector()} and {@link
* Page#evaluate Page.evaluate()} methods.
*
* <p> <strong>NOTE:</strong> In most cases, you would want to use the {@code Locator} object instead. You should only use {@code ElementHandle} if you want to
* retain a handle to a particular DOM Node that you intend to pass into {@link Page#evaluate Page.evaluate()} as an
* argument.
*
* <p> The difference between the {@code Locator} and ElementHandle is that the ElementHandle points to a particular element, while
* {@code Locator} captures the logic of how to retrieve an element.
*
* <p> In the example below, handle points to a particular DOM element on page. If that element changes text or is used by
* React to render an entirely different component, handle is still pointing to that very DOM element. This can lead to
* unexpected behaviors.
* <pre>{@code
* ElementHandle handle = page.querySelector("text=Submit");
* handle.hover();
* handle.click();
* }</pre>
*
* <p> With the locator, every time the {@code element} is used, up-to-date DOM element is located in the page using the selector. So
* in the snippet below, underlying DOM element is going to be located twice.
* <pre>{@code
* Locator locator = page.locator("text=Submit");
* locator.hover();
* locator.click();
* }</pre>
*/
public interface ElementHandle extends JSHandle {
class CheckOptions {
@@ -1120,13 +1131,13 @@ public interface ElementHandle extends JSHandle {
*/
String innerText();
/**
* Returns {@code input.value} for {@code <input>} or {@code <textarea>} element. Throws for non-input elements.
* Returns {@code input.value} for {@code <input>} or {@code <textarea>} or {@code <select>} element. Throws for non-input elements.
*/
default String inputValue() {
return inputValue(null);
}
/**
* Returns {@code input.value} for {@code <input>} or {@code <textarea>} element. Throws for non-input elements.
* Returns {@code input.value} for {@code <input>} or {@code <textarea>} or {@code <select>} element. Throws for non-input elements.
*/
String inputValue(InputValueOptions options);
/**
@@ -406,11 +406,21 @@ public interface Frame {
* inaccessible pages. Defaults to {@code false}.
*/
public Boolean noWaitAfter;
/**
* Clicks on the source element at this point relative to the top-left corner of the element's padding box. If not
* specified, some visible point of the element is used.
*/
public Position sourcePosition;
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
public Boolean strict;
/**
* Drops on the target element at this point relative to the top-left corner of the element's padding box. If not
* specified, some visible point of the element is used.
*/
public Position targetPosition;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass {@code 0} to disable timeout. The default value can be changed by
* using the {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()} or {@link Page#setDefaultTimeout
@@ -432,10 +442,24 @@ public interface Frame {
this.noWaitAfter = noWaitAfter;
return this;
}
public DragAndDropOptions setSourcePosition(double x, double y) {
return setSourcePosition(new Position(x, y));
}
public DragAndDropOptions setSourcePosition(Position sourcePosition) {
this.sourcePosition = sourcePosition;
return this;
}
public DragAndDropOptions setStrict(boolean strict) {
this.strict = strict;
return this;
}
public DragAndDropOptions setTargetPosition(double x, double y) {
return setTargetPosition(new Position(x, y));
}
public DragAndDropOptions setTargetPosition(Position targetPosition) {
this.targetPosition = targetPosition;
return this;
}
public DragAndDropOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -2079,7 +2103,7 @@ public interface Frame {
*/
String innerText(String selector, InnerTextOptions options);
/**
* Returns {@code input.value} for the selected {@code <input>} or {@code <textarea>} element. Throws for non-input elements.
* Returns {@code input.value} for the selected {@code <input>} or {@code <textarea>} or {@code <select>} element. Throws for non-input elements.
*
* @param selector A selector to search for an element. If there are multiple elements satisfying the selector, the first will be used. See
* <a href="https://playwright.dev/java/docs/selectors/">working with selectors</a> for more details.
@@ -2088,7 +2112,7 @@ public interface Frame {
return inputValue(selector, null);
}
/**
* Returns {@code input.value} for the selected {@code <input>} or {@code <textarea>} element. Throws for non-input elements.
* Returns {@code input.value} for the selected {@code <input>} or {@code <textarea>} or {@code <select>} element. Throws for non-input elements.
*
* @param selector A selector to search for an element. If there are multiple elements satisfying the selector, the first will be used. See
* <a href="https://playwright.dev/java/docs/selectors/">working with selectors</a> for more details.
@@ -23,24 +23,29 @@ import java.util.*;
/**
* Locator represents a view to the element(s) on the page. It captures the logic sufficient to retrieve the element at any
* given moment. Locator can be created with the {@link Page#locator Page.locator()} method.
* <pre>{@code
* Locator locator = page.locator("text=Submit");
* locator.click();
* }</pre>
*
* <p> The difference between the Locator and {@code ElementHandle} is that the latter points to a particular element, while Locator
* only captures the logic of how to retrieve an element at any given moment.
* captures the logic of how to retrieve that element.
*
* <p> In the example below, handle points to a particular DOM element on page. If that element changes text or is used by
* React to render an entirely different component, handle is still pointing to that very DOM element.
* React to render an entirely different component, handle is still pointing to that very DOM element. This can lead to
* unexpected behaviors.
* <pre>{@code
* ElementHandle handle = page.querySelector("text=Submit");
* handle.hover();
* handle.click();
* }</pre>
*
* <p> With the locator, every time the {@code element} is used, corresponding DOM element is located in the page using given
* selector. So in the snippet below, underlying DOM element is going to be located twice, using the given selector.
* <p> With the locator, every time the {@code element} is used, up-to-date DOM element is located in the page using the selector. So
* in the snippet below, underlying DOM element is going to be located twice.
* <pre>{@code
* Locator element = page.locator("text=Submit");
* element.hover();
* element.click();
* Locator locator = page.locator("text=Submit");
* locator.hover();
* locator.click();
* }</pre>
*/
public interface Locator {
@@ -887,6 +892,14 @@ public interface Locator {
return this;
}
}
/**
* Returns an array of {@code node.innerText} values for all matching nodes.
*/
List<String> allInnerTexts();
/**
* Returns an array of {@code node.textContent} values for all matching nodes.
*/
List<String> allTextContents();
/**
* This method returns the bounding box of the element, or {@code null} if the element is not visible. The bounding box is
* calculated relative to the main frame viewport - which is usually the same as the browser window.
@@ -1446,13 +1459,13 @@ public interface Locator {
*/
String innerText(InnerTextOptions options);
/**
* Returns {@code input.value} for {@code <input>} or {@code <textarea>} element. Throws for non-input elements.
* Returns {@code input.value} for {@code <input>} or {@code <textarea>} or {@code <select>} element. Throws for non-input elements.
*/
default String inputValue() {
return inputValue(null);
}
/**
* Returns {@code input.value} for {@code <input>} or {@code <textarea>} element. Throws for non-input elements.
* Returns {@code input.value} for {@code <input>} or {@code <textarea>} or {@code <select>} element. Throws for non-input elements.
*/
String inputValue(InputValueOptions options);
/**
@@ -664,11 +664,21 @@ public interface Page extends AutoCloseable {
* inaccessible pages. Defaults to {@code false}.
*/
public Boolean noWaitAfter;
/**
* Clicks on the source element at this point relative to the top-left corner of the element's padding box. If not
* specified, some visible point of the element is used.
*/
public Position sourcePosition;
/**
* When true, the call requires selector to resolve to a single element. If given selector resolves to more then one
* element, the call throws an exception.
*/
public Boolean strict;
/**
* Drops on the target element at this point relative to the top-left corner of the element's padding box. If not
* specified, some visible point of the element is used.
*/
public Position targetPosition;
/**
* Maximum time in milliseconds, defaults to 30 seconds, pass {@code 0} to disable timeout. The default value can be changed by
* using the {@link BrowserContext#setDefaultTimeout BrowserContext.setDefaultTimeout()} or {@link Page#setDefaultTimeout
@@ -690,10 +700,24 @@ public interface Page extends AutoCloseable {
this.noWaitAfter = noWaitAfter;
return this;
}
public DragAndDropOptions setSourcePosition(double x, double y) {
return setSourcePosition(new Position(x, y));
}
public DragAndDropOptions setSourcePosition(Position sourcePosition) {
this.sourcePosition = sourcePosition;
return this;
}
public DragAndDropOptions setStrict(boolean strict) {
this.strict = strict;
return this;
}
public DragAndDropOptions setTargetPosition(double x, double y) {
return setTargetPosition(new Position(x, y));
}
public DragAndDropOptions setTargetPosition(Position targetPosition) {
this.targetPosition = targetPosition;
return this;
}
public DragAndDropOptions setTimeout(double timeout) {
this.timeout = timeout;
return this;
@@ -3225,7 +3249,7 @@ public interface Page extends AutoCloseable {
*/
String innerText(String selector, InnerTextOptions options);
/**
* Returns {@code input.value} for the selected {@code <input>} or {@code <textarea>} element. Throws for non-input elements.
* Returns {@code input.value} for the selected {@code <input>} or {@code <textarea>} or {@code <select>} element. Throws for non-input elements.
*
* @param selector A selector to search for an element. If there are multiple elements satisfying the selector, the first will be used. See
* <a href="https://playwright.dev/java/docs/selectors/">working with selectors</a> for more details.
@@ -3234,7 +3258,7 @@ public interface Page extends AutoCloseable {
return inputValue(selector, null);
}
/**
* Returns {@code input.value} for the selected {@code <input>} or {@code <textarea>} element. Throws for non-input elements.
* Returns {@code input.value} for the selected {@code <input>} or {@code <textarea>} or {@code <select>} element. Throws for non-input elements.
*
* @param selector A selector to search for an element. If there are multiple elements satisfying the selector, the first will be used. See
* <a href="https://playwright.dev/java/docs/selectors/">working with selectors</a> for more details.
@@ -561,7 +561,7 @@ public class FrameImpl extends ChannelOwner implements Frame {
@Override
public Locator locator(String selector) {
return new LoccatorImpl(this, selector);
return new LocatorImpl(this, selector);
}
boolean isVisibleImpl(String selector, IsVisibleOptions options) {
@@ -15,12 +15,12 @@ import java.util.function.BiFunction;
import static com.microsoft.playwright.impl.Utils.convertViaJson;
class LoccatorImpl implements Locator {
class LocatorImpl implements Locator {
private final FrameImpl frame;
private final String selector;
private final String visibleSelector;
public LoccatorImpl(FrameImpl frame, String selector) {
public LocatorImpl(FrameImpl frame, String selector) {
this.frame = frame;
this.selector = selector;
this.visibleSelector = selector + " >> _visible=true";
@@ -45,6 +45,16 @@ class LoccatorImpl implements Locator {
}
}
@Override
public List<String> allInnerTexts() {
return (List<String>) frame.evalOnSelectorAll(selector, "ee => ee.map(e => e.innerText)");
}
@Override
public List<String> allTextContents() {
return (List<String>) frame.evalOnSelectorAll(selector, "ee => ee.map(e => e.textContent || '')");
}
@Override
public BoundingBox boundingBox(BoundingBoxOptions options) {
return withElement((h, o) -> h.boundingBox(), options);
@@ -128,7 +138,7 @@ class LoccatorImpl implements Locator {
@Override
public Locator first() {
return new LoccatorImpl(frame, selector + " >> _nth=first");
return new LocatorImpl(frame, selector + " >> _nth=first");
}
@Override
@@ -229,17 +239,17 @@ class LoccatorImpl implements Locator {
@Override
public Locator last() {
return new LoccatorImpl(frame, selector + " >> _nth=last");
return new LocatorImpl(frame, selector + " >> _nth=last");
}
@Override
public Locator locator(String selector) {
return new LoccatorImpl(frame, this.selector + " >> " + selector);
return new LocatorImpl(frame, this.selector + " >> " + selector);
}
@Override
public Locator nth(int index) {
return new LoccatorImpl(frame, selector + " >> _nth=" + index);
return new LocatorImpl(frame, selector + " >> _nth=" + index);
}
@Override
@@ -385,6 +395,6 @@ class LoccatorImpl implements Locator {
@Override
public String toString() {
return "Loccator@" + selector;
return "Locator@" + selector;
}
}
@@ -59,10 +59,10 @@ class TracingImpl implements Tracing {
@Override
public void stop(StopOptions options) {
context.withLogging("Tracing.stop", () -> {
context.sendMessage("tracingStop");
if (options != null && options.path != null) {
export(options.path);
}
context.sendMessage("tracingStop");
});
}
}
@@ -0,0 +1,206 @@
/*
* 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.Test;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;
public class TestLocatorConvenience extends TestBase {
@Test
void shouldHaveANicePreview() {
page.navigate(server.PREFIX + "/dom.html");
Locator outer = page.locator("#outer");
Locator inner = outer.locator("#inner");
Locator check = page.locator("#check");
JSHandle text = inner.evaluateHandle("e => e.firstChild");
page.evaluate("() => 1"); // Give them a chance to calculate the preview.
assertEquals("Locator@#outer", outer.toString());
assertEquals("Locator@#outer >> #inner", inner.toString());
assertEquals("JSHandle@#text=Text,↵more text", text.toString());
assertEquals("Locator@#check", check.toString());
}
@Test
void getAttributeShouldWork() {
page.navigate(server.PREFIX + "/dom.html");
Locator locator = page.locator("#outer");
assertEquals("value", locator.getAttribute("name"));
assertNull(locator.getAttribute("foo"));
assertEquals("value", page.getAttribute("#outer", "name"));
assertNull(page.getAttribute("#outer", "foo"));
}
@Test
void inputValueShouldWork() {
page.navigate(server.PREFIX + "/dom.html");
page.selectOption("#select", "foo");
assertEquals("foo", page.inputValue("#select"));
page.fill("#textarea", "text value");
assertEquals("text value", page.inputValue("#textarea"));
page.fill("#input", "input value");
assertEquals("input value", page.inputValue("#input"));
Locator locator = page.locator("#input");
assertEquals("input value", locator.inputValue());
try {
page.inputValue("#inner");
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("Node is not an HTMLInputElement or HTMLTextAreaElement or HTMLSelectElement"));
}
try {
Locator locator2 = page.locator("#inner");
locator2.inputValue();
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("Node is not an HTMLInputElement or HTMLTextAreaElement or HTMLSelectElement"));
}
}
@Test
void innerHTMLShouldWork() {
page.navigate(server.PREFIX + "/dom.html");
Locator locator = page.locator("#outer");
assertEquals("<div id=\"inner\">Text,\nmore text</div>", locator.innerHTML());
assertEquals("<div id=\"inner\">Text,\nmore text</div>", page.innerHTML("#outer"));
}
@Test
void innerTextShouldWork() {
page.navigate(server.PREFIX + "/dom.html");
Locator locator = page.locator("#inner");
assertEquals("Text, more text", locator.innerText());
assertEquals("Text, more text", page.innerText("#inner"));
}
@Test
void innerTextShouldThrow() {
page.setContent("<svg>text</svg>");
try {
page.innerText("svg");
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("Not an HTMLElement"));
}
Locator locator = page.locator("svg");
try {
locator.innerText();
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("Not an HTMLElement"));
}
}
@Test
void textContentShouldWork() {
page.navigate(server.PREFIX + "/dom.html");
Locator locator = page.locator("#inner");
assertEquals("Text,\nmore text", locator.textContent());
assertEquals("Text,\nmore text", page.textContent("#inner"));
}
@Test
void isVisibleAndIsHiddenShouldWork() {
page.setContent("<div>Hi</div><span></span>");
Locator div = page.locator("div");
assertTrue(div.isVisible());
assertFalse(div.isHidden());
assertTrue(page.isVisible("div"));
assertFalse(page.isHidden("div"));
Locator span = page.locator("span");
assertFalse(span.isVisible());
assertTrue(span.isHidden());
assertFalse(page.isVisible("span"));
assertTrue(page.isHidden("span"));
assertFalse(page.isVisible("no-such-element"));
assertTrue(page.isHidden("no-such-element"));
}
@Test
void isEnabledAndIsDisabledShouldWork() {
page.setContent("<button disabled>button1</button>\n" +
"<button>button2</button>\n" +
"<div>div</div>");
Locator div = page.locator("div");
assertTrue(div.isEnabled());
assertFalse(div.isDisabled());
assertTrue(page.isEnabled("div"));
assertEquals(false, page.isDisabled("div"));
Locator button1 = page.locator(":text('button1')");
assertEquals(false, button1.isEnabled());
assertTrue(button1.isDisabled());
assertEquals(false, page.isEnabled(":text('button1')"));
assertTrue(page.isDisabled(":text('button1')"));
Locator button2 = page.locator(":text('button2')");
assertTrue(button2.isEnabled());
assertEquals(false, button2.isDisabled());
assertTrue(page.isEnabled(":text('button2')"));
assertEquals(false, page.isDisabled(":text('button2')"));
}
@Test
void isEditableShouldWork() {
page.setContent("<input id=input1 disabled><textarea></textarea><input id=input2>");
page.evalOnSelector("textarea", "t => t.readOnly = true");
Locator input1 = page.locator("#input1");
assertFalse(input1.isEditable());
assertFalse(page.isEditable("#input1"));
Locator input2 = page.locator("#input2");
assertTrue(input2.isEditable());
assertTrue(page.isEditable("#input2"));
Locator textarea = page.locator("textarea");
assertFalse(textarea.isEditable());
assertFalse(page.isEditable("textarea"));
}
@Test
void isCheckedShouldWork() {
page.setContent("<input type='checkbox' checked><div>Not a checkbox</div>");
Locator element = page.locator("input");
assertTrue(element.isChecked());
assertTrue(page.isChecked("input"));
element.evaluate("input => input.checked = false");
assertFalse(element.isChecked());
assertFalse(page.isChecked("input"));
try {
page.isChecked("div");
fail("did not throw");
} catch (PlaywrightException e) {
assertTrue(e.getMessage().contains("Not a checkbox or radio button"));
}
}
@Test
void allTextContentsShouldWork() {
page.setContent("<div>A</div><div>B</div><div>C</div>");
assertEquals(asList("A", "B", "C"), page.locator("div").allTextContents());
}
@Test
void allInnerTextsShouldWork() {
page.setContent("<div>A</div><div>B</div><div>C</div>");
assertEquals(asList("A", "B", "C"), page.locator("div").allInnerTexts());
}
}
@@ -0,0 +1,119 @@
/*
* 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 com.google.gson.Gson;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import static com.microsoft.playwright.Utils.assertJsonEquals;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestPageDrag extends TestBase {
@Test
void shouldWorkIfTheDragIsCanceled() {
page.navigate(server.PREFIX + "/drag-n-drop.html");
page.evaluate("() => {\n" +
" document.body.addEventListener('dragstart', event => {\n" +
" event.preventDefault();\n" +
" }, false);\n" +
" }");
page.hover("#source");
page.mouse().down();
page.hover("#target");
page.mouse().up();
assertEquals(false, page.evalOnSelector("#target", "target => target.contains(document.querySelector('#source'))"));
}
@Test
void shouldWorkIfTheDragEventIsCapturedButNotCanceled() {
page.navigate(server.PREFIX + "/drag-n-drop.html");
page.evaluate("() => {\n" +
" document.body.addEventListener('dragstart', event => {\n" +
" event.stopImmediatePropagation();\n" +
" }, false);\n" +
" }");
page.hover("#source");
page.mouse().down();
page.hover("#target");
page.mouse().up();
assertEquals(true, page.evalOnSelector("#target", "target => target.contains(document.querySelector('#source'))"));
}
@Test
void shouldBeAbleToDragTheMouseInAFrame() {
page.navigate(server.PREFIX + "/frames/one-frame.html");
JSHandle eventsHandle = trackEvents(page.frames().get(1).querySelector("html"));
page.mouse().move(30, 30);
page.mouse().down();
page.mouse().move(60, 60);
page.mouse().up();
assertEquals(asList("mousemove", "mousedown", "mousemove", "mouseup"), eventsHandle.jsonValue());
}
private static JSHandle trackEvents(ElementHandle target) {
return target.evaluateHandle("target => {\n" +
" const events = [];\n" +
" for (const event of [\n" +
" 'mousedown', 'mousemove', 'mouseup',\n" +
" 'dragstart', 'dragend', 'dragover', 'dragenter', 'dragleave', 'dragexit',\n" +
" 'drop'\n" +
" ])\n" +
" target.addEventListener(event, () => events.push(event), false);\n" +
" return events;\n" +
"}");
}
@Test
void shouldWorkWithTheHelperMethod() {
page.navigate(server.PREFIX + "/drag-n-drop.html");
page.dragAndDrop("#source", "#target");
assertEquals(true, page.evalOnSelector("#target",
"target => target.contains(document.querySelector('#source'))")); // could not find source in target
}
@Test
void shouldAllowSpecifyingThePosition() {
page.setContent("<div style='width:100px;height:100px;background:red;' id='red'>\n" +
"</div>\n" +
"<div style='width:100px;height:100px;background:blue;' id='blue'>\n" +
"</div>");
JSHandle eventsHandle = page.evaluateHandle("() => {\n" +
" const events = [];\n" +
" document.getElementById('red').addEventListener('mousedown', event => {\n" +
" events.push({\n" +
" type: 'mousedown',\n" +
" x: event.offsetX,\n" +
" y: event.offsetY,\n" +
" });\n" +
" });\n" +
" document.getElementById('blue').addEventListener('mouseup', event => {\n" +
" events.push({\n" +
" type: 'mouseup',\n" +
" x: event.offsetX,\n" +
" y: event.offsetY,\n" +
" });\n" +
" });\n" +
" return events;\n" +
" }");
page.dragAndDrop("#red", "#blue", new Page.DragAndDropOptions()
.setSourcePosition(34, 7).setTargetPosition(10, 20));
Object json = eventsHandle.jsonValue();
assertJsonEquals("[{type: \"mousedown\", x: 34, y: 7},{type: \"mouseup\", x: 10, y: 20}]", json);
}
}
@@ -66,7 +66,11 @@ public class TestWorkers extends TestBase {
void shouldHaveJSHandlesForConsoleLogs() {
ConsoleMessage log = page.waitForConsoleMessage(() -> page.evaluate(
"() => new Worker(URL.createObjectURL(new Blob(['console.log(1,2,3,this)'], {type: 'application/javascript'})))"));
assertEquals("1 2 3 JSHandle@object", log.text());
if (isFirefox()) {
assertEquals("1 2 3 JSHandle@object", log.text());
} else {
assertEquals("1 2 3 DedicatedWorkerGlobalScope", log.text());
}
assertEquals(4, log.args().size());
assertEquals("null", (log.args().get(3).getProperty("origin")).jsonValue());
}
+1
View File
@@ -2,3 +2,4 @@
more text</div></div><input id="check" type=checkbox checked foo="bar&quot;">
<input id="input"></input>
<textarea id="textarea"></textarea>
<select id="select"><option></option><option value="foo"></option></select>
+1 -1
View File
@@ -1 +1 @@
1.14.0-next-1627483012000
1.14.0-next-1628276501000
@@ -259,6 +259,11 @@ class TypeRef extends Element {
customTypeNames.put("FileChooser.setFiles.files", "FilePayload");
customTypeNames.put("Frame.setInputFiles.files", "FilePayload");
customTypeNames.put("Page.setInputFiles.files", "FilePayload");
customTypeNames.put("Page.dragAndDrop.options.sourcePosition", "Position");
customTypeNames.put("Frame.dragAndDrop.options.sourcePosition", "Position");
customTypeNames.put("Page.dragAndDrop.options.targetPosition", "Position");
customTypeNames.put("Frame.dragAndDrop.options.targetPosition", "Position");
}
TypeRef(Element parent, JsonElement jsonElement) {