diff --git a/playwright/src/main/java/com/microsoft/playwright/APIRequestContext.java b/playwright/src/main/java/com/microsoft/playwright/APIRequestContext.java index 8dd88c08..6570d532 100644 --- a/playwright/src/main/java/com/microsoft/playwright/APIRequestContext.java +++ b/playwright/src/main/java/com/microsoft/playwright/APIRequestContext.java @@ -30,15 +30,15 @@ import java.nio.file.Path; * *
**Cookie management** * - *
{@code APIRequestContext} retuned by {@link BrowserContext#request BrowserContext.request()} and {@link Page#request + *
{@code APIRequestContext} returned by {@link BrowserContext#request BrowserContext.request()} and {@link Page#request * Page.request()} shares cookie storage with the corresponding {@code BrowserContext}. Each API request will have {@code Cookie} * header populated with the values from the browser context. If the API response contains {@code Set-Cookie} header it will * automatically update {@code BrowserContext} cookies and requests made from the page will pick them up. This means that if you * log in using this API, your e2e test will be logged in and vice versa. * - *
If you want API requests to not interfere with the browser cookies you shoud create a new {@code APIRequestContext} by calling - * {@link APIRequest#newContext APIRequest.newContext()}. Such {@code APIRequestContext} object will have its own isolated cookie - * storage. + *
If you want API requests to not interfere with the browser cookies you should create a new {@code APIRequestContext} by + * calling {@link APIRequest#newContext APIRequest.newContext()}. Such {@code APIRequestContext} object will have its own + * isolated cookie storage. */ public interface APIRequestContext { class StorageStateOptions { diff --git a/playwright/src/main/java/com/microsoft/playwright/Browser.java b/playwright/src/main/java/com/microsoft/playwright/Browser.java index 92d81946..c388486d 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Browser.java +++ b/playwright/src/main/java/com/microsoft/playwright/Browser.java @@ -1099,7 +1099,7 @@ public interface Browser extends AutoCloseable { /** * Creates a new browser context. It won't share cookies/cache with other browser contexts. * - *
NOTE: If directly using this method to create {@code BrowserContext}s, it is best practice to explicilty close the returned context + *
NOTE: If directly using this method to create {@code BrowserContext}s, it is best practice to explicitly close the returned context * via {@link BrowserContext#close BrowserContext.close()} when your code is done with the {@code BrowserContext}, and before * calling {@link Browser#close Browser.close()}. This will ensure the {@code context} is closed gracefully and any * artifacts—like HARs and videos—are fully flushed and saved. @@ -1111,7 +1111,7 @@ public interface Browser extends AutoCloseable { * Page page = context.newPage(); * page.navigate('https://example.com'); * - * // Gracefull close up everything + * // Graceful close up everything * context.close(); * browser.close(); * } @@ -1122,7 +1122,7 @@ public interface Browser extends AutoCloseable { /** * Creates a new browser context. It won't share cookies/cache with other browser contexts. * - *
NOTE: If directly using this method to create {@code BrowserContext}s, it is best practice to explicilty close the returned context + *
NOTE: If directly using this method to create {@code BrowserContext}s, it is best practice to explicitly close the returned context
* via {@link BrowserContext#close BrowserContext.close()} when your code is done with the {@code BrowserContext}, and before
* calling {@link Browser#close Browser.close()}. This will ensure the {@code context} is closed gracefully and any
* artifacts—like HARs and videos—are fully flushed and saved.
@@ -1134,7 +1134,7 @@ public interface Browser extends AutoCloseable {
* Page page = context.newPage();
* page.navigate('https://example.com');
*
- * // Gracefull close up everything
+ * // Graceful close up everything
* context.close();
* browser.close();
* }
diff --git a/playwright/src/main/java/com/microsoft/playwright/ElementHandle.java b/playwright/src/main/java/com/microsoft/playwright/ElementHandle.java
index a02ebd07..aa1579a6 100644
--- a/playwright/src/main/java/com/microsoft/playwright/ElementHandle.java
+++ b/playwright/src/main/java/com/microsoft/playwright/ElementHandle.java
@@ -586,7 +586,7 @@ public interface ElementHandle extends JSHandle {
*/
public ScreenshotCaret caret;
/**
- * Specify locators that should be masked when the screenshot is taken. Masked elements will be overlayed with a pink box
+ * Specify locators that should be masked when the screenshot is taken. Masked elements will be overlaid with a pink box
* {@code #FF00FF} that completely covers its bounding box.
*/
public List{@code
* PlaywrightAssertions.setDefaultAssertionTimeout(30_000);
* }
diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/APIResponseAssertionsImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/APIResponseAssertionsImpl.java
index 9fb08a9b..67d7dfc5 100644
--- a/playwright/src/main/java/com/microsoft/playwright/impl/APIResponseAssertionsImpl.java
+++ b/playwright/src/main/java/com/microsoft/playwright/impl/APIResponseAssertionsImpl.java
@@ -21,6 +21,7 @@ import com.microsoft.playwright.assertions.APIResponseAssertions;
import org.opentest4j.AssertionFailedError;
import java.util.List;
+import java.util.regex.Pattern;
public class APIResponseAssertionsImpl implements APIResponseAssertions {
private final APIResponse actual;
@@ -54,6 +55,20 @@ public class APIResponseAssertionsImpl implements APIResponseAssertions {
if (!log.isEmpty()) {
log = "\nCall log:\n" + log;
}
- throw new AssertionFailedError(message + log);
+
+ String contentType = actual.headers().get("content-type");
+ boolean isTextEncoding = contentType == null ? false : isTextualMimeType(contentType);
+ String responseText = "";
+ if (isTextEncoding) {
+ String text = actual.text();
+ if (text != null) {
+ responseText = "\nResponse text:\n" + (text.length() > 1000 ? text.substring(0, 1000) : text);
+ }
+ }
+
+ throw new AssertionFailedError(message + log + responseText);
+ }
+ static boolean isTextualMimeType(String mimeType) {
+ return Pattern.matches("^(text/.*?|application/(json|(x-)?javascript|xml.*?|ecmascript|graphql|x-www-form-urlencoded)|image/svg(\\+xml)?|application/.*?(\\+json|\\+xml))(;\\s*charset=.*)?$", mimeType);
}
}
diff --git a/playwright/src/test/java/com/microsoft/playwright/Server.java b/playwright/src/test/java/com/microsoft/playwright/Server.java
index 0d98bf32..8774fd50 100644
--- a/playwright/src/test/java/com/microsoft/playwright/Server.java
+++ b/playwright/src/test/java/com/microsoft/playwright/Server.java
@@ -195,6 +195,7 @@ public class Server implements HttpHandler {
String resourcePath = "resources" + path;
InputStream resource = getClass().getClassLoader().getResourceAsStream(resourcePath);
if (resource == null) {
+ exchange.getResponseHeaders().add("Content-Type", "text/plain");
exchange.sendResponseHeaders(404, 0);
try (Writer writer = new OutputStreamWriter(exchange.getResponseBody())) {
writer.write("File not found: " + resourcePath);
diff --git a/playwright/src/test/java/com/microsoft/playwright/TestAPIResponseAssertions.java b/playwright/src/test/java/com/microsoft/playwright/TestAPIResponseAssertions.java
index d84f3852..02ab8ba9 100644
--- a/playwright/src/test/java/com/microsoft/playwright/TestAPIResponseAssertions.java
+++ b/playwright/src/test/java/com/microsoft/playwright/TestAPIResponseAssertions.java
@@ -19,8 +19,11 @@ package com.microsoft.playwright;
import org.junit.jupiter.api.Test;
import org.opentest4j.AssertionFailedError;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.*;
public class TestAPIResponseAssertions extends TestBase {
@Test
@@ -38,14 +41,62 @@ public class TestAPIResponseAssertions extends TestBase {
@Test
void fail() {
APIResponse res = page.request().get(server.PREFIX + "/unknown");
- boolean didThrow = false;
- try {
- assertThat(res).isOK();
- } catch (AssertionFailedError e) {
- didThrow = true;
- assertTrue(e.getMessage().contains("→ GET " + server.PREFIX + "/unknown"), "Actual error: " + e.toString());
- assertTrue(e.getMessage().contains("← 404 Not Found"), "Actual error: " + e.toString());
+ AssertionFailedError e = assertThrows(AssertionFailedError.class, () -> assertThat(res).isOK());
+ assertTrue(e.getMessage().contains("→ GET " + server.PREFIX + "/unknown"), "Actual error: " + e.toString());
+ assertTrue(e.getMessage().contains("← 404 Not Found"), "Actual error: " + e.toString());
+ }
+
+ @Test
+ void shouldPrintResponseTextIfIdOkFails() {
+ APIResponse res = page.request().get(server.PREFIX + "/unknown");
+ AssertionFailedError e = assertThrows(AssertionFailedError.class, () -> assertThat(res).isOK());
+ assertTrue(e.getMessage().contains("File not found"), "Actual error: " + e.toString());
+ }
+
+ @Test
+ void shouldOnlyPrintResponseWithTextContentTypeIfIsOkFails() {
+ {
+ server.setRoute("/text-content-type", exchange -> {
+ exchange.getResponseHeaders().set("Content-type", "text/plain");
+ exchange.sendResponseHeaders(404, 0);
+ try (Writer writer = new OutputStreamWriter(exchange.getResponseBody())) {
+ writer.write("Text error");
+ }
+ });
+ AssertionFailedError e = assertThrows(AssertionFailedError.class, () -> assertThat(page.request().get(server.PREFIX + "/text-content-type")).isOK());
+ assertTrue(e.getMessage().contains("Text error"), "Actual error: " + e);
+ }
+ {
+ server.setRoute("/svg-xml-content-type", exchange -> {
+ exchange.getResponseHeaders().set("Content-type", "image/svg+xml");
+ exchange.sendResponseHeaders(404, 0);
+ try (Writer writer = new OutputStreamWriter(exchange.getResponseBody())) {
+ writer.write("Json error");
+ }
+ });
+ AssertionFailedError e = assertThrows(AssertionFailedError.class, () -> assertThat(page.request().get(server.PREFIX + "/svg-xml-content-type")).isOK());
+ assertTrue(e.getMessage().contains("Json error"), "Actual error: " + e);
+ }
+ {
+ server.setRoute("/no-content-type", exchange -> {
+ exchange.sendResponseHeaders(404, 0);
+ try (Writer writer = new OutputStreamWriter(exchange.getResponseBody())) {
+ writer.write("No content type error");
+ }
+ });
+ AssertionFailedError e = assertThrows(AssertionFailedError.class, () -> assertThat(page.request().get(server.PREFIX + "/no-content-type")).isOK());
+ assertFalse(e.getMessage().contains("No content type error"), "Actual error: " + e);
+ }
+ {
+ server.setRoute("/image-content-type", exchange -> {
+ exchange.getResponseHeaders().set("Content-type", "image/bmp");
+ exchange.sendResponseHeaders(404, 0);
+ try (Writer writer = new OutputStreamWriter(exchange.getResponseBody())) {
+ writer.write("Image type error");
+ }
+ });
+ AssertionFailedError e = assertThrows(AssertionFailedError.class, () -> assertThat(page.request().get(server.PREFIX + "/image-content-type")).isOK());
+ assertFalse(e.getMessage().contains("Image type error"), "Actual error: " + e);
}
- assertTrue(didThrow);
}
}
diff --git a/scripts/CLI_VERSION b/scripts/CLI_VERSION
index 85e87281..ad219194 100644
--- a/scripts/CLI_VERSION
+++ b/scripts/CLI_VERSION
@@ -1 +1 @@
-1.25.0-alpha-1659998098000
+1.25.0