Aller au contenu principal

Service de Comparaison d'Images (Tests de Régression Visuelle)

@wdio/visual-service est un package tiers, pour plus d'informations, veuillez consulter GitHub | npm

Pour la documentation sur les tests visuels avec WebdriverIO, veuillez consulter la documentation. Ce projet contient tous les modules pertinents pour exécuter des tests visuels avec WebdriverIO. Dans le répertoire ./packages, vous trouverez :

  • @wdio/visual-testing : le service WebdriverIO pour l'intĂ©gration des tests visuels
  • webdriver-image-comparison : Un module de comparaison d'images qui peut ĂȘtre utilisĂ© pour diffĂ©rents frameworks de test d'automatisation NodeJS supportant le protocole WebDriver

ExĂ©cuteur Storybook (BETA)​

Cliquez pour découvrir plus de documentation sur l'Exécuteur Storybook BETA

L'Exécuteur Storybook est encore en BETA, la documentation sera ultérieurement déplacée vers les pages de documentation WebdriverIO.

Ce module prend dĂ©sormais en charge Storybook avec un nouvel ExĂ©cuteur Visuel. Cet exĂ©cuteur analyse automatiquement une instance locale/distante de Storybook et crĂ©era des captures d'Ă©cran d'Ă©lĂ©ments pour chaque composant. Cela peut ĂȘtre fait en ajoutant

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

à vos services et en exécutant npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook via la ligne de commande. Il utilisera Chrome en mode headless comme navigateur par défaut.

[!NOTE]

  • La plupart des options de Test Visuel fonctionneront Ă©galement pour l'ExĂ©cuteur Storybook, voir la documentation WebdriverIO.
  • L'ExĂ©cuteur Storybook Ă©crasera toutes vos capacitĂ©s et ne peut s'exĂ©cuter que sur les navigateurs qu'il prend en charge, voir --browsers.
  • L'ExĂ©cuteur Storybook ne prend pas en charge une configuration existante qui utilise des capacitĂ©s Multiremote et gĂ©nĂ©rera une erreur.
  • L'ExĂ©cuteur Storybook ne prend en charge que le Web Desktop, pas le Web Mobile.

Options de service de l'ExĂ©cuteur Storybook​

Les options de service peuvent ĂȘtre fournies comme ceci

export const config: WebdriverIO.Config  = {
// ...
services: [
[
'visual',
{
// Quelques options par défaut
baselineFolder: join(process.cwd(), './__snapshots__/'),
debug: true,
// Les options storybook, voir les options cli pour la description
storybook: {
additionalSearchParams: new URLSearchParams({foo: 'bar', abc: 'def'}),
clip: false,
clipSelector: ''#some-id,
numShards: 4,
// `skipStories` peut ĂȘtre une chaĂźne ('example-button--secondary'),
// un tableau (['example-button--secondary', 'example-button--small'])
// ou une expression rĂ©guliĂšre qui doit ĂȘtre fournie sous forme de chaĂźne ("/.*button.*/gm")
skipStories: ['example-button--secondary', 'example-button--small'],
url: 'https://www.bbc.co.uk/iplayer/storybook/',
version: 6,
// Optionnel - Permet de remplacer le chemin des références. Par défaut, il regroupera les références par catégorie et composant (par exemple forms/input/baseline.png)
getStoriesBaselinePath: (category, component) => `path__${category}__${component}`,
},
},
],
],
// ....
}

Options CLI de l'ExĂ©cuteur Storybook​

--additionalSearchParams​

  • Type: string
  • Obligatoire: Non
  • DĂ©faut: ''
  • Exemple: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --additionalSearchParams="foo=bar&abc=def"

Ajoutera des paramĂštres de recherche supplĂ©mentaires Ă  l'URL Storybook. Voir la documentation URLSearchParams pour plus d'informations. La chaĂźne doit ĂȘtre une chaĂźne URLSearchParams valide.

