其他定位器
簡介
查看主要的定位器指南,了解最常見和推薦的定位器。
除了推薦的定位器如 page.getByRole 和 page.getByText,Playwright 支援本指南中描述的各種其他定位器。
CSS 定位器
我們建議優先考慮使用 使用者可見的定位器,例如文字或可訪問的角色,而不是使用與實作綁定的 CSS,因為當頁面變更時可能會失效。
Playwright 可以透過 CSS 選擇器定位元素。
await page.locator('css=button').click();
Playwright 增強了標準 CSS 選擇器的兩種方式:
- CSS 選擇器穿透開放的 shadow DOM。
- Playwright 添加了自訂偽類,如
:visible
,:has-text()
,:has()
,:is()
,:nth-match()
等。
CSS: 根據文字匹配
Playwright 包含許多 CSS 偽類別來根據其文字內容匹配元素。
-
article:has-text("Playwright")
-:has-text()
匹配包含指定文字的任何元素,可能在子元素或後代元素內。匹配不區分大小寫,會修剪空白並搜尋子字串。例如,
article:has-text("Playwright")
匹配<article><div>Playwright</div></article>
。注意,
:has-text()
應與其他 CSS 指定符一起使用,否則它會匹配所有包含指定文字的元素,包括<body>
。// 錯誤,將匹配許多元素包括 <body>
await page.locator(':has-text("Playwright")').click();
// 正確,只匹配 <article> 元素
await page.locator('article:has-text("Playwright")').click(); -
#nav-bar :text("Home")
-:text()
偽類匹配包含指定文字的最小元素。匹配不區分大小寫,會修剪空白並搜尋子字串。例如,這將在
#nav-bar
元素內找到包含文字 "Home" 的元素:await page.locator('#nav-bar :text("Home")').click();
-
#nav-bar :text-is("Home")
-:text-is()
偽類匹配具有精確文字的最小元素。精確匹配區分大小寫,會修剪空白並搜尋完整字串。例如,
:text-is("Log")
不匹配<button>Log in</button>
因為<button>
包含的單一文字節點"Log in"
不等於"Log"
。然而,:text-is("Log")
匹配<button> Log <span>in</span></button>
,因為<button>
包含一個文字節點" Log "
。同樣,
:text-is("Download")
不會匹配<button>download</button>
因為它區分大小寫。
-
#nav-bar :text-matches("reg?ex", "i")
-:text-matches()
偽類別匹配具有與 JavaScript-like regex 相匹配的文本內容的最小元素。例如,
:text-matches("Log\s*in", "i")
匹配<button>Login</button>
和<button>log IN</button>
。
文字匹配總是會正規化空白。例如,它會將多個空格變成一個空格,將換行符變成空格,並忽略前後的空白。
Input 元素類型 button
和 submit
是通過它們的 value
而不是文本內容來匹配的。例如,:text("Log in")
匹配 <input type=button value="Log in">
。
CSS: 僅匹配可見元素
Playwright 支援 CSS 選擇器中的 :visible
偽類別。例如,css=button
匹配頁面上的所有按鈕,而 css=button:visible
只匹配可見的按鈕。這對於區分非常相似但在可見性上有所不同的元素非常有用。
考慮一個有兩個按鈕的頁面,第一個不可見,第二個可見。
<button style='display: none'>Invisible</button>
<button>Visible</button>
-
這將會找到兩個按鈕並拋出一個嚴格性違規錯誤:
await page.locator('button').click();
-
這將只會找到第二個按鈕,因為它是可見的,然後點擊它。
await page.locator('button:visible').click();
CSS: 包含其他元素的元素
:has()
偽類別是一個實驗性的 CSS 偽類別。如果任何作為參數傳遞的選擇器相對於給定元素的 :scope
匹配至少一個元素,它會返回一個元素。
以下程式碼片段返回具有 <div class=promo>
的 <article>
元素的文本內容。
await page.locator('article:has(div.promo)').textContent();
CSS: 符合其中一個條件的元素
逗號分隔的 CSS 選擇器列表將匹配該列表中任一選擇器可以選擇的所有元素。
// Clicks a <button> that has either a "Log in" or "Sign in" text.
await page.locator('button:has-text("Log in"), button:has-text("Sign in")').click();
:is()
偽類別是一個實驗性 CSS 偽類別,可能對於指定元素上的額外條件列表很有用。
CSS: 根據佈局匹配元素
根據版面配置進行匹配可能會產生意想不到的結果。例如,當版面配置改變一個像素時,可能會匹配到不同的元素。
有時候,當目標元素缺乏明顯特徵時,很難想出一個好的選擇器。在這種情況下,使用 Playwright 佈局 CSS 偽類可能會有所幫助。這些可以與常規 CSS 結合,以精確定位多個選擇中的一個。
例如,input:right-of(:text("Password"))
匹配位於 "Password" 文字右側的輸入欄位 - 當頁面有多個難以區分的輸入欄位時非常有用。
請注意,佈局偽類別除了其他東西外(如 input
)也很有用。如果單獨使用佈局偽類別,如 :right-of(:text("Password"))
,很可能你會得到的不是你要找的 input,而是文本和目標 input 之間的一些空元素。
佈局偽類別使用 bounding client rect 計算元素的距離和相對位置。
:right-of(div > button)
- 匹配在任何符合內部選擇器的元素右側的元素,在任何垂直位置。:left-of(div > button)
- 匹配在任何符合內部選擇器的元素左側的元素,在任何垂直位置。:above(div > button)
- 匹配在任何符合內部選擇器的元素上方的元素,在任何水平位置。:below(div > button)
- 匹配在任何符合內部選擇器的元素下方的元素,在任何水平位置。:near(div > button)
- 匹配在任何符合內部選擇器的元素附近(50 個 CSS 像素內)的元素。
請注意,結果匹配是根據它們與錨點元素的距離進行排序的,因此您可以使用 locator.first() 來選擇最近的一個。這只有在您有類似元素列表的情況下才有用,其中最近的顯然是正確的。然而,在其他情況下使用 locator.first() 很可能不會按預期工作——它不會定位到您正在搜索的元素,而是一些碰巧最近的其他元素,如隨機的空 <div>
,或是已經滾動出來且當前不可見的元素。
// Fill an input to the right of "Username".
await page.locator('input:right-of(:text("Username"))').fill('value');
// Click a button near the promo card.
await page.locator('button:near(.promo-card)').click();
// Click the radio input in the list closest to the "Label 3".
await page.locator('[type=radio]:left-of(:text("Label 3"))').first().click();
所有布局偽類別支持可選的最大像素距離作為最後一個參數。例如 button:near(:text("Username"), 120)
匹配距離文本為 "Username" 的元素最多 120 個 CSS 像素的按鈕。
CSS: 從查詢結果中選擇第 n 個匹配
通常可以通過某些屬性或文本內容來區分元素,這樣對頁面變更更具彈性。
有時頁面包含許多相似的元素,很難選擇特定的一個。例如:
<section> <button>Buy</button> </section>
<article><div> <button>Buy</button> </div></article>
<div><div> <button>Buy</button> </div></div>
在這種情況下,:nth-match(:text("Buy"), 3)
將會 選擇上面程式碼片段中的第三個按鈕。請注意,索引是從 1 開始的。
// Click the third "Buy" button
await page.locator(':nth-match(:text("Buy"), 3)').click();
:nth-match()
也可用於等待直到出現指定數量的元素,使用 locator.waitFor()。
// Wait until all three buttons are visible
await page.locator(':nth-match(:text("Buy"), 3)').waitFor();
與 :nth-child()
不同,元素不必是兄弟元素,它們可以在頁面的任何位置。在上面的程式碼片段中,所有三個按鈕都符合 :text("Buy")
選擇器,而 :nth-match()
選擇了第三個按鈕。
第 N 個元素定位器
您可以使用 nth=
定位器傳遞從零開始的索引來縮小查詢到第 n 個匹配項。
// Click first button
await page.locator('button').locator('nth=0').click();
// Click last button
await page.locator('button').locator('nth=-1').click();
父元素定位器
當你需要定位某個元素的父元素時,大多數情況下你應該通過子定位器來locator.filter()。例如,考慮以下 DOM 結構:
<li><label>Hello</label></li>
<li><label>World</label></li>
如果你想定位包含文字 "Hello"
的標籤的父 <li>
,使用 locator.filter() 是最好的方法:
const child = page.getByText('Hello');
const parent = page.getByRole('listitem').filter({ has: child });
或者,如果您無法找到適合的父元素定位器,請使用 xpath=..
。請注意,這種方法不太可靠,因為對 DOM 結構的任何更改都會破壞您的測試。盡可能使用 locator.filter()。
const parent = page.getByText('Hello').locator('xpath=..');
React locator
React 定位器是實驗性的,並以 _
為前綴。其功能未來可能會改變。
React locator 允許通過元件名稱和屬性值來查找元素。語法與 CSS attribute selectors 非常相似,並支援所有 CSS 屬性選擇器運算子。
在 React 定位器中,元件名稱以 CamelCase 轉錄。
await page.locator('_react=BookItem').click();
更多範例:
- 根據 component 匹配:
_react=BookItem
- 根據 component 和 精確屬性值 匹配,區分大小寫:
_react=BookItem[author = "Steven King"]
- 僅根據屬性值匹配,不區分大小寫:
_react=[author = "steven king" i]
- 根據 component 和 真值屬性值 匹配:
_react=MyButton[enabled]
- 根據 component 和 布林值 匹配:
_react=MyButton[enabled = false]
- 根據屬性 值子串 匹配:
_react=[author *= "King"]
- 根據 component 和 多個屬性 匹配:
_react=BookItem[author *= "king" i][year = 1990]
- 根據 嵌套 屬性值匹配:
_react=[some.nested.value = 12]
- 根據 component 和屬性值 前綴 匹配:
_react=BookItem[author ^= "Steven"]
- 根據 component 和屬性值 後綴 匹配:
_react=BookItem[author $= "Steven"]
- 根據 component 和 key 匹配:
_react=BookItem[key = '2']
- 根據屬性值 正則表達式 匹配:
_react=[author = /Steven(\\s+King)?/i]
要在樹中找到 React 元素名稱,請使用 React DevTools。
React locator 支援 React 15 及以上版本。
React 定位器,以及 React DevTools,僅適用於 未壓縮 的應用程式建構。