Məzmuna keç

Modul 4: İddialar

Səhifə ilə qarşılıqlı əlaqə qurmağı öyrəndiniz. İndi isə hər testin digər yarısından — tətbiqin həqiqətən istədiyinizi etdiyini yoxlamaqdan — danışaq. Bu modul Playwright-in tam expect() API-sini əhatə edir və assertion-ları düzgün yazmanın bütöv bir flakey test kateqoriyasını niyə aradan qaldırdığını izah edir.

🎬 Video tezliklə əlavə olunacaq


Playwright assertion-ları veb-first-dir: bir dəfə qiymətləndirib uğur ya uğursuzluq bildirmir. DOM-u sıx bir dövrə üzərindən (təxminən hər 50 ms-də bir) sorğulayır və assertion keçənə — ya da vaxt aşımı bitənə qədər yenidən cəhd edir.

Bu tək dizayn qərarı sayəsində assertion-dan əvvəl demək olar ki, heç vaxt açıq gözləmə yazmağa ehtiyac qalmır.

// Element görünənə qədər (ya da vaxt aşımı bitənə qədər) avtomatik yenidən cəhd edir
await expect(page.locator('.success-banner')).toBeVisible();
// YANLIŞ — bir dəfə qiymətləndirir, yenidən cəhd yoxdur, yavaş səhifələrdə uğursuz olur
const visible = await page.locator('.success-banner').isVisible();
expect(visible).toBe(true);

Qızıl qayda: expect()-ə həmişə bir Locator verin, artıq gözlənilmiş dəyər deyil. Birinci forma avtomatik yenidən cəhd edir. İkincisi etmir.

ŞablonAvtomatik yenidən cəhd?Bunu istifadə et
expect(locator).toBeVisible()BəliHəmişə
expect(await locator.isVisible()).toBe(true)XeyrHeç vaxt
expect(locator).toHaveText('...')BəliHəmişə
expect(await locator.textContent()).toBe('...')XeyrHeç vaxt

Yadda saxla: expect()Locator ver — o, sorğulayıb yenidən cəhd edir; artıq gözlənilmiş boolean bir dəfə yoxlanılır və yenidən cəhd edə bilmir.


toBeVisible() element DOM-da olduqda görünür olduqda — display: none, visibility: hidden, opacity: 0 ilə gizlənmədikdə və ya görüntü sahəsindən kənarda olmadıqda keçir.

// Elementin görünür olduğunu iddia edin
await expect(page.locator('.welcome-message')).toBeVisible();
// Yükləmə fırlacının yox olduğunu iddia edin
await expect(page.locator('.spinner')).not.toBeVisible();
// Click etdikdən sonra modalın göstərildiyini iddia edin
await page.getByRole('button', { name: 'Open Modal' }).click();
await expect(page.locator('.modal')).toBeVisible();

toBeVisible vs toBeAttached:

  • toBeVisible — element DOM-dadır ekranda görünür
  • toBeAttached — element gizli olsa belə DOM-dadır

React bir komponenti render etdiyini amma gizli ola biləcəyini iddia etmək istədiyinizdə toBeAttached istifadə edin. İstifadəçinin həqiqətən görə biləcəyi hər şey üçün toBeVisible istifadə edin.

// Varlıq vacibdir amma görünürlük vacib deyil
await expect(page.locator('[data-testid="lazy-component"]')).toBeAttached();
// İstifadəçi onu görə bilməlidir
await expect(page.locator('.notification')).toBeVisible();

Yadda saxla: toBeVisible = DOM-da ekranda; toBeAttached = gizli olsa belə DOM-da.


Bu, assertion çaşqınlığının ən yaygın mənbəyidir. Yanlışını seçmək real debug vaxtına mal olur.

toHaveText — dəqiq uyğunluq

Bölmə: “toHaveText — dəqiq uyğunluq”

toHaveText elementin tam mətn məzmununun gözlənilən stringlə dəqiq uyğunlaşdığını iddia edir (boş yerləri kəsdikdən sonra).

