主要コンテンツへスキップ

JavaScriptの評価

はじめに

PlaywrightスクリプトはPlaywright環境で実行されます。ページのスクリプトはブラウザのページ環境で実行されます。これらの環境は交差せず、異なる仮想マシン、異なるプロセス、場合によっては異なるコンピュータで実行されます。

Page.EvaluateAsync() APIは、ウェブページのコンテキストでJavaScript関数を実行し、結果をPlaywright環境に持ち帰ることができます。evaluateでは、windowdocumentのようなブラウザのグローバル変数を使用できます。

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