Məzmuna keç

Modul 11: Vizual, Mobil və Əlçatımlılıq testləri

Modul 11-ə xoş gəldiniz. Autentifikasiya vəziyyəti, API testləri, CI pipeline-lar və fixtures-i mənimsədiniz. İndi isə sadə keçən testlər toplusunu real istifadəçi səviyyəsindəki xətaları aşkarlayan bir topluya çevirən üç imkanı öyrənəcəyik: vizual reqressiya, mobil cihaz emulyasiyasıavtomatik əlçatımlılıq auditi.

Bu modulun sonunda UI-nızı piksel səviyyəsində ekran görüntüsü təkidləri ilə möhkəmləndirəcək, həqiqi cihaz olmadan iPhone 13 viewport-unda eyni testləri işlədəcək və bir analyze() çağırışı ilə WCAG pozuntularını avtomatik üzə çıxaracaqsınız.

🎬 Video tezliklə əlavə olunacaq


toHaveScreenshot ilə vizual reqressiya

Bölmə: “toHaveScreenshot ilə vizual reqressiya”

Playwright öz daxilində ekran görüntüsü müqayisəsi ilə gəlir — üçüncü tərəf vizual diff alətinə ehtiyac yoxdur. Təkid expect(locator).toHaveScreenshot() və ya expect(page).toHaveScreenshot() şəklindədir.

import { test, expect } from '@playwright/test';
test('məhsul kartı bazis xəttinə uyğun gəlir', async ({ page }) => {
await page.goto('/');
await expect(page.locator('.product-card').first()).toBeVisible();
await expect(page.locator('.product-card').first()).toHaveScreenshot('product-card.png');
});

Bazis xətləri necə işləyir. İlk işlətmədə snapshot faylı hələ mövcud deyil, ona görə Playwright onu yazır — test keçdi ya uğursuz oldu kimi deyil, “yazıldı” kimi qeyd edilir. Sonrakı hər işlətmə həmin bazis faylına qarşı piksel-piksel müqayisə aparır. Fərq konfiqurasiya edilmiş tolerantlığı keçərsə, test uğursuz olur və Playwright nəzarəti asanlaşdırmaq üçün bazis faylının yanına -diff.png-actual.png yazır.

Snapshot-lar harda saxlanır. Varsayılan olaraq hər spec faylının yanında öz <spec-faylı>-snapshots/ qovluğu yaranır; layihə adı və platforma isə fayl adının bir hissəsi olur (məsələn, ...-chromium-linux.png):

tests/
visual/
product-card.spec.ts
product-card.spec.ts-snapshots/
product-card-chromium-linux.png

Platforma şəkilçisi (linux, darwin, win32) avtomatik əlavə edilir, çünki render OS-lər arasında fərqlənir. Hədəf CI platformanız üçün bazis fayllarını commit edin.

Yadda saxla: ilk işlətmə bazis xəttini yazır (status “yazıldı”, keçdi/uğursuz deyil); sonrakı hər işlətmə piksel-piksel müqayisə aparır və uğursuzluqda -diff.png / -actual.png buraxır. Bazis xətləri platforma şəkilçisi ilə <spec>-snapshots/ qovluğunda yaşayır — CI OS-nizə uyğun olanı commit edin.


Snapshot bazis xətlərini idarə etmək

Bölmə: “Snapshot bazis xətlərini idarə etmək”

Qəsdən edilən UI dəyişikliklərindən sonra bazis xətlərini yeniləmək

Bölmə: “Qəsdən edilən UI dəyişikliklərindən sonra bazis xətlərini yeniləmək”

Qəsdli vizual dəyişiklik (yenidən dizayn edilmiş kart, yeni rəng, düzəldilmiş şrift) edəndə mövcud bazis xətti artıq düzgün deyil. --update-snapshots bayrağı (və ya onun qısaltması -u) ilə yeniləyin:

Terminal window
npx playwright test --update-snapshots

