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