mirror of
https://github.com/microsoft/playwright-java.git
synced 2025-09-08 21:01:00 +00:00
feat: launchPersistentContext (#53)
This commit is contained in:
parent
707efeebbb
commit
dca206d28d
@ -238,6 +238,9 @@ class Method extends Element {
|
||||
customSignature.put("Page.setViewportSize", new String[]{"void setViewportSize(int width, int height);"});
|
||||
// The method is deprecated in ts, just remove it in Java.
|
||||
customSignature.put("BrowserContext.setHTTPCredentials", new String[0]);
|
||||
// No connect for now.
|
||||
customSignature.put("BrowserType.connect", new String[0]);
|
||||
customSignature.put("BrowserType.launchServer", new String[0]);
|
||||
customSignature.put("BrowserContext.route", new String[]{
|
||||
"void route(String url, BiConsumer<Route, Request> handler);",
|
||||
"void route(Pattern url, BiConsumer<Route, Request> handler);",
|
||||
@ -928,6 +931,9 @@ public class ApiGenerator {
|
||||
System.out.println("Writing files to: " + dir.getCanonicalPath());
|
||||
for (Map.Entry<String, JsonElement> entry: api.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
if ("BrowserServer".equals(name)) {
|
||||
continue;
|
||||
}
|
||||
List<String> lines = new ArrayList<>();
|
||||
new Interface(entry.getValue().getAsJsonObject()).writeTo(lines, "");
|
||||
String text = String.join("\n", lines);
|
||||
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* 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 java.util.*;
|
||||
|
||||
public interface BrowserServer {
|
||||
void close();
|
||||
void kill();
|
||||
Object process();
|
||||
String wsEndpoint();
|
||||
}
|
||||
|
@ -488,7 +488,6 @@ public interface BrowserType {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
Browser connect(ConnectOptions options);
|
||||
String executablePath();
|
||||
default Browser launch() {
|
||||
return launch(null);
|
||||
@ -498,10 +497,6 @@ public interface BrowserType {
|
||||
return launchPersistentContext(userDataDir, null);
|
||||
}
|
||||
BrowserContext launchPersistentContext(String userDataDir, LaunchPersistentContextOptions options);
|
||||
default BrowserServer launchServer() {
|
||||
return launchServer(null);
|
||||
}
|
||||
BrowserServer launchServer(LaunchServerOptions options);
|
||||
String name();
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,11 @@ class BrowserContextImpl extends ChannelOwner implements BrowserContext {
|
||||
|
||||
protected BrowserContextImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
if (parent instanceof BrowserImpl) {
|
||||
browser = (BrowserImpl) parent;
|
||||
} else {
|
||||
browser = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -16,24 +16,21 @@
|
||||
|
||||
package com.microsoft.playwright.impl;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.microsoft.playwright.Browser;
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import com.microsoft.playwright.BrowserContext;
|
||||
import com.microsoft.playwright.BrowserServer;
|
||||
import com.microsoft.playwright.BrowserType;
|
||||
import com.microsoft.playwright.PlaywrightException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
class BrowserTypeImpl extends ChannelOwner implements BrowserType {
|
||||
BrowserTypeImpl(ChannelOwner parent, String type, String guid, JsonObject initializer) {
|
||||
super(parent, type, guid, initializer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Browser connect(ConnectOptions options) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrowserImpl launch(LaunchOptions options) {
|
||||
if (options == null) {
|
||||
@ -48,14 +45,60 @@ class BrowserTypeImpl extends ChannelOwner implements BrowserType {
|
||||
return initializer.get("executablePath").getAsString();
|
||||
}
|
||||
|
||||
|
||||
private static class ColorSchemeAdapter extends TypeAdapter<LaunchPersistentContextOptions.ColorScheme> {
|
||||
@Override
|
||||
public BrowserContext launchPersistentContext(String userDataDir, LaunchPersistentContextOptions options) {
|
||||
return null;
|
||||
public void write(JsonWriter out, LaunchPersistentContextOptions.ColorScheme value) throws IOException {
|
||||
String stringValue;
|
||||
switch (value) {
|
||||
case DARK:
|
||||
stringValue = "dark";
|
||||
break;
|
||||
case LIGHT:
|
||||
stringValue = "light";
|
||||
break;
|
||||
case NO_PREFERENCE:
|
||||
stringValue = "no-preference";
|
||||
break;
|
||||
default:
|
||||
throw new PlaywrightException("Unexpected value: " + value);
|
||||
}
|
||||
out.value(stringValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrowserServer launchServer(LaunchServerOptions options) {
|
||||
return null;
|
||||
public LaunchPersistentContextOptions.ColorScheme read(JsonReader in) throws IOException {
|
||||
String value = in.nextString();
|
||||
switch (value) {
|
||||
case "dark": return LaunchPersistentContextOptions.ColorScheme.DARK;
|
||||
case "light": return LaunchPersistentContextOptions.ColorScheme.LIGHT;
|
||||
case "no-preference": return LaunchPersistentContextOptions.ColorScheme.NO_PREFERENCE;
|
||||
default: throw new PlaywrightException("Unexpected value: " + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BrowserContext launchPersistentContext(String userDataDir, LaunchPersistentContextOptions options) {
|
||||
if (options == null) {
|
||||
options = new LaunchPersistentContextOptions();
|
||||
}
|
||||
Gson gson = new GsonBuilder().registerTypeAdapter(LaunchPersistentContextOptions.ColorScheme.class, new ColorSchemeAdapter().nullSafe()).create();
|
||||
JsonObject params = gson.toJsonTree(options).getAsJsonObject();
|
||||
if (options.extraHTTPHeaders != null) {
|
||||
params.remove("extraHTTPHeaders");
|
||||
JsonArray jsonArray = new JsonArray();
|
||||
for (Map.Entry<String, String> e : options.extraHTTPHeaders.entrySet()) {
|
||||
JsonObject header = new JsonObject();
|
||||
header.addProperty("name", e.getKey());
|
||||
header.addProperty("value", e.getValue());
|
||||
jsonArray.add(header);
|
||||
}
|
||||
params.add("extraHTTPHeaders", jsonArray);
|
||||
}
|
||||
params.addProperty("userDataDir", userDataDir);
|
||||
JsonObject json = sendMessage("launchPersistentContext", params).getAsJsonObject();
|
||||
return connection.getExistingObject(json.getAsJsonObject("context").get("guid").getAsString());
|
||||
}
|
||||
|
||||
public String name() {
|
||||
|
@ -0,0 +1,146 @@
|
||||
package com.microsoft.playwright;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import static com.microsoft.playwright.BrowserType.LaunchPersistentContextOptions.ColorScheme.DARK;
|
||||
import static com.microsoft.playwright.Utils.mapOf;
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class TestDefaultBrowserContext2 extends TestBase {
|
||||
|
||||
|
||||
private BrowserContext persistentContext;
|
||||
|
||||
@AfterEach
|
||||
private void closePersistentContext() {
|
||||
if (persistentContext != null) {
|
||||
persistentContext.close();
|
||||
}
|
||||
}
|
||||
|
||||
private Page launchPersistent() {
|
||||
return launchPersistent(null);
|
||||
}
|
||||
private Page launchPersistent(BrowserType.LaunchPersistentContextOptions options) {
|
||||
Path userDataDir = null;
|
||||
try {
|
||||
userDataDir = Files.createTempDirectory("user-data-dir-");
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
assertNull(persistentContext);
|
||||
persistentContext = browserType.launchPersistentContext(userDataDir.toString(), options);
|
||||
return persistentContext.pages().get(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupportHasTouchOption() {
|
||||
Page page = launchPersistent(new BrowserType.LaunchPersistentContextOptions().withHasTouch(true));
|
||||
page.navigate(server.PREFIX + "/mobile.html");
|
||||
assertEquals(true, page.evaluate("() => 'ontouchstart' in window"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldWorkInPersistentContext() {
|
||||
// TODO: test.skip(browserName === "firefox");
|
||||
// Firefox does not support mobile.
|
||||
Page page = launchPersistent(new BrowserType.LaunchPersistentContextOptions()
|
||||
.withViewport(320,480).withIsMobile(true));
|
||||
page.navigate(server.PREFIX + "/empty.html");
|
||||
assertEquals(980, page.evaluate("() => window.innerWidth"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupportColorSchemeOption() {
|
||||
Page page = launchPersistent(new BrowserType.LaunchPersistentContextOptions().withColorScheme(DARK));
|
||||
assertEquals(false, page.evaluate("matchMedia('(prefers-color-scheme: light)').matches"));
|
||||
assertEquals(true, page.evaluate("matchMedia('(prefers-color-scheme: dark)').matches"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupportTimezoneIdOption() {
|
||||
Page page = launchPersistent(new BrowserType.LaunchPersistentContextOptions()
|
||||
.withLocale("en-US").withTimezoneId("America/Jamaica"));
|
||||
assertEquals("Sat Nov 19 2016 13:12:34 GMT-0500 (Eastern Standard Time)",
|
||||
page.evaluate("new Date(1479579154987).toString()"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupportLocaleOption() {
|
||||
Page page = launchPersistent(new BrowserType.LaunchPersistentContextOptions()
|
||||
.withLocale("fr-CH"));
|
||||
assertEquals("fr-CH", page.evaluate("navigator.language"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupportGeolocationAndPermissionsOptions() {
|
||||
Page page = launchPersistent(new BrowserType.LaunchPersistentContextOptions()
|
||||
.withGeolocation(new Geolocation(10, 10))
|
||||
.withPermissions(asList("geolocation")));
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
Object geolocation = page.evaluate("() => new Promise(resolve => navigator.geolocation.getCurrentPosition(position => {\n" +
|
||||
" resolve({latitude: position.coords.latitude, longitude: position.coords.longitude});\n" +
|
||||
"}))");
|
||||
assertEquals(mapOf("latitude", 10, "longitude", 10), geolocation);
|
||||
}
|
||||
|
||||
// @Test
|
||||
void shouldSupportIgnoreHTTPSErrorsOption() {
|
||||
// TODO: net::ERR_EMPTY_RESPONSE at https://localhost:8908/empty.html
|
||||
// Page page = launchPersistent(new BrowserType.LaunchPersistentContextOptions().withIgnoreHTTPSErrors(true));
|
||||
// Response response = page.navigate(httpsServer.EMPTY_PAGE);
|
||||
// assertTrue(response.ok());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSupportExtraHTTPHeadersOption() throws ExecutionException, InterruptedException {
|
||||
// TODO: test.flaky(browserName === "firefox" && headful && platform === "linux", "Intermittent timeout on bots");
|
||||
Page page = launchPersistent(new BrowserType.LaunchPersistentContextOptions().withExtraHTTPHeaders(mapOf("foo", "bar")));
|
||||
Future<Server.Request> request = server.waitForRequest("/empty.html");
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
assertEquals(asList("bar"), request.get().headers.get("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAcceptUserDataDir() throws IOException {
|
||||
// TODO: test.flaky(browserName === "chromium");
|
||||
Path userDataDir = Files.createTempDirectory("user-data-dir-");
|
||||
BrowserContext context = browserType.launchPersistentContext(userDataDir.toString());
|
||||
assertTrue(userDataDir.toFile().listFiles().length > 0);
|
||||
context.close();
|
||||
assertTrue(userDataDir.toFile().listFiles().length > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRestoreStateFromUserDataDir() throws IOException {
|
||||
// TODO: test.slow();
|
||||
Path userDataDir = Files.createTempDirectory("user-data-dir-");
|
||||
BrowserType.LaunchPersistentContextOptions browserOptions = null;
|
||||
BrowserContext browserContext = browserType.launchPersistentContext(userDataDir.toString(), browserOptions);
|
||||
Page page = browserContext.newPage();
|
||||
page.navigate(server.EMPTY_PAGE);
|
||||
page.evaluate("() => localStorage.hey = 'hello'");
|
||||
browserContext.close();
|
||||
|
||||
BrowserContext browserContext2 = browserType.launchPersistentContext(userDataDir.toString(), 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);
|
||||
Page page3 = browserContext3.newPage();
|
||||
page3.navigate(server.EMPTY_PAGE);
|
||||
assertNotEquals("hello", page3.evaluate("localStorage.hey"));
|
||||
browserContext3.close();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user