Yeniləmədən əvvəl HTML reporter-da fərqi mütləq nəzərdən keçirin. Fərq görünümü solda bazis xəttini, sağda faktiki olanı, ortada isə fərqi göstərir. Nəzərdən keçirmədən yeniləmək reqressiyaların fark edilmədən içəri sızmasının yoludur.

Vizual testlər mühitə həssasdır. Eyni piksel OS şrift yığınları, GPU sürücüləri və subpiksel kənar düzəltmə tətbiqləri arasında fərqli render ola bilər. Tövsiyə olunan yanaşma:

  1. Vizual testləri CI-da yalnız bir platformada (adətən Linux) işlədin.
  2. Bazis xəttini həmin Linux runner-da yaradın və commit edin.
  3. Lokal olaraq kiçik fərqləri səs-küy kimi qəbul edin — yalnız fərq həddini keçdikdə CI-ı uğursuz edin.

Linux bazis xətlərinin yanına Windows və ya macOS bazis xətlərini heç vaxt commit etməyin. Bu CI-da yanlış uğursuzluqlara səbəb olacaq.

Dinamik bölgələri maskalamaq

Bölmə: “Dinamik bölgələri maskalamaq”

Bəzi səhifə sahələri hər yükləmədə dəyişir: vaxt damğaları, istifadəçi avatarları, tövsiyə karuselləri. Onları maskalamaq yanlış müsbətləri önləyir:

await expect(page).toHaveScreenshot('checkout.png', {
mask: [
page.locator('.timestamp'),
page.locator('.user-avatar'),
page.locator('[data-testid="recommended-products"]'),
],
});

Maskalanan bölgələr fərqdə bərk düzbucaqlı ilə əvəzlənir, ona görə onların məzmunu nəzərə alınmır, amma ətraf düzün hələ də müqayisə edilir.

Yadda saxla: bazis xətlərini -u ilə yalnız fərqi HTML reporter-da gözdən keçirdikdən sonra yeniləyin; vizual testləri tək bir CI OS-a sabitləyin (Linux/macOS/Windows bazis xətlərini heç vaxt qarışdırmayın) və dəyişkən bölgələri (vaxt damğaları, avatarlar) mask edin ki, yanlış uğursuzluqlara səbəb olmasınlar.


Müqayisənin nə qədər ciddi olduğunu iki konfiqurasiya parametri idarə edir.

maxDiffPixels — testin uğursuz olmadan əvvəl fərqlənə biləcəyi piksellərin mütləq sayı. Subpiksel kənar düzəltmə səs-küyünü bastırmaq üçün yaxşıdır:

playwright.config.ts
export default defineConfig({
expect: {
toHaveScreenshot: {
maxDiffPixels: 100,
},
},
});

Və ya təkid daxilindəki sətirdə:

await expect(page).toHaveScreenshot('homepage.png', { maxDiffPixels: 50 });

threshold — ümumi piksel sayına nisbətən qəbul edilə bilən fərqli piksellərin faizini ifadə edən 0-dan 1-ə qədər nisbət. Səhifə ölçüsü dəyişəndə bunu istifadə edin:

await expect(page).toHaveScreenshot('homepage.png', { threshold: 0.02 }); // 2 %

Kiçik, sabit ölçülü komponentlər üçün maxDiffPixels istifadə edin. Ümumi piksel sayı viewport və ya məzmunla dəyişən tam səhifələr üçün threshold istifadə edin.

Yadda saxla: maxDiffPixels fərqlənən piksellərin mütləq sayını məhdudlaşdırır — kiçik, sabit ölçülü komponentlər üçün ən yaxşısıdır; threshold isə ümumi sayın 0–1 nisbətidir — piksel sayı dəyişən tam səhifələr üçün ən yaxşısıdır.


Tam səhifə vs element ekran görüntüləri

Bölmə: “Tam səhifə vs element ekran görüntüləri”

Element ekran görüntüsü — yalnız uyğun locator-un əhatə qutusunu çəkir:

