Hoppa till huvudinnehåll

Bildanalys (Visuell regressionstestning) tjänst

@wdio/visual-service är ett tredjepartspaket, för mer information se GitHub | npm

För dokumentation om visuell testning med WebdriverIO, se docs. Detta projekt innehåller alla relevanta moduler för att köra visuella tester med WebdriverIO. I katalogen ./packages hittar du:

  • @wdio/visual-testing: WebdriverIO-tjänsten för integrering av visuell testning
  • webdriver-image-comparison: En bildanalysmodul som kan användas för olika NodeJS-testautomatiseringsramverk som stöder WebDriver-protokollet

Storybook Runner (BETA)

Klicka för att se mer dokumentation om Storybook Runner BETA

Storybook Runner är fortfarande i BETA, dokumentationen kommer senare att flyttas till WebdriverIO dokumentationssidor.

Denna modul stöder nu Storybook med en ny Visual Runner. Denna runner söker automatiskt efter en lokal/fjärransluten Storybook-instans och skapar element-skärmbilder av varje komponent. Detta kan göras genom att lägga till

export const config: WebdriverIO.Config = {
// ...
services: ["visual"],
// ....
};

till dina services och köra npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook genom kommandoraden. Den kommer att använda Chrome i headless-läge som standardwebbläsare.

[!NOTE]

  • De flesta Visual Testing-alternativen fungerar också för Storybook Runner, se WebdriverIO dokumentationen.
  • Storybook Runner kommer att skriva över alla dina capabilities och kan bara köras på de webbläsare som den stöder, se --browsers.
  • Storybook Runner stöder inte en befintlig konfiguration som använder Multiremote capabilities och kommer att kasta ett fel.
  • Storybook Runner stöder endast Desktop Web, inte Mobile Web.

Storybook Runner Service-alternativ

Service-alternativ kan tillhandahållas så här

export const config: WebdriverIO.Config  = {
// ...
services: [
[
'visual',
{
// Några standardalternativ
baselineFolder: join(process.cwd(), './__snapshots__/'),
debug: true,
// Storybook-alternativen, se cli-alternativ för beskrivningen
storybook: {
additionalSearchParams: new URLSearchParams({foo: 'bar', abc: 'def'}),
clip: false,
clipSelector: ''#some-id,
numShards: 4,
// `skipStories` kan vara en sträng ('example-button--secondary'),
// en array (['example-button--secondary', 'example-button--small'])
// eller ett reguljärt uttryck som måste anges som en sträng ("/.*button.*/gm")
skipStories: ['example-button--secondary', 'example-button--small'],
url: 'https://www.bbc.co.uk/iplayer/storybook/',
version: 6,
// Valfritt - Tillåter överskrivning av baseline-sökvägen. Som standard grupperas baselines efter kategori och komponent (t.ex. forms/input/baseline.png)
getStoriesBaselinePath: (category, component) => `path__${category}__${component}`,
},
},
],
],
// ....
}

Storybook Runner CLI-alternativ

--additionalSearchParams

  • Typ: string
  • Obligatoriskt: Nej
  • Standard: ''
  • Exempel: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --additionalSearchParams="foo=bar&abc=def"

Det lägger till ytterligare sökparametrar till Storybook-URL:en. Se URLSearchParams-dokumentationen för mer information. Strängen måste vara en giltig URLSearchParams-sträng.

[!NOTE] De dubbla citattecknen behövs för att förhindra att & tolkas som en kommandoseparator. Till exempel med --additionalSearchParams="foo=bar&abc=def" kommer det att generera följande Storybook-URL för stories-test: http://storybook.url/iframe.html?id=story-id&foo=bar&abc=def.

--browsers

  • Typ: string
  • Obligatoriskt: Nej
  • Standard: chrome, du kan välja mellan chrome|firefox|edge|safari
  • Exempel: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --browsers=chrome,firefox,edge,safari
  • OBS: Endast tillgängligt via CLI

Den kommer att använda de angivna webbläsarna för att ta komponentskärmbilder