[!NOTE] Les guillemets doubles sont nĂ©cessaires pour empĂȘcher le & d'ĂȘtre interprĂ©tĂ© comme un sĂ©parateur de commande. Par exemple avec --additionalSearchParams="foo=bar&abc=def", cela gĂ©nĂ©rera l'URL Storybook suivante pour le test des histoires : http://storybook.url/iframe.html?id=story-id&foo=bar&abc=def.

--browsers​

  • Type: string
  • Obligatoire: Non
  • DĂ©faut: chrome, vous pouvez sĂ©lectionner parmi chrome|firefox|edge|safari
  • Exemple: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --browsers=chrome,firefox,edge,safari
  • REMARQUE: Disponible uniquement via la CLI

Il utilisera les navigateurs fournis pour prendre des captures d'écran des composants

[!NOTE] Assurez-vous d'avoir installé les navigateurs sur lesquels vous souhaitez exécuter les tests sur votre machine locale

--clip​

  • Type: boolean
  • Obligatoire: Non
  • DĂ©faut: true
  • Exemple: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --clip=false

Lorsqu'il est désactivé, il créera une capture d'écran de la vue complÚte. Lorsqu'il est activé, il créera des captures d'écran d'éléments basées sur le --clipSelector qui réduira la quantité d'espace blanc autour de la capture d'écran du composant et réduira la taille de la capture d'écran.

--clipSelector​

  • Type: string
  • Obligatoire: Non
  • DĂ©faut: #storybook-root > :first-child pour Storybook V7 et #root > :first-child:not(script):not(style) pour Storybook V6, voir aussi --version
  • Exemple: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --clipSelector="#some-id"

C'est le sélecteur qui sera utilisé :

  • pour sĂ©lectionner l'Ă©lĂ©ment dont on prendra la capture d'Ă©cran
  • pour l'Ă©lĂ©ment Ă  attendre qu'il soit visible avant qu'une capture d'Ă©cran ne soit prise

--devices​

  • Type: string
  • Obligatoire: Non
  • DĂ©faut: Vous pouvez sĂ©lectionner parmi deviceDescriptors.ts
  • Exemple: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --devices="iPhone 14 Pro Max","Pixel 3 XL"
  • REMARQUE: Disponible uniquement via la CLI

Il utilisera les appareils fournis qui correspondent à deviceDescriptors.ts pour prendre des captures d'écran des composants

