chore: roll driver to 1.43.0-beta, implement clearCookie(filter) (#1525)
This commit is contained in:
@@ -11,9 +11,9 @@ Playwright is a Java library to automate [Chromium](https://www.chromium.org/Hom
|
||||
|
||||
| | Linux | macOS | Windows |
|
||||
| :--- | :---: | :---: | :---: |
|
||||
| Chromium <!-- GEN:chromium-version -->123.0.6312.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Chromium <!-- GEN:chromium-version -->124.0.6367.8<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| WebKit <!-- GEN:webkit-version -->17.4<!-- GEN:stop --> | ✅ | ✅ | ✅ |
|
||||
| Firefox <!-- GEN:firefox-version -->123.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Firefox <!-- GEN:firefox-version -->124.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
|
||||
Headless execution is supported for all the browsers on all platforms. Check out [system requirements](https://playwright.dev/java/docs/intro#system-requirements) for details.
|
||||
|
||||
|
||||
@@ -186,6 +186,63 @@ public interface BrowserContext extends AutoCloseable {
|
||||
*/
|
||||
void offResponse(Consumer<Response> handler);
|
||||
|
||||
class ClearCookiesOptions {
|
||||
/**
|
||||
* Only removes cookies with the given domain.
|
||||
*/
|
||||
public Object domain;
|
||||
/**
|
||||
* Only removes cookies with the given name.
|
||||
*/
|
||||
public Object name;
|
||||
/**
|
||||
* Only removes cookies with the given path.
|
||||
*/
|
||||
public Object path;
|
||||
|
||||
/**
|
||||
* Only removes cookies with the given domain.
|
||||
*/
|
||||
public ClearCookiesOptions setDomain(String domain) {
|
||||
this.domain = domain;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Only removes cookies with the given domain.
|
||||
*/
|
||||
public ClearCookiesOptions setDomain(Pattern domain) {
|
||||
this.domain = domain;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Only removes cookies with the given name.
|
||||
*/
|
||||
public ClearCookiesOptions setName(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Only removes cookies with the given name.
|
||||
*/
|
||||
public ClearCookiesOptions setName(Pattern name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Only removes cookies with the given path.
|
||||
*/
|
||||
public ClearCookiesOptions setPath(String path) {
|
||||
this.path = path;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Only removes cookies with the given path.
|
||||
*/
|
||||
public ClearCookiesOptions setPath(Pattern path) {
|
||||
this.path = path;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
class CloseOptions {
|
||||
/**
|
||||
* The reason to be reported to the operations interrupted by the context closure.
|
||||
@@ -492,11 +549,41 @@ public interface BrowserContext extends AutoCloseable {
|
||||
*/
|
||||
Browser browser();
|
||||
/**
|
||||
* Clears context cookies.
|
||||
* Removes cookies from context. Accepts optional filter.
|
||||
*
|
||||
* <p> **Usage**
|
||||
* <pre>{@code
|
||||
* context.clearCookies();
|
||||
* context.clearCookies(new BrowserContext.ClearCookiesOptions().setName("session-id"));
|
||||
* context.clearCookies(new BrowserContext.ClearCookiesOptions().setDomain("my-origin.com"));
|
||||
* context.clearCookies(new BrowserContext.ClearCookiesOptions().setPath("/api/v1"));
|
||||
* context.clearCookies(new BrowserContext.ClearCookiesOptions()
|
||||
* .setName("session-id")
|
||||
* .setDomain("my-origin.com"));
|
||||
* }</pre>
|
||||
*
|
||||
* @since v1.8
|
||||
*/
|
||||
void clearCookies();
|
||||
default void clearCookies() {
|
||||
clearCookies(null);
|
||||
}
|
||||
/**
|
||||
* Removes cookies from context. Accepts optional filter.
|
||||
*
|
||||
* <p> **Usage**
|
||||
* <pre>{@code
|
||||
* context.clearCookies();
|
||||
* context.clearCookies(new BrowserContext.ClearCookiesOptions().setName("session-id"));
|
||||
* context.clearCookies(new BrowserContext.ClearCookiesOptions().setDomain("my-origin.com"));
|
||||
* context.clearCookies(new BrowserContext.ClearCookiesOptions().setPath("/api/v1"));
|
||||
* context.clearCookies(new BrowserContext.ClearCookiesOptions()
|
||||
* .setName("session-id")
|
||||
* .setDomain("my-origin.com"));
|
||||
* }</pre>
|
||||
*
|
||||
* @since v1.8
|
||||
*/
|
||||
void clearCookies(ClearCookiesOptions options);
|
||||
/**
|
||||
* Clears all permission overrides for the browser context.
|
||||
*
|
||||
|
||||
@@ -182,8 +182,7 @@ public interface BrowserType {
|
||||
*/
|
||||
public Boolean chromiumSandbox;
|
||||
/**
|
||||
* **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is {@code true}, the {@code
|
||||
* headless} option will be set {@code false}.
|
||||
* @deprecated Use <a href="https://playwright.dev/java/docs/debug">debugging tools</a> instead.
|
||||
*/
|
||||
public Boolean devtools;
|
||||
/**
|
||||
@@ -291,8 +290,7 @@ public interface BrowserType {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is {@code true}, the {@code
|
||||
* headless} option will be set {@code false}.
|
||||
* @deprecated Use <a href="https://playwright.dev/java/docs/debug">debugging tools</a> instead.
|
||||
*/
|
||||
public LaunchOptions setDevtools(boolean devtools) {
|
||||
this.devtools = devtools;
|
||||
@@ -468,8 +466,7 @@ public interface BrowserType {
|
||||
*/
|
||||
public Double deviceScaleFactor;
|
||||
/**
|
||||
* **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is {@code true}, the {@code
|
||||
* headless} option will be set {@code false}.
|
||||
* @deprecated Use <a href="https://playwright.dev/java/docs/debug">debugging tools</a> instead.
|
||||
*/
|
||||
public Boolean devtools;
|
||||
/**
|
||||
@@ -760,8 +757,7 @@ public interface BrowserType {
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* **Chromium-only** Whether to auto-open a Developer Tools panel for each tab. If this option is {@code true}, the {@code
|
||||
* headless} option will be set {@code false}.
|
||||
* @deprecated Use <a href="https://playwright.dev/java/docs/debug">debugging tools</a> instead.
|
||||
*/
|
||||
public LaunchPersistentContextOptions setDevtools(boolean devtools) {
|
||||
this.devtools = devtools;
|
||||
|
||||
@@ -42,11 +42,13 @@ import java.util.regex.Pattern;
|
||||
*
|
||||
* <p> **Converting Locator to FrameLocator**
|
||||
*
|
||||
* <p> If you have a {@code Locator} object pointing to an {@code iframe} it can be converted to {@code FrameLocator} using <a
|
||||
* href="https://developer.mozilla.org/en-US/docs/Web/CSS/:scope">{@code :scope}</a> CSS selector:
|
||||
* <pre>{@code
|
||||
* Locator frameLocator = locator.frameLocator(':scope');
|
||||
* }</pre>
|
||||
* <p> If you have a {@code Locator} object pointing to an {@code iframe} it can be converted to {@code FrameLocator} using
|
||||
* {@link Locator#contentFrame Locator.contentFrame()}.
|
||||
*
|
||||
* <p> **Converting FrameLocator to Locator**
|
||||
*
|
||||
* <p> If you have a {@code FrameLocator} object it can be converted to {@code Locator} pointing to the same {@code iframe}
|
||||
* using {@link FrameLocator#owner FrameLocator.owner()}.
|
||||
*/
|
||||
public interface FrameLocator {
|
||||
class GetByAltTextOptions {
|
||||
@@ -1003,5 +1005,24 @@ public interface FrameLocator {
|
||||
* @since v1.17
|
||||
*/
|
||||
FrameLocator nth(int index);
|
||||
/**
|
||||
* Returns a {@code Locator} object pointing to the same {@code iframe} as this frame locator.
|
||||
*
|
||||
* <p> Useful when you have a {@code FrameLocator} object obtained somewhere, and later on would like to interact with the
|
||||
* {@code iframe} element.
|
||||
*
|
||||
* <p> For a reverse operation, use {@link Locator#contentFrame Locator.contentFrame()}.
|
||||
*
|
||||
* <p> **Usage**
|
||||
* <pre>{@code
|
||||
* FrameLocator frameLocator = page.frameLocator("iframe[name=\"embedded\"]");
|
||||
* // ...
|
||||
* Locator locator = frameLocator.owner();
|
||||
* assertThat(locator).isVisible();
|
||||
* }</pre>
|
||||
*
|
||||
* @since v1.43
|
||||
*/
|
||||
Locator owner();
|
||||
}
|
||||
|
||||
|
||||
@@ -2704,6 +2704,25 @@ public interface Locator {
|
||||
* @since v1.14
|
||||
*/
|
||||
List<ElementHandle> elementHandles();
|
||||
/**
|
||||
* Returns a {@code FrameLocator} object pointing to the same {@code iframe} as this locator.
|
||||
*
|
||||
* <p> Useful when you have a {@code Locator} object obtained somewhere, and later on would like to interact with the content
|
||||
* inside the frame.
|
||||
*
|
||||
* <p> For a reverse operation, use {@link FrameLocator#owner FrameLocator.owner()}.
|
||||
*
|
||||
* <p> **Usage**
|
||||
* <pre>{@code
|
||||
* Locator locator = page.locator("iframe[name=\"embedded\"]");
|
||||
* // ...
|
||||
* FrameLocator frameLocator = locator.contentFrame();
|
||||
* frameLocator.getByRole(AriaRole.BUTTON).click();
|
||||
* }</pre>
|
||||
*
|
||||
* @since v1.43
|
||||
*/
|
||||
FrameLocator contentFrame();
|
||||
/**
|
||||
* Execute JavaScript code in the page, taking the matching element as an argument.
|
||||
*
|
||||
|
||||
@@ -5918,9 +5918,11 @@ public interface Page extends AutoCloseable {
|
||||
*/
|
||||
List<ElementHandle> querySelectorAll(String selector);
|
||||
/**
|
||||
* When testing a web page, sometimes unexpected overlays like a coookie consent dialog appear and block actions you want
|
||||
* to automate, e.g. clicking a button. These overlays don't always show up in the same way or at the same time, making
|
||||
* them tricky to handle in automated tests.
|
||||
* <strong>NOTE:</strong> This method is experimental and its behavior may change in the upcoming releases.
|
||||
*
|
||||
* <p> When testing a web page, sometimes unexpected overlays like a "Sign up" dialog appear and block actions you want to
|
||||
* automate, e.g. clicking a button. These overlays don't always show up in the same way or at the same time, making them
|
||||
* tricky to handle in automated tests.
|
||||
*
|
||||
* <p> This method lets you set up a special function, called a handler, that activates when it detects that overlay is
|
||||
* visible. The handler's job is to remove the overlay, allowing your test to continue as if the overlay wasn't there.
|
||||
@@ -5932,7 +5934,8 @@ public interface Page extends AutoCloseable {
|
||||
* <li> Playwright checks for the overlay every time before executing or retrying an action that requires an <a
|
||||
* href="https://playwright.dev/java/docs/actionability">actionability check</a>, or before performing an auto-waiting
|
||||
* assertion check. When overlay is visible, Playwright calls the handler first, and then proceeds with the
|
||||
* action/assertion.</li>
|
||||
* action/assertion. Note that the handler is only called when you perform an action/assertion - if the overlay becomes
|
||||
* visible but you don't perform any actions, the handler will not be triggered.</li>
|
||||
* <li> The execution time of the handler counts towards the timeout of the action/assertion that executed the handler. If your
|
||||
* handler takes too long, it might cause timeouts.</li>
|
||||
* <li> You can register multiple handlers. However, only a single handler will be running at a time. Make sure the actions
|
||||
@@ -5951,11 +5954,11 @@ public interface Page extends AutoCloseable {
|
||||
*
|
||||
* <p> **Usage**
|
||||
*
|
||||
* <p> An example that closes a cookie consent dialog when it appears:
|
||||
* <p> An example that closes a "Sign up to the newsletter" dialog when it appears:
|
||||
* <pre>{@code
|
||||
* // Setup the handler.
|
||||
* page.addLocatorHandler(page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Accept all cookies")), () => {
|
||||
* page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Reject all cookies")).click();
|
||||
* page.addLocatorHandler(page.getByText("Sign up to the newsletter"), () => {
|
||||
* page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("No thanks")).click();
|
||||
* });
|
||||
*
|
||||
* // Write the test as usual.
|
||||
|
||||
@@ -37,6 +37,7 @@ import java.util.regex.Pattern;
|
||||
import static com.microsoft.playwright.impl.Serialization.addHarUrlFilter;
|
||||
import static com.microsoft.playwright.impl.Serialization.gson;
|
||||
import static com.microsoft.playwright.impl.Utils.isSafeCloseError;
|
||||
import static com.microsoft.playwright.impl.Utils.toJsRegexFlags;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.nio.file.Files.readAllBytes;
|
||||
import static java.util.Arrays.asList;
|
||||
@@ -335,8 +336,29 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearCookies() {
|
||||
withLogging("BrowserContext.clearCookies", () -> sendMessage("clearCookies"));
|
||||
public void clearCookies(ClearCookiesOptions options) {
|
||||
withLogging("BrowserContext.clearCookies", () -> clearCookiesImpl(options));
|
||||
}
|
||||
|
||||
private void clearCookiesImpl(ClearCookiesOptions options) {
|
||||
if (options == null) {
|
||||
options = new ClearCookiesOptions();
|
||||
}
|
||||
JsonObject params = new JsonObject();
|
||||
setStringOrRegex(params, "name", options.name);
|
||||
setStringOrRegex(params, "domain", options.domain);
|
||||
setStringOrRegex(params, "path", options.path);
|
||||
sendMessage("clearCookies", params);
|
||||
}
|
||||
|
||||
private static void setStringOrRegex(JsonObject params, String name, Object value) {
|
||||
if (value instanceof String) {
|
||||
params.addProperty(name, (String) value);
|
||||
} else if (value instanceof Pattern) {
|
||||
Pattern pattern = (Pattern) value;
|
||||
params.addProperty(name + "RegexSource", pattern.pattern());
|
||||
params.addProperty(name + "RegexFlags", toJsRegexFlags(pattern));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -133,4 +133,9 @@ class FrameLocatorImpl implements FrameLocator {
|
||||
public FrameLocator nth(int index) {
|
||||
return new FrameLocatorImpl(frame, frameSelector + " >> nth=" + index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Locator owner() {
|
||||
return new LocatorImpl(frame, frameSelector);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,12 @@ public class JSHandleImpl extends ChannelOwner implements JSHandle {
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
withLogging("JSHandle.dispose", () -> sendMessage("dispose"));
|
||||
withLogging("JSHandle.dispose", () -> {
|
||||
try {
|
||||
sendMessage("dispose");
|
||||
} catch (TargetClosedError e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -39,6 +39,10 @@ class LocatorImpl implements Locator {
|
||||
final FrameImpl frame;
|
||||
final String selector;
|
||||
|
||||
LocatorImpl(FrameImpl frame, String frameSelector) {
|
||||
this(frame, frameSelector, null);
|
||||
}
|
||||
|
||||
public LocatorImpl(FrameImpl frame, String selector, LocatorOptions options) {
|
||||
this.frame = frame;
|
||||
if (options != null) {
|
||||
@@ -203,6 +207,11 @@ class LocatorImpl implements Locator {
|
||||
return frame.querySelectorAll(selector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrameLocator contentFrame() {
|
||||
return new FrameLocatorImpl(frame, selector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object evaluate(String expression, Object arg, EvaluateOptions options) {
|
||||
return withElement((h, o) -> h.evaluate(expression, arg), options);
|
||||
|
||||
@@ -24,6 +24,10 @@ public class TargetClosedError extends PlaywrightException {
|
||||
}
|
||||
|
||||
public TargetClosedError(String message) {
|
||||
super(message != null ? message : "Target page, context or browser has been closed");
|
||||
this(message, null);
|
||||
}
|
||||
|
||||
public TargetClosedError(String message, Throwable cause) {
|
||||
super(message != null ? message : "Target page, context or browser has been closed", cause);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,8 @@ class WaitableResult<T> implements Waitable<T> {
|
||||
if (exception != null) {
|
||||
if (exception instanceof TimeoutError) {
|
||||
throw new TimeoutError(exception.getMessage(), exception);
|
||||
} if (exception instanceof TargetClosedError) {
|
||||
throw new TargetClosedError(exception.getMessage(), exception);
|
||||
}
|
||||
throw new PlaywrightException(exception.getMessage(), exception);
|
||||
}
|
||||
|
||||
+85
-3
@@ -16,16 +16,25 @@
|
||||
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import com.microsoft.playwright.junit.FixtureTest;
|
||||
import com.microsoft.playwright.junit.UsePlaywright;
|
||||
import com.microsoft.playwright.options.Cookie;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class TestBrowserContextClearCookies extends TestBase {
|
||||
@FixtureTest
|
||||
@UsePlaywright(TestOptionsFactories.BasicOptionsFactory.class)
|
||||
public class TestBrowserContextClearCookies {
|
||||
@Test
|
||||
void shouldClearCookies() {
|
||||
void shouldClearCookies(Page page, BrowserContext context, Server server) {
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
context.addCookies(asList(
|
||||
new Cookie("cookie1", "1").setUrl(server.EMPTY_PAGE)));
|
||||
@@ -37,7 +46,7 @@ public class TestBrowserContextClearCookies extends TestBase {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldIsolateCookiesWhenClearing() {
|
||||
void shouldIsolateCookiesWhenClearing(BrowserContext context, Browser browser, Server server) {
|
||||
BrowserContext anotherContext = browser.newContext();
|
||||
context.addCookies(asList(
|
||||
new Cookie("page1cookie", "page1value").setUrl(server.EMPTY_PAGE)));
|
||||
@@ -56,4 +65,77 @@ public class TestBrowserContextClearCookies extends TestBase {
|
||||
assertEquals(0, (anotherContext.cookies()).size());
|
||||
anotherContext.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRemoveCookiesByName(Page page, BrowserContext context, Server server) throws MalformedURLException {
|
||||
context.addCookies(Arrays.asList(
|
||||
new Cookie("cookie1", "1").setDomain(new URL(server.PREFIX).getHost()).setPath("/"),
|
||||
new Cookie("cookie2", "2").setDomain(new URL(server.PREFIX).getHost()).setPath("/")
|
||||
));
|
||||
|
||||
page.navigate(server.PREFIX);
|
||||
assertEquals("cookie1=1; cookie2=2", page.evaluate("document.cookie"));
|
||||
context.clearCookies(new BrowserContext.ClearCookiesOptions().setName("cookie1"));
|
||||
assertEquals("cookie2=2", page.evaluate("document.cookie"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveCookiesByNameRegex(Page page, BrowserContext context, Server server) throws MalformedURLException {
|
||||
context.addCookies(Arrays.asList(
|
||||
new Cookie("cookie1", "1").setDomain(new URL(server.PREFIX).getHost()).setPath("/"),
|
||||
new Cookie("cookie2", "2").setDomain(new URL(server.PREFIX).getHost()).setPath("/")
|
||||
));
|
||||
|
||||
page.navigate(server.PREFIX);
|
||||
assertEquals("cookie1=1; cookie2=2", page.evaluate("document.cookie"));
|
||||
context.clearCookies(new BrowserContext.ClearCookiesOptions().setName(Pattern.compile("coo.*1")));
|
||||
assertEquals("cookie2=2", page.evaluate("document.cookie"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveCookiesByDomain(Page page, BrowserContext context, Server server) throws MalformedURLException {
|
||||
context.addCookies(Arrays.asList(
|
||||
new Cookie("cookie1", "1").setDomain(new URL(server.PREFIX).getHost()).setPath("/"),
|
||||
new Cookie("cookie2", "2").setDomain(new URL(server.CROSS_PROCESS_PREFIX).getHost()).setPath("/")
|
||||
));
|
||||
page.navigate(server.PREFIX);
|
||||
assertEquals("cookie1=1", page.evaluate("document.cookie"));
|
||||
page.navigate(server.CROSS_PROCESS_PREFIX);
|
||||
assertEquals("cookie2=2", page.evaluate("document.cookie"));
|
||||
context.clearCookies(new BrowserContext.ClearCookiesOptions().setDomain(new URL(server.CROSS_PROCESS_PREFIX).getHost()));
|
||||
assertEquals("", page.evaluate("document.cookie"));
|
||||
page.navigate(server.PREFIX);
|
||||
assertEquals("cookie1=1", page.evaluate("document.cookie"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveCookiesByPath(Page page, BrowserContext context, Server server) throws MalformedURLException {
|
||||
context.addCookies(Arrays.asList(
|
||||
new Cookie("cookie1", "1").setDomain(new URL(server.PREFIX).getHost()).setPath("/api/v1"),
|
||||
new Cookie("cookie2", "2").setDomain(new URL(server.PREFIX).getHost()).setPath("/api/v2"),
|
||||
new Cookie("cookie3", "3").setDomain(new URL(server.PREFIX).getHost()).setPath("/")
|
||||
));
|
||||
page.navigate(server.PREFIX + "/api/v1");
|
||||
assertEquals("cookie1=1; cookie3=3", page.evaluate("document.cookie"));
|
||||
context.clearCookies(new BrowserContext.ClearCookiesOptions().setPath("/api/v1"));
|
||||
assertEquals("cookie3=3", page.evaluate("document.cookie"));
|
||||
page.navigate(server.PREFIX + "/api/v2");
|
||||
assertEquals("cookie2=2; cookie3=3", page.evaluate("document.cookie"));
|
||||
page.navigate(server.PREFIX + "/");
|
||||
assertEquals("cookie3=3", page.evaluate("document.cookie"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRemoveCookiesByNameAndDomain(Page page, BrowserContext context, Server server) throws MalformedURLException {
|
||||
context.addCookies(Arrays.asList(
|
||||
new Cookie("cookie1", "1").setDomain(new URL(server.PREFIX).getHost()).setPath("/"),
|
||||
new Cookie("cookie1", "1").setDomain(new URL(server.CROSS_PROCESS_PREFIX).getHost()).setPath("/")
|
||||
));
|
||||
page.navigate(server.PREFIX);
|
||||
assertEquals("cookie1=1", page.evaluate("document.cookie"));
|
||||
context.clearCookies(new BrowserContext.ClearCookiesOptions().setName("cookie1").setDomain(new URL(server.PREFIX).getHost()));
|
||||
assertEquals("", page.evaluate("document.cookie"));
|
||||
page.navigate(server.CROSS_PROCESS_PREFIX);
|
||||
assertEquals("cookie1=1", page.evaluate("document.cookie"));
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -46,17 +46,17 @@ public class TestBrowserContextStorageState extends TestBase {
|
||||
assertJsonEquals("{" +
|
||||
"cookies:[]," +
|
||||
"origins:[{\n" +
|
||||
" origin: 'https://www.example.com',\n" +
|
||||
" localStorage: [{\n" +
|
||||
" name: 'name1',\n" +
|
||||
" value: 'value1'\n" +
|
||||
" }]\n" +
|
||||
"}, {\n" +
|
||||
" origin: 'https://www.domain.com',\n" +
|
||||
" localStorage: [{\n" +
|
||||
" name: 'name2',\n" +
|
||||
" value: 'value2'\n" +
|
||||
" }]\n" +
|
||||
"}, {\n" +
|
||||
" origin: 'https://www.example.com',\n" +
|
||||
" localStorage: [{\n" +
|
||||
" name: 'name1',\n" +
|
||||
" value: 'value1'\n" +
|
||||
" }]\n" +
|
||||
"}]}", new Gson().fromJson(storageState, JsonObject.class));
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
public class TestElementHandleMisc extends TestBase {
|
||||
@Test
|
||||
@@ -108,4 +109,12 @@ public class TestElementHandleMisc extends TestBase {
|
||||
assertEquals(asList("blue"), page.evaluate("() => window['result'].onChange"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAllowDisposingTwice() {
|
||||
page.setContent("<section>39</section>");
|
||||
ElementHandle element = page.querySelector("section");
|
||||
assertNotNull(element);
|
||||
element.dispose();
|
||||
element.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import static org.junit.jupiter.api.Assertions.*;
|
||||
public class TestLocatorFrame extends TestBase {
|
||||
private static void routeIframe(Page page) {
|
||||
page.route("**/empty.html", route -> route.fulfill(new Route.FulfillOptions()
|
||||
.setBody("<iframe src='iframe.html'></iframe>").setContentType("text/html")));
|
||||
.setBody("<iframe src='iframe.html' name='frame1'></iframe>").setContentType("text/html")));
|
||||
page.route("**/iframe.html", route -> {
|
||||
route.fulfill(new Route.FulfillOptions().setBody("<html>\n" +
|
||||
" <div>\n" +
|
||||
@@ -263,4 +263,25 @@ public class TestLocatorFrame extends TestBase {
|
||||
assertThat(input4).hasValue("");
|
||||
}
|
||||
|
||||
@Test
|
||||
void locatorContentFrameShouldWork() {
|
||||
routeIframe(page);
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
Locator locator = page.locator("iframe");
|
||||
FrameLocator frameLocator = locator.contentFrame();
|
||||
Locator button = frameLocator.locator("button");
|
||||
assertEquals("Hello iframe", button.innerText());
|
||||
assertThat(button).hasText("Hello iframe");
|
||||
button.click();
|
||||
}
|
||||
|
||||
@Test
|
||||
void frameLocatorOwnerShouldWork() {
|
||||
routeIframe(page);
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
FrameLocator frameLocator = page.frameLocator("iframe");
|
||||
Locator locator = frameLocator.owner();
|
||||
assertThat(locator).isVisible();
|
||||
assertEquals("frame1", locator.getAttribute("name"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,4 +134,31 @@ public class TestPageNetworkRequest extends TestBase {
|
||||
assertTrue(request[0].isNavigationRequest());
|
||||
assertTrue(error[0].getMessage().contains("Frame for this navigation request is not available"), error[0].getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldParseDataIfContentTypeIsApplicationFormUrlEncoded() {
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
server.setRoute("/post", exchange -> exchange.close());
|
||||
Request[] request = {null};
|
||||
page.onRequest(r -> request[0] = r);
|
||||
page.setContent("<form method='POST' action='/post'><input type='text' name='foo' value='bar'><input type='number' name='baz' value='123'><input type='submit'></form>");
|
||||
page.click("input[type=submit]");
|
||||
assertNotNull(request[0]);
|
||||
assertEquals("foo=bar&baz=123", request[0].postData());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldParseDataIfContentTypeIsApplicationFormUrlEncodedCharsetUTF8() {
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
Request request = page.waitForRequest("**/post", () -> {
|
||||
page.evaluate("() => fetch('./post', {\n" +
|
||||
" method: 'POST',\n" +
|
||||
" headers: {\n" +
|
||||
" 'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',\n" +
|
||||
" },\n" +
|
||||
" body: 'foo=bar&baz=123'\n" +
|
||||
"})");
|
||||
});
|
||||
assertEquals("foo=bar&baz=123", request.postData());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
1.42.1
|
||||
1.43.0-beta-1711493485000
|
||||
|
||||
@@ -9,13 +9,13 @@ cd "$(dirname "$0")/.."
|
||||
PLAYWRIGHT_CLI="unknown"
|
||||
case $(uname) in
|
||||
Darwin)
|
||||
PLAYWRIGHT_CLI=./driver-bundle/src/main/resources/driver/mac/playwright.sh
|
||||
PLAYWRIGHT_CLI=./driver-bundle/src/main/resources/driver/mac/package/cli.js
|
||||
;;
|
||||
Linux)
|
||||
PLAYWRIGHT_CLI=./driver-bundle/src/main/resources/driver/linux/playwright.sh
|
||||
PLAYWRIGHT_CLI=./driver-bundle/src/main/resources/driver/linux/package/cli.js
|
||||
;;
|
||||
MINGW64*)
|
||||
PLAYWRIGHT_CLI=./driver-bundle/src/main/resources/driver/win32_x64/playwright.cmd
|
||||
PLAYWRIGHT_CLI=./driver-bundle/src/main/resources/driver/win32_x64/package/cli.js
|
||||
;;
|
||||
*)
|
||||
echo "Unknown platform '$(uname)'"
|
||||
@@ -25,7 +25,7 @@ esac
|
||||
|
||||
echo "Updating api.json from $($PLAYWRIGHT_CLI --version)"
|
||||
|
||||
$PLAYWRIGHT_CLI print-api-json > ./tools/api-generator/src/main/resources/api.json
|
||||
node $PLAYWRIGHT_CLI print-api-json > ./tools/api-generator/src/main/resources/api.json
|
||||
|
||||
mvn compile -f ./tools/api-generator --no-transfer-progress
|
||||
|
||||
|
||||
Reference in New Issue
Block a user