// Yalnız tam mətn "Order Confirmed" olduqda keçir
await expect(page.locator('h1')).toHaveText('Order Confirmed');
// Regex ilə — tam uyğunluq tələb olunur
await expect(page.locator('.status-badge')).toHaveText(/Processing/);

Sizi aldatdığı hal: Element " Order Confirmed " (əlavə boş yerlə) saxlayırsa, Playwright boş yeri normallaşdırır, buna görə yenə keçir. Amma element "Your Order Confirmed" saxlayırsa, uğursuz olur.

toContainText — alt string uyğunluğu

Bölmə: “toContainText — alt string uyğunluğu”

toContainText elementin mətninin gözlənilən stringi içindəki hər hansı bir yerdə ehtiva etdiyini iddia edir.

// Mətn "Order" içeriyorsa keçir
await expect(page.locator('h1')).toContainText('Order');
// Dinamik məzmun üçün çox faydalıdır — ID-lər, tarixlər, istifadəçi adları
await expect(page.locator('.confirmation')).toContainText('order #');
// Alt string semantikası ilə regex
await expect(page.locator('.message')).toContainText(/\d+ items/);
// toHaveText — dəqiq stringi siz idarə edirsiniz
await expect(page.locator('.cart-empty')).toHaveText('Your cart is empty');
// toContainText — string dinamikdir ya da başqa mətnlə əhatə olunub
await expect(page.locator('h1')).toContainText('Order'); // "Order #12345" ilə uyğunlaşır
// Dinamik URL-lər üçün regex ilə toHaveURL
await expect(page).toHaveURL(/\/orders\/\d+/);

Əsas qayda: Dəqiq mətn hər hansı bir dinamik şey (ID-lər, zaman damgaları, istifadəçi adları) ehtiva edirsə toContainText-ə müraciət edin. Stringi tamamilə siz idarə edirsizsə toHaveText istifadə edin.

Yadda saxla: toHaveText = dəqiq (boş yer normallaşdırılır), toContainText = alt string — dinamik hər şey üçün toContainText-i default seç.


toHaveValue form sahəsinin — <input>, <textarea> ya da <select>-in — hazırkı dəyərini iddia edir.

// Mətn daxiletməsinin dəyərini iddia edin
await expect(page.locator('#email')).toHaveValue('customer@test.io');
// Textarea-nı iddia edin
await expect(page.locator('#description')).toHaveValue('Test product description');
// Select dropdown-ının hazırkı seçimini iddia edin
await expect(page.locator('#category')).toHaveValue('electronics');
// Qismən dəyər uyğunluğu üçün regex istifadə edin
await expect(page.locator('#search')).toHaveValue(/widget/i);

Yaygın şablon — doldurun, sonra yoxlayın:

await page.locator('#shipping_name').fill('Jane Doe');
await expect(page.locator('#shipping_name')).toHaveValue('Jane Doe');
await page.locator('#category').selectOption('electronics');
await expect(page.locator('#category')).toHaveValue('electronics');

Qeyd: toHaveValue DOM-un value xassəsini oxuyur, görünən mətni deyil. <select> üçün option-ın etiket mətni deyil, value atributunu qaytarır.

Yadda saxla: toHaveValue sahənin DOM value-sunu oxuyur; <select> üçün bu, etiket deyil, option-ın value-sudur.


toHaveAttribute bir elementin müəyyən bir dəyərə sahib xüsusi bir atribut daşıdığını iddia edir.

