Перейти к основному содержимому

WebView2

Введение

Далее будет объяснено, как использовать Playwright с Microsoft Edge WebView2. WebView2 — это элемент управления WinForms, который использует Microsoft Edge для отображения веб-контента. Он является частью браузера Microsoft Edge и доступен на Windows 10 и Windows 11. Playwright может использоваться для автоматизации приложений WebView2 и тестирования веб-контента в WebView2. Для подключения к WebView2 Playwright использует BrowserType.connectOverCDP(), который подключается к нему через протокол Chrome DevTools Protocol (CDP).

Обзор

Элемент управления WebView2 можно настроить на прослушивание входящих подключений CDP, установив переменную окружения WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS с --remote-debugging-port=9222 или вызвав EnsureCoreWebView2Async с аргументом --remote-debugging-port=9222. Это запустит процесс WebView2 с включенным протоколом Chrome DevTools Protocol, что позволит автоматизировать его с помощью Playwright. В данном случае 9222 — это пример порта, но можно использовать любой другой неиспользуемый порт.

await this.webView.EnsureCoreWebView2Async(await CoreWebView2Environment.CreateAsync(null, null, new CoreWebView2EnvironmentOptions()
{
AdditionalBrowserArguments = "--remote-debugging-port=9222",
})).ConfigureAwait(false);

После того как ваше приложение с элементом управления WebView2 запущено, вы можете подключиться к нему через Playwright:

Browser browser = playwright.chromium().connectOverCDP("http://localhost:9222");
BrowserContext context = browser.contexts().get(0);
Page page = context.pages().get(0);

Чтобы убедиться, что элемент управления WebView2 готов, вы можете дождаться события CoreWebView2InitializationCompleted:

this.webView.CoreWebView2InitializationCompleted += (_, e) =>
{
if (e.IsSuccess)
{
Console.WriteLine("WebView2 initialized");
}
};

Написание и выполнение тестов

По умолчанию элемент управления WebView2 будет использовать один и тот же каталог данных пользователя для всех экземпляров. Это означает, что если вы запускаете несколько тестов параллельно, они будут мешать друг другу. Чтобы этого избежать, вы должны установить переменную окружения WEBVIEW2_USER_DATA_FOLDER (или использовать WebView2.EnsureCoreWebView2Async Method) в разные папки для каждого теста. Это обеспечит выполнение каждого теста в собственном каталоге данных пользователя.

Используя следующее, Playwright запустит ваше приложение WebView2 как подпроцесс, назначит ему уникальный каталог данных пользователя и предоставит экземпляр Page вашему тесту:

WebView2Process.java
package com.example;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

public class WebView2Process {
public int cdpPort;
private Path _dataDir;
private Process _process;
private Path _executablePath = Path.of("../webview2-app/bin/Debug/net8.0-windows/webview2.exe");

public WebView2Process() throws IOException {
cdpPort = nextFreePort();
_dataDir = Files.createTempDirectory("pw-java-webview2-tests-");

if (!Files.exists(_executablePath)) {
throw new RuntimeException("Executable not found: " + _executablePath);
}
ProcessBuilder pb = new ProcessBuilder().command(_executablePath.toAbsolutePath().toString());
Map<String, String> envMap = pb.environment();
envMap.put("WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS", "--remote-debugging-port=" + cdpPort);
envMap.put("WEBVIEW2_USER_DATA_FOLDER", _dataDir.toString());
_process = pb.start();
// wait until "WebView2 initialized" got printed
BufferedReader reader = new BufferedReader(new InputStreamReader(_process.getInputStream()));
while (true) {
String line = reader.readLine();
if (line == null) {
throw new RuntimeException("WebView2 process exited");
}
if (line.contains("WebView2 initialized")) {
break;
}
}
}

private static final AtomicInteger nextUnusedPort = new AtomicInteger(9000);

private static boolean available(int port) {
try (ServerSocket ignored = new ServerSocket(port)) {
return true;
} catch (IOException ignored) {
return false;
}
}

static int nextFreePort() {
for (int i = 0; i < 100; i++) {
int port = nextUnusedPort.getAndIncrement();
if (available(port)) {
return port;
}
}
throw new RuntimeException("Cannot find free port: " + nextUnusedPort.get());
}

public void dispose() {
_process.destroy();
try {
_process.waitFor();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
TestExample.java
package com.example;

import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.Locator;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;
import org.junit.jupiter.api.*;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;

import java.io.IOException;

public class TestExample {
// Shared between all tests in this class.
static WebView2Process webview2Process;
static Playwright playwright;
static Browser browser;
static BrowserContext context;
static Page page;

@BeforeAll
static void launchBrowser() throws IOException {
playwright = Playwright.create();
webview2Process = new WebView2Process();
browser = playwright.chromium().connectOverCDP("http://127.0.0.1:" + webview2Process.cdpPort);
context = browser.contexts().get(0);
page = context.pages().get(0);
}

@AfterAll
static void closeBrowser() {
webview2Process.dispose();
}

@Test
public void shouldClickButton() {
page.navigate("https://playwright.dev");
Locator gettingStarted = page.getByText("Get started");
assertThat(gettingStarted).isVisible();
}
}

Отладка

Внутри вашего элемента управления WebView2 вы можете просто щелкнуть правой кнопкой мыши, чтобы открыть контекстное меню и выбрать "Inspect", чтобы открыть DevTools, или нажать F12. Вы также можете использовать метод WebView2.CoreWebView2.OpenDevToolsWindow для программного открытия DevTools.

Для отладки тестов смотрите руководство Playwright Debugging guide.