ハンドル
導入
Playwright は、ページ DOM 要素またはページ内のその他のオブジェクトへのハンドルを作成できます。これらのハンドルは Playwright プロセス内に存在しますが、実際のオブジェクトはブラウザー内に存在します。ハンドルには 2 種類あります
- JSHandle - ページ内の任意の JavaScript オブジェクトを参照します
- ElementHandle - ページ内の DOM 要素を参照します。要素に対してアクションを実行したり、そのプロパティをアサートしたりするための追加メソッドがあります。
ページ内のすべての DOM 要素は JavaScript オブジェクトでもあるため、すべてのElementHandle は JSHandle でもあります。
ハンドルは、ページ内の実際のオブジェクトに対する操作を実行するために使用されます。ハンドルで評価したり、ハンドルのプロパティを取得したり、ハンドルを評価パラメーターとして渡したり、ページオブジェクトを JSON などにシリアル化したりできます。これらのメソッドについては、JSHandle クラス API を参照してください。
API リファレンス
JSHandle を取得する最も簡単な方法はこちらです。
const jsHandle = await page.evaluateHandle('window');
// Use jsHandle for evaluations.
Element Handles
ElementHandle の使用は推奨されません。Locator オブジェクトとウェブファーストのアサーションを代わりに使用してください。
ElementHandle が必要な場合は、page.waitForSelector() または frame.waitForSelector() メソッドで取得することをお勧めします。これらの API は、要素がアタッチされて表示されるのを待ちます。
// Get the element handle
const elementHandle = page.waitForSelector('#box');
// Assert bounding box for the element
const boundingBox = await elementHandle.boundingBox();
expect(boundingBox.width).toBe(100);
// Assert attribute for the element
const classNames = await elementHandle.getAttribute('class');
expect(classNames.includes('highlighted')).toBeTruthy();
パラメーターとしてのハンドル
ハンドルは、page.evaluate() および同様のメソッドに渡すことができます。次のスニペットは、ページ内に新しい配列を作成し、データで初期化し、この配列へのハンドルを Playwright に返します。その後、後続の評価でハンドルを使用します。
// Create new array in page.
const myArrayHandle = await page.evaluateHandle(() => {
window.myArray = [1];
return myArray;
});
// Get the length of the array.
const length = await page.evaluate(a => a.length, myArrayHandle);
// Add one more element to the array using the handle
await page.evaluate(arg => arg.myArray.push(arg.newElement), {
myArray: myArrayHandle,
newElement: 2
});
// Release the object when it's no longer needed.
await myArrayHandle.dispose();
ハンドルのライフサイクル
ハンドルは、page.evaluateHandle()、page.$()、page.$$() などのページメソッド、またはそれらに対応するフレームメソッド frame.evaluateHandle()、frame.$()、frame.$$() を使用して取得できます。作成されたハンドルは、ページがナビゲートするか、jsHandle.dispose() メソッドを使用して手動で破棄されない限り、ガベージコレクションからオブジェクトを保持します。
API リファレンス
- JSHandle
- ElementHandle
- elementHandle.boundingBox()
- elementHandle.getAttribute()
- elementHandle.innerText()
- elementHandle.innerHTML()
- elementHandle.textContent()
- jsHandle.evaluate()
- page.evaluateHandle()
- page.$()
- page.$$()
Locator vs ElementHandle
静的なページで広範な DOM トラバーサルを実行する必要があるまれなケースでのみ、ElementHandle を使用することをお勧めします。すべてのユーザーアクションとアサーションには、代わりにロケーターを使用してください。
Locator と ElementHandle の違いは、後者が特定の要素を指すのに対し、Locator はその要素を取得する方法のロジックを捉えることです。
以下の例では、ハンドルはページ上の特定の DOM 要素を指します。その要素のテキストが変更されたり、React によってまったく異なるコンポーネントをレンダリングするために使用されたりした場合でも、ハンドルは依然として非常に古い DOM 要素を指しています。これにより、予期しない動作が発生する可能性があります。
const handle = await page.$('text=Submit');
// ...
await handle.hover();
await handle.click();
ロケーターを使用すると、ロケーターが使用されるたびに、最新の DOM 要素がセレクターを使用してページ内で特定されます。したがって、以下のスニペットでは、基になる DOM 要素が 2 回特定されます。
const locator = page.getByText('Submit');
// ...
await locator.hover();
await locator.click();