// href atributunu iddia edin
await expect(page.getByRole('link', { name: 'Terms' })).toHaveAttribute(
'href',
'/terms'
);
// Data atributunu iddia edin
await expect(page.locator('.product-card').first()).toHaveAttribute(
'data-product-id',
'42'
);
// Əlçatanlıq testi üçün aria atributlarını iddia edin
await expect(page.getByRole('button', { name: 'Submit' })).toHaveAttribute(
'aria-disabled',
'true'
);
// Qismən atribut dəyərləri üçün regex istifadə edin
await expect(page.locator('img.hero')).toHaveAttribute('src', /\/images\//);

İpucu: toHaveAttribute xüsusən disabled, aria-label, data-testid, typehref dəyərlərini iddia etmək üçün faydalıdır.

// Daxiletmədəki type atributunu iddia edin
await expect(page.locator('#password')).toHaveAttribute('type', 'password');
// "Parolu göstər" toggle-dan sonra
await page.locator('#show-password').click();
await expect(page.locator('#password')).toHaveAttribute('type', 'text');

Yadda saxla: toHaveAttribute(ad, dəyər) bir atributu yoxlayır — qismən uyğunluq üçün regex ver.


toHaveCount bir lokatorla uyğunlaşan elementlərin sayını iddia edir. Bütün veb-first assertion-lar kimi, say uyğunlaşana ya da vaxt aşımı bitənə qədər yenidən cəhd edir.

// Siyahıda tam olaraq 3 element olduğunu iddia edin
await expect(page.locator('.cart-item')).toHaveCount(3);
// Cədvəlin tam olaraq 5 sətrə sahib olduğunu iddia edin
await expect(page.locator('.product-table tbody tr')).toHaveCount(5);
// Elementlərin silindiğini iddia edin — say 0-a çatana qədər yenidən cəhd edir
await expect(page.locator('.cart-item')).toHaveCount(0);

toHaveCount(0) güclüdür. Hazırda 3 element varsa və toHaveCount(0) iddia edirsizsə, Playwright hamısı yox olana qədər yoxlamanı yenidən cəhd edəcək. Bu, silmə axınlarını test etmənin düzgün yoludur.

// 3 element əlavə edin, sonra hamısını silin, sonra təmiz vəziyyəti iddia edin
await expect(page.locator('.cart-item')).toHaveCount(3);
await page.locator('.remove-all-btn').click();
// Bütün elementlər DOM-dan silinənə qədər yenidən cəhd edir
await expect(page.locator('.cart-item')).toHaveCount(0);
await expect(page.locator('.empty-cart-message')).toBeVisible();

toHaveCount vs manual say:

// OTOMATİK YENİDƏN CƏHD EDIR — elementlər asinxron olaraq göründüyündə bunu istifadə edin
await expect(page.locator('.search-result')).toHaveCount(5);
// OTOMATİK YENİDƏN CƏHD ETMİR — yalnız sinxron anlıq görüntülər üçün istifadə edin
const count = await page.locator('.search-result').count();
expect(count).toBeGreaterThan(0);

Yadda saxla: toHaveCount(n) say dəqiq n olana qədər yenidən cəhd edir; toHaveCount(0) “hamısı getdi”-ni iddia etmənin təmiz yoludur.


Bu assertion-lar form kontrolunun interaktiv olub olmadığını yoxlayır. Otomatik yenidən cəhd edirlər — məcburi sahələr doldurulduqdan sonra göndər düyməsinin aktiv hala gəldiyini iddia etmək üçün faydalıdır.

// Göndər düyməsinin aktiv olduğunu iddia edin
await expect(page.locator('button[type="submit"]')).toBeEnabled();
// Form boş olduqda göndər düyməsinin deaktiv olduğunu iddia edin
await expect(page.locator('button[type="submit"]')).toBeDisabled();

Şablon — yalnız forma düzgün olduqda aktivləşən düymə:

Bəzi tətbiqlər bütün məcburi sahələr doldurulana qədər göndər düyməsini deaktiv saxlayır. Bu assertion-lar avtomatik yenidən cəhd etdiyi üçün keçidi manual gözləmə olmadan iddia edə bilərsiniz:

// Forma düzgün olana qədər düyməsini deaktiv saxlayan signup formasında
await expect(page.locator('#signup-btn')).toBeDisabled();
await page.getByLabel('Email').fill('new@user.io');
await page.getByLabel('Password').fill('secret123');
await page.getByLabel('Confirm Password').fill('secret123');
// Playwright düymə aktivə keçənə qədər yenidən cəhd edir
await expect(page.locator('#signup-btn')).toBeEnabled();

toBeEnabled vs not.toBeDisabled: Ekvivalentdirlər. Test ssenarinizdə daha natural oxunanı seçin.

// Bu iki sətir eyni şeyi iddia edir
await expect(page.locator('#submit')).toBeEnabled();
await expect(page.locator('#submit')).not.toBeDisabled();

Yadda saxla: toBeEnabled/toBeDisabled avtomatik yenidən cəhd edir, ona görə kontrolun vəziyyət dəyişməsini gözləyir; toBeEnablednot.toBeDisabled.


İstənilən Playwright assertion-ı .not ilə inkar edilə bilər. İnkar edilmiş assertion da otomatik yenidən cəhd edir — şərt yanlış olana qədər gözləyir.

// Bir element artıq görünməyənə qədər gözləyin (məsələn, yükləmə fırlacı)
await expect(page.locator('.loading-spinner')).not.toBeVisible();
// Admin olmayan istifadəçilərin admin kontrollarını görə bilmədiyini iddia edin
await expect(page.locator('#admin-panel')).not.toBeVisible();
// URL-in admin bölməsinə getmədiyini iddia edin
await expect(page).not.toHaveURL('/admin');
// Mətni olmadığını iddia edin
await expect(page.locator('.status')).not.toHaveText('Error');
// Sahənin təmizləndiyini iddia edin
await expect(page.locator('#search')).not.toHaveValue('old query');

Giriş kontrolu üçün mənfi assertion-lar:

test('admin olmayan istifadəçi admin bölməsindən yönləndirilir', async ({ page }) => {
// Normal müştəri (admin deyil) kimi daxil olun
await page.goto('/admin');
// Səhifənin yönləndirildiyini iddia edin — URL /admin ehtiva etməməlidir
await expect(page).not.toHaveURL(/\/admin/);
// Admin panel başlığının görünmədiyini iddia edin
await expect(page.locator('h1')).not.toHaveText('Admin Dashboard');
// Bunun əvəzinə xəta xəbərdarlığının görünür olduğunu iddia edin
await expect(page.locator('.alert.alert-error')).toBeVisible();
});

Yadda saxla: .not da yenidən cəhd edir — şərt yanlış olana qədər gözləyir (fırlacın yox olması, sahənin təmizlənməsi).


Defolt olaraq uğursuz bir assertion testi dərhal dayandırır. Soft assertion-lar fərqlidir — soft assertion uğursuz olsa belə test davam edir. Bütün uğursuzluqlar toplanır və testin sonunda birlikdə bildirilir.

// Soft assertion-lar — bunlar uğursuz olsa belə test davam edir
await expect.soft(page.locator('.widget-revenue')).toBeVisible();
await expect.soft(page.locator('.widget-orders')).toBeVisible();
await expect.soft(page.locator('.widget-users')).toBeVisible();
await expect.soft(page.locator('.widget-products')).toBeVisible();
// Testin sonunda Playwright bütün uğursuzluqları bir anda bildirir
// yuxarıdakılardan biri uğursuz olsa belə

Soft assertion-lar nə vaxt istifadə edilər:

  • Panel smoke testləri — 10+ vidgeti yoxlamaq və yalnız birincini deyil, bütün uğursuzları görmək istəyirsiniz
  • Vizual tamlıq yoxlamaları — bir səhifənin bütün bölümlərinin düzgün render olunduğunu yoxlamaq
  • Paralel forma validasiyası — eyni anda bir neçə sahəni yoxlamaq
test('admin panel smoke testi', async ({ page }) => {
// (admin kimi daxil olunub)
await page.goto('/admin');
// Hər stat kartını yoxlayın — bütün çatışmayanları bir anda bildirin
await expect.soft(page.getByRole('heading', { name: 'Total Products' })).toBeVisible();
await expect.soft(page.getByRole('heading', { name: 'Total Users' })).toBeVisible();
await expect.soft(page.getByRole('heading', { name: 'Total Orders' })).toBeVisible();
await expect.soft(page.getByRole('heading', { name: 'Recent Orders' })).toBeVisible();
// İsteğe bağlı: soft uğursuzluqların toplanmadığını iddia edin
expect(test.info().errors).toHaveLength(0);
});

Diqqət: Soft assertion-lar güclüdür, amma onlardan səhv istifadə etmək asandır. Bir testin 15 soft assertion-ı varsa və 10-u uğursuz olarsa, bildiriş çox qarışıq olur. Onları test strukturu haqqında düşünməmənin bir yolu kimi deyil, smoke yoxlamaları üçün qəsdən istifadə edin.

Yadda saxla: expect.soft(...) uğursuzluğu qeyd edib davam edir — smoke yoxlamaları üçün, kritik yol axını üçün yox.


Xüsusi expect vaxt aşımları

Bölmə: “Xüsusi expect vaxt aşımları”

Defolt olaraq, hər veb-first assertion uğursuz olmazdan əvvəl 5 saniyə gözləyir. Bunu hər assertion üçün ayrıca ya da qlobal olaraq dəyişdirə bilərsiniz.

Assertion-başına vaxt aşımı

Bölmə: “Assertion-başına vaxt aşımı”
// Bu xüsusi assertion üçün 10 saniyəyə qədər gözləyin
await expect(page.locator('.slow-component')).toBeVisible({ timeout: 10_000 });
// Qısa vaxt aşımı — element tez görünmürsə sürətlə uğursuz olun
await expect(page.locator('.instant-feedback')).toBeVisible({ timeout: 1_000 });
// İstənilən assertion-da xüsusi vaxt aşımı
await expect(page.locator('.report-table')).toHaveCount(50, { timeout: 15_000 });

playwright.config.js-də qlobal vaxt aşımı

Bölmə: “playwright.config.js-də qlobal vaxt aşımı”
playwright.config.js
import { defineConfig } from '@playwright/test';
export default defineConfig({
expect: {
timeout: 10_000, // bütün assertion-lar üçün 10 saniyə
},
});

Xüsusi vaxt aşımı nə vaxt istifadə edilər:

  • Məlum yavaş əməliyyatlar (hesabat yaratma, fayl emalı, email çatdırılması)
  • Yerli geliştirme mühitindən əhəmiyyətli dərəcədə daha yavaş olan CI mühitləri
  • Başlatmaq üçün vaxt tələb edən üçüncü tərəf vidgetləri

Xüsusi vaxt aşımı nə vaxt istifadə edilməməlidir: yavaş ya da flakey bir tətbiq üçün plaster kimi. Hər yerə timeout: 30_000 əlavə edirsinizsə, doğru düzəliş testi deyil, tətbiqin profilini çıxarmaqdır.

Yadda saxla: { timeout } ilə hər assertion üçün və ya expect.timeout ilə qlobal olaraq dəyiş — həqiqətən yavaş əməliyyatlar üçün, flakey tətbiqi gizlətmək üçün yox.


Nəyi iddia etmək istəyirəm…İstifadə et
Element görünür / gizlitoBeVisible() · not.toBeVisible()
Element DOM-da (bəlkə gizli)toBeAttached()
Dəqiq mətntoHaveText('…')
Mətnin alt stringitoContainText('…')
Form sahəsinin dəyəritoHaveValue('…')
Atributun dəyəritoHaveAttribute('ad', '…')
Neçə element uyğun gəlirtoHaveCount(n) (0 daxil)
Kontrol interaktivdirtoBeEnabled() · toBeDisabled()
Checkbox / radio vəziyyətitoBeChecked() (Modul 3-ə bax)
Hazırkı səhifə URL-itoHaveURL('…' və ya /regex/)
Səhifədəki bütün uğursuzluqları toplaexpect.soft(…)
Yavaş element üçün daha çox gözlə…({ timeout: 10_000 })


Bu tapşırıqlar http://localhost:3000-də yerli olaraq işləyən TestMarket Lab istifadə edir.


Tapşırıq 1: Səbət vəziyyətini iddia edin

Bölmə: “Tapşırıq 1: Səbət vəziyyətini iddia edin”

tests/starter/mod4/cart-assertions.spec.js yaradın. beforeEach daxil olur; sonra hər test veb-first assertion-larla bir səbət vəziyyətini iddia edir.

import { test, expect } from '@playwright/test';
test.describe('Səbət assertion-ları', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/auth/login');
await page.locator('#email').fill('customer@test.io');
await page.locator('#password').fill('customer123');
await page.getByTestId('login-submit').click();
await expect(page.locator('.alert.alert-success')).toBeVisible();
});
test('elementləri olan səbət sətirlər, cəm və ödəniş keçidi göstərir', async ({ page }) => {
await page.goto('/products');
await page.getByTestId('add-to-cart').first().click();
await page.goto('/cart');
await expect(page.locator('.cart-table .table-row')).not.toHaveCount(0);
await expect(page.locator('.total-row h3')).toBeVisible();
await expect(page.getByRole('link', { name: 'Proceed to Checkout' })).toBeVisible();
});
test('boş səbət boş vəziyyət mesajını göstərir', async ({ page }) => {
// Təzə brauzer konteksti boş (sessiya əhatəli) səbətlə başlayır
await page.goto('/cart');
await expect(page.getByText('Your cart is empty')).toBeVisible();
await expect(page.locator('.cart-table .table-row')).toHaveCount(0);
await expect(page.locator('.total-row h3')).not.toBeVisible();
});
});

