From 06082438fed178caf70c66868cd2d4c45270dbc8 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Thu, 30 Jun 2022 13:17:18 -0700 Subject: [PATCH] cherry-pick(#982): feat: roll driver to 1.23.1-beta, implement routeFromHar.update (#983) --- .../microsoft/playwright/BrowserContext.java | 15 ++-- .../java/com/microsoft/playwright/Page.java | 15 ++-- .../playwright/impl/BrowserContextImpl.java | 63 ++++++++++++++- .../playwright/impl/BrowserImpl.java | 25 +++--- .../playwright/impl/BrowserTypeImpl.java | 53 ++++++++++--- .../playwright/impl/ChannelOwner.java | 6 ++ .../playwright/impl/LocatorImpl.java | 4 +- .../microsoft/playwright/impl/PageImpl.java | 4 + .../playwright/impl/Serialization.java | 21 +++-- .../com/microsoft/playwright/impl/Utils.java | 2 +- .../playwright/impl/WritableStream.java | 6 -- .../playwright/TestBrowserContextHar.java | 79 ++++++++++++++++++- scripts/CLI_VERSION | 2 +- 13 files changed, 237 insertions(+), 58 deletions(-) diff --git a/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java b/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java index b72f694aa..f9355815e 100644 --- a/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java +++ b/playwright/src/main/java/com/microsoft/playwright/BrowserContext.java @@ -184,6 +184,10 @@ class RouteFromHAROptions { *

Defaults to abort. */ public HarNotFound notFound; + /** + * If specified, updates the given HAR with the actual network information instead of serving from file. + */ + public Boolean update; /** * A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern * will be surved from the HAR file. If not specified, all requests are served from the HAR file. @@ -203,18 +207,17 @@ public RouteFromHAROptions setNotFound(HarNotFound notFound) { return this; } /** - * A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern - * will be surved from the HAR file. If not specified, all requests are served from the HAR file. + * If specified, updates the given HAR with the actual network information instead of serving from file. */ - public RouteFromHAROptions setUrl(String url) { - this.url = url; + public RouteFromHAROptions setUpdate(boolean update) { + this.update = update; return this; } /** * A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern * will be surved from the HAR file. If not specified, all requests are served from the HAR file. */ - public RouteFromHAROptions setUrl(Pattern url) { + public RouteFromHAROptions setUrl(String url) { this.url = url; return this; } @@ -222,7 +225,7 @@ public RouteFromHAROptions setUrl(Pattern url) { * A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern * will be surved from the HAR file. If not specified, all requests are served from the HAR file. */ - public RouteFromHAROptions setUrl(Predicate url) { + public RouteFromHAROptions setUrl(Pattern url) { this.url = url; return this; } diff --git a/playwright/src/main/java/com/microsoft/playwright/Page.java b/playwright/src/main/java/com/microsoft/playwright/Page.java index 4c537ce0b..d820f0161 100644 --- a/playwright/src/main/java/com/microsoft/playwright/Page.java +++ b/playwright/src/main/java/com/microsoft/playwright/Page.java @@ -2007,6 +2007,10 @@ class RouteFromHAROptions { *

Defaults to abort. */ public HarNotFound notFound; + /** + * If specified, updates the given HAR with the actual network information instead of serving from file. + */ + public Boolean update; /** * A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern * will be surved from the HAR file. If not specified, all requests are served from the HAR file. @@ -2026,18 +2030,17 @@ public RouteFromHAROptions setNotFound(HarNotFound notFound) { return this; } /** - * A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern - * will be surved from the HAR file. If not specified, all requests are served from the HAR file. + * If specified, updates the given HAR with the actual network information instead of serving from file. */ - public RouteFromHAROptions setUrl(String url) { - this.url = url; + public RouteFromHAROptions setUpdate(boolean update) { + this.update = update; return this; } /** * A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern * will be surved from the HAR file. If not specified, all requests are served from the HAR file. */ - public RouteFromHAROptions setUrl(Pattern url) { + public RouteFromHAROptions setUrl(String url) { this.url = url; return this; } @@ -2045,7 +2048,7 @@ public RouteFromHAROptions setUrl(Pattern url) { * A glob pattern, regular expression or predicate to match the request URL. Only requests with URL matching the pattern * will be surved from the HAR file. If not specified, all requests are served from the HAR file. */ - public RouteFromHAROptions setUrl(Predicate url) { + public RouteFromHAROptions setUrl(Pattern url) { this.url = url; return this; } diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/BrowserContextImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/BrowserContextImpl.java index 73a1fb2aa..214c8c918 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/BrowserContextImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/BrowserContextImpl.java @@ -27,13 +27,16 @@ import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.*; import java.util.function.Consumer; import java.util.function.Predicate; 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; @@ -51,7 +54,17 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext { final TimeoutSettings timeoutSettings = new TimeoutSettings(); Path videosDir; URL baseUrl; - Path recordHarPath; + final Map harRecorders = new HashMap<>(); + + static class HarRecorder { + final Path path; + final HarContentPolicy contentPolicy; + + HarRecorder(Path har, HarContentPolicy policy) { + path = har; + contentPolicy = policy; + } + } enum EventType { CLOSE, @@ -74,6 +87,12 @@ enum EventType { this.request = connection.getExistingObject(initializer.getAsJsonObject("APIRequestContext").get("guid").getAsString()); } + void setRecordHar(Path path, HarContentPolicy policy) { + if (path != null) { + harRecorders.put("", new HarRecorder(path, policy)); + } + } + void setBaseUrl(String spec) { try { this.baseUrl = new URL(spec); @@ -178,15 +197,31 @@ private void closeImpl() { } isClosedOrClosing = true; try { - if (recordHarPath != null) { - JsonObject json = sendMessage("harExport").getAsJsonObject(); + for (Map.Entry entry : harRecorders.entrySet()) { + JsonObject params = new JsonObject(); + params.addProperty("harId", entry.getKey()); + JsonObject json = sendMessage("harExport", params).getAsJsonObject(); ArtifactImpl artifact = connection.getExistingObject(json.getAsJsonObject("artifact").get("guid").getAsString()); // In case of CDP connection browser is null but since the connection is established by // the driver it is safe to consider the artifact local. if (browser() != null && browser().isRemote) { artifact.isRemote = true; } - artifact.saveAs(recordHarPath); + + // Server side will compress artifact if content is attach or if file is .zip. + HarRecorder harParams = entry.getValue(); + boolean isCompressed = harParams.contentPolicy == HarContentPolicy.ATTACH || harParams.path.toString().endsWith(".zip"); + boolean needCompressed = harParams.path.toString().endsWith(".zip"); + if (isCompressed && !needCompressed) { + String tmpPath = harParams.path + ".tmp"; + artifact.saveAs(Paths.get(tmpPath)); + JsonObject unzipParams = new JsonObject(); + unzipParams.addProperty("zipFile", tmpPath); + unzipParams.addProperty("harFile", harParams.path.toString()); + connection.localUtils.sendMessage("harUnzip", unzipParams); + } else { + artifact.saveAs(harParams.path); + } artifact.delete(); } @@ -351,6 +386,10 @@ public void routeFromHAR(Path har, RouteFromHAROptions options) { if (options == null) { options = new RouteFromHAROptions(); } + if (options.update != null && options.update) { + recordIntoHar(null, har, options); + return; + } UrlMatcher matcher = UrlMatcher.forOneOf(baseUrl, options.url); HARRouter harRouter = new HARRouter(connection.localUtils, har, options.notFound); onClose(context -> harRouter.dispose()); @@ -368,6 +407,22 @@ private void route(UrlMatcher matcher, Consumer handler, RouteOptions opt }); } + void recordIntoHar(PageImpl page, Path har, RouteFromHAROptions options) { + JsonObject params = new JsonObject(); + if (page != null) { + params.add("page", page.toProtocolRef()); + } + JsonObject jsonOptions = new JsonObject(); + jsonOptions.addProperty("path", har.toAbsolutePath().toString()); + jsonOptions.addProperty("content", HarContentPolicy.ATTACH.name().toLowerCase()); + jsonOptions.addProperty("mode", HarMode.MINIMAL.name().toLowerCase()); + addHarUrlFilter(jsonOptions, options.url); + params.add("options", jsonOptions); + JsonObject json = sendMessage("harStart", params).getAsJsonObject(); + String harId = json.get("harId").getAsString(); + harRecorders.put(harId, new HarRecorder(har, HarContentPolicy.ATTACH)); + } + @Override public void setDefaultNavigationTimeout(double timeout) { withLogging("BrowserContext.setDefaultNavigationTimeout", () -> { diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/BrowserImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/BrowserImpl.java index 46910562d..ad5684c0a 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/BrowserImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/BrowserImpl.java @@ -30,6 +30,7 @@ import java.util.function.Consumer; 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.*; import static com.microsoft.playwright.impl.Utils.convertType; @@ -137,24 +138,22 @@ private BrowserContextImpl newContextImpl(NewContextOptions options) { } JsonObject recordHar = null; Path recordHarPath = options.recordHarPath; + HarContentPolicy harContentPolicy = null; if (options.recordHarPath != null) { recordHar = new JsonObject(); recordHar.addProperty("path", options.recordHarPath.toString()); if (options.recordHarContent != null) { - recordHar.addProperty("content", options.recordHarContent.toString().toLowerCase()); + harContentPolicy = options.recordHarContent; } else if (options.recordHarOmitContent != null && options.recordHarOmitContent) { - recordHar.addProperty("content", HarContentPolicy.OMIT.toString().toLowerCase()); + harContentPolicy = HarContentPolicy.OMIT; } - if (options.recordHarMode != null) { - recordHar.addProperty("mode", options.recordHarMode.toString().toLowerCase()); + if (harContentPolicy != null) { + recordHar.addProperty("content", harContentPolicy.name().toLowerCase()); } - if (options.recordHarUrlFilter instanceof String) { - recordHar.addProperty("urlGlob", (String) options.recordHarUrlFilter); - } else if (options.recordHarUrlFilter instanceof Pattern) { - Pattern pattern = (Pattern) options.recordHarUrlFilter; - recordHar.addProperty("urlRegexSource", pattern.pattern()); - recordHar.addProperty("urlRegexFlags", toJsRegexFlags(pattern)); + if (options.recordHarMode != null) { + recordHar.addProperty("mode", options.recordHarMode.name().toLowerCase()); } + addHarUrlFilter(recordHar, options.recordHarUrlFilter); options.recordHarPath = null; options.recordHarMode = null; options.recordHarOmitContent = null; @@ -210,7 +209,7 @@ private BrowserContextImpl newContextImpl(NewContextOptions options) { if (options.baseURL != null) { context.setBaseUrl(options.baseURL); } - context.recordHarPath = recordHarPath; + context.setRecordHar(recordHarPath, harContentPolicy); contexts.add(context); return context; } @@ -231,9 +230,7 @@ private void startTracingImpl(Page page, StartTracingOptions options) { } JsonObject params = gson().toJsonTree(options).getAsJsonObject(); if (page != null) { - JsonObject jsonPage = new JsonObject(); - jsonPage.addProperty("guid", ((PageImpl) page).guid); - params.add("page", jsonPage); + params.add("page", ((PageImpl) page).toProtocolRef()); } sendMessage("startTracing", params); } diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/BrowserTypeImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/BrowserTypeImpl.java index 370f7d8d4..6f96fcb06 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/BrowserTypeImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/BrowserTypeImpl.java @@ -22,12 +22,15 @@ import com.microsoft.playwright.Browser; import com.microsoft.playwright.BrowserType; import com.microsoft.playwright.PlaywrightException; +import com.microsoft.playwright.options.HarContentPolicy; import java.io.IOException; import java.nio.file.Path; import java.util.function.Consumer; +import static com.microsoft.playwright.impl.Serialization.addHarUrlFilter; import static com.microsoft.playwright.impl.Serialization.gson; +import static com.microsoft.playwright.impl.Utils.convertType; class BrowserTypeImpl extends ChannelOwner implements BrowserType { LocalUtils localUtils; @@ -152,20 +155,52 @@ public BrowserContextImpl launchPersistentContext(Path userDataDir, LaunchPersis private BrowserContextImpl launchPersistentContextImpl(Path userDataDir, LaunchPersistentContextOptions options) { if (options == null) { options = new LaunchPersistentContextOptions(); + } else { + // Make a copy so that we can nullify some fields below. + options = convertType(options, LaunchPersistentContextOptions.class); } - JsonObject params = gson().toJsonTree(options).getAsJsonObject(); - params.addProperty("userDataDir", userDataDir.toString()); + JsonObject recordHar = null; + Path recordHarPath = options.recordHarPath; + HarContentPolicy harContentPolicy = null; if (options.recordHarPath != null) { - JsonObject recordHar = new JsonObject(); + recordHar = new JsonObject(); recordHar.addProperty("path", options.recordHarPath.toString()); + if (options.recordHarContent != null) { + harContentPolicy = options.recordHarContent; + } else if (options.recordHarOmitContent != null && options.recordHarOmitContent) { + harContentPolicy = HarContentPolicy.OMIT; + } + if (harContentPolicy != null) { + recordHar.addProperty("content", harContentPolicy.name().toLowerCase()); + } + if (options.recordHarMode != null) { + recordHar.addProperty("mode", options.recordHarMode.toString().toLowerCase()); + } + addHarUrlFilter(recordHar, options.recordHarUrlFilter); + options.recordHarPath = null; + options.recordHarMode = null; + options.recordHarOmitContent = null; + options.recordHarContent = null; + options.recordHarUrlFilter = null; + } else { if (options.recordHarOmitContent != null) { - recordHar.addProperty("omitContent", true); + throw new PlaywrightException("recordHarOmitContent is set but recordHarPath is null"); + } + if (options.recordHarUrlFilter != null) { + throw new PlaywrightException("recordHarUrlFilter is set but recordHarPath is null"); } - params.remove("recordHarPath"); - params.remove("recordHarOmitContent"); + if (options.recordHarMode != null) { + throw new PlaywrightException("recordHarMode is set but recordHarPath is null"); + } + if (options.recordHarContent != null) { + throw new PlaywrightException("recordHarContent is set but recordHarPath is null"); + } + } + + JsonObject params = gson().toJsonTree(options).getAsJsonObject(); + params.addProperty("userDataDir", userDataDir.toString()); + if (recordHar != null) { params.add("recordHar", recordHar); - } else if (options.recordHarOmitContent != null) { - throw new PlaywrightException("recordHarOmitContent is set but recordHarPath is null"); } if (options.recordVideoDir != null) { JsonObject recordVideo = new JsonObject(); @@ -195,7 +230,7 @@ private BrowserContextImpl launchPersistentContextImpl(Path userDataDir, LaunchP if (options.baseURL != null) { context.setBaseUrl(options.baseURL); } - context.recordHarPath = options.recordHarPath; + context.setRecordHar(recordHarPath, harContentPolicy); return context; } diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/ChannelOwner.java b/playwright/src/main/java/com/microsoft/playwright/impl/ChannelOwner.java index 3562ffa5c..63cab5d9f 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/ChannelOwner.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/ChannelOwner.java @@ -108,4 +108,10 @@ T runUntil(Runnable code, Waitable waitable) { void handleEvent(String event, JsonObject parameters) { } + + JsonObject toProtocolRef() { + JsonObject json = new JsonObject(); + json.addProperty("guid", guid); + return json; + } } diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java b/playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java index 1e8a2beff..22f64f293 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/LocatorImpl.java @@ -510,9 +510,7 @@ FrameExpectResult expect(String expression, FrameExpectOptions options) { JsonObject toProtocol() { JsonObject result = new JsonObject(); - JsonObject frameJson = new JsonObject(); - frameJson.addProperty("guid", frame.guid); - result.add("frame", frameJson); + result.add("frame", frame.toProtocolRef()); result.addProperty("selector", selector); return result; } 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 0f11373f7..68c8e59ad 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/PageImpl.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/PageImpl.java @@ -974,6 +974,10 @@ public void routeFromHAR(Path har, RouteFromHAROptions options) { if (options == null) { options = new RouteFromHAROptions(); } + if (options.update != null && options.update) { + browserContext.recordIntoHar(this, har, convertType(options, BrowserContext.RouteFromHAROptions.class)); + return; + } UrlMatcher matcher = UrlMatcher.forOneOf(browserContext.baseUrl, options.url); HARRouter harRouter = new HARRouter(connection.localUtils, har, options.notFound); onClose(context -> harRouter.dispose()); diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java b/playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java index 824a6b9f5..b238ea1da 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/Serialization.java @@ -31,6 +31,9 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.*; +import java.util.regex.Pattern; + +import static com.microsoft.playwright.impl.Utils.toJsRegexFlags; class Serialization { private static final Gson gson = new GsonBuilder() @@ -288,9 +291,7 @@ static JsonObject toProtocol(FilePayload p) { static JsonArray toProtocol(ElementHandle[] handles) { JsonArray jsonElements = new JsonArray(); for (ElementHandle handle : handles) { - JsonObject jsonHandle = new JsonObject(); - jsonHandle.addProperty("guid", ((ElementHandleImpl) handle).guid); - jsonElements.add(jsonHandle); + jsonElements.add(((ElementHandleImpl) handle).toProtocolRef()); } return jsonElements; } @@ -299,6 +300,16 @@ static JsonArray toProtocol(Map map) { return toNameValueArray(map); } + static void addHarUrlFilter(JsonObject options, Object urlFilter) { + if (urlFilter instanceof String) { + options.addProperty("urlGlob", (String) urlFilter); + } else if (urlFilter instanceof Pattern) { + Pattern pattern = (Pattern) urlFilter; + options.addProperty("urlRegexSource", pattern.pattern()); + options.addProperty("urlRegexFlags", toJsRegexFlags(pattern)); + } + } + static JsonArray toNameValueArray(Map map) { JsonArray array = new JsonArray(); for (Map.Entry e : map.entrySet()) { @@ -349,9 +360,7 @@ public JsonElement serialize(Optional src, Type typeOfSrc, JsonSerializationC private static class HandleSerializer implements JsonSerializer { @Override public JsonElement serialize(JSHandleImpl src, Type typeOfSrc, JsonSerializationContext context) { - JsonObject json = new JsonObject(); - json.addProperty("guid", src.guid); - return json; + return src.toProtocolRef(); } } diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/Utils.java b/playwright/src/main/java/com/microsoft/playwright/impl/Utils.java index 5d464f37e..51c18ff29 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/Utils.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/Utils.java @@ -176,7 +176,7 @@ static void addLargeFileUploadParams(Path[] files, JsonObject params, BrowserCon } catch (IOException e) { throw new PlaywrightException("Failed to copy file to remote server.", e); } - jsonStreams.add(temp.toProtocol()); + jsonStreams.add(temp.toProtocolRef()); } params.add("streams", jsonStreams); } else { diff --git a/playwright/src/main/java/com/microsoft/playwright/impl/WritableStream.java b/playwright/src/main/java/com/microsoft/playwright/impl/WritableStream.java index e67229c60..b1216ebd2 100644 --- a/playwright/src/main/java/com/microsoft/playwright/impl/WritableStream.java +++ b/playwright/src/main/java/com/microsoft/playwright/impl/WritableStream.java @@ -30,10 +30,4 @@ public void write(byte[] b, int off, int len) throws IOException { } }; } - - JsonObject toProtocol() { - JsonObject json = new JsonObject(); - json.addProperty("guid", guid); - return json; - } } diff --git a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextHar.java b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextHar.java index 72492bc09..13084505b 100644 --- a/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextHar.java +++ b/playwright/src/test/java/com/microsoft/playwright/TestBrowserContextHar.java @@ -16,6 +16,7 @@ package com.microsoft.playwright; +import com.microsoft.playwright.options.HarContentPolicy; import com.microsoft.playwright.options.HarMode; import com.microsoft.playwright.options.HarNotFound; import org.junit.jupiter.api.Test; @@ -26,6 +27,7 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; @@ -35,6 +37,7 @@ import static com.microsoft.playwright.Utils.copy; import static com.microsoft.playwright.Utils.extractZip; import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; +import static com.microsoft.playwright.options.HarContentPolicy.ATTACH; import static org.junit.jupiter.api.Assertions.*; public class TestBrowserContextHar extends TestBase { @@ -264,7 +267,29 @@ void shouldRoundTripHarZip(@TempDir Path tmpDir) { } try (BrowserContext context2 = browser.newContext()) { context2.routeFromHAR(harPath, new BrowserContext.RouteFromHAROptions().setNotFound(HarNotFound.ABORT)); - Page page2 = context.newPage(); + Page page2 = context2.newPage(); + page2.navigate(server.PREFIX + "/one-style.html"); + assertTrue(page2.content().contains("hello, world!")); + assertThat(page2.locator("body")).hasCSS("background-color", "rgb(255, 192, 203)"); + } + } + + @Test + void shouldProduceExtractedZip(@TempDir Path tmpDir) throws IOException { + Path harPath = tmpDir.resolve("har.har"); + try (BrowserContext context1 = browser.newContext(new Browser.NewContextOptions() + .setRecordHarPath(harPath) + .setRecordHarMode(HarMode.MINIMAL) + .setRecordHarContent(ATTACH))) { + Page page1 = context1.newPage(); + page1.navigate(server.PREFIX + "/one-style.html"); + } + assertTrue(Files.exists(harPath)); + String har = new String(Files.readAllBytes(harPath), StandardCharsets.UTF_8); + assertFalse(har.contains("background-color")); + try (BrowserContext context2 = browser.newContext()) { + context2.routeFromHAR(harPath, new BrowserContext.RouteFromHAROptions().setNotFound(HarNotFound.ABORT)); + Page page2 = context2.newPage(); page2.navigate(server.PREFIX + "/one-style.html"); assertTrue(page2.content().contains("hello, world!")); assertThat(page2.locator("body")).hasCSS("background-color", "rgb(255, 192, 203)"); @@ -286,7 +311,7 @@ void shouldRoundTripExtractedHarZip(@TempDir Path tmpDir) throws IOException { try (BrowserContext context2 = browser.newContext()) { context2.routeFromHAR(harDir.resolve("har.har")); - Page page2 = context.newPage(); + Page page2 = context2.newPage(); page2.navigate(server.PREFIX + "/one-style.html"); assertTrue(page2.content().contains("hello, world!")); assertThat(page2.locator("body")).hasCSS("background-color", "rgb(255, 192, 203)"); @@ -380,4 +405,54 @@ void shouldDisambiguateByHeader(@TempDir Path tmpDir) { } } + @Test + void shouldUpdateHarZipForContext(@TempDir Path tmpDir) { + Path harPath = tmpDir.resolve("har.zip"); + try (BrowserContext context1 = browser.newContext()) { + context1.routeFromHAR(harPath, new BrowserContext.RouteFromHAROptions().setUpdate(true)); + Page page1 = context1.newPage(); + page1.navigate(server.PREFIX + "/one-style.html"); + } + try (BrowserContext context2 = browser.newContext()) { + context2.routeFromHAR(harPath, new BrowserContext.RouteFromHAROptions().setNotFound(HarNotFound.ABORT)); + Page page2 = context2.newPage(); + page2.navigate(server.PREFIX + "/one-style.html"); + assertTrue(page2.content().contains("hello, world!")); + assertThat(page2.locator("body")).hasCSS("background-color", "rgb(255, 192, 203)"); + } + } + + @Test + void shouldUpdateHarZipForPage(@TempDir Path tmpDir) { + Path harPath = tmpDir.resolve("har.zip"); + try (BrowserContext context1 = browser.newContext()) { + Page page1 = context1.newPage(); + page1.routeFromHAR(harPath, new Page.RouteFromHAROptions().setUpdate(true)); + page1.navigate(server.PREFIX + "/one-style.html"); + } + try (BrowserContext context2 = browser.newContext()) { + Page page2 = context2.newPage(); + page2.routeFromHAR(harPath, new Page.RouteFromHAROptions().setNotFound(HarNotFound.ABORT)); + page2.navigate(server.PREFIX + "/one-style.html"); + assertTrue(page2.content().contains("hello, world!")); + assertThat(page2.locator("body")).hasCSS("background-color", "rgb(255, 192, 203)"); + } + } + + @Test + void shouldUpdateExtractedHarZipForPage(@TempDir Path tmpDir) { + Path harPath = tmpDir.resolve("har.har"); + try (BrowserContext context1 = browser.newContext()) { + Page page1 = context1.newPage(); + page1.routeFromHAR(harPath, new Page.RouteFromHAROptions().setUpdate(true)); + page1.navigate(server.PREFIX + "/one-style.html"); + } + try (BrowserContext context2 = browser.newContext()) { + Page page2 = context2.newPage(); + page2.routeFromHAR(harPath, new Page.RouteFromHAROptions().setNotFound(HarNotFound.ABORT)); + page2.navigate(server.PREFIX + "/one-style.html"); + assertTrue(page2.content().contains("hello, world!")); + assertThat(page2.locator("body")).hasCSS("background-color", "rgb(255, 192, 203)"); + } + } } diff --git a/scripts/CLI_VERSION b/scripts/CLI_VERSION index a6c2798a4..49e0a31d4 100644 --- a/scripts/CLI_VERSION +++ b/scripts/CLI_VERSION @@ -1 +1 @@ -1.23.0 +1.23.1