[!NOTE] Se till att du har de webbläsare du vill köra på installerade på din lokala maskin

--clip

  • Typ: boolean
  • Obligatoriskt: Nej
  • Standard: true
  • Exempel: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --clip=false

När den är inaktiverad skapas en viewport-skärmbild. När den är aktiverad skapas element-skärmbilder baserade på --clipSelector vilket minskar mängden tomt utrymme runt komponentskärmbilden och minskar skärmbildens storlek.

--clipSelector

  • Typ: string
  • Obligatoriskt: Nej
  • Standard: #storybook-root > :first-child för Storybook V7 och #root > :first-child:not(script):not(style) för Storybook V6, se även --version
  • Exempel: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --clipSelector="#some-id"

Detta är den väljare som kommer att användas:

  • för att välja elementet som skärmbilden ska tas av
  • för elementet som ska vänta på att bli synligt innan en skärmbild tas

--devices

  • Typ: string
  • Obligatoriskt: Nej
  • Standard: Du kan välja från deviceDescriptors.ts
  • Exempel: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --devices="iPhone 14 Pro Max","Pixel 3 XL"
  • OBS: Endast tillgängligt via CLI

Den kommer att använda de angivna enheterna som matchar deviceDescriptors.ts för att ta komponentskärmbilder

[!NOTE]

  • Om du saknar en enhetskonfiguration, välkommen att skicka in en Feature request
  • Detta fungerar endast med Chrome:
    • om du anger --devices kommer alla Chrome-instanser att köras i Mobile Emulation-läge
    • om du också anger andra webbläsare än Chrome, som --devices --browsers=firefox,safari,edge kommer det automatiskt att lägga till Chrome i Mobile emulation-läge
  • Storybook Runner kommer som standard att skapa elementskärmbilder, om du vill se den kompletta Mobile Emulated-skärmbilden, ange --clip=false via kommandoraden
  • Filnamnet kommer till exempel att se ut som __snapshots__/example/button/desktop_chrome/example-button--large-local-chrome-iPhone-14-Pro-Max-430x932-dpr-3.png
  • KÄLLA: Att testa en mobilwebbplats på en dator med mobil emulering kan vara användbart, men testare bör vara medvetna om att det finns många subtila skillnader såsom:
    • helt annan GPU, vilket kan leda till stora prestandaförändringar;
    • mobil UI emuleras inte (särskilt påverkar dölj-url-fältet sidhöjden);
    • disambigueringspopup (där du väljer ett av flera pekbara mål) stöds inte;
    • många hårdvaru-API:er (till exempel orientationchange-händelsen) är inte tillgängliga.

--headless

  • Typ: boolean
  • Obligatoriskt: Nej
  • Standard: true
  • Exempel: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --headless=false
  • OBS: Endast tillgängligt via CLI

Detta kommer som standard att köra testerna i headless-läge (när webbläsaren stöder det) eller kan inaktiveras

--numShards

  • Typ: number
  • Obligatoriskt: Nej
  • Standard: true
  • Exempel: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --numShards=10

Detta kommer att vara antalet parallella instanser som kommer att användas för att köra stories. Detta kommer att begränsas av maxInstances i din wdio.conf-fil.

[!IMPORTANT] När du kör i headless-läge, öka inte antalet till mer än 20 för att förhindra instabilitet på grund av resursbegränsningar

--skipStories

  • Typ: string|regex
  • Obligatoriskt: Nej
  • Standard: null
  • Exempel: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --skipStories="/.*button.*/gm"

Detta kan vara:

  • en sträng (example-button--secondary,example-button--small)
  • eller ett reguljärt uttryck ("/.*button.*/gm")

för att hoppa över vissa stories. Använd id för storyn som kan hittas i URL:en för storyn. Till exempel är id i denna URL http://localhost:6006/?path=/story/example-page--logged-out example-page--logged-out

--url

  • Typ: string
  • Obligatoriskt: Nej
  • Standard: http://127.0.0.1:6006
  • Exempel: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --url="https://example.com"

URL:en där din Storybook-instans är värd.

