Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.util.stream.Collectors;

import static com.microsoft.playwright.impl.Utils.toJsRegexFlags;
import static com.microsoft.playwright.impl.Utils.toJsRegexSource;
import static java.util.Arrays.asList;

abstract class AssertionsBase {
Expand Down Expand Up @@ -95,7 +96,7 @@ protected static ValueWrapper formatValue(Object value) {

static ExpectedTextValue expectedRegex(Pattern pattern) {
ExpectedTextValue expected = new ExpectedTextValue();
expected.regexSource = pattern.pattern();
expected.regexSource = toJsRegexSource(pattern);
if (pattern.flags() != 0) {
expected.regexFlags = toJsRegexFlags(pattern);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import static com.microsoft.playwright.impl.Serialization.gson;
import static com.microsoft.playwright.impl.Utils.toJsRegexFlags;
import static com.microsoft.playwright.impl.Utils.toJsRegexSource;

public class LocatorUtils {
static String getByTextSelector(Object text, Locator.GetByTextOptions options) {
Expand Down Expand Up @@ -132,6 +133,6 @@ private static String escapeForAttributeSelector(Object value, boolean exact) {
}

private static String toJsRegExp(Pattern pattern) {
return "/" + pattern.pattern() + "/" + toJsRegexFlags(pattern);
return "/" + toJsRegexSource(pattern) + "/" + toJsRegexFlags(pattern);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import java.util.regex.Pattern;

import static com.microsoft.playwright.impl.Utils.toJsRegexFlags;
import static com.microsoft.playwright.impl.Utils.toJsRegexSource;
import static com.microsoft.playwright.impl.Utils.fromJsRegexFlags;

class Serialization {
Expand Down Expand Up @@ -85,7 +86,7 @@
.registerTypeAdapter(OffsetDateTime.class, new OffsetDateTimeSerializer())
.serializeNulls().create();

static SerializedError serializeError(Throwable e) {

Check failure on line 89 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, chromium)

cannot find symbol

Check failure on line 89 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, webkit)

cannot find symbol

Check failure on line 89 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (ubuntu-latest, chrome)

cannot find symbol

Check failure on line 89 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (macos-15-xlarge, webkit)

cannot find symbol

Check failure on line 89 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, firefox)

cannot find symbol

Check failure on line 89 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, chrome)

cannot find symbol

Check failure on line 89 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, msedge)

cannot find symbol

Check failure on line 89 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (macos-latest, firefox)

cannot find symbol
SerializedError result = new SerializedError();
result.error = new SerializedError.Error();
result.error.message = e.getMessage();
Expand Down Expand Up @@ -119,13 +120,13 @@
private final Map<HashableValue, Integer> valueToId = new HashMap<>();
private int lastId = 0;
private final List<JSHandleImpl> handles = new ArrayList<>();
private final SerializedValue serializedValue;

Check failure on line 123 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, chromium)

cannot find symbol

Check failure on line 123 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, webkit)

cannot find symbol

Check failure on line 123 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (ubuntu-latest, chrome)

cannot find symbol

Check failure on line 123 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (macos-15-xlarge, webkit)

cannot find symbol

Check failure on line 123 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, firefox)

cannot find symbol

Check failure on line 123 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, chrome)

cannot find symbol

Check failure on line 123 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, msedge)

cannot find symbol

Check failure on line 123 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (macos-latest, firefox)

cannot find symbol

ValueSerializer(Object value) {
serializedValue = serializeValue(value);
}

SerializedArgument toSerializedArgument() {

Check failure on line 129 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, chromium)

cannot find symbol

Check failure on line 129 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, webkit)

cannot find symbol

Check failure on line 129 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (ubuntu-latest, chrome)

cannot find symbol

Check failure on line 129 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (macos-15-xlarge, webkit)

cannot find symbol

Check failure on line 129 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, firefox)

cannot find symbol

Check failure on line 129 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, chrome)

cannot find symbol

Check failure on line 129 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, msedge)

cannot find symbol

Check failure on line 129 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (macos-latest, firefox)

cannot find symbol
SerializedArgument result = new SerializedArgument();
result.value = serializedValue;
result.handles = new Channel[handles.size()];
Expand All @@ -138,7 +139,7 @@
return result;
}

private SerializedValue serializeValue(Object value) {

Check failure on line 142 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, chromium)

cannot find symbol

Check failure on line 142 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, webkit)

cannot find symbol

Check failure on line 142 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (ubuntu-latest, chrome)

cannot find symbol

Check failure on line 142 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (macos-15-xlarge, webkit)

cannot find symbol

Check failure on line 142 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, firefox)

cannot find symbol

Check failure on line 142 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, chrome)