Tapşırıqlar:

  • Birinci testdə not.toHaveCount(0)-u toHaveCount(5)-ə dəyişin və assertion-ın uğursuz olmazdan əvvəl tam vaxt aşımı boyunca yenidən cəhd etməsinə baxın.
  • add-to-cart sətrini silin — indi not.toHaveCount(0) uğursuz olur, çünki səbət boşdur.

Tapşırıq 2: Ödəniş təsdiqi assertion-ları

Bölmə: “Tapşırıq 2: Ödəniş təsdiqi assertion-ları”

tests/starter/mod4/checkout-assertions.spec.js yaradın. beforeEach daxil olur, məhsul əlavə edir və ödənişi açır.

import { test, expect } from '@playwright/test';
test.describe('Ödəniş assertion-ları', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/auth/login');
await page.locator('#email').fill('customer@test.io');
await page.locator('#password').fill('customer123');
await page.getByTestId('login-submit').click();
await page.goto('/products');
await page.getByTestId('add-to-cart').first().click();
await page.goto('/checkout');
});
test('sifariş vermək təsdiq səhifəsinə aparır', async ({ page }) => {
await page.locator('#shipping_name').fill('Jane Doe');
await page.locator('#shipping_address').fill('123 Main Street');
await page.locator('#shipping_city').fill('Portland');
await page.locator('#shipping_zip').fill('97201');
await page.getByTestId('place-order').click();
// Dinamik sifariş URL-i — regex ilə uyğunlaşdır
await expect(page).toHaveURL(/\/orders\/\d+/);
// Başlıq "Order Confirmation" oxuyur — alt string uyğunluğu
await expect(page.locator('h1')).toContainText('Order');
await expect(page.locator('.alert.alert-success')).toBeVisible();
});
test('boş forma HTML5 validasiyası ilə bloklanır', async ({ page }) => {
// Məcburi sahələr göndərməni client tərəfdə dayandırır — səhifə naviqasiya etmir
await page.getByTestId('place-order').click();
await expect(page).toHaveURL(/\/checkout/);
});
});

