ハンドル
はじめに
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.
要素ハンドル
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.$$()
ロケーター vs 要素ハンドル
静的なページで広範なDOMトラバーサルを実行する必要があるまれなケースでのみ、ElementHandleの使用を推奨します。すべてのユーザーアクションとアサーションにはロケーターを使用してください。
ロケーターとElementHandleの違いは、後者が特定の要素を指すのに対し、ロケーターはその要素を取得する方法のロジックをキャプチャする点です。
以下の例では、ハンドルはページ上の特定の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();