Skip to content

Commit

Permalink
chore: roll driver to 1.43.0-beta, implement clearCookie(filter) (#1525)
Browse files Browse the repository at this point in the history
  • Loading branch information
yury-s committed Mar 28, 2024
1 parent a135675 commit e7653dd
Show file tree
Hide file tree
Showing 19 changed files with 355 additions and 43 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -492,11 +549,41 @@ public WaitForPageOptions setTimeout(double timeout) {
*/
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
*/
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();
void clearCookies(ClearCookiesOptions options);
/**
* Clears all permission overrides for the browser context.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,7 @@ class LaunchOptions {
*/
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;
/**
Expand Down Expand Up @@ -291,8 +290,7 @@ public LaunchOptions setChromiumSandbox(boolean chromiumSandbox) {
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;
Expand Down Expand Up @@ -468,8 +466,7 @@ class LaunchPersistentContextOptions {
*/
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;
/**
Expand Down Expand Up @@ -760,8 +757,7 @@ public LaunchPersistentContextOptions setDeviceScaleFactor(double deviceScaleFac
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,13 @@
*
* <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 {
Expand Down Expand Up @@ -1003,5 +1005,24 @@ default Locator locator(Locator selectorOrLocator) {
* @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();
}

19 changes: 19 additions & 0 deletions playwright/src/main/java/com/microsoft/playwright/Locator.java
Original file line number Diff line number Diff line change
Expand Up @@ -2704,6 +2704,25 @@ default ElementHandle elementHandle() {
* @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.
*
Expand Down
17 changes: 10 additions & 7 deletions playwright/src/main/java/com/microsoft/playwright/Page.java
Original file line number Diff line number Diff line change
Expand Up @@ -5918,9 +5918,11 @@ default ElementHandle querySelector(String selector) {
*/
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.
Expand All @@ -5932,7 +5934,8 @@ default ElementHandle querySelector(String selector) {
* <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
Expand All @@ -5951,11 +5954,11 @@ default ElementHandle querySelector(String selector) {
*
* <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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
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;
Expand Down Expand Up @@ -335,8 +336,29 @@ public BrowserImpl browser() {
}

@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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,9 @@ public Locator locator(Locator selectorOrLocator, LocatorOptions options) {
public FrameLocator nth(int index) {
return new FrameLocatorImpl(frame, frameSelector + " >> nth=" + index);
}

@Override
public Locator owner() {
return new LocatorImpl(frame, frameSelector);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,12 @@ public ElementHandle asElement() {

@Override
public void dispose() {
withLogging("JSHandle.dispose", () -> sendMessage("dispose"));
withLogging("JSHandle.dispose", () -> {
try {
sendMessage("dispose");
} catch (TargetClosedError e) {
}
});
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -203,6 +207,11 @@ public List<ElementHandle> elementHandles() {
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public TargetClosedError() {
}

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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public T get() {
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);
}
Expand Down
Loading

0 comments on commit e7653dd

Please sign in to comment.