Storybook Runner befindet sich noch in der BETA-Phase, die Dokumentation wird später auf die WebdriverIO Dokumentationsseiten verschoben.
Dieses Modul unterstützt jetzt Storybook mit einem neuen Visual Runner. Dieser Runner scannt automatisch nach einer lokalen/entfernten Storybook-Instanz und erstellt Element-Screenshots für jede Komponente. Dies kann erreicht werden, indem Sie
export const config: WebdriverIO.Config = {
services: ["visual"],
};
zu Ihren services
hinzufügen und npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook
über die Befehlszeile ausführen.
Es verwendet standardmäßig Chrome im Headless-Modus als Browser.
[!NOTE]
- Die meisten Optionen für Visual Testing funktionieren auch für den Storybook Runner, siehe die WebdriverIO Dokumentation.
- Der Storybook Runner überschreibt alle Ihre Capabilities und kann nur auf den Browsern ausgeführt werden, die er unterstützt, siehe
--browsers
.
- Der Storybook Runner unterstützt keine bestehende Konfiguration mit Multiremote-Capabilities und wirft einen Fehler.
- Der Storybook Runner unterstützt nur Desktop Web, nicht Mobile Web.
Storybook Runner Service-Optionen
Service-Optionen können wie folgt bereitgestellt werden
export const config: WebdriverIO.Config = {
services: [
[
'visual',
{
baselineFolder: join(process.cwd(), './__snapshots__/'),
debug: true,
storybook: {
additionalSearchParams: new URLSearchParams({foo: 'bar', abc: 'def'}),
clip: false,
clipSelector: ''#some-id,
numShards: 4,
skipStories: ['example-button--secondary', 'example-button--small'],
url: 'https://www.bbc.co.uk/iplayer/storybook/',
version: 6,
getStoriesBaselinePath: (category, component) => `path__${category}__${component}`,
},
},
],
],
}
Storybook Runner CLI-Optionen
--additionalSearchParams
- Typ:
string
- Erforderlich: Nein
- Standard: ''
- Beispiel:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --additionalSearchParams="foo=bar&abc=def"
Es fügt zusätzliche Suchparameter zur Storybook-URL hinzu.
Siehe die URLSearchParams Dokumentation für weitere Informationen. Der String muss ein gültiger URLSearchParams-String sein.
[!NOTE]
Die doppelten Anführungszeichen sind notwendig, um zu verhindern, dass das &
als Befehlstrennzeichen interpretiert wird.
Zum Beispiel mit --additionalSearchParams="foo=bar&abc=def"
wird die folgende Storybook-URL für den Story-Test generiert: http://storybook.url/iframe.html?id=story-id&foo=bar&abc=def
.
--browsers
- Typ:
string
- Erforderlich: Nein
- Standard:
chrome
, Sie können aus chrome|firefox|edge|safari
wählen
- Beispiel:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --browsers=chrome,firefox,edge,safari
- HINWEIS: Nur über die CLI verfügbar
Es verwendet die angegebenen Browser, um Komponenten-Screenshots zu erstellen
[!NOTE]
Stellen Sie sicher, dass die Browser, die Sie verwenden möchten, auf Ihrem lokalen Computer installiert sind
--clip
- Typ:
boolean
- Erforderlich: Nein
- Standard:
true
- Beispiel:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --clip=false
Wenn deaktiviert, wird ein Viewport-Screenshot erstellt. Wenn aktiviert, werden Element-Screenshots basierend auf dem --clipSelector
erstellt, was die Menge an Leerraum um den Komponenten-Screenshot reduziert und die Größe des Screenshots verringert.
--clipSelector
- Typ:
string
- Erforderlich: Nein
- Standard:
#storybook-root > :first-child
für Storybook V7 und #root > :first-child:not(script):not(style)
für Storybook V6, siehe auch --version
- Beispiel:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --clipSelector="#some-id"
Dies ist der Selektor, der verwendet wird:
- um das Element auszuwählen, von dem ein Screenshot erstellt werden soll
- für das Element, das sichtbar sein muss, bevor ein Screenshot erstellt wird
--devices
- Typ:
string
- Erforderlich: Nein
- Standard: Sie können aus den
deviceDescriptors.ts
wählen
- Beispiel:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --devices="iPhone 14 Pro Max","Pixel 3 XL"
- HINWEIS: Nur über die CLI verfügbar
Es verwendet die angegebenen Geräte, die mit den deviceDescriptors.ts
übereinstimmen, um Komponenten-Screenshots zu erstellen
[!NOTE]
- Wenn Ihnen eine Gerätekonfiguration fehlt, können Sie gerne eine Feature-Anfrage einreichen
- Dies funktioniert nur mit Chrome:
- wenn Sie
--devices
angeben, werden alle Chrome-Instanzen im Mobile Emulation-Modus ausgeführt
- wenn Sie auch andere Browser als Chrome angeben, wie
--devices --browsers=firefox,safari,edge
, wird Chrome im Mobile-Emulationsmodus automatisch hinzugefügt
- Der Storybook Runner erstellt standardmäßig Element-Snapshots. Wenn Sie den vollständigen Mobile-Emulierten Screenshot sehen möchten, geben Sie
--clip=false
über die Befehlszeile an
- Der Dateiname sieht zum Beispiel so aus:
__snapshots__/example/button/desktop_chrome/example-button--large-local-chrome-iPhone-14-Pro-Max-430x932-dpr-3.png
- SRC: Das Testen einer mobilen Website auf einem Desktop mit mobiler Emulation kann nützlich sein, aber Tester sollten sich bewusst sein, dass es viele subtile Unterschiede gibt, wie:
- völlig unterschiedliche GPU, was zu großen Leistungsänderungen führen kann;
- mobile UI wird nicht emuliert (insbesondere beeinflusst die ausgeblendete URL-Leiste die Seitenhöhe);
- das Disambiguation-Popup (bei dem Sie eines von mehreren Touch-Zielen auswählen) wird nicht unterstützt;
- viele Hardware-APIs (zum Beispiel das orientationchange-Event) sind nicht verfügbar.
--headless
- Typ:
boolean
- Erforderlich: Nein
- Standard:
true
- Beispiel:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --headless=false
- HINWEIS: Nur über die CLI verfügbar
Dies führt die Tests standardmäßig im Headless-Modus aus (wenn der Browser dies unterstützt) oder kann deaktiviert werden
--numShards
- Typ:
number
- Erforderlich: Nein
- Standard:
true
- Beispiel:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --numShards=10
Dies ist die Anzahl der parallelen Instanzen, die zum Ausführen der Stories verwendet werden. Dies wird durch die maxInstances
in Ihrer wdio.conf
-Datei begrenzt.
[!IMPORTANT]
Wenn Sie im headless
-Modus ausführen, erhöhen Sie die Anzahl nicht auf mehr als 20, um Instabilität aufgrund von Ressourcenbeschränkungen zu vermeiden
--skipStories
- Typ:
string|regex
- Erforderlich: Nein
- Standard: null
- Beispiel:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --skipStories="/.*button.*/gm"
Dies kann sein:
- ein String (
example-button--secondary,example-button--small
)
- oder ein Regex (
"/.*button.*/gm"
)
um bestimmte Stories zu überspringen. Verwenden Sie die id
der Story, die in der URL der Story zu finden ist. Zum Beispiel ist die id
in dieser URL http://localhost:6006/?path=/story/example-page--logged-out
example-page--logged-out
--url
- Typ:
string
- Erforderlich: Nein
- Standard:
http://127.0.0.1:6006
- Beispiel:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --url="https://example.com"
Die URL, unter der Ihre Storybook-Instanz gehostet wird.
--version
- Typ:
number
- Erforderlich: Nein
- Standard: 7
- Beispiel:
npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --version=6
Dies ist die Version von Storybook, standardmäßig 7
. Dies ist notwendig, um zu wissen, ob der V6 clipSelector
verwendet werden muss.
Storybook Interaktionstests
Storybook Interaktionstests ermöglichen es Ihnen, mit Ihrer Komponente zu interagieren, indem Sie benutzerdefinierte Skripte mit WDIO-Befehlen erstellen, um eine Komponente in einen bestimmten Zustand zu versetzen. Siehe zum Beispiel den Codeausschnitt unten:
import { browser, expect } from "@wdio/globals";
describe("Storybook Interaction", () => {
it("should create screenshots for the logged in state when it logs out", async () => {
const componentId = "example-page--logged-in";
await browser.waitForStorybookComponentToBeLoaded({ id: componentId });
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-in-state`
);
await $("button=Log out").click();
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-out-state`
);
});
it("should create screenshots for the logged out state when it logs in", async () => {
const componentId = "example-page--logged-out";
await browser.waitForStorybookComponentToBeLoaded({ id: componentId });
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-out-state`
);
await $("button=Log in").click();
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-in-state`
);
});
});
Es werden zwei Tests an zwei verschiedenen Komponenten ausgeführt. Jeder Test setzt zuerst einen Zustand und macht dann einen Screenshot. Sie werden auch bemerken, dass ein neuer benutzerdefinierter Befehl eingeführt wurde, der hier zu finden ist.
Die obige Spezifikationsdatei kann in einem Ordner gespeichert und mit folgendem Befehl zur Befehlszeile hinzugefügt werden:
pnpm run test.local.desktop.storybook.localhost -- --spec='tests/specs/storybook-interaction/*.ts'
Der Storybook Runner scannt zuerst automatisch Ihre Storybook-Instanz und fügt dann Ihre Tests zu den Stories hinzu, die verglichen werden müssen. Wenn Sie nicht möchten, dass die Komponenten, die Sie für Interaktionstests verwenden, zweimal verglichen werden, können Sie einen Filter hinzufügen, um die "Standardstories" aus dem Scan zu entfernen, indem Sie den --skipStories
Filter angeben. Dies würde so aussehen:
pnpm run test.local.desktop.storybook.localhost -- --skipStories="/example-page.*/gm" --spec='tests/specs/storybook-interaction/*.ts'
Neuer benutzerdefinierter Befehl
Ein neuer benutzerdefinierter Befehl namens browser.waitForStorybookComponentToBeLoaded({ id: 'componentId' })
wird zum browser/driver
-Objekt hinzugefügt, der automatisch die Komponente lädt und wartet, bis sie fertig ist, sodass Sie die Methode browser.url('url.com')
nicht verwenden müssen. Es kann wie folgt verwendet werden
import { browser, expect } from "@wdio/globals";
describe("Storybook Interaction", () => {
it("should create screenshots for the logged in state when it logs out", async () => {
const componentId = "example-page--logged-in";
await browser.waitForStorybookComponentToBeLoaded({ id: componentId });
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-in-state`
);
await $("button=Log out").click();
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-out-state`
);
});
it("should create screenshots for the logged out state when it logs in", async () => {
const componentId = "example-page--logged-out";
await browser.waitForStorybookComponentToBeLoaded({ id: componentId });
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-out-state`
);
await $("button=Log in").click();
await expect($("header")).toMatchElementSnapshot(
`${componentId}-logged-in-state`
);
});
});
Die Optionen sind:
additionalSearchParams
- Typ:
URLSearchParams
- Erforderlich: Nein
- Standard:
new URLSearchParams()
- Beispiel:
await browser.waitForStorybookComponentToBeLoaded({
additionalSearchParams: new URLSearchParams({ foo: "bar", abc: "def" }),
id: "componentId",
});
Dies fügt zusätzliche Suchparameter zur Storybook-URL hinzu. Im obigen Beispiel wird die URL http://storybook.url/iframe.html?id=story-id&foo=bar&abc=def
sein.
Siehe die URLSearchParams Dokumentation für weitere Informationen.
clipSelector
- Typ:
string
- Erforderlich: Nein
- Standard:
#storybook-root > :first-child
für Storybook V7 und #root > :first-child:not(script):not(style)
für Storybook V6
- Beispiel:
await browser.waitForStorybookComponentToBeLoaded({
clipSelector: "#your-selector",
id: "componentId",
});
Dies ist der Selektor, der verwendet wird:
- um das Element auszuwählen, von dem ein Screenshot erstellt werden soll
- für das Element, das sichtbar sein muss, bevor ein Screenshot erstellt wird
- Typ:
string
- Erforderlich: ja
- Beispiel:
await browser.waitForStorybookComponentToBeLoaded({ '#your-selector', id: 'componentId' })
Verwenden Sie die id
der Story, die in der URL der Story zu finden ist. Zum Beispiel ist die id
in dieser URL http://localhost:6006/?path=/story/example-page--logged-out
example-page--logged-out
timeout
- Typ:
number
- Erforderlich: Nein
- Standard: 1100 Millisekunden
- Beispiel:
await browser.waitForStorybookComponentToBeLoaded({
id: "componentId",
timeout: 20000,
});
Die maximale Wartezeit, die wir nach dem Laden der Komponente auf der Seite warten möchten, bis sie sichtbar wird
url
- Typ:
string
- Erforderlich: Nein
- Standard:
http://127.0.0.1:6006
- Beispiel:
await browser.waitForStorybookComponentToBeLoaded({
id: "componentId",
url: "https://your.url",
});
Die URL, unter der Ihre Storybook-Instanz gehostet wird.