Zum Hauptinhalt springen

Selektoren

Das WebDriver Protocol bietet mehrere Auswahlstrategien zum Abfragen eines Elements an. WebdriverIO vereinfacht sie, um die Auswahl von Elementen einfach zu halten. Bitte beachten Sie, dass die Befehle zum Abfragen von Elementen zwar $ und $$ heißen, aber nichts mit jQuery oder der Sizzle Selector Engine zu tun haben.

Obwohl so viele verschiedene Selektoren verfügbar sind, bieten nur wenige von ihnen eine verlässliche Möglichkeit, das richtige Element zu finden. Zum Beispiel mit der folgenden Schaltfläche:

<button
id="main"
class="btn btn-large"
name="submission"
role="button"
data-testid="submit"
>
Submit
</button>

Empfehlen wir (oder nicht) die folgenden Selektoren:

SelektorEmpfehlungAnmerkungen
$('button')🚨 NiemalsAm schlimmsten - zu allgemein, kein Kontext.
$('.btn.btn-large')🚨 NiemalsWeniger Gut. Verbunden mit Styling. Fehler durch Style-Änderungen möglich.
$('#main')⚠️ SparsamBesser. Aber immer noch an Styling oder JS-Event-Listener gekoppelt.
$(() => document.queryElement('button'))⚠️ SparsamErmöglicht effektive Abfragen, allerdings komplex zu schreiben.
$('button[name="submission"]')⚠️ SparsamGekoppelt an das Attribut name, das HTML-Semantik hat.
$('button[data-testid="submit"]')✅ GutErfordert zusätzliches Attribut, das keine weitere Funktion hat.
$('aria/Submit') or $('button=Submit')✅ ImmerAm besten geeignet. Ähnelt, wie der Benutzer mit der Seite interagiert.

CSS-Selektoren

Wenn nicht anders angegeben, fragt WebdriverIO Elemente mit dem CSS Selektor ab, z. B.:

selectors/example.js
loading...

Um ein Link-Element mit einem bestimmtem Text zu bekommen, fragen Sie den Text beginnend mit einem Gleichheitszeichen (=) ab.

Zum Beispiel:

selectors/example.html
loading...

Sie können dieses Element abfragen, indem Sie Folgendes aufrufen:

selectors/example.js
loading...

Teillinktext

Um ein Link-Element zu finden, dessen sichtbarer Text teilweise mit Ihrem Suchwert übereinstimmt, fragen Sie es ab, indem Sie *= vor die Abfragezeichenfolge setzen (z. B. *=driver).

Sie können das Element aus dem obigen Beispiel abfragen, indem Sie auch Folgendes aufrufen:

selectors/example.js
loading...

Hinweis: Sie können nicht mehrere Selektorstrategien in einem Selektor mischen. Verwenden Sie mehrere verkettete Elementabfragen, um dasselbe Ziel zu erreichen, z. B.:

const elem = await $('header h1*=Welcome') // doesn't work!!!
// use instead
const elem = await $('header').$('*=driver')

Element mit bestimmtem Text

Die gleiche Technik kann auch auf Elemente angewendet werden.

Hier ist zum Beispiel eine Abfrage für eine Überschrift der Ebene 1 mit dem Text „Welcome to my page“:

selectors/example.html
loading...

Sie können dieses Element abfragen, indem Sie Folgendes aufrufen:

selectors/example.js
loading...

Oder verwenden Sie die Teiltext-Abfrage:

selectors/example.js
loading...

Das gleiche funktioniert für id und class Namen:

selectors/example.html
loading...

Sie können dieses Element abfragen, indem Sie Folgendes aufrufen:

selectors/example.js
loading...

Hinweis: Sie können nicht mehrere Selektorstrategien in einem Selektor mischen. Verwenden Sie mehrere verkettete Elementabfragen, um dasselbe Ziel zu erreichen, z. B.:

const elem = await $('header h1*=Welcome') // doesn't work!!!
// use instead
const elem = await $('header').$('h1*=Welcome')

Tag-Name

Um ein Element mit einem bestimmten Tag-Namen abzufragen, verwenden Sie <tag> oder <tag />.

selectors/example.html
loading...

