diff --git a/playwright/src/main/java/com/microsoft/playwright/Frame.java b/playwright/src/main/java/com/microsoft/playwright/Frame.java index 35075fc2..e54e4bbd 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Frame.java +++ b/playwright/src/main/java/com/microsoft/playwright/Frame.java @@ -765,9 +765,7 @@ public interface Frame { /** * URL string, URL regex pattern or predicate receiving [URL] to match while waiting for the navigation. */ - public String glob; - public Pattern pattern; - public Predicate predicate; + public Object url; /** * When to consider operation succeeded, defaults to {@code load}. Events can be either: * - {@code 'domcontentloaded'} - consider operation to be finished when the {@code DOMContentLoaded} event is fired. @@ -780,16 +778,16 @@ public interface Frame { this.timeout = timeout; return this; } - public WaitForNavigationOptions withUrl(String glob) { - this.glob = glob; + public WaitForNavigationOptions withUrl(String url) { + this.url = url; return this; } - public WaitForNavigationOptions withUrl(Pattern pattern) { - this.pattern = pattern; + public WaitForNavigationOptions withUrl(Pattern url) { + this.url = url; return this; } - public WaitForNavigationOptions withUrl(Predicate predicate) { - this.predicate = predicate; + public WaitForNavigationOptions withUrl(Predicate url) { + this.url = url; return this; } public WaitForNavigationOptions withWaitUntil(WaitUntilState waitUntil) { diff --git a/playwright/src/main/java/com/microsoft/playwright/Page.java b/playwright/src/main/java/com/microsoft/playwright/Page.java index d7ade866..ba9370b9 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Page.java +++ b/playwright/src/main/java/com/microsoft/playwright/Page.java @@ -1197,9 +1197,7 @@ public interface Page extends AutoCloseable { /** * A glob pattern, regex pattern or predicate receiving [URL] to match while waiting for the navigation. */ - public String glob; - public Pattern pattern; - public Predicate predicate; + public Object url; /** * When to consider operation succeeded, defaults to {@code load}. Events can be either: * - {@code 'domcontentloaded'} - consider operation to be finished when the {@code DOMContentLoaded} event is fired. @@ -1212,16 +1210,16 @@ public interface Page extends AutoCloseable { this.timeout = timeout; return this; } - public WaitForNavigationOptions withUrl(String glob) { - this.glob = glob; + public WaitForNavigationOptions withUrl(String url) { + this.url = url; return this; } - public WaitForNavigationOptions withUrl(Pattern pattern) { - this.pattern = pattern; + public WaitForNavigationOptions withUrl(Pattern url) { + this.url = url; return this; } - public WaitForNavigationOptions withUrl(Predicate predicate) { - this.predicate = predicate; + public WaitForNavigationOptions withUrl(Predicate url) { + this.url = url; return this; } public WaitForNavigationOptions withWaitUntil(WaitUntilState waitUntil) { diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java index 616ef630..976605b1 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/FrameImpl.java @@ -841,7 +841,7 @@ public class FrameImpl extends ChannelOwner implements Frame { } List> waitables = new ArrayList<>(); - UrlMatcher matcher = UrlMatcher.forOneOf(options.glob, options.pattern, options.predicate); + UrlMatcher matcher = UrlMatcher.forOneOf(options.url); waitables.add(new WaitForNavigationHelper(matcher, convertViaJson(options.waitUntil, LoadState.class))); waitables.add(page.createWaitForCloseHelper()); waitables.add(page.createWaitableFrameDetach(this)); diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/PageImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/PageImpl.java index b451499a..a00184fe 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/PageImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/PageImpl.java @@ -1169,9 +1169,7 @@ public class PageImpl extends ChannelOwner implements Page { if (options != null) { frameOptions.timeout = options.timeout; frameOptions.waitUntil = options.waitUntil; - frameOptions.glob = options.glob; - frameOptions.pattern = options.pattern; - frameOptions.predicate = options.predicate; + frameOptions.url = options.url; } return mainFrame.waitForNavigationImpl(code, frameOptions); } diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/UrlMatcher.java b/playwright/src/main/java/com/microsoft/playwright/impl/UrlMatcher.java index 9d348367..af6f7bfd 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/UrlMatcher.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/UrlMatcher.java @@ -16,6 +16,8 @@ package com.microsoft.playwright.impl; +import com.microsoft.playwright.PlaywrightException; + import java.util.Objects; import java.util.function.Predicate; import java.util.regex.Pattern; @@ -34,25 +36,20 @@ class UrlMatcher { return new UrlMatcher(null, null); } - static UrlMatcher forOneOf(String glob, Pattern pattern, Predicate predicate) { - UrlMatcher result = UrlMatcher.any(); - int conditionCount = 0; - if (glob != null) { - conditionCount += 1; - result = new UrlMatcher(glob); + static UrlMatcher forOneOf(Object object) { + if (object == null) { + return UrlMatcher.any(); } - if (pattern != null) { - conditionCount += 1; - result = new UrlMatcher(pattern); + if (object instanceof String) { + return new UrlMatcher((String) object); } - if (predicate != null) { - conditionCount += 1; - result = new UrlMatcher(predicate); + if (object instanceof Pattern) { + return new UrlMatcher((Pattern) object); } - if (conditionCount > 1) { - throw new IllegalArgumentException("Only one of glob, pattern and predicate can be specified"); + if (object instanceof Predicate) { + return new UrlMatcher((Predicate) object); } - return result; + throw new PlaywrightException("Url must be String, Pattern or Predicate, found: " + object.getClass().getTypeName()); } UrlMatcher(String url) { diff --git a/playwright/src/test/java/com/microsoft/playwright/TestPageWaitForNavigation.java b/playwright/src/test/java/com/microsoft/playwright/TestPageWaitForNavigation.java index 2e625843..07717dac 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestPageWaitForNavigation.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestPageWaitForNavigation.java @@ -235,5 +235,29 @@ public class TestPageWaitForNavigation extends TestBase { } } + @Test + void shouldThrowOnInvalidUrlMatcherTypeInPage() { + try { + Page.WaitForNavigationOptions options = new Page.WaitForNavigationOptions(); + options.url = new Object(); + page.waitForNavigation(options, () -> {}); + fail("did not throw"); + } catch (PlaywrightException e) { + assertTrue(e.getMessage().contains("Url must be String, Pattern or Predicate")); + } + } + @Test + void shouldThrowOnInvalidUrlMatcherTypeInFrame() { + page.navigate(server.PREFIX + "/frames/one-frame.html"); + Frame frame = page.frames().get(1); + try { + Frame.WaitForNavigationOptions options = new Frame.WaitForNavigationOptions(); + options.url = new Object(); + frame.waitForNavigation(options, () -> {}); + fail("did not throw"); + } catch (PlaywrightException e) { + assertTrue(e.getMessage().contains("Url must be String, Pattern or Predicate")); + } + } } diff --git a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java index 8a9b48c3..477e9d92 100644 --- a/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java +++ b/tools/api-generator/src/main/java/com/microsoft/playwright/tools/ApiGenerator.java @@ -306,6 +306,9 @@ class TypeRef extends Element { String name = jsonType.get("name").getAsString(); if (jsonType.has("union")) { if (name.isEmpty()) { + if (parent instanceof Field) { + return "Object"; + } throw new RuntimeException("Unexpected enum without name: " + jsonType); } return name; @@ -690,13 +693,6 @@ class Field extends Element { void writeTo(List output, String offset) { writeJavadoc(output, offset, comment()); - if (asList("Frame.waitForNavigation.options.url", - "Page.waitForNavigation.options.url").contains(jsonPath)) { - output.add(offset + "public String glob;"); - output.add(offset + "public Pattern pattern;"); - output.add(offset + "public Predicate predicate;"); - return; - } String typeStr = type.toJava(); if (type.isNullable()) { typeStr = "Optional<" + typeStr + ">"; @@ -715,20 +711,10 @@ class Field extends Element { } void writeBuilderMethod(List output, String offset, String parentClass) { - if (asList("Frame.waitForNavigation.options.url", - "Page.waitForNavigation.options.url").contains(jsonPath)) { - output.add(offset + "public WaitForNavigationOptions withUrl(String glob) {"); - output.add(offset + " this.glob = glob;"); - output.add(offset + " return this;"); - output.add(offset + "}"); - output.add(offset + "public WaitForNavigationOptions withUrl(Pattern pattern) {"); - output.add(offset + " this.pattern = pattern;"); - output.add(offset + " return this;"); - output.add(offset + "}"); - output.add(offset + "public WaitForNavigationOptions withUrl(Predicate predicate) {"); - output.add(offset + " this.predicate = predicate;"); - output.add(offset + " return this;"); - output.add(offset + "}"); + if (type.customType == null && type.isTypeUnion()) { + for (int i = 0; i < type.unionSize(); i++) { + writeGenericBuilderMethod(output, offset, parentClass, type.formatTypeFromUnion(i)); + } return; } if (asList("Page.click.options.position", @@ -781,13 +767,19 @@ class Field extends Element { } else if ("Double".equals(paramType)) { paramType = "double"; } - output.add(offset + "public " + parentClass + " with" + toTitle(name) + "(" + paramType + " " + name + ") {"); - String rvalue = type.isNullable() ? "Optional.ofNullable(" + name + ")" : name; - output.add(offset + " this." + name + " = " + rvalue + ";"); - output.add(offset + " return this;"); + writeGenericBuilderMethod(output, offset, parentClass, paramType); + return; } output.add(offset + "}"); } + + private void writeGenericBuilderMethod(List output, String offset, String parentClass, String paramType) { + output.add(offset + "public " + parentClass + " with" + toTitle(name) + "(" + paramType + " " + name + ") {"); + String rvalue = type.isNullable() ? "Optional.ofNullable(" + name + ")" : name; + output.add(offset + " this." + name + " = " + rvalue + ";"); + output.add(offset + " return this;"); + output.add(offset + "}"); + } } class Interface extends TypeDefinition {