[!NOTE]

  • Si vous manquez une configuration d'appareil, n'hĂ©sitez pas Ă  soumettre une demande de fonctionnalitĂ©
  • Cela ne fonctionnera qu'avec Chrome :
    • si vous fournissez --devices, toutes les instances Chrome s'exĂ©cuteront en mode Émulation Mobile
    • si vous fournissez Ă©galement d'autres navigateurs que Chrome, comme --devices --browsers=firefox,safari,edge, cela ajoutera automatiquement Chrome en mode d'Ă©mulation mobile
  • L'ExĂ©cuteur Storybook crĂ©era par dĂ©faut des instantanĂ©s d'Ă©lĂ©ments, si vous souhaitez voir la capture d'Ă©cran complĂšte de l'Ă©mulation mobile, fournissez --clip=false via la ligne de commande
  • Le nom de fichier ressemblera par exemple Ă  __snapshots__/example/button/desktop_chrome/example-button--large-local-chrome-iPhone-14-Pro-Max-430x932-dpr-3.png
  • SRC: Tester un site Web mobile sur un ordinateur de bureau Ă  l'aide de l'Ă©mulation mobile peut ĂȘtre utile, mais les testeurs doivent ĂȘtre conscients qu'il existe de nombreuses diffĂ©rences subtiles telles que :
    • un GPU complĂštement diffĂ©rent, ce qui peut entraĂźner d'importants changements de performance ;
    • l'interface utilisateur mobile n'est pas Ă©mulĂ©e (en particulier, la barre d'URL masquĂ©e affecte la hauteur de la page) ;
    • la boĂźte contextuelle de dĂ©sambiguĂŻsation (oĂč vous sĂ©lectionnez l'une des cibles tactiles) n'est pas prise en charge ;
    • de nombreuses API matĂ©rielles (par exemple, l'Ă©vĂ©nement orientationchange) ne sont pas disponibles.

--headless​

  • Type: boolean
  • Obligatoire: Non
  • DĂ©faut: true
  • Exemple: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --headless=false
  • REMARQUE: Disponible uniquement via la CLI

Cela exĂ©cutera les tests par dĂ©faut en mode headless (lorsque le navigateur le prend en charge) ou peut ĂȘtre dĂ©sactivĂ©

--numShards​

  • Type: number
  • Obligatoire: Non
  • DĂ©faut: true
  • Exemple: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --numShards=10

Il s'agit du nombre d'instances parallÚles qui seront utilisées pour exécuter les histoires. Cela sera limité par le maxInstances dans votre fichier wdio.conf.

[!IMPORTANT] Lors de l'exécution en mode headless, n'augmentez pas le nombre à plus de 20 pour éviter l'instabilité due aux restrictions de ressources

--skipStories​

  • Type: string|regex
  • Obligatoire: Non
  • DĂ©faut: null
  • Exemple: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --skipStories="/.*button.*/gm"

Cela peut ĂȘtre :

  • une chaĂźne (example-button--secondary,example-button--small)
  • ou une regex ("/.*button.*/gm")

pour ignorer certaines histoires. Utilisez l'id de l'histoire qui peut ĂȘtre trouvĂ© dans l'URL de l'histoire. Par exemple, l'id dans cette URL http://localhost:6006/?path=/story/example-page--logged-out est example-page--logged-out

--url​

  • Type: string
  • Obligatoire: Non
  • DĂ©faut: http://127.0.0.1:6006
  • Exemple: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --url="https://example.com"

L'URL oĂč votre instance Storybook est hĂ©bergĂ©e.

--version​

  • Type: number
  • Obligatoire: Non
  • DĂ©faut: 7
  • Exemple: npx wdio tests/configs/wdio.local.desktop.storybook.conf.ts --storybook --version=6

Il s'agit de la version de Storybook, par dĂ©faut 7. Cela est nĂ©cessaire pour savoir si le clipSelector V6 doit ĂȘtre utilisĂ©.

Tests d'interaction Storybook​

Les tests d'interaction Storybook vous permettent d'interagir avec votre composant en créant des scripts personnalisés avec des commandes WDIO pour mettre un composant dans un certain état. Par exemple, voir l'extrait de code ci-dessous :

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

Deux tests sur deux composants différents sont exécutés. Chaque test définit d'abord un état puis prend une capture d'écran. Vous remarquerez également qu'une nouvelle commande personnalisée a été introduite, qui se trouve ici.

Le fichier de spĂ©cification ci-dessus peut ĂȘtre enregistrĂ© dans un dossier et ajoutĂ© Ă  la ligne de commande avec la commande suivante :

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

L'exĂ©cuteur Storybook analysera d'abord automatiquement votre instance Storybook, puis ajoutera vos tests aux histoires qui doivent ĂȘtre comparĂ©es. Si vous ne souhaitez pas que les composants que vous utilisez pour les tests d'interaction soient comparĂ©s deux fois, vous pouvez ajouter un filtre pour supprimer les histoires "par dĂ©faut" de l'analyse en fournissant le filtre --skipStories. Cela ressemblerait Ă  ceci :

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

Nouvelle commande personnalisĂ©e​

Une nouvelle commande personnalisĂ©e appelĂ©e browser.waitForStorybookComponentToBeLoaded({ id: 'componentId' }) sera ajoutĂ©e Ă  l'objet browser/driver qui chargera automatiquement le composant et attendra qu'il soit prĂȘt, vous n'aurez donc pas besoin d'utiliser la mĂ©thode browser.url('url.com'). Elle peut ĂȘtre utilisĂ©e comme ceci

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

Les options sont :

additionalSearchParams​

  • Type: URLSearchParams
  • Obligatoire: Non
  • DĂ©faut: new URLSearchParams()
  • Exemple:
await browser.waitForStorybookComponentToBeLoaded({
additionalSearchParams: new URLSearchParams({ foo: "bar", abc: "def" }),
id: "componentId",
});

Cela ajoutera des paramÚtres de recherche supplémentaires à l'URL Storybook, dans l'exemple ci-dessus, l'URL sera http://storybook.url/iframe.html?id=story-id&foo=bar&abc=def. Voir la documentation URLSearchParams pour plus d'informations.

clipSelector​

  • Type: string
  • Obligatoire: Non
  • DĂ©faut: #storybook-root > :first-child pour Storybook V7 et #root > :first-child:not(script):not(style) pour Storybook V6
  • Exemple:
await browser.waitForStorybookComponentToBeLoaded({
clipSelector: "#your-selector",
id: "componentId",
});

C'est le sélecteur qui sera utilisé :

  • pour sĂ©lectionner l'Ă©lĂ©ment dont on prendra la capture d'Ă©cran
  • pour l'Ă©lĂ©ment Ă  attendre qu'il soit visible avant qu'une capture d'Ă©cran ne soit prise

id​

  • Type: string
  • Obligatoire: oui
  • Exemple:
await browser.waitForStorybookComponentToBeLoaded({ '#your-selector', id: 'componentId' })

Utilisez l'id de l'histoire qui peut ĂȘtre trouvĂ© dans l'URL de l'histoire. Par exemple, l'id dans cette URL http://localhost:6006/?path=/story/example-page--logged-out est example-page--logged-out

timeout​

  • Type: number
  • Obligatoire: Non
  • DĂ©faut: 1100 millisecondes
  • Exemple:
await browser.waitForStorybookComponentToBeLoaded({
id: "componentId",
timeout: 20000,
});

Le délai maximum d'attente pour qu'un composant soit visible aprÚs le chargement sur la page

url​

  • Type: string
  • Obligatoire: Non
  • DĂ©faut: http://127.0.0.1:6006
  • Exemple:
await browser.waitForStorybookComponentToBeLoaded({
id: "componentId",
url: "https://your.url",
});

L'URL oĂč votre instance Storybook est hĂ©bergĂ©e.

Contribuer​

Mise à jour des packages​

Vous pouvez mettre à jour les packages avec un simple outil CLI. Assurez-vous d'avoir installé toutes les dépendances, vous pouvez ensuite exécuter

pnpm update.packages

Cela déclenchera une CLI qui vous posera les questions suivantes

==========================
đŸ€– Assistant de mise Ă  jour de packages 🧙
==========================

? Quelle version cible souhaitez-vous mettre Ă  jour ? (Minor|Latest)
? Voulez-vous mettre Ă  jour les fichiers package.json ? (O/n)
? Voulez-vous supprimer tous les "node_modules" et réinstaller les dépendances ? (O/n)
? Souhaitez-vous réinstaller les dépendances ? (O/n)

Questions​

Veuillez rejoindre notre serveur Discord si vous avez des questions ou des problùmes pour contribuer à ce projet. Retrouvez-nous contributeurs dans le canal 🙏-contributing.

Problùmes​

Si vous avez des questions, des bugs ou des demandes de fonctionnalités, veuillez créer un ticket. Avant de soumettre un ticket, veuillez rechercher dans les archives de tickets pour réduire les doublons et lire la FAQ.

Si vous ne trouvez pas d'information, vous pouvez soumettre un ticket oĂč vous pouvez :

  • 🐛Rapport de bug: CrĂ©er un rapport pour nous aider Ă  amĂ©liorer
  • 📖Documentation: SuggĂ©rer des amĂ©liorations ou signaler une documentation manquante/peu claire.
  • 💡Demande de fonctionnalitĂ©: SuggĂ©rer une idĂ©e pour ce module.
  • 💬Question: Poser des questions.

Flux de dĂ©veloppement​

Pour créer une PR pour ce projet et commencer à contribuer, suivez ce guide étape par étape :

  • Forkez le projet.

  • Clonez le projet quelque part sur votre ordinateur

    $ git clone https://github.com/webdriverio/visual-testing.git
  • Allez dans le rĂ©pertoire et configurez le projet

    $ cd visual-testing
    $ corepack enable
    $ pnpm pnpm.install.workaround
  • ExĂ©cutez le mode watch qui transpirera automatiquement le code

    $ pnpm watch

    pour construire le projet, exécutez :

    $ pnpm build
  • Assurez-vous que vos modifications ne cassent aucun test, exĂ©cutez :

    $ pnpm test

Ce projet utilise changesets pour créer automatiquement des changelogs et des versions.

Tests​

Plusieurs tests doivent ĂȘtre exĂ©cutĂ©s pour pouvoir tester le module. Lors de l'ajout d'une PR, tous les tests doivent au moins passer les tests locaux. Chaque PR est automatiquement testĂ©e sur Sauce Labs, voir notre pipeline GitHub Actions. Avant d'approuver une PR, les contributeurs principaux testeront la PR sur des Ă©mulateurs/simulateurs / appareils rĂ©els.

Tests locaux​

Tout d'abord, une rĂ©fĂ©rence locale doit ĂȘtre créée. Cela peut ĂȘtre fait avec :

// Avec le protocole webdriver
$ pnpm run test.local.init

Cette commande créera un dossier appelé localBaseline qui contiendra toutes les images de référence.

Ensuite, exécutez :

// Avec le protocole webdriver
pnpm run test.local.desktop

Cela exécutera tous les tests sur une machine locale sur Chrome.

Tests locaux de l'ExĂ©cuteur Storybook (Beta)​

Tout d'abord, une rĂ©fĂ©rence locale doit ĂȘtre créée. Cela peut ĂȘtre fait avec :

pnpm run test.local.desktop.storybook

Cela exécutera les tests Storybook avec Chrome en mode headless sur un dépÎt de démo Storybook situé à https://govuk-react.github.io/govuk-react/.

Pour exécuter les tests avec plus de navigateurs, vous pouvez exécuter

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

[!NOTE] Assurez-vous d'avoir installé les navigateurs sur lesquels vous souhaitez exécuter les tests sur votre machine locale

Tests CI avec Sauce Labs (non nĂ©cessaires pour une PR)​

La commande ci-dessous est utilisĂ©e pour tester la build sur GitHub Actions, elle ne peut ĂȘtre utilisĂ©e que lĂ -bas et non pour le dĂ©veloppement local.

$ pnpm run test.saucelabs

Elle testera de nombreuses configurations qui peuvent ĂȘtre trouvĂ©es ici. Toutes les PR sont automatiquement vĂ©rifiĂ©es sur Sauce Labs.

Publication​

Pour publier une version de l'un des packages listés ci-dessus, procédez comme suit :

  • dĂ©clenchez le pipeline de publication
  • une PR de publication est gĂ©nĂ©rĂ©e, faites-la examiner et approuver par un autre membre de WebdriverIO
  • fusionnez la PR
  • dĂ©clenchez Ă  nouveau le pipeline de publication
  • une nouvelle version devrait ĂȘtre publiĂ©e 🎉

CrĂ©dits​

@wdio/visual-testing utilise une licence open-source de LambdaTest et Sauce Labs.

Welcome! How can I help?

WebdriverIO AI Copilot