Sie können dieses Element abfragen, indem Sie Folgendes aufrufen:

selectors/example.js
loading...

Namensattribut

Zum Abfragen von Elementen mit einem bestimmten Namensattribut können Sie entweder einen normalen CSS3-Selektor verwenden oder die bereitgestellte Namensstrategie aus dem JSONWireProtocol verwenden, indem Sie etwas wie [name="some-name"] als Selektorparameter übergeben:

selectors/example.html
loading...
selectors/example.js
loading...

Hinweis: Diese Auswahlstrategie ist veraltet und funktioniert nur in alten Browsern, die vom JSONWireProtocol-Protokoll oder von Appium ausgeführt werden.

xPath

Es ist auch möglich, Elemente über einen bestimmten xPathabzufragen.

Ein xPath-Selektor hat ein Format wie //body/div[6]/div[1]/span[1].

selectors/xpath.html
loading...

Sie können den zweiten `

` Tag abfragen, indem Sie Folgendes aufrufen:

selectors/example.js
loading...

Sie können xPath auch verwenden, um den DOM-Baum nach oben und unten zu durchlaufen:

selectors/example.js
loading...

Accessibility Name Selektor

Fragen Sie Elemente nach ihrem Accessibility Namen ab. Der Accessibility Name wird von einem Screenreader angesagt, wenn dieses Element den Fokus erhält. Der Accessibility Name kann sowohl visueller Inhalt als auch versteckte Textalternativen darstellen.

info

Weitere Informationen zu diesem Selektor finden Sie in unserem Release-Blogbeitrag

Finden von Elementen via Aria-Label

selectors/aria.html
loading...
selectors/example.js
loading...

Finden von Elementen via aria-labelledby

selectors/aria.html
loading...
selectors/example.js
loading...

Finden von Elementen via dessen Inhalt

selectors/aria.html
loading...
selectors/example.js
loading...

Finden von Elementen durch ein "titel" Attribut

selectors/aria.html
loading...
selectors/example.js
loading...

Finden von Elementen durch ein alt Attribut

selectors/aria.html
loading...
selectors/example.js
loading...

ARIA - Rollen-Attribut

Um Elemente basierend auf ARIA-Rollen zu finden, können Sie die Rolle des Elements direkt angeben, z. B. [role=button] als Selektor:

selectors/aria.html
loading...
selectors/example.js
loading...

ID Attribut

Die Locator-Strategie „id“ wird im WebDriver-Protokoll nicht unterstützt, man sollte stattdessen entweder CSS- oder xPath-Selector-Strategien verwenden, um Elemente mit ID zu finden.

Einige Treiber (z.B. Appium You.i Engine Driver) unterstützen diesen Selektor jedoch möglicherweise immer noch.

Aktuell unterstützte Selektor-Syntax für ID sind:

//css locator
const button = await $('#someid')
//xpath locator
const button = await $('//*[@id="someid"]')
//id strategy
// Note: works only in Appium or similar frameworks which supports locator strategy "ID"
const button = await $('id=resource-id/iosname')

Elemente finden via JavaScript-Funktion

Sie können auch JavaScript-Funktionen verwenden, um Elemente mithilfe web-nativer APIs zu abzufragen. Natürlich können Sie dies nur innerhalb eines Webkontexts tun (z. B. browseroder im Web-Kontext auf Mobilgeräten).

Bei folgender HTML-Struktur:

selectors/js.html
loading...

können Sie das Geschwisterelement von #elem wie folgt abfragen:

selectors/example.js
loading...

Tiefe Selektoren

Viele Frontend-Anwendungen verlassen sich stark auf Elemente mit Shadow DOM. Es ist technisch nicht möglich, Elemente innerhalb des Shadow-DOM ohne Workarounds abzufragen. Die shadow$ und shadow$$ waren Möglichkeiten, die ihre Einschränkungen hatten. Mit dem Tiefenselektor können Sie jetzt alle Elemente in jedem Schatten-DOM mit dem allgemeinen Abfragebefehl abfragen.

Angenommen, wir haben eine Anwendung mit der folgenden Struktur:

Chrome-Beispiel

Mit diesem Selektor können Sie das <button /> Element abfragen, das in einem anderen Schatten-DOM verschachtelt ist, z.B.:

selectors/example.js
loading...

Mobile Selektoren

Für hybride mobile Tests ist es wichtig, dass sich der Automatisierungsserver im richtigen context befindet, bevor Befehle ausgeführt werden. Für die Automatisierung von Gesten sollte der Treiber idealerweise auf nativen Kontext eingestellt werden. Um jedoch Elemente aus dem DOM auszuwählen, muss der Treiber auf den Webview-Kontext der Plattform eingestellt werden. Erst dann können die oben genannten Methoden verwendet werden.

Beim nativen mobilen Testen gibt es keinen Wechsel zwischen Kontexten, da Sie mobile Strategien verwenden und die zugrunde liegende Geräteautomatisierungstechnologie direkt verwenden müssen. Dies ist besonders nützlich, wenn ein Test eine feinkörnige Kontrolle über das Finden von Elementen erfordert.

Android UiAutomator

Das UI Automator-Framework von Android bietet eine Reihe von Möglichkeiten zum Suchen von Elementen. Sie können die UI Automator API, insbesondere die UiSelector-Klasse verwenden, um Elemente zu lokalisieren. In Appium können Sie den Java-Code als Zeichenfolge an den Server senden, der in der Umgebung der Anwendung ausgeführt wird und das Element oder die Elemente zurückgibt.

const selector = 'new UiSelector().text("Cancel").className("android.widget.Button")'
const button = await $(`android=${selector}`)
await button.click()

Android DataMatcher und ViewMatcher (nur Espresso)

Die View-Tag-Strategie bietet eine bequeme Möglichkeit, Elemente anhand ihres -Tagszu finden.

const menuItem = await $({
"name": "hasEntry",
"args": ["title", "ViewTitle"]
})
await menuItem.click()

Die DataMatcher-Strategie von Android bietet eine Möglichkeit, Elemente mit DataMatcherzu finden.

const menuItem = await $({
"name": "hasEntry",
"args": ["title", "ViewTitle"],
"class": "androidx.test.espresso.matcher.ViewMatchers"
})
await menuItem.click()

Android View Tag (nur Espresso)

Und ähnlich View Matcher

const elem = await $('-android viewtag:tag_identifier')
await elem.click()

iOS UIAutomation

Bei der Automatisierung einer iOS-Anwendung kann Apples UI Automation Framework verwendet werden, um Elemente zu finden.

Diese JavaScript API verfügt über Methoden für den Zugriff auf die View und alles darin enthaltene.

const selector = 'UIATarget.localTarget().frontMostApp().mainWindow().buttons()[0]'
const button = await $(`ios=${selector}`)
await button.click()

Sie können auch das "Predicate Searching" innerhalb der iOS-UI-Automatisierung in Appium verwenden, um die Elementauswahl noch weiter zu verfeinern. Siehe iOS Predicate für weitere Details.

iOS XCUITest Prädikatzeichenfolgen und Klassenketten

Und Klassenketten:

const selector = `type == 'XCUIElementTypeSwitch' && name CONTAINS 'Allow'`
const switch = await $(`-ios predicate string:${selector}`)
await switch.click()

Mit iOS 10 und höher (unter Verwendung des XCUITest Treibers) können Sie Prädikatzeichenfolgen verwenden:

const selector = '**/XCUIElementTypeCell[`name BEGINSWITH "D"`]/**/XCUIElementTypeButton'
const button = await $(`-ios class chain:${selector}`)
await button.click()

Accessibility ID

Die Locator-Strategie Accessibility ID wurde entwickelt, um eine eindeutige Kennung für ein UI-Element zu bekommen. Dies hat den Vorteil, dass sich durch Übersetzungen oder andere Umstände, die den Text ändern könnte, der Selektor stabil bleibt. Außerdem kann es hilfreich sein, plattformübergreifende Tests zu erstellen, wenn funktional gleiche Elemente dieselbe Accessibility-ID haben.

  • Für iOS ist es der accessibility identifier und ist von Apple hier festgelegt.
  • Für Android wird die Accessibility-ID der content-description für das Element zugeordnet, wie hier beschrieben.

