Locators
Ein Locator repräsentiert ein oder mehrere Elemente. Jeder Locator wird durch einen String, einen sogenannten Selektor, definiert. Vitest abstrahiert diesen Selektor, indem es praktische Methoden bereitstellt, die diesen im Hintergrund generieren.
Die Locator-API basiert auf einer Abspaltung von Playwrights Locators, genannt Ivya. Vitest stellt diese API jedoch jedem Provider zur Verfügung, nicht nur Playwright.
TIP
Diese Seite behandelt die API-Nutzung. Um Locators und deren Verwendung besser zu verstehen, lesen Sie die Playwright-Dokumentation über "Locators".
getByRole
function getByRole(
role: ARIARole | string,
options?: LocatorByRoleOptions
): Locator;
Erstellt einen Locator, um ein Element anhand seiner ARIA-Rolle, ARIA-Attribute und seines zugänglichen Namens zu finden.
TIP
Wenn Sie ein einzelnes Element mit getByText('Der Name')
abfragen, ist es oft besser, getByRole(erwarteteRolle, { name: 'Der Name' })
zu verwenden. Die Abfrage des zugänglichen Namens ersetzt andere Abfragen wie *ByAltText
oder *ByTitle
nicht. Obwohl der zugängliche Name diesen Attributen entsprechen kann, ersetzt er nicht deren Funktionalität.
Betrachten Sie die folgende DOM-Struktur:
<h3>Sign up</h3>
<label>
Login
<input type="text" />
</label>
<label>
Password
<input type="password" />
</label>
<br />
<button>Submit</button>
Sie können jedes Element anhand seiner impliziten Rolle lokalisieren:
await expect
.element(page.getByRole('heading', { name: 'Sign up' }))
.toBeVisible();
await page.getByRole('textbox', { name: 'Login' }).fill('admin');
await page.getByRole('textbox', { name: 'Password' }).fill('admin');
await page.getByRole('button', { name: /submit/i }).click();
WARNING
Rollen werden durch String-Gleichheit abgeglichen und erben dabei nicht von der ARIA-Rollenhierarchie. Infolgedessen werden bei der Abfrage einer Oberklassenrolle wie checkbox
Elemente mit einer Unterklassenrolle wie switch
nicht eingeschlossen.
Standardmäßig haben viele semantische HTML-Elemente eine Rolle; zum Beispiel hat <input type="radio">
die Rolle "radio". Nicht-semantische HTML-Elemente haben keine Rolle; <div>
und <span>
ohne hinzugefügte Semantik liefern null
zurück. Das role
-Attribut kann Semantik bereitstellen.
Die Bereitstellung von Rollen über role
- oder aria-*
-Attribute für integrierte Elemente, die bereits eine implizite Rolle besitzen, wird von den ARIA-Richtlinien dringend abgeraten.
Optionen
exact: boolean
Gibt an, ob der
name
exakt abgeglichen wird: Groß-/Kleinschreibung und ganzer String. Standardmäßig ist dies deaktiviert. Diese Option wird ignoriert, wennname
ein regulärer Ausdruck ist. Beachten Sie, dass die exakte Übereinstimmung dennoch Leerzeichen trimmt.tsx<button>Hello World</button>; page.getByRole('button', { name: 'hello world' }); // ✅ page.getByRole('button', { name: 'hello world', exact: true }); // ❌ page.getByRole('button', { name: 'Hello World', exact: true }); // ✅
checked: boolean
Sollen aktivierte Elemente (gesetzt durch
aria-checked
oder<input type="checkbox"/>
) eingeschlossen werden? Standardmäßig wird der Filter nicht angewandt.Weitere Informationen finden Sie unter
aria-checked
.tsx<> <button role="checkbox" aria-checked="true" /> <input type="checkbox" checked /> </>; page.getByRole('checkbox', { checked: true }); // ✅ page.getByRole('checkbox', { checked: false }); // ❌
disabled: boolean
Sollen deaktivierte Elemente eingeschlossen werden? Standardmäßig wird der Filter nicht angewandt. Beachten Sie, dass der Deaktivierungszustand im Gegensatz zu anderen Attributen vererbt wird.
Weitere Informationen finden Sie unter
aria-disabled
.tsx<input type="text" disabled />; page.getByRole('textbox', { disabled: true }); // ✅ page.getByRole('textbox', { disabled: false }); // ❌
expanded: boolean
Sollen erweiterte Elemente eingeschlossen werden? Standardmäßig wird der Filter nicht angewandt.
Weitere Informationen finden Sie unter
aria-expanded
.tsx<a aria-expanded="true" href="example.com"> Link </a>; page.getByRole('link', { expanded: true }); // ✅ page.getByRole('link', { expanded: false }); // ❌
includeHidden: boolean
Gibt an, ob Elemente, die normalerweise vom Zugänglichkeitsbaum ausgeschlossen sind, abgefragt werden sollen. Standardmäßig werden nur sichtbare Elemente vom Rollenselektor abgeglichen.
Beachten Sie, dass die Rollen
none
undpresentation
immer eingeschlossen sind.tsx<button style="display: none" />; page.getByRole('button'); // ❌ page.getByRole('button', { includeHidden: false }); // ❌ page.getByRole('button', { includeHidden: true }); // ✅
level: number
Ein Zahlenattribut, das normalerweise für die Rollen
heading
,listitem
,row
,treeitem
vorhanden ist und Standardwerte für<h1>-<h6>
-Elemente aufweist. Standardmäßig wird der Filter nicht angewandt.Weitere Informationen finden Sie unter
aria-level
.tsx<> <h1>Heading Level One</h1> <div role="heading" aria-level="1"> Second Heading Level One </div> </>; page.getByRole('heading', { level: 1 }); // ✅ page.getByRole('heading', { level: 2 }); // ❌
name: string | RegExp
Ein zugänglicher Name. Standardmäßig unterscheidet der Abgleich nicht zwischen Groß- und Kleinschreibung und sucht nach einem Teilstring. Verwenden Sie die Option
exact
, um dieses Verhalten zu steuern.tsx<button>Click Me!</button>; page.getByRole('button', { name: 'Click Me!' }); // ✅ page.getByRole('button', { name: 'click me!' }); // ✅ page.getByRole('button', { name: 'Click Me?' }); // ❌
pressed: boolean
Sollen gedrückte Elemente eingeschlossen werden? Standardmäßig wird der Filter nicht angewandt.
Weitere Informationen finden Sie unter
aria-pressed
.tsx<button aria-pressed="true">👍</button>; page.getByRole('button', { pressed: true }); // ✅ page.getByRole('button', { pressed: false }); // ❌
selected: boolean
Sollen ausgewählte Elemente eingeschlossen werden? Standardmäßig wird der Filter nicht angewandt.
Weitere Informationen finden Sie unter
aria-selected
.tsx<button role="tab" aria-selected="true"> Vue </button>; page.getByRole('button', { selected: true }); // ✅ page.getByRole('button', { selected: false }); // ❌
Siehe auch
getByAltText
function getByAltText(text: string | RegExp, options?: LocatorOptions): Locator;
Erstellt einen Locator, der ein Element mit einem alt
-Attribut finden kann, das dem angegebenen Text entspricht. Im Gegensatz zur Implementierung der testing-library findet Vitest jedes Element, das ein passendes alt
-Attribut besitzt.
<img alt="Incredibles 2 Poster" src="/incredibles-2.png" />;
page.getByAltText(/incredibles.*? poster/i); // ✅
page.getByAltText('non existing alt text'); // ❌
Optionen
exact: boolean
Gibt an, ob der
text
exakt abgeglichen wird: Groß-/Kleinschreibung und ganzer String. Standardmäßig ist dies deaktiviert. Diese Option wird ignoriert, wenntext
ein regulärer Ausdruck ist. Beachten Sie, dass die exakte Übereinstimmung dennoch Leerzeichen trimmt.
Siehe auch
getByLabelText
function getByLabelText(
text: string | RegExp,
options?: LocatorOptions
): Locator;
Erstellt einen Locator, der ein Element finden kann, das ein zugehöriges Label hat.
Der Locator page.getByLabelText('Username')
findet jedes Eingabefeld im folgenden Beispiel:
// for/htmlFor Beziehung zwischen Label und der ID des Formularelements
<label for="username-input">Username</label>
<input id="username-input" />
// Das aria-labelledby Attribut in Verbindung mit Formularelementen
<label id="username-label">Username</label>
<input aria-labelledby="username-label" />
// Wrapper-Labels
<label>Username <input /></label>
// Wrapper-Labels, bei denen sich der Label-Text in einem anderen Kindelement befindet
<label>
<span>Username</span>
<input />
</label>
// aria-label Attribute
// Vorsicht ist geboten, da dies kein Label ist, das Benutzer auf der Seite sehen können, daher muss der Zweck Ihrer Eingabe für visuelle Benutzer offensichtlich sein.
<input aria-label="Username" />
Optionen
exact: boolean
Gibt an, ob der
text
exakt abgeglichen wird: Groß-/Kleinschreibung und ganzer String. Standardmäßig ist dies deaktiviert. Diese Option wird ignoriert, wenntext
ein regulärer Ausdruck ist. Beachten Sie, dass die exakte Übereinstimmung dennoch Leerzeichen trimmt.
Siehe auch
getByPlaceholder
function getByPlaceholder(
text: string | RegExp,
options?: LocatorOptions
): Locator;
Erstellt einen Locator, der ein Element mit dem angegebenen placeholder
-Attribut finden kann. Vitest findet jedes Element, das ein passendes placeholder
-Attribut besitzt, und nicht nur input
-Elemente.
<input placeholder="Username" />;
page.getByPlaceholder('Username'); // ✅
page.getByPlaceholder('not found'); // ❌
WARNING
Im Allgemeinen ist es besser, ein Label mittels getByLabelText
zu verwenden als einen Platzhalter.
Optionen
exact: boolean
Gibt an, ob der
text
exakt abgeglichen wird: Groß-/Kleinschreibung und ganzer String. Standardmäßig ist dies deaktiviert. Diese Option wird ignoriert, wenntext
ein regulärer Ausdruck ist. Beachten Sie, dass die exakte Übereinstimmung dennoch Leerzeichen trimmt.
Siehe auch
getByText
function getByText(text: string | RegExp, options?: LocatorOptions): Locator;
Erstellt einen Locator, der ein Element finden kann, das den angegebenen Text enthält. Der Text wird mit dem nodeValue
eines TextNode oder dem Wert des Eingabefeldes abgeglichen, wenn der Typ button
oder reset
ist. Der Abgleich nach Text normalisiert immer Leerzeichen, selbst bei exakter Übereinstimmung. Zum Beispiel werden mehrere Leerzeichen zu einem zusammengefasst, Zeilenumbrüche in Leerzeichen umgewandelt und führende sowie nachfolgende Leerzeichen ignoriert.
<a href="/about">About ℹ️</a>;
page.getByText(/about/i); // ✅
page.getByText('about', { exact: true }); // ❌
TIP
Dieser Locator ist nützlich, um nicht-interaktive Elemente zu lokalisieren. Wenn Sie ein interaktives Element, wie einen Button oder ein Eingabefeld, lokalisieren müssen, sollten Sie getByRole
bevorzugen.
Optionen
exact: boolean
Gibt an, ob der
text
exakt abgeglichen wird: Groß-/Kleinschreibung und ganzer String. Standardmäßig ist dies deaktiviert. Diese Option wird ignoriert, wenntext
ein regulärer Ausdruck ist. Beachten Sie, dass die exakte Übereinstimmung dennoch Leerzeichen trimmt.
Siehe auch
getByTitle
function getByTitle(text: string | RegExp, options?: LocatorOptions): Locator;
Erstellt einen Locator, der ein Element mit dem angegebenen title
-Attribut finden kann. Im Gegensatz zu dem getByTitle
der testing-library kann Vitest keine title
-Elemente innerhalb eines SVG finden.
<span title="Delete" id="2"></span>;
page.getByTitle('Delete'); // ✅
page.getByTitle('Create'); // ❌
Optionen
exact: boolean
Gibt an, ob der
text
exakt abgeglichen wird: Groß-/Kleinschreibung und ganzer String. Standardmäßig ist dies deaktiviert. Diese Option wird ignoriert, wenntext
ein regulärer Ausdruck ist. Beachten Sie, dass die exakte Übereinstimmung dennoch Leerzeichen trimmt.
Siehe auch
getByTestId
function getByTestId(text: string | RegExp): Locator;
Erstellt einen Locator, der ein Element finden kann, das dem angegebenen Test-ID-Attribut entspricht. Sie können den Attributnamen über browser.locators.testIdAttribute
konfigurieren.
<div data-testid="custom-element" />;
page.getByTestId('custom-element'); // ✅
page.getByTestId('non-existing-element'); // ❌
WARNING
Es wird empfohlen, dies nur zu verwenden, wenn andere Locators für Ihren Anwendungsfall nicht ausreichen. Die Verwendung von data-testid
-Attributen entspricht nicht der tatsächlichen Nutzung Ihrer Software und sollte, wenn möglich, vermieden werden.
Optionen
exact: boolean
Gibt an, ob der
text
exakt abgeglichen wird: Groß-/Kleinschreibung und ganzer String. Standardmäßig ist dies deaktiviert. Diese Option wird ignoriert, wenntext
ein regulärer Ausdruck ist. Beachten Sie, dass die exakte Übereinstimmung dennoch Leerzeichen trimmt.
Siehe auch
nth
function nth(index: number): Locator;
Diese Methode gibt einen neuen Locator zurück, der nur einen bestimmten Index innerhalb eines Abfrageergebnisses mit mehreren Elementen abgleicht. Die Zählung ist nullbasiert, nth(0)
wählt das erste Element aus. Im Gegensatz zu elements()[n]
versucht der nth
-Locator wiederholt, das Element zu finden, bis es vorhanden ist.
<div aria-label="one"><input /><input /><input /></div>
<div aria-label="two"><input /></div>
page.getByRole('textbox').nth(0); // ✅
page.getByRole('textbox').nth(4); // ❌
TIP
Bevor Sie auf nth
zurückgreifen, ist es oft nützlich, verkettete Locators zu verwenden, um Ihre Suche einzugrenzen. Manchmal gibt es keine bessere Möglichkeit zur Unterscheidung als nach Elementposition; obwohl dies zu Instabilität führen kann, ist es besser als nichts.
page.getByLabel('two').getByRole('input'); // ✅ eine bessere Alternative zu page.getByRole('textbox').nth(3)
page.getByLabel('one').getByRole('input'); // ❌ zu mehrdeutig
page.getByLabel('one').getByRole('input').nth(1); // ✅ pragmatischer Kompromiss
first
function first(): Locator;
Diese Methode gibt einen neuen Locator zurück, der nur den ersten Index eines Abfrageergebnisses mit mehreren Elementen abgleicht. Es ist eine vereinfachte Schreibweise für nth(0)
.
<input /> <input /> <input />
page.getByRole('textbox').first(); // ✅
last
function last(): Locator;
Diese Methode gibt einen neuen Locator zurück, der nur den letzten Index eines Abfrageergebnisses mit mehreren Elementen abgleicht. Es ist eine vereinfachte Schreibweise für nth(-1)
.
<input /> <input /> <input />
page.getByRole('textbox').last(); // ✅
and
function and(locator: Locator): Locator;
Diese Methode erstellt einen neuen Locator, der sowohl den übergeordneten Locator als auch den bereitgestellten Locator abgleicht. Das folgende Beispiel findet einen Button mit einem bestimmten Titel:
page.getByRole('button').and(page.getByTitle('Subscribe'));
or
function or(locator: Locator): Locator;
Diese Methode erstellt einen neuen Locator, der einen oder beide Locators abgleicht.
WARNING
Beachten Sie, dass, wenn der Locator mehr als ein einzelnes Element abgleicht, das Aufrufen einer anderen Methode einen Fehler auslösen könnte, falls diese ein einzelnes Element erwartet:
<>
<button>Click me</button>
<a href="https://vitest.dev">Error happened!</a>
</>;
page.getByRole('button').or(page.getByRole('link')).click(); // ❌ findet mehrere Elemente
filter
function filter(options: LocatorOptions): Locator;
Diese Methode schränkt den Locator gemäß den Optionen ein, beispielsweise durch Filtern nach Text. Sie kann verkettet werden, um mehrere Filter anzuwenden.
has
- Typ:
Locator
Diese Option grenzt den Selektor so ein, dass er Elemente abgleicht, die andere Elemente enthalten, welche dem bereitgestellten Locator entsprechen. Zum Beispiel mit diesem HTML:
<article>
<div>Vitest</div>
</article>
<article>
<div>Rolldown</div>
</article>
Wir können den Locator so eingrenzen, dass er nur den article
mit dem Text Vitest
darin findet:
page.getByRole('article').filter({ has: page.getByText('Vitest') }); // ✅
WARNING
Der bereitgestellte Locator (page.getByText('Vitest')
im Beispiel) muss sich relativ zum übergeordneten Locator (page.getByRole('article')
im Beispiel) verhalten. Er wird beginnend mit dem übergeordneten Locator abgefragt und nicht vom Dokumentstamm aus.
Das bedeutet: Sie können keinen Locator übergeben, der das Element außerhalb des übergeordneten Locators abfragt:
page.getByText('Vitest').filter({ has: page.getByRole('article') }); // ❌
Dieses Beispiel wird fehlschlagen, da sich das article
-Element außerhalb des Elements mit dem Text Vitest
befindet.
TIP
Diese Methode kann verkettet werden, um die Suche nach dem Element noch weiter zu verfeinern:
page
.getByRole('article')
.filter({ has: page.getByRole('button', { name: 'delete row' }) })
.filter({ has: page.getByText('Vitest') });
hasNot
- Typ:
Locator
Diese Option grenzt den Selektor so ein, dass er Elemente abgleicht, die keine anderen Elemente enthalten, welche dem bereitgestellten Locator entsprechen. Zum Beispiel mit diesem HTML:
<article>
<div>Vitest</div>
</article>
<article>
<div>Rolldown</div>
</article>
Wir können den Locator so eingrenzen, dass er nur den article
findet, der Rolldown
nicht enthält.
page.getByRole('article').filter({ hasNot: page.getByText('Rolldown') }); // ✅
page.getByRole('article').filter({ hasNot: page.getByText('Vitest') }); // ❌
WARNING
Beachten Sie, dass der bereitgestellte Locator wie die Option has
gegen das übergeordnete Element abgefragt wird und nicht gegen den Dokumentstamm.
hasText
- Typ:
string | RegExp
Diese Option grenzt den Selektor so ein, dass er nur Elemente abgleicht, die den bereitgestellten Text enthalten. Wenn der string
übergeben wird, unterscheidet der Abgleich nicht zwischen Groß- und Kleinschreibung und sucht nach einem Teilstring.
<article>
<div>Vitest</div>
</article>
<article>
<div>Rolldown</div>
</article>
Beide Locators finden dasselbe Element, da die Suche nicht zwischen Groß- und Kleinschreibung unterscheidet:
page.getByRole('article').filter({ hasText: 'Vitest' }); // ✅
page.getByRole('article').filter({ hasText: 'Vite' }); // ✅
hasNotText
- Typ:
string | RegExp
Diese Option grenzt den Selektor so ein, dass er nur Elemente abgleicht, die den bereitgestellten Text nicht enthalten. Wenn der string
übergeben wird, unterscheidet der Abgleich nicht zwischen Groß- und Kleinschreibung und sucht nach einem Teilstring.
Methoden
Alle Methoden sind asynchron und müssen mit await
aufgerufen werden. Seit Vitest 3 schlagen Tests fehl, wenn eine Methode nicht mit await
aufgerufen wird.
click
function click(options?: UserEventClickOptions): Promise<void>;
Klickt auf ein Element. Sie können die Optionen nutzen, um die Cursorposition festzulegen.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).click();
dblClick
function dblClick(options?: UserEventDoubleClickOptions): Promise<void>;
Löst ein Doppelklick-Ereignis an einem Element aus. Sie können die Optionen nutzen, um die Cursorposition festzulegen.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).dblClick();
tripleClick
function tripleClick(options?: UserEventTripleClickOptions): Promise<void>;
Löst ein Dreifachklick-Ereignis an einem Element aus. Da es keine Dreifachklick-API im Browser gibt, wird diese Methode drei Klick-Ereignisse hintereinander auslösen.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).tripleClick();
clear
function clear(options?: UserEventClearOptions): Promise<void>;
Löscht den Inhalt des Eingabeelements.
import { page } from '@vitest/browser/context';
await page.getByRole('textbox', { name: 'Full Name' }).clear();
hover
function hover(options?: UserEventHoverOptions): Promise<void>;
Bewegt die Cursorposition auf das ausgewählte Element.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).hover();
unhover
function unhover(options?: UserEventHoverOptions): Promise<void>;
Dies funktioniert genauso wie locator.hover
, bewegt den Cursor jedoch stattdessen auf das document.body
-Element.
import { page } from '@vitest/browser/context';
await page.getByRole('img', { name: 'Rose' }).unhover();
fill
function fill(text: string, options?: UserEventFillOptions): Promise<void>;
Setzt den Wert des aktuellen input
-, textarea
- oder contenteditable
-Elements.
import { page } from '@vitest/browser/context';
await page.getByRole('input', { name: 'Full Name' }).fill('Mr. Bean');
dropTo
function dropTo(
target: Locator,
options?: UserEventDragAndDropOptions
): Promise<void>;
Zieht das aktuelle Element zur Zielposition.
import { page } from '@vitest/browser/context';
const paris = page.getByText('Paris');
const france = page.getByText('France');
await paris.dropTo(france);
selectOptions
function selectOptions(
values: HTMLElement | HTMLElement[] | Locator | Locator[] | string | string[],
options?: UserEventSelectOptions
): Promise<void>;
Wählen Sie einen oder mehrere Werte aus einem <select>
-Element.
import { page } from '@vitest/browser/context';
const languages = page.getByRole('select', { name: 'Languages' });
await languages.selectOptions('EN');
await languages.selectOptions(['ES', 'FR']);
await languages.selectOptions([
languages.getByRole('option', { name: 'Spanish' }),
languages.getByRole('option', { name: 'French' }),
]);
screenshot
function screenshot(
options: LocatorScreenshotOptions & { save: false }
): Promise<string>;
function screenshot(
options: LocatorScreenshotOptions & { base64: true }
): Promise<{
path: string;
base64: string;
}>;
function screenshot(
options?: LocatorScreenshotOptions & { base64?: false }
): Promise<string>;
Erstellt einen Screenshot des Elements, das dem Selektor des Locators entspricht.
Sie können den Speicherort für den Screenshot mit der Option path
angeben, der relativ zur aktuellen Testdatei ist. Wenn die Option path
nicht gesetzt ist, verwendet Vitest standardmäßig browser.screenshotDirectory
(standardmäßig __screenshot__
), zusammen mit den Namen der Datei und des Tests, um den Dateipfad des Screenshots zu bestimmen.
Wenn Sie auch den Inhalt des Screenshots benötigen, können Sie base64: true
angeben, um ihn zusammen mit dem Speicherpfad des Screenshots zurückzugeben.
import { page } from '@vitest/browser/context';
const button = page.getByRole('button', { name: 'Click Me!' });
const path = await button.screenshot();
const { path, base64 } = await button.screenshot({
path: './button-click-me.png',
base64: true, // auch base64-String zurückgeben
});
// path - vollständiger Pfad zum Screenshot
// base64 - base64-kodierter String des Screenshots
WARNUNG 3.2.0+
Beachten Sie, dass screenshot
immer einen base64-String zurückgibt, wenn save
auf false
gesetzt ist. Der path
wird in diesem Fall ebenfalls ignoriert.
query
function query(): Element | null;
Diese Methode gibt ein einzelnes Element zurück, das dem Selektor des Locators entspricht, oder null
, falls kein Element gefunden wird.
Falls mehrere Elemente dem Selektor entsprechen, löst diese Methode einen Fehler aus. Verwenden Sie .elements()
, wenn Sie alle übereinstimmenden DOM-Elemente benötigen, oder .all()
, wenn Sie ein Array von Locators benötigen, das dem Selektor entspricht.
Betrachten Sie die folgende DOM-Struktur:
<div>Hello <span>World</span></div>
<div>Hello</div>
Diese Locators lösen keinen Fehler aus:
page.getByText('Hello World').query(); // ✅ HTMLDivElement
page.getByText('Hello Germany').query(); // ✅ null
page.getByText('World').query(); // ✅ HTMLSpanElement
page.getByText('Hello', { exact: true }).query(); // ✅ HTMLSpanElement
Diese Locators lösen einen Fehler aus:
// gibt mehrere Elemente zurück
page.getByText('Hello').query(); // ❌
page.getByText(/^Hello/).query(); // ❌
element
function element(): Element;
Diese Methode gibt ein einzelnes Element zurück, das dem Selektor des Locators entspricht.
Falls kein Element dem Selektor entspricht, wird ein Fehler ausgelöst. Erwägen Sie die Verwendung von .query()
, wenn Sie lediglich prüfen müssen, ob das Element existiert.
Falls mehrere Elemente dem Selektor entsprechen, wird ein Fehler ausgelöst. Verwenden Sie .elements()
, wenn Sie alle übereinstimmenden DOM-Elemente benötigen, oder .all()
, wenn Sie ein Array von Locators benötigen, das dem Selektor entspricht.
TIP
Diese Methode kann nützlich sein, wenn Sie sie an eine externe Bibliothek übergeben müssen. Sie wird automatisch aufgerufen, wenn der Locator mit expect.element
verwendet wird, und zwar jedes Mal, wenn die Assertion wiederholt wird:
await expect.element(page.getByRole('button')).toBeDisabled();
Betrachten Sie die folgende DOM-Struktur:
<div>Hello <span>World</span></div>
<div>Hello Germany</div>
<div>Hello</div>
Diese Locators lösen keinen Fehler aus:
page.getByText('Hello World').element(); // ✅
page.getByText('Hello Germany').element(); // ✅
page.getByText('World').element(); // ✅
page.getByText('Hello', { exact: true }).element(); // ✅
Diese Locators lösen einen Fehler aus:
// gibt mehrere Elemente zurück
page.getByText('Hello').element(); // ❌
page.getByText(/^Hello/).element(); // ❌
// gibt keine Elemente zurück
page.getByText('Hello USA').element(); // ❌
elements
function elements(): Element[];
Diese Methode gibt ein Array von Elementen zurück, die dem Selektor des Locators entsprechen.
Diese Funktion löst keinen Fehler aus. Falls keine Elemente dem Selektor entsprechen, gibt diese Methode ein leeres Array zurück.
Betrachten Sie die folgende DOM-Struktur:
<div>Hello <span>World</span></div>
<div>Hello</div>
Diese Locators sind immer erfolgreich:
page.getByText('Hello World').elements(); // ✅ [HTMLElement]
page.getByText('World').elements(); // ✅ [HTMLElement]
page.getByText('Hello', { exact: true }).elements(); // ✅ [HTMLElement]
page.getByText('Hello').element(); // ✅ [HTMLElement, HTMLElement]
page.getByText('Hello USA').elements(); // ✅ []
all
function all(): Locator[];
Diese Methode gibt ein Array neuer Locators zurück, die dem Selektor entsprechen.
Intern ruft diese Methode .elements
auf und umschließt jedes Element mit page.elementLocator
.
Eigenschaften
selector
Der selector
ist ein String, der vom Browser-Provider zur Lokalisierung des Elements verwendet wird. Playwright verwendet eine Playwright-Locator-Syntax, während preview
und webdriverio
CSS verwenden.
DANGER
Verwenden Sie diesen String nicht direkt in Ihrem Testcode. Der selector
-String sollte nur bei der Arbeit mit der Commands API verwendet werden:
import type { BrowserCommand } from 'vitest/node';
const test: BrowserCommand<string> = function test(context, selector) {
// playwright
await context.iframe.locator(selector).click();
// webdriverio
await context.browser.$(selector).click();
};
import { test } from 'vitest';
import { commands, page } from '@vitest/browser/context';
test('works correctly', async () => {
await commands.test(page.getByText('Hello').selector); // ✅
// Vitest wird es automatisch in einen String umwandeln
await commands.test(page.getByText('Hello')); // ✅
});
Benutzerdefinierte Locators 3.2.0+ erweitert
Sie können die integrierte Locators-API erweitern, indem Sie ein Objekt mit Locator-Fabriken definieren. Diese Methoden existieren als Methoden auf dem page
-Objekt und jedem erstellten Locator.
Diese Locators können nützlich sein, falls die integrierten Locators nicht ausreichen. Zum Beispiel, wenn Sie ein benutzerdefiniertes Framework für Ihre Benutzeroberfläche verwenden.
Die Locator-Fabrik muss einen Selektor-String oder den Locator selbst zurückgeben.
TIP
Die Selektor-Syntax ist identisch mit den Playwright-Locators. Bitte lesen Sie deren Anleitung, um besser zu verstehen, wie Sie mit ihnen arbeiten.
import { locators } from '@vitest/browser/context';
locators.extend({
getByArticleTitle(title) {
return `[data-title="${title}"]`;
},
getByArticleCommentsCount(count) {
return `.comments :text("${count} comments")`;
},
async previewComments() {
// Sie haben über "this" Zugriff auf den aktuellen Locator
// Beachten Sie: Wenn die Methode auf `page` aufgerufen wurde, wird `this` `page` sein,
// nicht der Locator!
if (this !== page) {
await this.click();
}
// ...
},
});
// Wenn Sie TypeScript verwenden, können Sie die LocatorSelectors-Schnittstelle erweitern,
// um die Autovervollständigung in locators.extend, page.* und locator.* Methoden zu haben
declare module '@vitest/browser/context' {
interface LocatorSelectors {
// Gibt die benutzerdefinierte Methode einen String zurück, wird dieser in einen Locator umgewandelt
// Gibt sie etwas anderes zurück, wird es unverändert zurückgegeben.
getByArticleTitle(title: string): Locator;
getByArticleCommentsCount(count: number): Locator;
// Vitest gibt ein `Promise` zurück und versucht nicht, es in einen Locator umzuwandeln
previewComments(this: Locator): Promise<void>;
}
}
Wird die Methode auf dem globalen page
-Objekt aufgerufen, wird der Selektor auf die gesamte Seite angewendet. Im folgenden Beispiel findet getByArticleTitle
alle Elemente mit einem Attribut data-title
mit dem Wert von title
. Wird die Methode jedoch auf dem Locator aufgerufen, so wird sie auf diesen Locator beschränkt.
<article data-title="Hello, World!">
Hello, World!
<button id="comments">2 comments</button>
</article>
<article data-title="Hello, Vitest!">
Hello, Vitest!
<button id="comments">0 comments</button>
</article>
const articles = page.getByRole('article');
const worldArticle = page.getByArticleTitle('Hello, World!'); // ✅
const commentsElement = worldArticle.getByArticleCommentsCount(2); // ✅
const wrongCommentsElement = worldArticle.getByArticleCommentsCount(0); // ❌
const wrongElement = page.getByArticleTitle('No Article!'); // ❌
await commentsElement.previewComments(); // ✅
await wrongCommentsElement.previewComments(); // ❌