await expect(page.locator('.product-card').first()).toHaveScreenshot('card.png');

Komponent səviyyəsindəki reqressiya üçün bunu istifadə edin: yalnız kartı test edirsiniz, buna görə səhifənin başqa yerindəki dəyişikliklər bu snapshot-a təsir etmir.

Tam səhifə ekran görüntüsü — yalnız görünən viewport deyil, bütün sürüşdürülə bilən sənədi çəkir:

await expect(page).toHaveScreenshot('checkout.png', { fullPage: true });

Qatlanma nöqtəsinin altındakı məzmun daxil olmaqla tam səhifə düzünü kilidləməyiniz lazım olduqda bunu istifadə edin. Tam səhifə ekran görüntülərinin daha yavaş olduğunu və daha böyük fayllar yaratdığını unutmayın.

Hansını üstün tutmaq lazım:

Əhatə dairəsiİstifadə edin
Tək komponentElement ekran görüntüsü
Qatlanma nöqtəsinin üstündəki düzViewport ekran görüntüsü (varsayılan)
Tam sənədfullPage: true

Ekran görüntüsü almadan əvvəl həmişə elementin və ya səhifənin render bitməsini gözləyin. Boş və ya qismən render edilmiş bir səhifənin ekran görüntüsünü almaq, vaxtlama bir az fərqləndikdə sonrakı hər işlətmədə uğursuz olacaq bir bazis xətti yaradır.

Yadda saxla: element görüntüsü tək komponenti təcrid edir, varsayılan viewport-u çəkir, fullPage: true isə bütün sürüşdürülə bilən sənədi tutur — hansını seçsəniz də, bazis xətti render ortasında tutulmasın deyə əvvəlcə məzmunun oturuşmasını gözləyin.


devices[...] vasitəsilə mobil emulyasiya

Bölmə: “devices[...] vasitəsilə mobil emulyasiya”

Playwright @playwright/test-dən ixrac edilmiş devices xəritəsindəki 50-dən çox cihaz tərifi ilə gəlir. Hər tərif bunları ehtiva edir:

  • viewport — piksel ölçüləri
  • deviceScaleFactor — DPR (cihaz piksel nisbəti)
  • userAgent — real cihaz user-agent sətri
  • isMobile: true — brauzerin mobil brauzer kimi davranmasına işarə edir
  • hasTouch: true — toxunma hadisəsi simulyasiyasını aktivləşdirir
import { test, expect, devices } from '@playwright/test';
const iPhone13 = devices['iPhone 13'];
test.use({ ...iPhone13 });
test('iPhone 13-də ana səhifə yüklənir', async ({ page }) => {
await page.goto('/');
await expect(page.locator('.product-card').first()).toBeVisible();
});

Mobil emulyasiya vizual bir hiylə deyil. ...devices['iPhone 13'] tətbiq etmək brauze rin faktiki davranışını dəyişdirir: siçan hadisələri əvəzinə toxunma hadisələri atəşlənir, meta viewport teqi nəzərə alınır və pointer: coarse-u hədəf alan CSS media sorğuları aktivləşir.

Yadda saxla: ...devices['iPhone 13']-i yaymaq sadəcə ölçü dəyişikliyi deyil — viewport, DPR, user-agent, hasTouchisMobile-i təyin edir, beləcə klik əvəzinə toxunma hadisələri atəşlənir və pointer: coarse media sorğuları aktivləşir.


Responsiv düzünlüqları test etmək

Bölmə: “Responsiv düzünlüqları test etmək”

Tövsiyə olunan yanaşma cihazı ayrıca bir Playwright layihəsi kimi əlavə etməkdir ki, beləliklə paketinizdəki hər test həmin cihazda avtomatik işləsin:

playwright.config.ts
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'mobile-chrome',
use: { ...devices['Pixel 5'] },
},
{
name: 'mobile-safari',
use: { ...devices['iPhone 13'] },
},
],
});