Für beide Plattformen ist es normalerweise die beste Methode, ein Element (oder mehrere Elemente) anhand ihrer Accessibility-ID zu erhalten. Es ist auch der bevorzugte Weg gegenüber der veralteten Name- Strategie.

const elem = await $('~my_accessibility_identifier')
await elem.click()

Klassenname

Die Klassenname- Strategie ist eine Zeichenfolge, die ein UI-Element in der aktuellen Ansicht darstellt.

  • Für iOS ist es der vollständige Name einer UIAutomation-Klasseund beginnt mit UIA-, z. B. UIATextField für ein Textfeld. Eine vollständige Referenz finden Sie hier.
  • Für Android ist es der vollständig qualifizierte Name eines UI Automator class, z. B. android.widget.EditText für ein Textfeld. Eine vollständige Referenz finden Sie hier.
  • Für Youi.tv ist es der vollständige Name einer Youi.tv-Klasse und wird mit CYI-sein, z. B. CYIPushButtonView für ein Button Element. Eine vollständige Referenz finden Sie auf GitHub Seite auf den Dokumentationsseiten des You.i Engine Driver
// iOS example
await $('UIATextField').click()
// Android example
await $('android.widget.DatePicker').click()
// Youi.tv example
await $('CYIPushButtonView').click()

Ketten-Selektoren

Wenn Sie in Ihrer Abfrage spezifischer sein möchten, können Sie Selektoren verketten, bis Sie das richtige Element gefunden haben. Befehle der Element API nutzen immer den Kontext des vorhergegangen Query Befehls.

Wenn Sie beispielsweise eine DOM-Struktur haben, die wie folgt aussieht:

<div class="row">
<div class="entry">
<label>Product A</label>
<button>Add to cart</button>
<button>More Information</button>
</div>
<div class="entry">
<label>Product B</label>
<button>Add to cart</button>
<button>More Information</button>
</div>
<div class="entry">
<label>Product C</label>
<button>Add to cart</button>
<button>More Information</button>
</div>
</div>

Und Sie möchten Produkt B in den Warenkorb legen, so wäre es schwierig, dies nur mit dem CSS-Selektor zu tun.

Mit der Selektorverkettung ist es viel einfacher. Einfach Schritt für Schritt das gewünschte Element eingrenzen:

await $('.row .entry:nth-child(2)').$('button*=Add').click()

Appium Bild Selektoren

Mit der -image- Selektor ist es möglich, Appium eine Bilddatei zu senden, die ein Element darstellt, auf das Sie zugreifen möchten.

Unterstützte Dateiformate jpg,png,gif,bmp,svg

Eine vollständige Referenz finden Sie hier

const elem = await $('./file/path/of/image/test.jpg')
await elem.click()

Hinweis: Die Art und Weise, wie Appium mit diesem Selektor arbeitet, ist, dass es intern einen (App-)Screenshot erstellt und den bereitgestellten Bildselektor verwendet, um zu überprüfen, ob das Element in diesem (App-)Screenshot gefunden werden kann.

Beachten Sie, dass Appium die Größe des aufgenommenen (App-) möglicherweise an die CSS-Größe Ihres (App-)Bildschirms anpasst (dies geschieht auf iPhones, aber auch auf Mac-Computern mit einem Retina-Display, da der DPR größer ist als 1). Dies führt dazu dass keine Übereinstimmung gefunden wird, da die bereitgestellte Bildauswahl möglicherweise aus dem ursprünglichen Screenshot stammt. Sie können dies beheben, indem Sie die Appium Server-Einstellungen aktualisieren, siehe die Appium-Dokumentation für die Einstellungen und diesen Kommentar für eine detaillierte Erklärung.

React Selektoren

WebdriverIO bietet eine Möglichkeit, React-Komponenten basierend auf dem Komponentennamen auszuwählen. Dazu stehen Ihnen zwei Befehle zur Auswahl: react$ und react$$.

Mit diesen Befehlen können Sie Komponenten aus dem React VirtualDOM auswählen und entweder ein einzelnes WebdriverIO-Element oder ein Array von Elementen zurückgeben (je nachdem, welche Funktion verwendet wird).