Tapşırıqlar:

  • toContainText('Order')-u toHaveText('Order') ilə dəyişin — dəqiq uyğunluq uğursuz olur (real mətn “Order Confirmation”-dır); geri qaytarın.
  • Boş forma testində yalnız #shipping_name-i doldurun, sonra göndərin — növbəti çatışmayan məcburi sahə yenə naviqasiyanı bloklayır.

Tapşırıq 3: Admin assertion-ları — cədvəl + giriş kontrolu

Bölmə: “Tapşırıq 3: Admin assertion-ları — cədvəl + giriş kontrolu”

tests/starter/mod4/admin-assertions.spec.js yaradın. Bir test admin kimi daxil olur; digəri müştərinin bloklandığını sübut edir.

import { test, expect } from '@playwright/test';
test.describe('Admin assertion-ları', () => {
test('admin məhsullar səhifəsi sətirlər və New Product düyməsi göstərir', async ({ page }) => {
await page.goto('/auth/login');
await page.locator('#email').fill('admin@test.io');
await page.locator('#password').fill('admin123');
await page.getByTestId('login-submit').click();
await page.goto('/admin/products');
await expect(page.locator('.table-row')).not.toHaveCount(0);
await expect(page.getByRole('link', { name: 'New Product' })).toBeVisible();
});
test('müştəri /admin-dən xəta ilə yönləndirilir', async ({ page }) => {
await page.goto('/auth/login');
await page.locator('#email').fill('customer@test.io');
await page.locator('#password').fill('customer123');
await page.getByTestId('login-submit').click();
await page.goto('/admin');
// /admin-dən yönləndirilir (tətbiq admin olmayanları ana səhifəyə göndərir)...
await expect(page).not.toHaveURL(/\/admin/);
// ...və giriş-rədd flash-ı həmin təyinat səhifəsində render olunur
await expect(page.locator('.alert.alert-error')).toContainText('Access denied');
});
});

