JavaScript の評価
はじめに
Playwright スクリプトは Playwright 環境で実行されます。ページスクリプトはブラウザページ環境で実行されます。これらの環境は交差せず、異なる仮想マシン、異なるプロセス、さらには異なるコンピュータ上で実行される可能性があります。
Page.EvaluateAsync() API は、Web ページのコンテキストで JavaScript 関数を実行し、結果を Playwright 環境に持ち帰ることができます。window
や document
のようなブラウザグローバル変数は evaluate
で使用できます。
var href = await page.EvaluateAsync<string>("document.location.href");
結果が Promise の場合、または関数が非同期の場合、evaluate は自動的に解決されるまで待機します。
int status = await page.EvaluateAsync<int>(@"async () => {
const response = await fetch(location.href);
return response.status;
}");
異なる環境
評価されるスクリプトはブラウザ環境で実行され、テストはテスト環境で実行されます。これは、テストの変数をページで使用したり、その逆もできないことを意味します。代わりに、引数として明示的に渡す必要があります。
次のスニペットは、変数を直接使用しているため、間違っています。
var data = "some data";
var result = await page.EvaluateAsync(@"() => {
// WRONG: there is no 'data' in the web page.
window.myApp.use(data);
}");
次のスニペットは、値を引数として明示的に渡しているため、正しいです。
var data = "some data";
// Pass |data| as a parameter.
var result = await page.EvaluateAsync("data => { window.myApp.use(data); }", data);
評価引数
Page.EvaluateAsync() のような Playwright 評価メソッドは、単一のオプションの引数を取ります。この引数は、シリアライズ可能な値と JSHandle インスタンスの組み合わせにすることができます。ハンドルは、それらが表す値に自動的に変換されます。
// A primitive value.
await page.EvaluateAsync<int>("num => num", 42);
// An array.
await page.EvaluateAsync<int[]>("array => array.length", new[] { 1, 2, 3 });
// An object.
await page.EvaluateAsync<object>("object => object.foo", new { foo = "bar" });
// A single handle.
var button = await page.EvaluateHandleAsync("window.button");
await page.EvaluateAsync<IJSHandle>("button => button.textContent", button);
// Alternative notation using JSHandle.EvaluateAsync.
await button.EvaluateAsync<string>("(button, from) => button.textContent.substring(from)", 5);
// Object with multiple handles.
var button1 = await page.EvaluateHandleAsync("window.button1");
var button2 = await page.EvaluateHandleAsync("window.button2");
await page.EvaluateAsync("o => o.button1.textContent + o.button2.textContent", new { button1, button2 });
// Object destructuring works. Note that property names must match
// between the destructured object and the argument.
// Also note the required parenthesis.
await page.EvaluateAsync("({ button1, button2 }) => button1.textContent + button2.textContent", new { button1, button2 });
// Array works as well. Arbitrary names can be used for destructuring.
// Note the required parenthesis.
await page.EvaluateAsync("([b1, b2]) => b1.textContent + b2.textContent", new[] { button1, button2 });
// Any mix of serializables and handles works.
await page.EvaluateAsync("x => x.button1.textContent + x.list[0].textContent + String(x.foo)", new { button1, list = new[] { button2 }, foo = null as object });
初期化スクリプト
ページが読み込みを開始する前に何かを評価すると便利な場合があります。たとえば、いくつかのモックまたはテストデータを設定したい場合があります。
この場合は、Page.AddInitScriptAsync() または BrowserContext.AddInitScriptAsync() を使用します。以下の例では、Math.random()
を定数値に置き換えます。
まず、モックを含む preload.js
ファイルを作成します。
// preload.js
Math.random = () => 42;
次に、初期化スクリプトをページに追加します。
// In your test, assuming the "preload.js" file is in the "mocks" directory.
await Page.AddInitScriptAsync(scriptPath: "mocks/preload.js");