İndi npx playwright test işlətmək hər testi üç dəfə icra edir — hər cihaz üçün bir dəfə. Responsiv düzün reqressiyası dərhal üzə çıxır: masaüstü layihəsi keçir, mobil layihə uğursuz olur, hansı breakpoint-in pozulduğunu dəqiq bilirsiniz.

Tək bir spec daxilindəki hədəfli responsiv yoxlamalar üçün describe səviyyəsindəki test.use() istifadə edin. Telefon viewport-unda TestMarket naviqasiya panelini hamburger toggle-ın arxasında gizlədir — siz menyunu açana qədər linklər gizli qalır:

test.describe('mobil naviqasiya', () => {
test.use({ ...devices['iPhone 13'] });
test('naviqasiya mobildə hamburger menyuya sıxılır', async ({ page }) => {
await page.goto('/');
// Toggle düyməsi yalnız dar enlərdə görünür
const toggle = page.getByRole('button', { name: 'Open navigation' });
await expect(toggle).toBeVisible();
// Linklər menyunu açana qədər gizlidir
await expect(page.getByTestId('nav-products')).not.toBeVisible();
await toggle.click();
await expect(page.getByTestId('nav-products')).toBeVisible();
});
});

Eyni paketi Desktop Chrome altında işlədin və təkidlər tərsinə çevrilir: hamburger gizlənir, linklər klik olmadan görünür. Həmin ziddiyyət — eyni test, layihəyə görə əks nəticə — məhz responsiv düzün reqressiyasının necə göründüyüdür.

Populyar daxili cihaz tərifləri

Bölmə: “Populyar daxili cihaz tərifləri”
Cihaz adıViewportDPR
Desktop Chrome1280×7201
iPhone 13390×8443
iPhone 13 Pro Max428×9263
Pixel 5393×8513
Pixel 7412×9153
iPad Pro 11834×11942
Galaxy S21360×8003

Yadda saxla: bütün paketi hər cihazda işlətmək üçün cihazları ayrıca projects kimi əlavə edin, ya da bir hədəfli mobil spec üçün describe səviyyəsində test.use() istifadə edin — responsiv reqressiya o zaman masaüstü keçərkən mobil layihənin uğursuz olması kimi üzə çıxır.


Coğrafi mövqe, lokal və icazə context seçimləri

Bölmə: “Coğrafi mövqe, lokal və icazə context seçimləri”

Viewport və user-agent-dən başqa, Playwright brauzer context-ləri cihaz və istifadəçi mühiti parametrlərini simulyasiya edən seçimləri qəbul edir. Bunlar context səviyyəsində (və ya konfiqurasiyasının use blokunda) təyin edilir:

const context = await browser.newContext({
geolocation: { latitude: 40.4093, longitude: 49.8671 }, // Bakı, Azərbaycan
permissions: ['geolocation'],
});

Bu ikisi birlikdə tələb olunur — geolocation icazəsinin verilməsi brauzərə API girişinə icazə verir; geolocation koordinatlarının təmin edilməsi navigator.geolocation API-sının qaytardığı dəyəri təyin edir.

const context = await browser.newContext({
locale: 'az-AZ',
timezoneId: 'Asia/Baku',
});

locale Intl.DateTimeFormat, Number.prototype.toLocaleString və brauzer UI dilinə təsir edir. timezoneId Date obyektinə və tətbiqdəki saat qurşağına həssas render-ə təsir edir.

const context = await browser.newContext({
permissions: ['geolocation', 'notifications', 'clipboard-read'],
});

Səhifə yüklənmədən əvvəl icazələri verin ki, tətbiq heç vaxt brauzer icazə sualı görməsin. Mövcud dəyərlər Permissions API-a uyğundur — 'camera', 'microphone', 'geolocation', 'notifications', 'clipboard-read', 'clipboard-write'.

Bu seçimlərin hamısı cihaz tərifləri ilə sərbəst birləşir:

const context = await browser.newContext({
...devices['iPhone 13'],
locale: 'az-AZ',
geolocation: { latitude: 40.4093, longitude: 49.8671 },
permissions: ['geolocation'],
});

Yadda saxla: bu newContext seçimləri real-istifadəçi şərtlərini simulyasiya edir — geolocation koordinatlarını geolocation icazəsi ilə cütləyin, i18n üçün locale/timezoneId təyin edin və icazələri qabaqcadan verin ki, heç bir sual səhifəni bloklamasın. Hamısı cihaz profili ilə birləşir.


@axe-core/playwright ilə əlçatımlılıq testi

Bölmə: “@axe-core/playwright ilə əlçatımlılıq testi”

axe-core ən geniş istifadə olunan açıq mənbəli əlçatımlılıq mühərrikidir. @axe-core/playwright paketi onu Playwright üçün əhatə edir və tək bir analyze() çağırışı ilə hər hansı bir səhifəni WCAG pozuntularına görə skan etməyə imkan verir.

Terminal window
npm install --save-dev @axe-core/playwright
import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
test('ana səhifədə əlçatımlılıq pozuntusu yoxdur', async ({ page }) => {
await page.goto('/');
await expect(page.locator('.product-card').first()).toBeVisible();
const accessibilityScanResults = await new AxeBuilder({ page }).analyze();
expect(accessibilityScanResults.violations).toEqual([]);
});

AxeBuilder aktiv səhifəyə qoşulur, brauzer daxilindəki axe-core mühərrikini işlədir və nəticələr obyekti qaytarır. violations qayda uğursuzluqlarının massividir — onun []-a bərabər olduğunu iddia etmək sıfır pozuntu deməkdir.

Müəyyən bir elementi skan etmək

Bölmə: “Müəyyən bir elementi skan etmək”

Auditi bütün səhifə əvəzinə bir komponentlə məhdudlaşdırmaq üçün:

const results = await new AxeBuilder({ page })
.include('form')
.analyze();
expect(results.violations).toEqual([]);

Məlum yanlış müsbətləri deaktiv etmək

Bölmə: “Məlum yanlış müsbətləri deaktiv etmək”

Bir üçüncü tərəf widget həll edə bilmədiyiniz bir qayda üzərində ardıcıl olaraq uğursuz olarsa, onu xaric edin:

const results = await new AxeBuilder({ page })
.exclude('#third-party-chat-widget')
.analyze();

Və ya müəyyən bir qaydanı deaktiv edin:

const results = await new AxeBuilder({ page })
.disableRules(['color-contrast'])
.analyze();

İstisnalardan ehtiyatla istifadə edin və hər birinin niyə mövcud olduğunu sənədləşdirin. Yoxlanılmamış istisna siyahısı auditin mənasız olana qədər böyüyür.

Yadda saxla: new AxeBuilder({ page }).analyze() axe-core-u səhifə daxilində işlədir və violations qaytarır; onun []-a bərabər olması sıfır problem deməkdir. Skanı .include() ilə daraldın və .exclude() / .disableRules()-ə yalnız nadir hallarda və sənədləşdirilmiş səbəblə müraciət edin.


axe-core tərəfindən yoxlanan ümumi WCAG yoxlamaları

Bölmə: “axe-core tərəfindən yoxlanan ümumi WCAG yoxlamaları”

analyze() uğursuz olanda violations massiv girişlərinin hər biri aşağıdakıları ehtiva edir:

  • id — axe qaydası identifikatoru, məs., "color-contrast", "image-alt", "label"
  • impact"critical", "serious", "moderate" və ya "minor"
  • nodes — CSS selektorları və HTML parçaları ilə uğursuz olan DOM elementlər

Avtomatik olaraq aşkarlanan ən ümumi WCAG xətaları:

