Skip to main content

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。

概述

WebView2 控制項可以透過設定 WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS 環境變數為 --remote-debugging-port=9222 或呼叫 EnsureCoreWebView2Async 並帶上 --remote-debugging-port=9222 參數來指示其監聽進入的 CDP 連接。這將啟動啟用 Chrome DevTools Protocol 的 WebView2 程序,允許 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");
}
};

Writing and running tests

預設情況下,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 除錯指南