Playwright — End-to-End testing, brauzerda test
Muammodan boshlaylik
Unit testlar yashil. Komponent testlari yashil. Deploy qildingiz — va "Buyurtma berish" ishlamayapti: middleware login sahifasiga yo'naltiradi, Server Action cookie ni ko'rmaydi, chunki production da secure cookie sozlamasi boshqacha.
Har bir qism alohida ishlaydi — lekin birgalikda emas. Bunday xatolarni faqat haqiqiy brauzerda, haqiqiy server bilan, foydalanuvchi kabi harakat qilib topish mumkin.
E2E nima?
End-to-End test — ilovani boshidan oxirigacha, haqiqiy foydalanuvchi kabi sinash: brauzer ochiladi, sahifaga kiriladi, tugmalar bosiladi, formalar to'ldiriladi.
Playwright — Microsoft ning E2E vositasi:
- Chromium, Firefox, WebKit (Safari) — uchala dvigatel
- Avtomatik kutish — element paydo bo'lishini o'zi kutadi
- Parallel ishga tushirish, trace va video yozish
- Mobil qurilmalar emulyatsiyasi
Hayotiy o'xshatma
Yangi restoranni ochishdan oldin "sinov kechasi": do'stlar haqiqiy mijozlardek kelib, stol band qiladi, buyurtma beradi, ovqatlanadi va hisob to'laydi. Oshxona, zal va kassa alohida sinalgan — lekin faqat shu kechada ular birga ishlay olishi aniq bo'ladi.
O'rnatish
npm init playwright@latest
Savollar: TypeScript, testlar papkasi (e2e), GitHub Actions workflow, brauzerlarni o'rnatish.
// playwright.config.ts
import { defineConfig, devices } from '@playwright/test'
export default defineConfig({
testDir: './e2e',
fullyParallel: true,
retries: process.env.CI ? 2 : 0,
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'mobil', use: { ...devices['Pixel 7'] } },
],
webServer: {
command: 'npm run build && npm run start',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
timeout: 120_000,
},
})
webServer — testlardan oldin Next.js ni production rejimida ishga tushiradi (development emas — production xatti-harakatini sinash uchun).
Birinchi test
// e2e/katalog.spec.ts
import { test, expect } from '@playwright/test'
test('katalogdan mahsulot sahifasiga o\'tish', async ({ page }) => {
await page.goto('/katalog')
await expect(page.getByRole('heading', { name: 'Katalog' })).toBeVisible()
await page.getByRole('link', { name: /Choynak/ }).first().click()
await expect(page).toHaveURL(/\/mahsulot\//)
await expect(page.getByRole('button', { name: 'Savatga' })).toBeVisible()
})
test('filtr URL ni o\'zgartiradi', async ({ page }) => {
await page.goto('/katalog')
await page.getByLabel('Kategoriya').selectOption('telefon')
await expect(page).toHaveURL(/kategoriya=telefon/)
})
npx playwright test # hammasi
npx playwright test --ui # interaktiv UI rejim
npx playwright test --headed # brauzerni ko'rib turish
npx playwright show-report # HTML hisobot
Lokatorlar — RTL dagi kabi (62-dars): getByRole, getByLabel, getByText. expect lar — avtomatik kutadi (standart 5 s).
To'liq oqim — buyurtma berish
test('mehmon savatga qo\'shib, kirib, buyurtma beradi', async ({ page }) => {
await page.goto('/mahsulot/choynak')
await page.getByRole('button', { name: 'Savatga' }).click()
await expect(page.getByTestId('savat-soni')).toHaveText('1')
await page.getByRole('link', { name: 'Savat' }).click()
await page.getByRole('button', { name: 'Rasmiylashtirish' }).click()
// login ga yo'naltirildi
await expect(page).toHaveURL(/\/login/)
await page.getByLabel('Email').fill('test@dokon.uz')
await page.getByLabel('Parol').fill('testparol123')
await page.getByRole('button', { name: 'Kirish' }).click()
// qaytib keldi
await page.getByLabel('Manzil').fill('Toshkent, Amir Temur 1')
await page.getByRole('button', { name: 'Buyurtma berish' }).click()
await expect(page.getByRole('heading', { name: /Buyurtma qabul qilindi/ })).toBeVisible()
})
Autentifikatsiyani qayta ishlatish
Har bir testda login qilish — sekin. Bir marta kirib, holatni saqlash:
// e2e/auth.setup.ts
import { test as setup, expect } from '@playwright/test'
setup('login', async ({ page }) => {
await page.goto('/login')
await page.getByLabel('Email').fill(process.env.E2E_EMAIL!)
await page.getByLabel('Parol').fill(process.env.E2E_PAROL!)
await page.getByRole('button', { name: 'Kirish' }).click()
await expect(page).toHaveURL('/dashboard')
await page.context().storageState({ path: 'e2e/.auth/user.json' })
})
// playwright.config.ts
projects: [
{ name: 'setup', testMatch: /auth\.setup\.ts/ },
{
name: 'chromium',
use: { ...devices['Desktop Chrome'], storageState: 'e2e/.auth/user.json' },
dependencies: ['setup'],
},
],
e2e/.auth/ ni .gitignore ga qo'shing — unda sessiya cookie si.
[!WARNING] E2E testlarni production bazasiga qarshi ishga tushirmang — testlar buyurtma yaratadi, foydalanuvchilarni o'zgartiradi. Alohida test bazasi, har bir ishga tushirishdan oldin seed (boshlang'ich ma'lumotlar), tashqi to'lov va SMS xizmatlari — test rejimida yoki mock (64-dars).
Tarmoqni mock qilish
test('API xatosida xabar ko\'rsatiladi', async ({ page }) => {
await page.route('**/api/tavsiyalar', (route) =>
route.fulfill({ status: 500, body: JSON.stringify({ xato: 'server' }) })
)
await page.goto('/')
await expect(page.getByText('Tavsiyalarni yuklab bo\'lmadi')).toBeVisible()
})
page.route — faqat brauzerdan ketadigan so'rovlarni ushlaydi. Server Component lardagi fetch lar serverda — ular uchun MSW (64-dars) yoki test API.
CI da
npm init playwright yaratgan .github/workflows/playwright.yml:
- run: npm ci
- run: npx playwright install --with-deps
- run: npx playwright test
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
Xato bo'lsa — hisobot va trace ni yuklab olib, Playwright Trace Viewer da har bir qadamni (DOM, tarmoq, konsol) ko'rish mumkin.
[!TIP] E2E testlar sekin va qimmat. Faqat muhim oqimlarni yozing: ro'yxatdan o'tish, kirish, to'lov, asosiy qidiruv. Detallarni unit va komponent testlarga qoldiring.
Tez-tez uchraydigan xatolar
1. waitForTimeout(3000)
Qattiq kutish — testlar sekin va beqaror. expect(...).toBeVisible() o'zi kutadi.
2. CSS selektorlar
page.locator('.btn-primary > span') — dizayn o'zgarsa buziladi. Rol va label bo'yicha.
3. Development serverga qarshi test
npm run dev — boshqa xatti-harakat (kesh, xatolar overlay). build && start.
Xulosa
E2E — haqiqiy brauzer, haqiqiy server, butun oqim
npm init playwright@latest; webServer: build && start
page.goto, getByRole/getByLabel, click, fill, expect(...).toBeVisible/toHaveURL
Avtomatik kutish — waitForTimeout yo'q
storageState — bir marta login, qayta ishlatish
Test bazasi; production ga qarshi emas
page.route — brauzer so'rovlarini mock; CI da trace va hisobot
Faqat muhim oqimlar
Keyingi dars
64-dars: MSW — API mock qilish Next.js da
Tashqi API larni testlarda va development da soxta javoblar bilan almashtirish.