cannot find symbol

Check failure on line 142 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, msedge)

cannot find symbol

Check failure on line 142 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (macos-latest, firefox)

cannot find symbol
SerializedValue result = new SerializedValue();
if (value instanceof JSHandleImpl) {
result.h = handles.size();
Expand Down Expand Up @@ -176,7 +177,7 @@
result.bi = ((BigInteger)value).toString();
} else if (value instanceof Pattern) {
result.r = new SerializedValue.R();
result.r.p = ((Pattern)value).pattern();
result.r.p = toJsRegexSource((Pattern)value);
result.r.f = toJsRegexFlags(((Pattern)value));
} else if (value instanceof Exception) {
Exception exception = (Exception) value;
Expand Down Expand Up @@ -226,16 +227,16 @@
}
}

static SerializedArgument serializeArgument(Object arg) {

Check failure on line 230 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, chromium)

cannot find symbol

Check failure on line 230 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, webkit)

cannot find symbol

Check failure on line 230 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (ubuntu-latest, chrome)

cannot find symbol

Check failure on line 230 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (macos-15-xlarge, webkit)

cannot find symbol

Check failure on line 230 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, firefox)

cannot find symbol

Check failure on line 230 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, chrome)

cannot find symbol

Check failure on line 230 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, msedge)

cannot find symbol

Check failure on line 230 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (macos-latest, firefox)

cannot find symbol
return new ValueSerializer(arg).toSerializedArgument();
}

static <T> T deserialize(SerializedValue value) {

Check failure on line 234 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, chromium)

cannot find symbol

Check failure on line 234 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, webkit)

cannot find symbol

Check failure on line 234 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (ubuntu-latest, chrome)

cannot find symbol

Check failure on line 234 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (macos-15-xlarge, webkit)

cannot find symbol

Check failure on line 234 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, firefox)

cannot find symbol

Check failure on line 234 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, chrome)

cannot find symbol

Check failure on line 234 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, msedge)

cannot find symbol

Check failure on line 234 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (macos-latest, firefox)

cannot find symbol
return deserialize(value, new HashMap<>());
}

@SuppressWarnings("unchecked")
private static <T> T deserialize(SerializedValue value, Map<Integer, Object> idToValue) {

Check failure on line 239 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, chromium)

cannot find symbol

Check failure on line 239 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, webkit)

cannot find symbol

Check failure on line 239 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (ubuntu-latest, chrome)

cannot find symbol

Check failure on line 239 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (macos-15-xlarge, webkit)

cannot find symbol

Check failure on line 239 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (ubuntu-latest, firefox)

cannot find symbol

Check failure on line 239 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, chrome)

cannot find symbol

Check failure on line 239 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / stable (macos-latest, msedge)

cannot find symbol

Check failure on line 239 in playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java

View workflow job for this annotation

GitHub Actions / dev (macos-latest, firefox)

