Migrer une suite Playwright d'Applitools Eyes vers Delta-QA
Une suite Playwright écrite pour Applitools Eyes tourne sur Delta-QA après deux changements : son import et ses variables d'environnement. Ses eyes.open, check, close, BatchInfo, addBrowser et ses régions restent.
Installer, et changer l'import
L'API Eyes de @delta-qa/vision reprend les noms et le sens d'Applitools Eyes pour Playwright. Elle demande Node.js 22 ou plus récent et @playwright/test 1.62 ou plus récent.
Le SDK Vision est d'abord disponible en avant-première : contactez-nous pour l'utiliser sur votre suite. Demander l'accès à Vision
| Applitools | Delta-QA |
|---|---|
import { test } from "@applitools/eyes-playwright/fixture"; | import { test } from "@delta-qa/vision/eyes/fixture"; |
import type { EyesFixture } from "@applitools/eyes-playwright/fixture"; | import type { EyesFixture } from "@delta-qa/vision/eyes/fixture"; |
import { Eyes, Target, … } from "@applitools/eyes-playwright"; | import { Eyes, Target, … } from "@delta-qa/vision/eyes"; |
eyesConfig dans playwright.config reste tel quel. Avec la fixture, un test ne change que son import :
// import { test } from "@applitools/eyes-playwright/fixture";
import { test } from "@delta-qa/vision/eyes/fixture";
test("checkout", async ({ page, eyes }) => {
await page.goto("https://shop.example/cart");
await eyes.check("Cart", { fully: true });
}); // opened before the test, closed by the fixturePoser les variables d'environnement
| Variable | Lue pour |
|---|---|
DELTAQA_API_KEY | La clé d'API de votre espace Delta-QA (dqa_…), au rôle « Peut modifier », créée dans Paramètres → Espace → Clés d'API. Rangez-la dans un secret de votre CI. |
APPLITOOLS_API_KEY | Lue quand DELTAQA_API_KEY n'est pas posée : gardez la variable, donnez-lui une clé Delta-QA. |
DELTAQA_SERVER_URL | Votre serveur Delta-QA, pour une installation On-Premise ; le cloud de Delta-QA sans elle. APPLITOOLS_SERVER_URL n'est jamais lue. |
APPLITOOLS_BATCH_ID | La version testée — le commit. L'id du lot donné dans le code passe avant. |
APPLITOOLS_BRANCH | La branche. setBranchName dans le code passe avant. |
APPLITOOLS_PARENT_BRANCHAPPLITOOLS_BASELINE_BRANCH | La branche de base, dont la référence sert tant que la branche n'en a pas. APPLITOOLS_BASELINE_BRANCH passe avant APPLITOOLS_PARENT_BRANCH ; le code passe avant les deux. |
Les formes _NAME des variables de branche (APPLITOOLS_BRANCH_NAME, APPLITOOLS_PARENT_BRANCH_NAME, APPLITOOLS_BASELINE_BRANCH_NAME) sont lues aussi. Une variable vide compte comme une variable absente. Sans clé, l'ouverture d'un test échoue et nomme la variable à poser.
Ces variables d'Applitools ne sont pas lues, et n'avertissent pas : APPLITOOLS_SERVER_URL, APPLITOOLS_BATCH_NAME, APPLITOOLS_DONT_CLOSE_BATCHES, APPLITOOLS_SHOW_LOGS.
Configurer votre CI
Le SDK ne lit ni git ni les variables de votre CI : les lignes ci-dessous en tirent la branche, la branche de base et le commit, dans les trois variables d'Applitools.
GitHub Actions
Sur un push, github.head_ref est vide : la branche est alors github.ref_name. Sur une pull request, github.sha est le commit de fusion que fabrique GitHub, pas le commit poussé : le commit de tête passe avant.
env:
APPLITOOLS_BRANCH: ${{ github.head_ref || github.ref_name }}
APPLITOOLS_PARENT_BRANCH: ${{ github.base_ref || github.event.repository.default_branch }}
APPLITOOLS_BATCH_ID: ${{ github.event.pull_request.head.sha || github.sha }}GitLab CI
Dans un pipeline de merge request, CI_MERGE_REQUEST_TARGET_BRANCH_NAME est la branche cible ; dans un pipeline de branche, elle est vide.
script:
- export APPLITOOLS_BRANCH="${CI_MERGE_REQUEST_SOURCE_BRANCH_NAME:-$CI_COMMIT_REF_NAME}"
- export APPLITOOLS_PARENT_BRANCH="${CI_MERGE_REQUEST_TARGET_BRANCH_NAME:-$CI_DEFAULT_BRANCH}"
- export APPLITOOLS_BATCH_ID="$CI_COMMIT_SHA"
- npx playwright testBitbucket Pipelines
BITBUCKET_PR_DESTINATION_BRANCH n'est posée que dans un pipeline de pull request.
script:
- export APPLITOOLS_BRANCH="$BITBUCKET_BRANCH"
- export APPLITOOLS_PARENT_BRANCH="$BITBUCKET_PR_DESTINATION_BRANCH"
- export APPLITOOLS_BATCH_ID="$BITBUCKET_COMMIT"
- npx playwright testAzure Pipelines
Les variables System.PullRequest ne sont posées que sur un build de pull request, sous la forme refs/heads/… pour Azure Repos. Build.SourceBranchName ne garde que le dernier segment d'une branche (feature/cart donne cart) : la branche se lit donc dans la référence complète.
- script: |
branch="${SYSTEM_PULLREQUEST_SOURCEBRANCH:-$BUILD_SOURCEBRANCH}"
base="${SYSTEM_PULLREQUEST_TARGETBRANCH:-}"
export APPLITOOLS_BRANCH="${branch#refs/heads/}"
export APPLITOOLS_PARENT_BRANCH="${base#refs/heads/}"
export APPLITOOLS_BATCH_ID="${SYSTEM_PULLREQUEST_SOURCECOMMITID:-$BUILD_SOURCEVERSION}"
npx playwright testUne branche de base égale à la branche ne sert pas : sur la branche par défaut, ces lignes ne donnent aucune base.
Fermer au démontage, jamais dans le corps du test
Avec la fixture, eyes se ferme au démontage du test. Sans elle, appelez eyes.close() dans un afterEach, et runner.getAllTestResults() dans un afterAll.
Ne fermez jamais dans le corps du test : l'attente du verdict prend le temps du test — 30 secondes par défaut dans Playwright Test — et une étape qui échoue avant close() laisse le test ouvert. Le démontage a son propre délai.
import { test } from "@playwright/test";
import { Eyes, Target, VisualGridRunner } from "@delta-qa/vision/eyes";
const runner = new VisualGridRunner();
let eyes: Eyes;
test.beforeEach(async ({ page }) => {
eyes = new Eyes(runner);
await eyes.open(page, "Shop", test.info().title);
});
test("checkout", async ({ page }) => {
await page.goto("https://shop.example/cart");
await eyes.check("Cart", Target.window().fully());
});
test.afterEach(async () => {
await eyes.close(); // throws DiffsFoundError when a difference awaits a judgment
});
test.afterAll(async () => {
await runner.getAllTestResults();
});Chaque réglage d'Applitools, et ce qu'il devient
Tout réglage d'Applitools Eyes est accepté : la suite compile et tourne. Chacun est soit appliqué par Delta-QA, soit accepté sans effet, avec un avertissement. Quelques appels n'existent pas.
Appliqués
| Réglage | Dans Delta-QA |
|---|---|
appName | L'application du test ; avec le nom du test, ce qui le reconnaît. Dans eyesConfig, My App sans elle, comme avec la fixture d'Applitools. |
testName | Le nom du test, sa clé : un nom changé est un test nouveau. Dans eyesConfig, il peut aussi être une fonction du test ; sans lui, le chemin de titres du test sans son fichier (describe > test), comme avec la fixture d'Applitools. |
apiKeysetApiKey | La clé, à la place de DELTAQA_API_KEY ou APPLITOOLS_API_KEY — une clé Delta-QA. Elle n'apparaît jamais dans un message, un journal ni un lien. |
branchName | La branche du lancement ; sans elle, APPLITOOLS_BRANCH, puis APPLITOOLS_BRANCH_NAME. |
parentBranchNamebaselineBranchName | La branche de base, baselineBranchName avant parentBranchName ; sans eux, leurs variables, dans le même ordre. |
batch | Son id est la version testée — le commit ; sans lui, APPLITOOLS_BATCH_ID ; sans les deux, une version par processus (voir les écarts, plus bas). |
saveNewTests | Si les pages d'un test nouveau deviennent sa référence ; true sans lui. |
viewportSize | La taille donnée à la page à l'ouverture du test. |
browsersInfoaddBrowser(width, height) | Chaque taille est un environnement, pour Chrome ou sans nom de navigateur. Sa langue, son fuseau, son thème et la densité de l'écran se lisent dans le navigateur du test. |
fullyfully(true) | La page entière — ce que Delta-QA vérifie de toute façon. |
withNamename | Le nom du check. |
Target.window | La page du test. |
Target.regionCheckSettings.regioncheckRegioncheckRegionBycheckRegionByElementcheckElementcheckElementBy | La seule partie de la page comparée : le premier élément que désigne un locator, un sélecteur ou une poignée d'élément, comme chez Applitools ; la dernière région donnée l'emporte. Les régions à ignorer qu'elle contient sont écartées. |
ignoreRegionsignoreRegionignoreignores | Chaque élément que désigne une région — un locator, un sélecteur, { selector, type }, une poignée d'élément — est écarté de la comparaison : chaque élément d'un locator, comme chez Applitools. Aussi la forme { region } et la clé ignoreRegions de la forme objet. |
eyesConfig.failTestsOnDiff | Quand un verdict qui n'est pas PASSED fait échouer, dans la fixture : 'afterEach', le test, à son démontage ; 'afterAll', le worker, ses tests finis ; false, rien, le verdict attendu quand même. Sans lui, 'afterAll' si la variable CI est posée, 'afterEach' sinon, comme en décide le code de la fixture d'Applitools. |
eyesConfig.afterAll | Appelé une fois les tests d'un worker finis, avec le résultat de chacun. |
Les appels
| Appel | Dans Delta-QA |
|---|---|
open(page, appName, testName, viewportSize?) | Le test se reconnaît à son application et à son nom : un nom changé est un test nouveau. La taille de la fenêtre est donnée à la page. |
check(name?, Target.window())checkWindow(tag?) | Vérifie la page telle qu'elle est, dans chaque environnement. Un check sans nom s'apparie par l'adresse de sa page ; deux checks du même nom sont acceptés. Il répond un MatchResult sans verdict, comme le check d'Applitools : le verdict vient à la fermeture. |
close(throwErr = true) | Attend le verdict : DiffsFoundError sur une différence à juger, NewTestError sur un test nouveau à juger (saveNewTests(false)), TestFailedError sur une différence jugée bug ou sur un échec. Le message donne le lien de la version dans Delta-QA. |
closeAsync()runner.getAllTestResults(throwErr = true) | closeAsync() ferme sans attendre ; le runner attend chaque verdict, ferme un test resté ouvert et lève sur un test qui n'a pas réussi — l'erreur d'un closeAsync() lui est gardée. |
abort()abortIfNotClosed()abortAsync() | Ferme sans attendre le verdict, et ne fait rien échouer : les résultats sont marqués abandonnés, sans résultat ; null sans test ouvert. Delta-QA compare quand même les lancements, et la version montre leur résultat. |
Acceptés sans effet
Un réglage que Delta-QA n'applique pas ne fait pas échouer le test : le test tourne sans lui. Son premier emploi dans un processus émet un avertissement de Node.js qui le nomme, de code DELTAQA_IGNORED_SETTING ; les emplois suivants ne disent plus rien, et node --disable-warning=DELTAQA_IGNORED_SETTING les fait taire. Une valeur vide — setX(process.env.VARIABLE) hors de la CI — est un réglage non donné, et n'avertit pas. Les noms ci-dessous sont ceux que donne l'avertissement.
Réglages de comparaison
Niveaux de correspondance, régions par niveau, régions flottantes et décalages règlent la comparaison d'Applitools. Delta-QA compare la page comme le ferait l'œil humain, sans niveau de tolérance à régler : chaque différence se montre, et une personne la juge dans Delta-QA.
matchLeveldefaultMatchSettingsenablePatternsignoreDisplacementsignoreCaretuseDomsendDomCheckSettings.matchLevelCheckSettings.layoutCheckSettings.exactCheckSettings.strictCheckSettings.contentCheckSettings.ignoreColorsCheckSettings.dynamicCheckSettings.enablePatternsCheckSettings.ignoreDisplacementsCheckSettings.ignoreCaretCheckSettings.ignoreMismatchCheckSettings.useDomCheckSettings.sendDomCheckSettings.layoutRegionCheckSettings.layoutRegionsCheckSettings.strictRegionCheckSettings.strictRegionsCheckSettings.contentRegionCheckSettings.contentRegionsCheckSettings.floatingCheckSettings.floatingsCheckSettings.floatingRegionCheckSettings.floatingRegionsCheckSettings.dynamicRegionCheckSettings.dynamicRegions
Réglages de capture
Assemblage, défilement, recadrage, attentes et captures de débogage façonnent la capture d'Applitools. Delta-QA vérifie la page entière telle que le test l'a laissée à l'appel de check : pour attendre un contenu ou charger une section paresseuse, faites-le dans le test, avant le check.
hideCarethideScrollbarsforceFullPageScreenshotstitchModestitchOverlapscrollRootElementcutrotationwaitBeforeScreenshotswaitBeforeCapturematchTimeoutsaveDebugScreenshotsdebugScreenshotsPathdebugScreenshotsPrefixfully(false)CheckSettings.fully(false)CheckSettings.scrollRootElementCheckSettings.stitchModeCheckSettings.timeoutCheckSettings.waitBeforeCaptureCheckSettings.lazyLoadCheckSettings.useSystemScreenshot
Navigateurs, appareils et environnements
Delta-QA rend dans Chromium : la taille donnée à addBrowser compte, pas le navigateur nommé, et deux navigateurs d'une même taille font un seul environnement. Un appareil de la grille d'Applitools (DeviceName, IosDeviceName, émulation, multi-appareil) n'ajoute aucun environnement. La langue, le fuseau, le thème et la densité de l'écran se lisent dans le navigateur du test, et les libellés d'environnement ne changent rien. ClassicRunner et VisualGridRunner se comportent de même.
addBrowser(chrome-one-version-back)addBrowser(chrome-two-versions-back)addBrowser(firefox)addBrowser(firefox-one-version-back)addBrowser(firefox-two-versions-back)addBrowser(safari)addBrowser(safari-one-version-back)addBrowser(safari-two-versions-back)addBrowser(edgechromium)addBrowser(edgechromium-one-version-back)addBrowser(edgechromium-two-versions-back)addBrowser(edgelegacy)addBrowser(ie)addBrowser(ie10)addBrowser(device)addDeviceEmulationaddMultiDeviceTargetmobileOptionscaptureStatusBarlayoutBreakpointsCheckSettings.layoutBreakpointsenvironmentNameenvNamebaselineEnvNamedeviceInfohostApphostAppInfohostOShostOSInfoscaleRatioCheckSettings.densityMetricseyesConfig.type
La grille de rendu d'Applitools
Options de rendu, hooks, récupération, caches et parallélisme de la grille d'Applitools n'ont pas d'équivalent : la page est vérifiée telle que le test l'a laissée. Un script joué dans un hook se joue dans le test, avant le check.
visualGridOptionsCheckSettings.ufgOptionCheckSettings.ufgOptionsCheckSettings.visualGridOptionCheckSettings.visualGridOptionsCheckSettings.variationGroupIdCheckSettings.hookCheckSettings.beforeRenderScreenshotHookCheckSettings.webHookdisableBrowserFetchingCheckSettings.disableBrowserFetchingdisableNMLUrlCacheautProxybypassCSPskipRootHtmlResourceconcurrentSessionsRunnerOptions.testConcurrencyRunnerOptions.fetchConcurrencyRunnerOptions.removeDuplicateTests
Lots, références et résultats
Une version porte le commit : elle n'a ni nom, ni séquence, ni propriétés, ni notification, et rien à fermer. Une référence ne change que lorsqu'une personne juge une différence dans Delta-QA ; un test sans référence est « Nouveau ». Les checks s'apparient par leur nom, sinon par l'adresse de leur page. isDisabled : un test qu'on veut sans vérification n'ouvre pas d'Eyes.
BatchInfo.nameBatchInfo.sequenceNameBatchInfo.startedAtBatchInfo.notifyOnCompletionBatchInfo.propertiesBatchInfo.buildIddontCloseBatchesBatchClosepropertiesremoveSessionsaveDiffssaveFailedTestsignoreBaselinedisplayNamesessionTypeCheckSettings.pageIdisDisabled
Git
Le SDK ne lit pas git : donnez la branche de base par parentBranchName ou baselineBranchName, et le commit par l'id du lot ou APPLITOOLS_BATCH_ID.
compareWithParentBranchignoreGitMergeBasegitMergeBaseTimestamplatestCommitInfo
Serveur, connexion et journaux
Ils portent sur le serveur d'Applitools, sa connexion et ses journaux. Le serveur de Delta-QA se lit dans DELTAQA_SERVER_URL ; le SDK n'écrit aucun journal d'Applitools et n'émet aucun de ses évènements.
serverUrlproxyagentIdhttpVersionconnectionTimeoutEyes.onEyes.setLogHandlerEyes.addSessionEventHandlereyesConfig.logConfigRunnerOptions.maskLog
Fonctions hors de Delta-QA
Delta-QA ne valide pas l'accessibilité, ne lit pas Figma et n'a pas de vérification en langage naturel ; une page Playwright n'a pas de vue web.
accessibilityValidationCheckSettings.accessibilityRegionCheckSettings.accessibilityRegionsfigmaBaselinesfigmaOptionsnlpOptionsTarget.webviewCheckSettings.webview
Régions sans élément
Delta-QA repère les éléments qui diffèrent : une région donnée par coordonnées ({ x, y, width, height }, { left, top, width, height }) n'a pas d'équivalent : la page est comparée sans elle — entière, pour Target.region. La zone est l'élément, sans marge ; un regionId nomme une région dans le tableau de bord d'Applitools. Avec Target.frame ou Target.shadow, la page est comparée entière, et une région donnée ensuite par un sélecteur fait échouer le check par un TypeError : une zone est un élément de la page elle-même.
CheckSettings.ignoreRegions(coordinates)Target.region(coordinates)CodedRegion.paddingCodedRegion.regionIdTarget.frameTarget.shadowCheckSettings.frameCheckSettings.shadow
Une clé inconnue de la forme objet d'une configuration ou d'un check avertit sous son nom (CheckSettings.<clé> dans un check).
Absents : ce qui ne compile pas
Ce ne sont pas des réglages : ils rendent une donnée que Delta-QA n'a pas, ou vérifient une image plutôt qu'une page. Une suite qui s'en sert ne compile pas, plutôt que de recevoir une valeur inventée.
| Absent | Pourquoi |
|---|---|
eyes.locateeyes.extractTexteyes.extractTextRegions | Ils rendent des régions ou du texte qu'Applitools lit dans sa capture. |
eyes.checkImageTarget.imageTarget.bufferTarget.base64Target.pathTarget.url | Delta-QA vérifie des pages, pas des images. |
eyes.getLoggereyes.logger | Le journal d'Applitools. |
eyes.run | Dans la fixture d'Applitools, sa vérification en langage naturel. |
Ce qui diffère d'Applitools
Des choix voulus de Delta-QA, à connaître avant le premier lancement.
| Situation | Delta-QA |
|---|---|
| Apparier un check à sa référence | Par le nom du check quand chaque nom est unique dans le test ; sinon dans l'ordre, par le nom, à défaut par l'adresse de la page : un check ajouté ou retiré ne décale pas les autres. |
| Un changement accepté sur une branche | Aucune fusion automatique des références d'une branche dans une autre. Quand la même différence apparaît sur une autre branche, Delta-QA propose « Déjà voulu sur … : appliquer ? ». |
| Accepter une différence | « Voulu » s'applique aux branches que vous cochez. |
Ni APPLITOOLS_BATCH_ID ni id de lot | Une version par processus : chaque worker de Playwright Test est un processus, donc plusieurs workers font plusieurs versions — avec la fixture aussi. Posez APPLITOOLS_BATCH_ID au commit de votre CI pour partager une version. |
| Une région à ignorer qui ne désigne aucun élément | Écartée, et le check part sans elle, comme chez Applitools — et un avertissement de Node.js de code DELTAQA_IGNORED_REGION la nomme, une fois par région et par processus (node --disable-warning=DELTAQA_IGNORED_REGION le fait taire). Une région à vérifier qui ne désigne rien fait échouer le check par ZoneNotFoundError, comme chez Applitools. |
runner.getAllTestResults() et un test resté ouvert | Le test est fermé et son verdict rendu ; Applitools l'abandonne. |
Fixture : eyesConfig en haut de playwright.config et dans un projet | Celui du projet remplace celui du haut, comme Playwright Test donne une option ; test.use ajoute ses clés à celui du projet. La fixture d'Applitools fusionne les deux clé par clé. |
Fixture : type: 'classic' avec browsersInfo | Chaque taille est un environnement, comme avec ClassicRunner hors de la fixture ; la fixture d'Applitools retire les tailles. type avertit. |
Fixture : expect(page).toHaveScreenshot() | Celui de Playwright Test : expect est celui de @playwright/test. La fixture d'Applitools en fait un check d'Eyes. |
| Un test resté sans check pendant 30 minutes | Delta-QA le ferme ; close() lit alors son verdict. |
Les données que vous envoyez
Ce que le SDK envoie — les pages que vos tests vérifient et les fichiers qu'elles utilisent — ne sert qu'à les comparer. Tester sur des données personnelles de production relève de votre responsabilité : faites tourner la suite sur des données de test.
Le SDK Vision : des vérifications Delta-QA dans vos tests Playwright
Applitools, Applitools Eyes et Eyes sont des marques d'Applitools Ltd. Delta-QA n'est ni affilié à Applitools, ni approuvé ni soutenu par lui.
Faites tourner votre suite Eyes sur Delta-QA
Pour utiliser Vision, contactez-nous : il est d'abord disponible en avant-première. Dites-nous quels tests vous voulez faire vérifier, nous vous ouvrons l'accès.