Tapşırıqlar:

  • İkinci testdə müştəri kimlik məlumatlarını admin-inkilərlə dəyişin — yönləndirmə assertion-ı indi uğursuz olur, çünki admin həqiqətən /admin-ə çatır.
  • Birinci testə await expect(page.locator('.alert.alert-error')).not.toBeVisible(); əlavə edin ki, düzgün admin yüklənməsində xəta görünmədiyini təsdiqləyəsiniz.

Tapşırıq 4: Sabit gözləmələri assertion-larla əvəz edin

Bölmə: “Tapşırıq 4: Sabit gözləmələri assertion-larla əvəz edin”

Bu flakey testi refaktor edin — hər waitForTimeout-u düzgün veb-first assertion-la əvəz edin:

// ƏVVƏL (flakey — hər yerdə sabit yuxular)
import { test, expect } from '@playwright/test';
test('flakey axtarış testi', async ({ page }) => {
await page.goto('/products');
await page.waitForTimeout(2000);
await page.fill('#search', 'Wireless');
await page.waitForTimeout(1000);
await page.click('#apply-filters');
await page.waitForTimeout(3000);
const count = await page.locator('.product-card').count();
expect(count).toBeGreaterThan(0);
await page.waitForTimeout(1000);
expect(page.url()).toContain('search=Wireless');
});
YuxuƏvəz et
waitForTimeout(2000)Silin — fill() artıq avtomatik gözləyir
waitForTimeout(1000)Silin — click() artıq avtomatik gözləyir
waitForTimeout(3000) + manual sayexpect(locator).not.toHaveCount(0)
waitForTimeout(1000) + page.url()expect(page).toHaveURL(/[?&]search=Wireless/)
// SONRA (veb-first — sabit yuxular yoxdur)
import { test, expect } from '@playwright/test';
test('etibarlı axtarış testi', async ({ page }) => {
await page.goto('/products');
await page.locator('#search').fill('Wireless');
await page.locator('#apply-filters').click();
await expect(page.locator('.product-card')).not.toHaveCount(0);
await expect(page).toHaveURL(/[?&]search=Wireless/);
});