Qayda IDNəyi yoxlayırWCAG meyarı
color-contrastMətn kontrast nisbəti ≥ 4,5:1 (normal) / 3:1 (böyük)1.4.3
image-alt<img> elementlərinin alt atributu var1.1.1
labelForma girişlərinin əlaqəli etiketləri var1.3.1
button-nameDüymələrin əlçatan adı var4.1.2
link-nameLövbər elementlərinin təsviri mətni var2.4.4
aria-required-attrARIA rollarının tələb olunan atributları var4.1.2
heading-orderBaşlıq səviyyələri atlamır (h2 olmadan h1→h3)1.3.1
html-lang<html> elementinin lang atributu var3.1.1

Faydalı uğursuzluq mesajı çap etmək

Bölmə: “Faydalı uğursuzluq mesajı çap etmək”

Pozuntular mövcud olduqda expect(violations).toEqual([]) üçün varsayılan Playwright təkid çıxışı çox oxunaqlı deyil. Köməkçi funksiya bunu əhəmiyyətli dərəcədə yaxşılaşdırır:

function formatViolations(violations: import('@axe-core/playwright').Result[]) {
return violations
.map(v => `[${v.impact}] ${v.id}: ${v.description}\n ${v.nodes.map(n => n.target.join(', ')).join('\n ')}`)
.join('\n\n');
}
test('ödəniş forması əlçatımlıdır', async ({ page }) => {
await page.goto('/checkout');
const results = await new AxeBuilder({ page }).include('form').analyze();
expect(results.violations, formatViolations(results.violations)).toEqual([]);
});

Yadda saxla: hər pozuntu id, impact və uğursuz olan nodes-u daşıyır — impact-a görə triaj edin (kritik → minor) və formatViolations köməkçisini təkid mesajı kimi ötürün ki, uğursuzluq xam obyektlər yox, aydın oxunsun.


Bu tapşırıqlar bu modulun iş vərəqəsindəki tapşırıqlara uyğundur. Onları təlim tətbiqi üzərində həll edin.

Tapşırıq 1 — Məhsul kartı ekran görüntüsü

Bölmə: “Tapşırıq 1 — Məhsul kartı ekran görüntüsü”

tests/starter/tests/visual/product-card.spec.js yaradın:

  1. /-ə keçin
  2. .product-card elementlərinin render bitməsini gözləyin
  3. İlk məhsul kartının element səviyyəsindəki ekran görüntüsünü alın: await expect(page.locator('.product-card').first()).toHaveScreenshot('product-card.png')
  4. Testi iki dəfə işlədin — ilk işlətmə bazis xəttini yazır, ikinci isə keçir (müqayisə)

Bazis xətti faylının spec faylınızın yanındakı *-snapshots/ qovluğunda yaradıldığını yoxlayın.

Tapşırıq 2 — Tam səhifə ödəniş ekran görüntüsü

Bölmə: “Tapşırıq 2 — Tam səhifə ödəniş ekran görüntüsü”

tests/starter/tests/visual/checkout.spec.js yaradın:

  1. [email protected] / customer123 kimi daxil olun
  2. Səbətə məhsul əlavə edin və /checkout-a keçin
  3. Ödəniş formasının görünür olmasını gözləyin
  4. Tam səhifə ekran görüntüsü alın: await expect(page).toHaveScreenshot('checkout.png', { fullPage: true })

Həm çatdırılma formasının, həm də sifariş xülasəsinin çəkildiyini yoxlayın.

Tapşırıq 3 — Mobil ödəniş smoke testi

Bölmə: “Tapşırıq 3 — Mobil ödəniş smoke testi”

tests/starter/tests/visual/mobile-checkout.spec.js yaradın:

const { test, expect, devices } = require('@playwright/test');
const iPhone13 = devices['iPhone 13'];
test.use({ ...iPhone13 });
test('iPhone 13-də ana səhifə render olunur', async ({ page }) => {
await page.goto('/');
await expect(page.locator('.product-card').first()).toBeVisible();
// Viewport eni 390 olmalıdır (iPhone 13)
expect(page.viewportSize().width).toBe(390);
});