Hinweis: Die Befehle react$ und react$$ sind in ihrer Funktionalität ähnlich, außer dass react$$ alle übereinstimmenden Instanzen als ein Array von WebdriverIO-Elementen zurückgibt und react$ nur die erste gefundene Instanz.

Einfaches Beispiel

// index.jsx
import React from 'react'
import ReactDOM from 'react-dom'

function MyComponent() {
return (
<div>
MyComponent
</div>
)
}

function App() {
return (<MyComponent />)
}

ReactDOM.render(<App />, document.querySelector('#root'))

Mit dem Befehl browser.react$ können Sie eine Instanz von MyComponentauswählen:

Im obigen Code gibt es eine einfache MyComponent -Instanz innerhalb der Anwendung, die React innerhalb eines HTML-Elements mit id="root"rendert.

const myCmp = await browser.react$('MyComponent')

Nachdem Sie nun das WebdriverIO-Element in der Variablen myCmp gespeichert haben, können Sie Elementbefehle dafür ausführen.

Komponenten filtern

Die Bibliothek, die WebdriverIO intern verwendet, ermöglicht es, Ihre Auswahl nach Props und/oder Zustand der Komponente zu filtern. Dazu müssen Sie dem Browser-Befehl ein zweites Argument für Props und/oder ein drittes Argument für State übergeben.

// index.jsx
import React from 'react'
import ReactDOM from 'react-dom'

function MyComponent(props) {
return (
<div>
Hello { props.name || 'World' }!
</div>
)
}

function App() {
return (
<div>
<MyComponent name="WebdriverIO" />
<MyComponent />
</div>
)
}

ReactDOM.render(<App />, document.querySelector('#root'))

Wenn Sie die Instanz von MyComponent mit einem Prop name als WebdriverIOauswählen möchten, können Sie den Befehl wie folgt ausführen:

const myCmp = await browser.react$('MyComponent', {
props: { name: 'WebdriverIO' }
})

Wenn Sie unsere Auswahl nach Status filtern möchten, sieht der Befehl browser ungefähr so aus:

const myCmp = await browser.react$('MyComponent', {
state: { myState: 'some value' }
})

Umgang mit React.Fragment

Wenn Sie den Befehl react$ verwenden, um React fragments auszuwählen, gibt WebdriverIO das erste untergeordnete Element dieser Komponente als Knoten der Komponente zurück. Wenn Sie react$$verwenden, erhalten Sie ein Array mit allen HTML-Knoten innerhalb der Fragmente, die mit dem Selektor übereinstimmen.

// index.jsx
import React from 'react'
import ReactDOM from 'react-dom'

function MyComponent() {
return (
<React.Fragment>
<div>
MyComponent
</div>
<div>
MyComponent
</div>
</React.Fragment>
)
}

function App() {
return (<MyComponent />)
}

ReactDOM.render(<App />, document.querySelector('#root'))

In Anbetracht des obigen Beispiels würden die Befehle so funktionieren:

await browser.react$('MyComponent') // returns the WebdriverIO Element for the first <div />
await browser.react$$('MyComponent') // returns the WebdriverIO Elements for the array [<div />, <div />]

Hinweis: Wenn Sie mehrere Instanzen von MyComponent haben und react$$ verwenden, um diese Fragmentkomponenten auszuwählen, erhalten Sie ein eindimensionales Array aller Knoten zurück. Mit anderen Worten, wenn Sie 3 <MyComponent /> Instanzen haben, erhalten Sie ein Array mit sechs WebdriverIO-Elementen zurück.

Benutzerdefinierte Selektoren

Wenn Ihre App eine bestimmte Methode zum Abrufen von Elementen erfordert, können Sie sich selbst eine benutzerdefinierte Selektorstrategie definieren, die Sie mit custom$ und custom$$verwenden können. Registrieren Sie dazu Ihre Strategie einmalig zu Beginn des Tests:

queryElements/customStrategy.js
loading...

Bei folgender HTML-Struktur:

queryElements/example.html
loading...

Verwenden Sie Ihren benutzerdefinierten Selektor wie folgt::

queryElements/customStrategy.js
loading...

Hinweis: Dies funktioniert nur in einer Webumgebung, in der der Befehl execute ausgeführt werden kann.

Welcome! How can I help?

WebdriverIO AI Copilot