Migrar uma suíte Playwright do Applitools Eyes para o Delta-QA
Uma suíte Playwright escrita para o Applitools Eyes roda no Delta-QA depois de duas mudanças: o import e as variáveis de ambiente. Seus eyes.open, check, close, BatchInfo, addBrowser e suas regiões continuam.
Instalar e trocar o import
A API Eyes do @delta-qa/vision retoma os nomes e o significado do Applitools Eyes para Playwright. Ela exige Node.js 22 ou mais recente e @playwright/test 1.62 ou mais recente.
O SDK Vision está disponível primeiro em acesso antecipado: fale conosco para usá-lo na sua suíte. Solicitar acesso ao 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 no playwright.config fica como está. Com a fixture, um teste só troca o 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 fixtureDefinir as variáveis de ambiente
| Variável | Lida para |
|---|---|
DELTAQA_API_KEY | A chave de API do seu espaço de trabalho Delta-QA (dqa_…), com o papel “Can edit”, criada em Settings → Workspace → API keys. Guarde-a em um segredo da sua CI. |
APPLITOOLS_API_KEY | Lida quando DELTAQA_API_KEY não está definida: mantenha a variável e atribua a ela uma chave Delta-QA. |
DELTAQA_SERVER_URL | O seu servidor Delta-QA, para uma instalação On-Premise; a nuvem do Delta-QA quando não está definida. APPLITOOLS_SERVER_URL nunca é lida. |
APPLITOOLS_BATCH_ID | A versão testada — o commit. O id do lote informado no código tem prioridade. |
APPLITOOLS_BRANCH | A branch. setBranchName no código tem prioridade. |
APPLITOOLS_PARENT_BRANCHAPPLITOOLS_BASELINE_BRANCH | A branch base, cuja referência é usada enquanto a branch não tem uma. APPLITOOLS_BASELINE_BRANCH vem antes de APPLITOOLS_PARENT_BRANCH; o código tem prioridade. |
As formas _NAME das variáveis de branch (APPLITOOLS_BRANCH_NAME, APPLITOOLS_PARENT_BRANCH_NAME, APPLITOOLS_BASELINE_BRANCH_NAME) também são lidas. Uma variável vazia conta como uma variável não definida. Sem chave, a abertura de um teste falha e nomeia a variável a definir.
Estas variáveis do Applitools não são lidas e não geram aviso: APPLITOOLS_SERVER_URL, APPLITOOLS_BATCH_NAME, APPLITOOLS_DONT_CLOSE_BATCHES, APPLITOOLS_SHOW_LOGS.
Configurar a sua CI
O SDK não lê nem o git nem as variáveis da sua CI: as linhas abaixo extraem delas a branch, a branch base e o commit, nas três variáveis do Applitools.
GitHub Actions
Em um push, github.head_ref está vazio: a branch é então github.ref_name. Em um pull request, github.sha é o commit de merge que o GitHub cria, não o commit enviado: o commit de head tem prioridade.
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
Em um pipeline de merge request, CI_MERGE_REQUEST_TARGET_BRANCH_NAME é a branch de destino; em um pipeline de branch, está vazia.
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 só é definida em um 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
As variáveis System.PullRequest só são definidas em um build de pull request, no formato refs/heads/… para o Azure Repos. Build.SourceBranchName mantém apenas o último segmento de uma branch (feature/cart dá cart), por isso a branch é lida na ref completa.
- 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 testUma branch base igual à branch não é usada: na branch padrão, estas linhas não informam nenhuma base.
Fechar no teardown, nunca no corpo do teste
Com a fixture, eyes é fechado no teardown do teste. Sem ela, chame eyes.close() em um afterEach, e runner.getAllTestResults() em um afterAll.
Nunca feche no corpo do teste: a espera pelo veredito consome o tempo do teste — 30 segundos por padrão no Playwright Test — e uma etapa que falha antes de close() deixa o teste aberto. O teardown tem o seu próprio timeout.
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();
});Cada configuração do Applitools, e no que ela se torna
Toda configuração do Applitools Eyes é aceita: a suíte compila e roda. Cada uma é aplicada pelo Delta-QA ou aceita sem efeito, com um aviso. Algumas chamadas não existem.
Aplicadas
| Configuração | No Delta-QA |
|---|---|
appName | A aplicação do teste; junto com o nome do teste, ela identifica o teste. No eyesConfig, My App quando não definida, como na fixture do Applitools. |
testName | O nome do teste, sua chave: um nome alterado é um teste novo. No eyesConfig, também pode ser uma função do teste; sem ele, o caminho de títulos do teste sem o arquivo (describe > test), como na fixture do Applitools. |
apiKeysetApiKey | A chave, no lugar de DELTAQA_API_KEY ou APPLITOOLS_API_KEY — uma chave Delta-QA. Ela nunca aparece em uma mensagem, um log ou um link. |
branchName | A branch da execução; sem ela, APPLITOOLS_BRANCH, depois APPLITOOLS_BRANCH_NAME. |
parentBranchNamebaselineBranchName | A branch base, baselineBranchName antes de parentBranchName; sem eles, as variáveis correspondentes, na mesma ordem. |
batch | O seu id é a versão testada — o commit; sem ele, APPLITOOLS_BATCH_ID; sem nenhum dos dois, uma versão por processo (veja as diferenças, abaixo). |
saveNewTests | Se as páginas de um teste novo se tornam a sua referência; true quando não definido. |
viewportSize | O tamanho dado à página quando o teste é aberto. |
browsersInfoaddBrowser(width, height) | Cada tamanho é um ambiente, para Chrome ou sem nome de navegador. O idioma, o fuso horário, o tema e a densidade de tela são lidos no navegador do teste. |
fullyfully(true) | A página inteira — o que o Delta-QA verifica de qualquer forma. |
withNamename | O nome do check. |
Target.window | A página do teste. |
Target.regionCheckSettings.regioncheckRegioncheckRegionBycheckRegionByElementcheckElementcheckElementBy | A única parte da página comparada: o primeiro elemento designado por um locator, um seletor ou um handle de elemento, como no Applitools; a última região informada prevalece. As regiões a ignorar que ela contém ficam de fora. |
ignoreRegionsignoreRegionignoreignores | Cada elemento designado por uma região — um locator, um seletor, { selector, type }, um handle de elemento — fica de fora da comparação: todos os elementos de um locator, como no Applitools. Vale também para a forma { region } e para a chave ignoreRegions da forma objeto. |
eyesConfig.failTestsOnDiff | Quando um veredito diferente de PASSED causa falha, na fixture: 'afterEach' faz o teste falhar no seu teardown; 'afterAll' faz o worker falhar quando seus testes terminam; false não faz nada falhar, mas o veredito continua sendo aguardado. Sem ela, 'afterAll' quando a variável CI está definida e 'afterEach' caso contrário, como decide o código da fixture do Applitools. |
eyesConfig.afterAll | Chamado quando os testes de um worker terminam, com o resultado de cada um. |
As chamadas
| Chamada | No Delta-QA |
|---|---|
open(page, appName, testName, viewportSize?) | O teste é identificado pela sua aplicação e pelo seu nome: um nome alterado é um teste novo. O tamanho do viewport é dado à página. |
check(name?, Target.window())checkWindow(tag?) | Verifica a página como está, em cada ambiente. Um check sem nome é associado pelo endereço da sua página; dois checks com o mesmo nome são aceitos. Ele retorna um MatchResult sem veredito, como o check do Applitools: o veredito vem no fechamento. |
close(throwErr = true) | Aguarda o veredito: DiffsFoundError em uma diferença a avaliar, NewTestError em um teste novo a avaliar (saveNewTests(false)), TestFailedError em uma diferença avaliada como bug ou em uma falha. A mensagem traz o link da versão no Delta-QA. |
closeAsync()runner.getAllTestResults(throwErr = true) | closeAsync() fecha sem esperar; o runner aguarda cada veredito, fecha um teste deixado aberto e lança um erro para um teste que não passou — o erro de um closeAsync() é reservado para ele. |
abort()abortIfNotClosed()abortAsync() | Fecha sem aguardar o veredito e não faz nada falhar: os resultados são marcados como abortados, sem resultado; null quando nenhum teste está aberto. O Delta-QA compara as execuções mesmo assim, e a versão mostra o resultado delas. |
Aceitas sem efeito
Uma configuração que o Delta-QA não aplica não faz o teste falhar: o teste roda sem ela. Seu primeiro uso em um processo emite um aviso do Node.js que a nomeia, com o código DELTAQA_IGNORED_SETTING; os usos seguintes não dizem mais nada, e node --disable-warning=DELTAQA_IGNORED_SETTING os silencia. Um valor vazio — setX(process.env.VARIABLE) fora da CI — é uma configuração não informada e não gera aviso. Os nomes abaixo são os que o aviso exibe.
Configurações de comparação
Níveis de correspondência, regiões por nível de correspondência, regiões flutuantes e deslocamentos ajustam a comparação do Applitools. O Delta-QA compara a página como faria o olho humano, sem nível de tolerância a ajustar: cada diferença é exibida, e uma pessoa a avalia no 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
Configurações de captura
Costura, rolagem, recorte, esperas e capturas de depuração moldam a captura do Applitools. O Delta-QA verifica a página inteira tal como o teste a deixou no momento da chamada a check: para esperar um conteúdo ou carregar uma seção lazy, faça isso no teste, antes do check.
hideCarethideScrollbarsforceFullPageScreenshotstitchModestitchOverlapscrollRootElementcutrotationwaitBeforeScreenshotswaitBeforeCapturematchTimeoutsaveDebugScreenshotsdebugScreenshotsPathdebugScreenshotsPrefixfully(false)CheckSettings.fully(false)CheckSettings.scrollRootElementCheckSettings.stitchModeCheckSettings.timeoutCheckSettings.waitBeforeCaptureCheckSettings.lazyLoadCheckSettings.useSystemScreenshot
Navegadores, dispositivos e ambientes
O Delta-QA renderiza no Chromium: conta o tamanho dado a addBrowser, não o navegador nomeado, então dois navegadores do mesmo tamanho formam um único ambiente. Um dispositivo da grid do Applitools (DeviceName, IosDeviceName, emulação, multidispositivo) não adiciona nenhum ambiente. O idioma, o fuso horário, o tema e a densidade de tela são lidos no navegador do teste, e os rótulos de ambiente não mudam nada. ClassicRunner e VisualGridRunner se comportam da mesma forma.
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
A grid de renderização do Applitools
Opções de renderização, hooks, fetching, caches e concorrência da grid do Applitools não têm equivalente: a página é verificada tal como o teste a deixou. Um script que você executava em um hook passa a rodar no teste, antes do check.
visualGridOptionsCheckSettings.ufgOptionCheckSettings.ufgOptionsCheckSettings.visualGridOptionCheckSettings.visualGridOptionsCheckSettings.variationGroupIdCheckSettings.hookCheckSettings.beforeRenderScreenshotHookCheckSettings.webHookdisableBrowserFetchingCheckSettings.disableBrowserFetchingdisableNMLUrlCacheautProxybypassCSPskipRootHtmlResourceconcurrentSessionsRunnerOptions.testConcurrencyRunnerOptions.fetchConcurrencyRunnerOptions.removeDuplicateTests
Lotes, referências e resultados
Uma versão carrega o commit: ela não tem nome, sequência, propriedades, notificação nem nada a fechar. Uma referência só muda quando uma pessoa avalia uma diferença no Delta-QA; um teste sem referência é “Novo”. Os checks são associados pelo nome, ou então pelo endereço da sua página. isDisabled: um teste que deve rodar sem check não abre nenhum Eyes.
BatchInfo.nameBatchInfo.sequenceNameBatchInfo.startedAtBatchInfo.notifyOnCompletionBatchInfo.propertiesBatchInfo.buildIddontCloseBatchesBatchClosepropertiesremoveSessionsaveDiffssaveFailedTestsignoreBaselinedisplayNamesessionTypeCheckSettings.pageIdisDisabled
Git
O SDK não lê o git: informe a branch base por parentBranchName ou baselineBranchName, e o commit pelo id do lote ou por APPLITOOLS_BATCH_ID.
compareWithParentBranchignoreGitMergeBasegitMergeBaseTimestamplatestCommitInfo
Servidor, conexão e logs
Elas dizem respeito ao servidor do Applitools, à sua conexão e aos seus logs. O servidor do Delta-QA é lido em DELTAQA_SERVER_URL; o SDK não grava nenhum log do Applitools e não emite nenhum evento do Applitools.
serverUrlproxyagentIdhttpVersionconnectionTimeoutEyes.onEyes.setLogHandlerEyes.addSessionEventHandlereyesConfig.logConfigRunnerOptions.maskLog
Recursos fora do Delta-QA
O Delta-QA não valida acessibilidade, não lê o Figma e não tem check em linguagem natural; uma página do Playwright não tem web view.
accessibilityValidationCheckSettings.accessibilityRegionCheckSettings.accessibilityRegionsfigmaBaselinesfigmaOptionsnlpOptionsTarget.webviewCheckSettings.webview
Regiões sem elemento
O Delta-QA identifica os elementos que diferem: uma região informada por coordenadas ({ x, y, width, height }, { left, top, width, height }) não tem equivalente: a página é comparada sem ela — inteira, no caso de Target.region. A zona é o elemento, sem padding; um regionId nomeia uma região no dashboard do Applitools. Com Target.frame ou Target.shadow, a página é comparada inteira, e uma região então informada por um seletor faz o check falhar com um TypeError: uma zona é um elemento da própria página.
CheckSettings.ignoreRegions(coordinates)Target.region(coordinates)CodedRegion.paddingCodedRegion.regionIdTarget.frameTarget.shadowCheckSettings.frameCheckSettings.shadow
Uma chave desconhecida na forma objeto de uma configuração ou de um check gera um aviso com o seu nome (CheckSettings.<key> em um check).
Ausentes: o que não compila
Não são configurações: elas retornam dados que o Delta-QA não tem, ou verificam uma imagem em vez de uma página. Uma suíte que as usa não compila, em vez de receber um valor inventado.
| Ausente | Por quê |
|---|---|
eyes.locateeyes.extractTexteyes.extractTextRegions | Retornam regiões ou texto que o Applitools lê na sua captura. |
eyes.checkImageTarget.imageTarget.bufferTarget.base64Target.pathTarget.url | O Delta-QA verifica páginas, não imagens. |
eyes.getLoggereyes.logger | O log do Applitools. |
eyes.run | Na fixture do Applitools, o seu check em linguagem natural. |
O que difere do Applitools
Escolhas deliberadas do Delta-QA, para conhecer antes da primeira execução.
| Situação | Delta-QA |
|---|---|
| Associar um check à sua referência | Pelo nome do check quando cada nome é único no teste; caso contrário, pela ordem, por nome, ou então pelo endereço da página: um check inserido ou removido não desloca os outros. |
| Uma mudança aceita em uma branch | Nenhum merge automático de referências de uma branch para outra. Quando a mesma diferença aparece em outra branch, o Delta-QA oferece “Already intended on … — apply?”. |
| Aceitar uma diferença | “Esperado” vale para as branches que você marcar. |
Sem APPLITOOLS_BATCH_ID nem id de lote | Uma versão por processo: cada worker do Playwright Test é um processo, então vários workers geram várias versões — com a fixture também. Defina APPLITOOLS_BATCH_ID com o commit da sua CI para compartilhar uma única versão. |
| Uma região a ignorar que não corresponde a nenhum elemento | Fica de fora, e o check é enviado sem ela, como faz o Applitools — e um aviso do Node.js com o código DELTAQA_IGNORED_REGION a nomeia, uma vez por região e por processo (node --disable-warning=DELTAQA_IGNORED_REGION o silencia). Uma região a verificar que não corresponde a nada faz o check falhar com ZoneNotFoundError, como no Applitools. |
runner.getAllTestResults() e um teste deixado aberto | O teste é fechado e seu veredito é dado; o Applitools o aborta. |
Fixture: eyesConfig no topo do playwright.config e em um projeto | O do projeto substitui o do topo, como o Playwright Test faz com uma opção; test.use adiciona suas chaves às do projeto. A fixture do Applitools mescla os dois chave por chave. |
Fixture: type: 'classic' com browsersInfo | Cada tamanho é um ambiente, como com ClassicRunner fora da fixture; a fixture do Applitools descarta os tamanhos. type gera um aviso. |
Fixture: expect(page).toHaveScreenshot() | O do próprio Playwright Test: expect é o do @playwright/test. A fixture do Applitools o transforma em um check do Eyes. |
| Um teste deixado sem check por 30 minutos | O Delta-QA o fecha; close() então lê o seu veredito. |
Os dados que você envia
O que o SDK envia — as páginas que seus testes verificam e os arquivos que elas usam — serve apenas para compará-las. Testar com dados pessoais de produção é responsabilidade sua: execute a suíte com dados de teste.
O SDK Vision: verificações do Delta-QA nos seus testes Playwright
Applitools, Applitools Eyes e Eyes são marcas comerciais da Applitools Ltd. O Delta-QA não é afiliado à Applitools, nem endossado ou patrocinado por ela.
Rode sua suíte Eyes no Delta-QA
Para usar o Vision, fale conosco: ele está disponível primeiro em acesso antecipado. Conte quais testes você quer verificar e liberamos seu acesso.