Cihaz emulyasiyası yalnız Chromium ilə işləyir. Firefox-da xəta görsəniz, bu gözlənilən davranışdır.

Tapşırıq 4 — Əlçatımlılıq yönümlü locator-lar

Bölmə: “Tapşırıq 4 — Əlçatımlılıq yönümlü locator-lar”

tests/starter/tests/visual/a11y-checkout.spec.js yaradın:

  1. [email protected] kimi daxil olun və /checkout-a keçin
  2. Hər çatdırılma sahəsini getByLabel() istifadə edərək doldurun — 'Shipping Name', 'Shipping Address', 'Shipping City', 'Shipping Zip Code'
  3. getByRole('button', { name: 'Place Order' }) istifadə edərək göndərin
  4. URL-in sifariş səhifəsi ilə — /\/orders\/\d+/ (məs., /orders/1042) — uyğun gəldiyini iddia edin
  5. Bonus: Boş formanı göndərən və URL-in /checkout-da qaldığını iddia edən ikinci bir test yazın (HTML5 tələb olunan yoxlaması göndərməni önləyir)

Tapşırıq 5 — Axe-core əlçatımlılıq skanı

Bölmə: “Tapşırıq 5 — Axe-core əlçatımlılıq skanı”

@axe-core/playwright-ı quraşdırın və tests/starter/tests/visual/a11y-scan.spec.ts yaradın:

import { test, expect } from '@playwright/test';
import AxeBuilder from '@axe-core/playwright';
test('ana səhifə əlçatımlılıq auditindən keçir', async ({ page }) => {
await page.goto('/');
await expect(page.locator('.product-card').first()).toBeVisible();
const results = await new AxeBuilder({ page }).analyze();
expect(results.violations).toEqual([]);
});

Pozuntular bildirilsə, hansı elementin niyə uğursuz olduğunu anlamaq üçün results.violations[0].idresults.violations[0].nodes-u yoxlayın.

Bonus tapşırıq — Çoxcihazlı vizual reqressiya

Bölmə: “Bonus tapşırıq — Çoxcihazlı vizual reqressiya”

Eyni ana səhifə ekran görüntüsünü Masaüstü, iPhone 13 və Pixel 5-də işlədin:

const { test, expect, devices } = require('@playwright/test');
const VIEWPORTS = [
{ name: 'Desktop', viewport: { width: 1920, height: 1080 } },
{ name: 'iPhone 13', ...devices['iPhone 13'] },
{ name: 'Pixel 5', ...devices['Pixel 5'] },
];
for (const vp of VIEWPORTS) {
test.describe(`${vp.name}`, () => {
test.use({ ...vp });
test(`ana səhifə ekran görüntüsü — ${vp.name}`, async ({ page }) => {
await page.goto('/');
await expect(page.locator('.product-card').first()).toBeVisible();
await expect(page).toHaveScreenshot(
`homepage-${vp.name.toLowerCase().replace(/\s+/g, '-')}.png`
);
});
});
}

Öz-özünü yoxlama sualları

Bölmə: “Öz-özünü yoxlama sualları”
  1. toHaveScreenshot() testinin ilk işlətməsindəki nə olur — keçir, uğursuz olur, yoxsa yazır?
  2. maxDiffPixels-i threshold-dan nə zaman üstün tutmalısınız?
  3. Ekran görüntüsü təkidindəki mask seçimi nə edir?
  4. isMobile: true brauzerdə viewport ölçülərindən başqa nəyi dəyişdirir?
  5. Real cihaz və ya real istifadəçi şərtlərini simulyasiya edən iki context seçimini adlandırın (viewport-dan başqa).
  6. @axe-core/playwright nəyi skan edir — vizual görünüşü test edirmi?
  7. Axe pozuntusundakı impact sahəsi nədir və üst növbəliliyini müəyyən etmək üçün niyə vacibdir?
  8. Niyə CI-da vizual testləri həmişə eyni OS-da işlətmək lazımdır?