mirror of
https://github.com/microsoft/playwright-java.git
synced 2025-09-08 21:01:00 +00:00
feat(har): support har logging (#84)
This commit is contained in:
parent
2c74b33de6
commit
975be31e63
@ -726,7 +726,7 @@ class Interface extends TypeDefinition {
|
||||
if ("Download".equals(jsonName)) {
|
||||
output.add("import java.io.InputStream;");
|
||||
}
|
||||
if (asList("Page", "Frame", "ElementHandle", "FileChooser", "ChromiumBrowser", "Download", "Route", "Selectors").contains(jsonName)) {
|
||||
if (asList("Page", "Frame", "ElementHandle", "FileChooser", "Browser", "BrowserType", "Download", "Route", "Selectors").contains(jsonName)) {
|
||||
output.add("import java.nio.file.Path;");
|
||||
}
|
||||
output.add("import java.util.*;");
|
||||
|
@ -107,6 +107,9 @@ class Types {
|
||||
add("ElementHandle.screenshot.options.path", "string", "Path");
|
||||
add("Route.fulfill.response.path", "string", "Path");
|
||||
add("Route.fulfill.response.status", "number", "int");
|
||||
add("Browser.newContext.options.recordHar.path", "string", "Path");
|
||||
add("BrowserType.launchPersistentContext.options.recordHar.path", "string", "Path");
|
||||
add("BrowserType.launchPersistentContext.userDataDir", "string", "Path");
|
||||
add("ChromiumBrowser.startTracing.options.path", "string", "Path");
|
||||
|
||||
// Route
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -104,7 +105,7 @@ public interface Browser {
|
||||
/**
|
||||
* Path on the filesystem to write the HAR file to.
|
||||
*/
|
||||
public String path;
|
||||
public Path path;
|
||||
|
||||
RecordHar() {
|
||||
}
|
||||
@ -116,7 +117,7 @@ public interface Browser {
|
||||
this.omitContent = omitContent;
|
||||
return this;
|
||||
}
|
||||
public RecordHar withPath(String path) {
|
||||
public RecordHar withPath(Path path) {
|
||||
this.path = path;
|
||||
return this;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -307,7 +308,7 @@ public interface BrowserType {
|
||||
/**
|
||||
* Path on the filesystem to write the HAR file to.
|
||||
*/
|
||||
public String path;
|
||||
public Path path;
|
||||
|
||||
RecordHar() {
|
||||
}
|
||||
@ -319,7 +320,7 @@ public interface BrowserType {
|
||||
this.omitContent = omitContent;
|
||||
return this;
|
||||
}
|
||||
public RecordHar withPath(String path) {
|
||||
public RecordHar withPath(Path path) {
|
||||
this.path = path;
|
||||
return this;
|
||||
}
|
||||
@ -799,7 +800,7 @@ public interface BrowserType {
|
||||
* @return Promise which resolves to browser instance.
|
||||
*/
|
||||
Browser launch(LaunchOptions options);
|
||||
default BrowserContext launchPersistentContext(String userDataDir) {
|
||||
default BrowserContext launchPersistentContext(Path userDataDir) {
|
||||
return launchPersistentContext(userDataDir, null);
|
||||
}
|
||||
/**
|
||||
@ -808,7 +809,7 @@ public interface BrowserType {
|
||||
* @param options Set of configurable options to set on the browser. Can have the following fields:
|
||||
* @return Promise that resolves to the persistent browser context instance.
|
||||
*/
|
||||
BrowserContext launchPersistentContext(String userDataDir, LaunchPersistentContextOptions options);
|
||||
BrowserContext launchPersistentContext(Path userDataDir, LaunchPersistentContextOptions options);
|
||||
/**
|
||||
* Returns browser name. For example: {@code 'chromium'}, {@code 'webkit'} or {@code 'firefox'}.
|
||||
*/
|
||||
|
@ -21,6 +21,8 @@ import com.google.gson.JsonObject;
|
||||
import com.microsoft.playwright.BrowserContext;
|
||||
import com.microsoft.playwright.BrowserType;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static com.microsoft.playwright.impl.Serialization.gson;
|
||||
|
||||
class BrowserTypeImpl extends ChannelOwner implements BrowserType {
|
||||
@ -44,7 +46,7 @@ class BrowserTypeImpl extends ChannelOwner implements BrowserType {
|
||||
|
||||
|
||||
@Override
|
||||
public BrowserContext launchPersistentContext(String userDataDir, LaunchPersistentContextOptions options) {
|
||||
public BrowserContext launchPersistentContext(Path userDataDir, LaunchPersistentContextOptions options) {
|
||||
if (options == null) {
|
||||
options = new LaunchPersistentContextOptions();
|
||||
}
|
||||
@ -53,7 +55,7 @@ class BrowserTypeImpl extends ChannelOwner implements BrowserType {
|
||||
params.remove("extraHTTPHeaders");
|
||||
params.add("extraHTTPHeaders", Serialization.toProtocol(options.extraHTTPHeaders));
|
||||
}
|
||||
params.addProperty("userDataDir", userDataDir);
|
||||
params.addProperty("userDataDir", userDataDir.toString());
|
||||
JsonObject json = sendMessage("launchPersistentContext", params).getAsJsonObject();
|
||||
return connection.getExistingObject(json.getAsJsonObject("context").get("guid").getAsString());
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public class TestDefaultBrowserContext2 extends TestBase {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
assertNull(persistentContext);
|
||||
persistentContext = browserType.launchPersistentContext(userDataDir.toString(), options);
|
||||
persistentContext = browserType.launchPersistentContext(userDataDir, options);
|
||||
return persistentContext.pages().get(0);
|
||||
}
|
||||
|
||||
@ -118,7 +118,7 @@ public class TestDefaultBrowserContext2 extends TestBase {
|
||||
void shouldAcceptUserDataDir() throws IOException {
|
||||
// TODO: test.flaky(browserName === "chromium");
|
||||
Path userDataDir = Files.createTempDirectory("user-data-dir-");
|
||||
BrowserContext context = browserType.launchPersistentContext(userDataDir.toString());
|
||||
BrowserContext context = browserType.launchPersistentContext(userDataDir);
|
||||
assertTrue(userDataDir.toFile().listFiles().length > 0);
|
||||
context.close();
|
||||
assertTrue(userDataDir.toFile().listFiles().length > 0);
|
||||
@ -129,20 +129,20 @@ public class TestDefaultBrowserContext2 extends TestBase {
|
||||
// TODO: test.slow();
|
||||
Path userDataDir = Files.createTempDirectory("user-data-dir-");
|
||||
BrowserType.LaunchPersistentContextOptions browserOptions = null;
|
||||
BrowserContext browserContext = browserType.launchPersistentContext(userDataDir.toString(), browserOptions);
|
||||
BrowserContext browserContext = browserType.launchPersistentContext(userDataDir, browserOptions);
|
||||
Page page = browserContext.newPage();
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
page.evaluate("() => localStorage.hey = 'hello'");
|
||||
browserContext.close();
|
||||
|
||||
BrowserContext browserContext2 = browserType.launchPersistentContext(userDataDir.toString(), browserOptions);
|
||||
BrowserContext browserContext2 = browserType.launchPersistentContext(userDataDir, browserOptions);
|
||||
Page page2 = browserContext2.newPage();
|
||||
page2.navigate(server.EMPTY_PAGE);
|
||||
assertEquals("hello", page2.evaluate("localStorage.hey"));
|
||||
browserContext2.close();
|
||||
|
||||
Path userDataDir2 = Files.createTempDirectory("user-data-dir-");
|
||||
BrowserContext browserContext3 = browserType.launchPersistentContext(userDataDir2.toString(), browserOptions);
|
||||
BrowserContext browserContext3 = browserType.launchPersistentContext(userDataDir2, browserOptions);
|
||||
Page page3 = browserContext3.newPage();
|
||||
page3.navigate(server.EMPTY_PAGE);
|
||||
assertNotEquals("hello", page3.evaluate("localStorage.hey"));
|
||||
@ -154,7 +154,7 @@ public class TestDefaultBrowserContext2 extends TestBase {
|
||||
// TODO: test.flaky(browserName === "chromium");
|
||||
Path userDataDir = Files.createTempDirectory("user-data-dir-");
|
||||
BrowserType.LaunchPersistentContextOptions browserOptions = null;
|
||||
BrowserContext browserContext = browserType.launchPersistentContext(userDataDir.toString(), browserOptions);
|
||||
BrowserContext browserContext = browserType.launchPersistentContext(userDataDir, browserOptions);
|
||||
Page page = browserContext.newPage();
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
Object documentCookie = page.evaluate("() => {\n" +
|
||||
@ -164,14 +164,14 @@ public class TestDefaultBrowserContext2 extends TestBase {
|
||||
assertEquals("doSomethingOnlyOnce=true", documentCookie);
|
||||
browserContext.close();
|
||||
|
||||
BrowserContext browserContext2 = browserType.launchPersistentContext(userDataDir.toString(), browserOptions);
|
||||
BrowserContext browserContext2 = browserType.launchPersistentContext(userDataDir, browserOptions);
|
||||
Page page2 = browserContext2.newPage();
|
||||
page2.navigate(server.EMPTY_PAGE);
|
||||
assertEquals("doSomethingOnlyOnce=true", page2.evaluate("() => document.cookie"));
|
||||
browserContext2.close();
|
||||
|
||||
Path userDataDir2 = Files.createTempDirectory("user-data-dir-");
|
||||
BrowserContext browserContext3 = browserType.launchPersistentContext(userDataDir2.toString(), browserOptions);
|
||||
BrowserContext browserContext3 = browserType.launchPersistentContext(userDataDir2, browserOptions);
|
||||
Page page3 = browserContext3.newPage();
|
||||
page3.navigate(server.EMPTY_PAGE);
|
||||
assertNotEquals("doSomethingOnlyOnce=true", page3.evaluate("() => document.cookie"));
|
||||
@ -192,7 +192,7 @@ public class TestDefaultBrowserContext2 extends TestBase {
|
||||
.withArgs(asList(server.EMPTY_PAGE));
|
||||
Path userDataDir = Files.createTempDirectory("user-data-dir-");
|
||||
try {
|
||||
browserType.launchPersistentContext(userDataDir.toString(), options);
|
||||
browserType.launchPersistentContext(userDataDir, options);
|
||||
fail("did not throw");
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("can not specify page"));
|
||||
|
178
playwright/src/test/java/com/microsoft/playwright/TestHar.java
Normal file
178
playwright/src/test/java/com/microsoft/playwright/TestHar.java
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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 com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class TestHar extends TestBase {
|
||||
private PageWithHar pageWithHar;
|
||||
|
||||
private class PageWithHar {
|
||||
final Path harFile;
|
||||
final BrowserContext context;
|
||||
final Page page;
|
||||
|
||||
PageWithHar() throws IOException {
|
||||
harFile = Files.createTempFile("test-", ".har");
|
||||
context = browser.newContext(new Browser.NewContextOptions().setRecordHar()
|
||||
.withPath(harFile).done().withIgnoreHTTPSErrors(true));
|
||||
page = context.newPage();
|
||||
}
|
||||
|
||||
JsonObject log() throws FileNotFoundException {
|
||||
context.close();
|
||||
return new Gson().fromJson(new FileReader(harFile.toFile()), JsonObject.class).getAsJsonObject("log");
|
||||
}
|
||||
|
||||
void dispose() throws IOException {
|
||||
context.close();
|
||||
Files.deleteIfExists(harFile);
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void createPageWithHar() throws IOException {
|
||||
pageWithHar = new PageWithHar();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void deletePageWithHar() throws IOException {
|
||||
pageWithHar.dispose();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldThrowWithoutPath() {
|
||||
try {
|
||||
browser.newContext(new Browser.NewContextOptions().setRecordHar().done());
|
||||
fail("did not throw");
|
||||
} catch (PlaywrightException e) {
|
||||
assertTrue(e.getMessage().contains("recordHar.path: expected string, got undefined"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHaveVersionAndCreator() throws FileNotFoundException {
|
||||
pageWithHar.page.navigate(server.EMPTY_PAGE);
|
||||
JsonObject log = pageWithHar.log();
|
||||
assertEquals("1.2", log.get("version").getAsString());
|
||||
assertEquals("Playwright", log.getAsJsonObject("creator").get("name").getAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHaveBrowser() throws FileNotFoundException {
|
||||
pageWithHar.page.navigate(server.EMPTY_PAGE);
|
||||
JsonObject log = pageWithHar.log();
|
||||
assertEquals(browserType.name(), log.getAsJsonObject("browser").get("name").getAsString().toLowerCase());
|
||||
assertEquals(browser.version(), log.getAsJsonObject("browser").get("version").getAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHavePages() throws FileNotFoundException {
|
||||
// For data: load comes before domcontentloaded...
|
||||
Deferred<Void> loadEvent = pageWithHar.page.waitForLoadState(Page.LoadState.DOMCONTENTLOADED);
|
||||
pageWithHar.page.navigate("data:text/html,<title>Hello</title>");
|
||||
loadEvent.get();
|
||||
JsonObject log = pageWithHar.log();
|
||||
|
||||
assertEquals(1, log.getAsJsonArray("pages").size());
|
||||
JsonObject pageEntry = log.getAsJsonArray("pages").get(0).getAsJsonObject();
|
||||
assertEquals("page_0", pageEntry.get("id").getAsString());
|
||||
assertEquals("Hello", pageEntry.get("title").getAsString());
|
||||
// expect(new Date(pageEntry.startedDateTime).valueOf()).toBeGreaterThan(Date.now() - 3600 * 1000);
|
||||
assertTrue(pageEntry.getAsJsonObject("pageTimings").get("onContentLoad").getAsDouble() > 0);
|
||||
assertTrue(pageEntry.getAsJsonObject("pageTimings").get("onLoad").getAsDouble() > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldHavePagesInPersistentContext() throws IOException {
|
||||
Path harPath = pageWithHar.harFile;
|
||||
Path userDataDir = Files.createTempDirectory("user-data-dir-");
|
||||
BrowserContext context = browserType.launchPersistentContext(userDataDir,
|
||||
new BrowserType.LaunchPersistentContextOptions()
|
||||
.setRecordHar().withPath(harPath).done().withIgnoreHTTPSErrors(true));
|
||||
Page page = context.pages().get(0);
|
||||
|
||||
Deferred<Void> loadEvent = page.waitForLoadState(Page.LoadState.DOMCONTENTLOADED);
|
||||
page.navigate("data:text/html,<title>Hello</title>");
|
||||
loadEvent.get();
|
||||
context.close();
|
||||
JsonObject log = new Gson().fromJson(new FileReader(harPath.toFile()), JsonObject.class).getAsJsonObject("log");
|
||||
|
||||
assertEquals(1, log.getAsJsonArray("pages").size());
|
||||
JsonObject pageEntry = log.getAsJsonArray("pages").get(0).getAsJsonObject();
|
||||
assertEquals("page_0", pageEntry.get("id").getAsString());
|
||||
assertEquals("Hello", pageEntry.get("title").getAsString());
|
||||
|
||||
Files.deleteIfExists(harPath);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldIncludeRequest() throws FileNotFoundException {
|
||||
pageWithHar.page.navigate(server.EMPTY_PAGE);
|
||||
JsonObject log = pageWithHar.log();
|
||||
assertEquals(1, log.getAsJsonArray("entries").size());
|
||||
JsonObject entry = log.getAsJsonArray("entries").get(0).getAsJsonObject();
|
||||
assertEquals("page_0", entry.get("pageref").getAsString());
|
||||
assertEquals(server.EMPTY_PAGE, entry.getAsJsonObject("request").get("url").getAsString());
|
||||
assertEquals("GET", entry.getAsJsonObject("request").get("method").getAsString());
|
||||
assertEquals("HTTP/1.1", entry.getAsJsonObject("request").get("httpVersion").getAsString());
|
||||
assertTrue(entry.getAsJsonObject("request").get("headers").getAsJsonArray().size() > 1);
|
||||
boolean foundUserAgentHeader = false;
|
||||
for (JsonElement item : entry.getAsJsonObject("request").get("headers").getAsJsonArray()) {
|
||||
if ("user-agent".equals(item.getAsJsonObject().get("name").getAsString().toLowerCase())) {
|
||||
foundUserAgentHeader = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertTrue(foundUserAgentHeader);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldIncludeResponse() throws FileNotFoundException {
|
||||
pageWithHar.page.navigate(server.EMPTY_PAGE);
|
||||
JsonObject log = pageWithHar.log();
|
||||
JsonObject entry = log.getAsJsonArray("entries").get(0).getAsJsonObject();
|
||||
assertEquals(200, entry.getAsJsonObject("response").get("status").getAsInt());
|
||||
assertEquals("OK", entry.getAsJsonObject("response").get("statusText").getAsString());
|
||||
assertEquals("HTTP/1.1", entry.getAsJsonObject("response").get("httpVersion").getAsString());
|
||||
assertTrue(entry.getAsJsonObject("response").get("headers").getAsJsonArray().size() > 1);
|
||||
|
||||
boolean foundUserContentType = false;
|
||||
for (JsonElement item : entry.getAsJsonObject("response").get("headers").getAsJsonArray()) {
|
||||
if ("content-type".equals(item.getAsJsonObject().get("name").getAsString().toLowerCase())) {
|
||||
foundUserContentType = true;
|
||||
assertEquals("text/html", item.getAsJsonObject().get("value").getAsString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertTrue(foundUserContentType);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user