Tapşırıq 5: Soft assertion-lar — bütün vidgetləri bir anda yoxlayın

Bölmə: “Tapşırıq 5: Soft assertion-lar — bütün vidgetləri bir anda yoxlayın”

tests/starter/mod4/soft-assertions.spec.js yaradın. Bu tamamilə öz-özünə yetərlidir — page.evaluate ilə mock panel inject edir, ona görə istənilən səhifədə işləyir.

import { test, expect } from '@playwright/test';
test('soft assertion-larla panel smoke yoxlaması', async ({ page }) => {
await page.goto('/products');
// Dörd stat vidgeti olan mock panel inject edin
await page.evaluate(() => {
const panel = document.createElement('div');
panel.id = 'dashboard';
panel.innerHTML = `
<div data-testid="widget-revenue">Revenue: $12,400</div>
<div data-testid="widget-orders">Orders: 87</div>
<div data-testid="widget-users">Users: 1,203</div>
<div data-testid="widget-products">Products: 56</div>`;
document.body.appendChild(panel);
});
// Soft assertion-lar: əvvəlki biri uğursuz olsa belə hər vidget yoxlanılır,
// və bütün uğursuzluqlar testin sonunda birlikdə bildirilir.
await expect.soft(page.getByTestId('widget-revenue')).toBeVisible();
await expect.soft(page.getByTestId('widget-orders')).toBeVisible();
await expect.soft(page.getByTestId('widget-users')).toBeVisible();
await expect.soft(page.getByTestId('widget-products')).toBeVisible();
// İsteğe bağlı qapı: hər hansı soft assertion uğursuz olubsa testi uğursuz et
expect(test.info().errors).toHaveLength(0);
});