--version

  • Typ: number
  • Obligatoriskt: Nej
  • Standard: 7
  • Exempel: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --version=6

Detta är versionen av Storybook, det är standard 7. Detta behövs för att veta om V6 clipSelector behöver användas.

Storybook Interaction Testing

Storybook Interaction Testing låter dig interagera med din komponent genom att skapa anpassade skript med WDIO-kommandon för att sätta en komponent i ett visst tillstånd. Till exempel, se kodavsnittet nedan:

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`
);
});
});

Två tester på två olika komponenter utförs. Varje test ställer först in ett tillstånd och tar sedan en skärmbild. Du kommer också att märka att ett nytt anpassat kommando har introducerats, som kan hittas här.

Ovanstående specifikationsfil kan sparas i en mapp och läggas till på kommandoraden med följande kommando:

pnpm run test.local.desktop.storybook.localhost -- --spec='tests/specs/storybook-interaction/*.ts'

Storybook-runnern kommer först automatiskt att skanna din Storybook-instans och sedan lägga till dina tester till de stories som behöver jämföras. Om du inte vill att komponenterna som du använder för interaktionstestning ska jämföras två gånger, kan du lägga till ett filter för att ta bort "standard"-stories från skanningen genom att ange filtret --skipStories. Det skulle se ut så här:

pnpm run test.local.desktop.storybook.localhost -- --skipStories="/example-page.*/gm" --spec='tests/specs/storybook-interaction/*.ts'

Nytt anpassat kommando

Ett nytt anpassat kommando kallat browser.waitForStorybookComponentToBeLoaded({ id: 'componentId' }) kommer att läggas till i browser/driver-objektet som automatiskt laddar komponenten och väntar på att den ska vara klar, så du behöver inte använda metoden browser.url('url.com'). Det kan användas så här

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`
);
});
});

Alternativen är:

additionalSearchParams

  • Typ: URLSearchParams
  • Obligatoriskt: Nej
  • Standard: new URLSearchParams()
  • Exempel:
await browser.waitForStorybookComponentToBeLoaded({
additionalSearchParams: new URLSearchParams({ foo: "bar", abc: "def" }),
id: "componentId",
});

Detta kommer att lägga till ytterligare sökparametrar till Storybook-URL:en, i exemplet ovan kommer URL:en att vara http://storybook.url/iframe.html?id=story-id&foo=bar&abc=def. Se URLSearchParams-dokumentationen för mer information.

clipSelector

  • Typ: string
  • Obligatoriskt: Nej
  • Standard: #storybook-root > :first-child för Storybook V7 och #root > :first-child:not(script):not(style) för Storybook V6
  • Exempel:
await browser.waitForStorybookComponentToBeLoaded({
clipSelector: "#your-selector",
id: "componentId",
});

Detta är den väljare som kommer att användas:

  • för att välja elementet som skärmbilden ska tas av
  • för elementet som ska vänta på att bli synligt innan en skärmbild tas

id

  • Typ: string
  • Obligatoriskt: ja
  • Exempel:
await browser.waitForStorybookComponentToBeLoaded({ '#your-selector', id: 'componentId' })

Använd id för storyn som kan hittas i URL:en för storyn. Till exempel är id i denna URL http://localhost:6006/?path=/story/example-page--logged-out example-page--logged-out

timeout

  • Typ: number
  • Obligatoriskt: Nej
  • Standard: 1100 millisekunder
  • Exempel:
await browser.waitForStorybookComponentToBeLoaded({
id: "componentId",
timeout: 20000,
});

Den maximala tiden vi vill vänta på att en komponent ska bli synlig efter att ha laddats på sidan

url

  • Typ: string
  • Obligatoriskt: Nej
  • Standard: http://127.0.0.1:6006
  • Exempel:
await browser.waitForStorybookComponentToBeLoaded({
id: "componentId",
url: "https://your.url",
});

URL:en där din Storybook-instans är värd.

Bidra

Uppdatera paketen

Du kan uppdatera paketen med ett enkelt CLI-verktyg. Se till att du har installerat alla beroenden, du kan sedan köra

