From a012836779d382636a97bdb344d4bec852bd5f2b Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Wed, 18 Aug 2021 15:08:08 -0700 Subject: [PATCH] chore: update driver, support context-level strict (#575) --- .../com/microsoft/playwright/Browser.java | 20 +++++++ .../com/microsoft/playwright/BrowserType.java | 10 ++++ .../java/com/microsoft/playwright/Frame.java | 2 - .../com/microsoft/playwright/Locator.java | 12 +++++ .../java/com/microsoft/playwright/Page.java | 2 - .../playwright/TestBrowserContextStrict.java | 54 +++++++++++++++++++ scripts/CLI_VERSION | 2 +- 7 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStrict.java diff --git a/playwright/src/main/java/com/microsoft/playwright/Browser.java b/playwright/src/main/java/com/microsoft/playwright/Browser.java index 9bb1fb8c..61283af9 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Browser.java +++ b/playwright/src/main/java/com/microsoft/playwright/Browser.java @@ -174,6 +174,12 @@ public interface Browser extends AutoCloseable { * state. */ public Path storageStatePath; + /** + * It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors + * that imply single target DOM element will throw when more than one element matches the selector. See {@code Locator} to learn + * more about the strict mode. + */ + public Boolean strictSelectors; /** * Changes the timezone of the context. See ICU's @@ -300,6 +306,10 @@ public interface Browser extends AutoCloseable { this.storageStatePath = storageStatePath; return this; } + public NewContextOptions setStrictSelectors(boolean strictSelectors) { + this.strictSelectors = strictSelectors; + return this; + } public NewContextOptions setTimezoneId(String timezoneId) { this.timezoneId = timezoneId; return this; @@ -435,6 +445,12 @@ public interface Browser extends AutoCloseable { * state. */ public Path storageStatePath; + /** + * It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors + * that imply single target DOM element will throw when more than one element matches the selector. See {@code Locator} to learn + * more about the strict mode. + */ + public Boolean strictSelectors; /** * Changes the timezone of the context. See ICU's @@ -561,6 +577,10 @@ public interface Browser extends AutoCloseable { this.storageStatePath = storageStatePath; return this; } + public NewPageOptions setStrictSelectors(boolean strictSelectors) { + this.strictSelectors = strictSelectors; + return this; + } public NewPageOptions setTimezoneId(String timezoneId) { this.timezoneId = timezoneId; return this; diff --git a/playwright/src/main/java/com/microsoft/playwright/BrowserType.java b/playwright/src/main/java/com/microsoft/playwright/BrowserType.java index aaa5cbc5..2df847aa 100644 --- a/playwright/src/main/java/com/microsoft/playwright/BrowserType.java +++ b/playwright/src/main/java/com/microsoft/playwright/BrowserType.java @@ -440,6 +440,12 @@ public interface BrowserType { * Slows down Playwright operations by the specified amount of milliseconds. Useful so that you can see what is going on. */ public Double slowMo; + /** + * It specified, enables strict selectors mode for this context. In the strict selectors mode all operations on selectors + * that imply single target DOM element will throw when more than one element matches the selector. See {@code Locator} to learn + * more about the strict mode. + */ + public Boolean strictSelectors; /** * Maximum time in milliseconds to wait for the browser instance to start. Defaults to {@code 30000} (30 seconds). Pass {@code 0} to * disable timeout. @@ -628,6 +634,10 @@ public interface BrowserType { this.slowMo = slowMo; return this; } + public LaunchPersistentContextOptions setStrictSelectors(boolean strictSelectors) { + this.strictSelectors = strictSelectors; + return this; + } public LaunchPersistentContextOptions setTimeout(double timeout) { this.timeout = timeout; return this; diff --git a/playwright/src/main/java/com/microsoft/playwright/Frame.java b/playwright/src/main/java/com/microsoft/playwright/Frame.java index dca065ac..ba70aa54 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Frame.java +++ b/playwright/src/main/java/com/microsoft/playwright/Frame.java @@ -2231,8 +2231,6 @@ public interface Frame { * element immediately before performing an action, so a series of actions on the same locator can in fact be performed on * different DOM elements. That would happen if the DOM structure between those actions has changed. * - *

Note that locator always implies visibility, so it will always be locating visible elements. - * * @param selector A selector to use when resolving DOM element. See working with * selectors for more details. */ diff --git a/playwright/src/main/java/com/microsoft/playwright/Locator.java b/playwright/src/main/java/com/microsoft/playwright/Locator.java index 8b3e4729..08c92057 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Locator.java +++ b/playwright/src/main/java/com/microsoft/playwright/Locator.java @@ -47,6 +47,18 @@ import java.util.*; * locator.hover(); * locator.click(); * } + * + *

**Strictness** + * + *

Locators are strict. This means that all operations on locators that imply some target DOM element will throw if more + * than one element matches given selector. + *

{@code
+ * // Throws if there are several buttons in DOM:
+ * page.locator("button").click();
+ *
+ * // Works because you explicitly tell locator to pick the first element:
+ * page.locator("button").first().click();
+ * }
*/ public interface Locator { class BoundingBoxOptions { diff --git a/playwright/src/main/java/com/microsoft/playwright/Page.java b/playwright/src/main/java/com/microsoft/playwright/Page.java index 4fe09a97..aabb7265 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Page.java +++ b/playwright/src/main/java/com/microsoft/playwright/Page.java @@ -3378,8 +3378,6 @@ public interface Page extends AutoCloseable { * element immediately before performing an action, so a series of actions on the same locator can in fact be performed on * different DOM elements. That would happen if the DOM structure between those actions has changed. * - *

Note that locator always implies visibility, so it will always be locating visible elements. - * *

Shortcut for main frame's {@link Frame#locator Frame.locator()}. * * @param selector A selector to use when resolving DOM element. See working with diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStrict.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStrict.java new file mode 100644 index 00000000..814712c4 --- /dev/null +++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextStrict.java @@ -0,0 +1,54 @@ +/* + * 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 org.junit.jupiter.api.Assertions.*; + +public class TestBrowserContextStrict extends TestBase { + @Override + BrowserContext createContext() { + return browser.newContext(new Browser.NewContextOptions().setStrictSelectors(true)); + } + + @Test + void shouldNotFailPageTextContentInNonStrictMode() { + try (BrowserContext context = browser.newContext()) { + Page page = context.newPage(); + page.setContent("span1

target
"); + assertEquals("span1", page.textContent("span")); + } + } + + @Test + void shouldFailPageTextContentInStrictMode() { + page.setContent("span1
target
"); + try { + page.textContent("span"); + fail("did not throw"); + } catch (PlaywrightException e) { + assertTrue(e.getMessage().contains("strict mode violation")); + } + } + + @Test + void shouldOptOutOfStrictMode() { + page.setContent("span1
target
"); + assertEquals("span1", page.textContent("span", new Page.TextContentOptions().setStrict(false))); + } +} diff --git a/scripts/CLI_VERSION b/scripts/CLI_VERSION index dcf2c60d..eb34cf7c 100644 --- a/scripts/CLI_VERSION +++ b/scripts/CLI_VERSION @@ -1 +1 @@ -1.14.0-1628878084000 +1.15.0-next-1629322356000