cannot find symbol
if (value.ref != null) {
return (T) idToValue.get(value.ref);
}
Expand Down Expand Up @@ -382,7 +383,7 @@
options.addProperty("urlGlob", (String) urlFilter);
} else if (urlFilter instanceof Pattern) {
Pattern pattern = (Pattern) urlFilter;
options.addProperty("urlRegexSource", pattern.pattern());
options.addProperty("urlRegexSource", toJsRegexSource(pattern));
options.addProperty("urlRegexFlags", toJsRegexFlags(pattern));
}
}
Expand All @@ -400,7 +401,7 @@
params.addProperty(name, (String) value);
} else if (value instanceof Pattern) {
Pattern pattern = (Pattern) value;
params.addProperty(name + "RegexSource", pattern.pattern());
params.addProperty(name + "RegexSource", toJsRegexSource(pattern));
params.addProperty(name + "RegexFlags", toJsRegexFlags(pattern));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.regex.Pattern;

import static com.microsoft.playwright.impl.Utils.toJsRegexFlags;
import static com.microsoft.playwright.impl.Utils.toJsRegexSource;

class UrlMatcher {
public final String glob;
Expand Down Expand Up @@ -128,7 +129,7 @@ public String toString() {
if (glob != null)
return String.format("<glob pattern=\"%s\">", glob);
if (pattern != null)
return String.format("<regex pattern=\"%s\" flags=\"%s\">", pattern.pattern(), toJsRegexFlags(pattern));
return String.format("<regex pattern=\"%s\" flags=\"%s\">", toJsRegexSource(pattern), toJsRegexFlags(pattern));
if (this.predicate != null)
return "<predicate>";
return "<true>";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,41 @@ static String toJsRegexFlags(Pattern pattern) {
return regexFlags;
}

// JavaScript regular expressions do not support \Q...\E quoting, so convert quoted sections into escaped literals.
static String toJsRegexSource(Pattern pattern) {
String source = pattern.pattern();
if (!source.contains("\\Q")) {
return source;
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < source.length(); i++) {
char c = source.charAt(i);
if (c != '\\' || i + 1 == source.length()) {
result.append(c);
continue;
}
char next = source.charAt(++i);
if (next != 'Q') {
result.append(c).append(next);
continue;
}
int end = source.indexOf("\\E", i + 1);
if (end == -1) {
end = source.length();
}
for (int j = i + 1; j < end; j++) {
char ch = source.charAt(j);
if ("^$\\.*+?()[]{}|/".indexOf(ch) != -1) {
result.append('\\');
}
result.append(ch);
}
// Skip past the closing \E.
i = end + 1;
}
return result.toString();
}

static int fromJsRegexFlags(String regexFlags) {
int flags = 0;
if (regexFlags.contains("i")) {
Expand Down Expand Up @@ -409,7 +444,7 @@ static JsonObject interceptionPatterns(List<UrlMatcher> matchers) {
if (matcher.glob != null) {
jsonPattern.addProperty("glob", matcher.glob);
} else if (matcher.pattern != null) {
jsonPattern.addProperty("regexSource", matcher.pattern.pattern());
jsonPattern.addProperty("regexSource", toJsRegexSource(matcher.pattern));
jsonPattern.addProperty("regexFlags", toJsRegexFlags(matcher.pattern));
} else {
// Match all requests.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* 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 java.util.regex.Pattern;

import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.*;

// Java's \Q...\E quoting (Pattern.quote) is not supported by JavaScript regular expressions.
public class TestRegexQuote extends TestBase {
@Test
void shouldFilterByQuotedPattern() {
page.setContent("<div>Hello Playwright</div><div>Hello world</div>");
Locator locator = page.locator("div").filter(new Locator.FilterOptions().setHasText(Pattern.compile(Pattern.quote("Playwright"))));
assertThat(locator).hasCount(1);
assertThat(locator).hasText("Hello Playwright");
}

@Test
void shouldEscapeRegexSpecialCharactersInQuotedPattern() {
page.setContent("<div>a.b(c)</div><div>aXbc</div>");
Locator locator = page.locator("div").filter(new Locator.FilterOptions().setHasText(Pattern.compile(Pattern.quote("a.b(c)"))));
assertThat(locator).hasCount(1);
assertThat(locator).hasText("a.b(c)");
assertThat(page.getByText(Pattern.compile("^" + Pattern.quote("a.b(c)") + "$"))).hasCount(1);
}

@Test
void shouldHandleQuotedPatternContainingQuoteEnd() {
page.setContent("<div>x\\Ey[1+1]/</div><div>xEy</div>");
Pattern pattern = Pattern.compile(Pattern.quote("x\\Ey[1+1]/"));
assertThat(page.locator("div").filter(new Locator.FilterOptions().setHasText(pattern))).hasCount(1);
assertThat(page.locator("div").first()).hasText(pattern);
assertThat(page.locator("div").last()).not().hasText(pattern);
}

@Test
void shouldAssertTextWithQuotedPattern() {
page.setContent("<div>Price: $9.99 (USD)</div>");
assertThat(page.locator("div")).hasText(Pattern.compile(Pattern.quote("$9.99 (USD)")));
assertThat(page.locator("div")).hasText(Pattern.compile("^Price: " + Pattern.quote("$9.99") + "\\s+\\(USD\\)$"));
assertThat(page.locator("div")).not().hasText(Pattern.compile(Pattern.quote("$9x99")));
}

@Test
void shouldNotTreatEscapedBackslashFollowedByQAsQuote() {
page.setContent("<div>a\\Qb</div>");
assertThat(page.locator("div")).hasText(Pattern.compile("a\\\\Qb"));
}

@Test
void shouldSerializeQuotedPatternAsEvaluateArgument() {
Object result = page.evaluate("r => [r.source, r.test('a.b(c)'), r.test('aXbc')]", Pattern.compile(Pattern.quote("a.b(c)")));
assertEquals(asList("a\\.b\\(c\\)", true, false), result);
}

@Test
void shouldRouteWithQuotedPattern() {
boolean[] intercepted = {false};
page.route(Pattern.compile(Pattern.quote(server.EMPTY_PAGE)), route -> {
intercepted[0] = true;
route.fulfill(new Route.FulfillOptions().setBody("intercepted"));
});
page.navigate(server.EMPTY_PAGE);
assertTrue(intercepted[0]);
assertThat(page.locator("body")).hasText("intercepted");
}
}
Loading