pnpm update.packages

Detta kommer att starta en CLI som kommer att fråga dig följande frågor

==========================
🤖 Package update Wizard 🧙
==========================

? Which version target would you like to update to? (Minor|Latest)
? Do you want to update the package.json files? (Y/n)
? Do you want to remove all "node_modules" and reinstall dependencies? (Y/n)
? Would you like reinstall the dependencies? (Y/n)

Detta kommer att resultera i följande loggar

Öppna för att se ett exempel på loggarna
==========================
🤖 Package update Wizard 🧙
==========================

? Which version target would you like to update to? Minor
? Do you want to update the package.json files? yes
Updating root 'package.json' for minor updates...
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/package.json
[====================] 38/38 100%

@typescript-eslint/eslint-plugin ^8.7.0 → ^8.8.0
@typescript-eslint/parser ^8.7.0 → ^8.8.0
@typescript-eslint/utils ^8.7.0 → ^8.8.0
@vitest/coverage-v8 ^2.1.1 → ^2.1.2
vitest ^2.1.1 → ^2.1.2

Run pnpm install to install new versions.
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing/packages/ocr-service...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/packages/ocr-service/package.json
[====================] 11/11 100%

All dependencies match the minor package versions :)
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing/packages/visual-reporter...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/packages/visual-reporter/package.json
[====================] 11/11 100%

eslint-config-next 14.2.13 → 14.2.14
next 14.2.13 → 14.2.14

Run pnpm install to install new versions.
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing/packages/visual-service...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/packages/visual-service/package.json
[====================] 5/5 100%

All dependencies match the minor package versions :)
Updating packages for minor updates in /Users/wswebcreation/Git/wdio/visual-testing/packages/webdriver-image-comparison...
Using pnpm
Upgrading /Users/wswebcreation/Git/wdio/visual-testing/packages/webdriver-image-comparison/package.json
[====================] 8/8 100%

All dependencies match the minor package versions :)
? Do you want to remove all "node_modules" and reinstall dependencies? yes
Removing root dependencies in /Users/wswebcreation/Git/wdio/visual-testing...
Removing dependencies in ocr-service...
Removing dependencies in visual-reporter...
Removing dependencies in visual-service...
Removing dependencies in webdriver-image-comparison...
? Would you like reinstall the dependencies? yes
Installing dependencies in /Users/wswebcreation/Git/wdio/visual-testing...

> @wdio/visual-testing-monorepo@ pnpm.install.workaround /Users/wswebcreation/Git/wdio/visual-testing
> pnpm install --shamefully-hoist

Scope: all 5 workspace projects
Lockfile is up to date, resolution step is skipped
Packages: +1274
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 1274, reused 1265, downloaded 0, added 1274, done

dependencies:

- @wdio/ocr-service 2.0.0 <- packages/ocr-service
- @wdio/visual-service 6.0.0 <- packages/visual-service

devDependencies:

- @changesets/cli 2.27.8
- @inquirer/prompts 5.5.0
- @tsconfig/node20 20.1.4
- @types/eslint 9.6.1
- @types/jsdom 21.1.7
- @types/node 20.16.4
- @types/react 18.3.5
- @types/react-dom 18.3.0
- @types/xml2js 0.4.14
- @typescript-eslint/eslint-plugin 8.8.0
- @typescript-eslint/parser 8.8.0
- @typescript-eslint/utils 8.8.0
- @vitest/coverage-v8 2.1.2
- @wdio/appium-service 9.1.2
- @wdio/cli 9.1.2
- @wdio/globals 9.1.2
- @wdio/local-runner 9.1.2
- @wdio/mocha-framework 9.1.2
- @wdio/sauce-service 9.1.2
- @wdio/shared-store-service 9.1.2
- @wdio/spec-reporter 9.1.2
- @wdio/types 9.1.2
- eslint 9.11.1
- eslint-plugin-import 2.30.0
- eslint-plugin-unicorn 55.0.0
- eslint-plugin-wdio 9.0.8
- husky 9.1.6
- jsdom 25.0.1
- pnpm-run-all2 6.2.3
- release-it 17.6.0
- rimraf 6.0.1
- saucelabs 8.0.0
- ts-node 10.9.2
- typescript 5.6.2
- vitest 2.1.2
- webdriverio 9.1.2

