feat(har): support har logging (#84)

This commit is contained in:
Yury Semikhatsky 2020-12-02 16:05:36 -08:00 committed by GitHub
parent 2c74b33de6
commit 975be31e63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 203 additions and 18 deletions

View File

@ -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.*;");

View File

@ -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

View File

@ -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;
}

View File

@ -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'}.
*/

View File

@ -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());
}

View File

@ -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"));

View 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);
}
}