Tapşırıqlar:

  • İnject edilmiş HTML-dən widget-users sətrini silin (assertion-ını saxlayın) və yenidən işlədin — test yenə hər dörd vidgeti yoxlayır, sonra bir uğursuzluğu sonda bildirir, ona toxunub dayanmır.
  • Hər dörd expect.soft-u sadə expect-ə dəyişin, vidget hələ də çatışmırkən — indi test ilk uğursuzluqda dayanır və qalanını heç vaxt yoxlamır. Bu fərq soft assertion-ların bütün məğzidir.

  1. Nə üçün expect(locator).toBeVisible() avtomatik yenidən cəhd edir, amma expect(await locator.isVisible()).toBe(true) etmir?
  2. toHaveText vs toContainText-i nə vaxt istifadə edərdiniz? Hər biri üçün bir nümunə verin.
  3. Hazırda 5 uyğun element varsa toHaveCount(0) nə edir?
  4. Adi assertion ilə soft assertion (expect.soft) arasındakı fərq nədir?
  5. Assertion-başına vaxt aşımını necə təyin edirsiniz? Qlobal defoltunu necə?
  6. Nə üçün toBeEnabled forma validasiya testləri üçün faydalıdır?
  7. toHaveAttribute('href', '/terms') nəyi iddia edir?
  8. Nə üçün expect(page.url()).toContain('/admin') expect(page).toHaveURL('/admin')-dən daha pisdir?

Hər testə apardığınız dörd qayda:

  1. expect()-ə həmişə Locator verin — gözlənilmiş dəyər deyil. expect(locator).toBeVisible() yenidən cəhd edir; expect(await locator.isVisible()).toBe(true) etmir.
  2. Dinamik məzmun üçün toContainText, dəqiq stringlər üçün toHaveText — şübhə etdikdə toContainText-i üstün tutun
  3. toHaveCount element siyahılarında yenidən cəhd edir — elementlər asinxron olaraq göründüyündə count()-dan əvəz istifadə edin
  4. Smoke testləri üçün soft assertion-lar, axın testləri üçün hard assertion-lar — səhifə səviyyəsindəki yoxlamada bütün uğursuzluqları toplayın; kritik yol testlərində sürətlə uğursuz olun

Modul 5 avtomatik gözləməni əhatə edir — Playwright-in daxili əməliyyat yoxlamalarının açıq gözləmələri necə aradan qaldırdığını və onlar kifayət etmədikdə nə edəcəyinizi öyrənəcəksiniz.