. prepare$ husky
└─ Done in 204ms
Done in 9.5s
All packages updated!

Frågor

Gå med i vår Discord-server om du har några frågor eller problem med att bidra till detta projekt. Fånga oss bidragsgivare i kanalen 🙏-contributing.

Problem

Om du har frågor, buggar eller funktionsförfrågningar, vänligen skapa ett ärende. Innan du skickar in ett ärende, sök i ärendearkivet för att hjälpa till att minska dubbletter och läs FAQ.

Om du inte kan hitta det där kan du skicka in ett ärende där du kan skicka:

  • 🐛Buggrapport: Skapa en rapport för att hjälpa oss förbättra
  • 📖Dokumentation: Föreslå förbättringar eller rapportera saknad/oklar dokumentation.
  • 💡Funktionsförfrågan: Föreslå en idé för denna modul.
  • 💬Fråga: Ställ frågor.

Utvecklingsarbetsflöde

För att skapa en PR för detta projekt och börja bidra, följ denna steg-för-steg guide:

  • Forka projektet.

  • Klona projektet någonstans på din dator

    $ git clone https://github.com/webdriverio/visual-testing.git
  • Gå till katalogen och ställ in projektet

    $ cd visual-testing
    $ corepack enable
    $ pnpm pnpm.install.workaround
  • Kör watch-läget som automatiskt transpilerar koden

    $ pnpm watch

    för att bygga projektet, kör:

    $ pnpm build
  • Se till att dina ändringar inte bryter några tester, kör:

    $ pnpm test

Detta projekt använder changesets för att automatiskt skapa ändringsloggar och releaser.

Testning

Flera tester måste utföras för att kunna testa modulen. När du lägger till en PR måste alla tester åtminstone klara de lokala testerna. Varje PR testas automatiskt mot Sauce Labs, se vår GitHub Actions-pipeline. Innan en PR godkänns kommer kärnbidragsgivarna att testa PR mot emulatorer/simulatorer/verkliga enheter.

Lokal testning

Först måste en lokal baseline skapas. Detta kan göras med:

// Med webdriver-protokollet
$ pnpm run test.local.init

Detta kommando kommer att skapa en mapp kallad localBaseline som kommer att innehålla alla baseline-bilder.

Kör sedan:

// Med webdriver-protokollet
pnpm run test.local.desktop

Detta kommer att köra alla tester på en lokal maskin på Chrome.

Lokal Storybook Runner-testning (Beta)

Först måste en lokal baseline skapas. Detta kan göras med:

pnpm run test.local.desktop.storybook

Detta kommer att köra Storybook-tester med Chrome i headless-läge mot en Demo Storybook-repo på https://govuk-react.github.io/govuk-react/.

För att köra testerna med fler webbläsare kan du köra

pnpm run test.local.desktop.storybook -- --browsers=chrome,firefox,edge,safari

[!NOTE] Se till att du har de webbläsare du vill köra på installerade på din lokala maskin

CI-testning med Sauce Labs (behövs inte för en PR)

Kommandot nedan används för att testa bygget på GitHub Actions, det kan bara användas där och inte för lokal utveckling.

$ pnpm run test.saucelabs

Det kommer att testa mot en mängd konfigurationer som kan hittas här. Alla PR kontrolleras automatiskt mot Sauce Labs.

Releaser

För att släppa en version av något av paketen som anges ovan, gör följande:

  • utlös release-pipelinen
  • en release-PR genereras, låt denna granskas och godkännas av en annan WebdriverIO-medlem
  • slå ihop PR:en
  • utlös release-pipelinen igen
  • en ny version borde släppas 🎉

Erkännanden

@wdio/visual-testing använder en öppen källkodslicens från LambdaTest och Sauce Labs.

Welcome! How can I help?

WebdriverIO AI Copilot