Modul 10: Autentifikasiya və Storage State
Modul 10-a xoş gəldiniz. POM-lar, fixture-lar, API testləri və CI pipeline-lar qurdunuz. İndi real test paketindəki ən böyük performans darboğazını həll edirik: hər testdən əvvəl giriş etmək.
Bu modulun sonunda bir dəfə giriş edəcək, həmin autentifikasiya vəziyyətini bütün paketiniz boyu təkrar istifadə edəcək və hansı təkrar-istifadə üsulunun hansı vəziyyətə uyğun gəldiyini dəqiq başa düşəcəksiniz — həm token əsaslı tətbiqlər, həm də üzərində məşq etdiyimiz HTTP-only sessiya tətbiqi üçün.
🎬 Video tezliklə əlavə olunacaq
Niyə hər testdə giriş etmək yavaş və kövrəkdir
Bölmə: “Niyə hər testdə giriş etmək yavaş və kövrəkdir”Əksər test paketləri giriş səhifəsinə keçən, kimlik məlumatlarını dolduran və formanı göndərən bir beforeEach ilə başlayır. Bu, təhlükəsiz və proqnozlaşdırıla bilən görünür. Praktikada iki ciddi problem yaradır.
Vaxt problemi. Tipik UI girişi 1–3 saniyə çəkir. Bunu 50 testə vurun və tək bir təkid işə düşməzdən əvvəl hər işlətmədə 2–3 dəqiqə itirirsiniz. 200 testdə əlavə yük 10 dəqiqəni keçir.
Kövrəklik problemi. Hər giriş cəhdi şəbəkəni keçir, forma sahələrini doldurur, yönləndirmələri gözləyir və serverin dar bir taymaut içində cavab verməsindən asılıdır. Bu addımların hər biri ayrıca uğursuz ola bilər. Kövrək giriş test xətası deyil — amma elə görünür və hər debug sessiyası eyni yerə gəlib çıxır.
Playwright bizə girişi təkrarlamamağın iki yolunu verir: storageState (autentifikasiya vəziyyətini diskə seriallaşdırıb yenidən oynatmaq) və autentifikasiya fixture-u (təkrar istifadə edilə bilən brauzer kontekstində bir dəfə giriş edib daxil olmuş səhifəni hər testə vermək). Bu modul hər ikisini öyrədir və — əsas məsələ — hər birinin nə zaman uyğun gəldiyini.
Yadda saxla: test başına giriş paketin işləmə vaxtına ən böyük və ən kövrək vergidir — bir dəfə giriş edin və nəticəni təkrar istifadə edin; storageState və autentifikasiya fixture-u bunu etməyin iki yoludur.
storageState konsepti
Bölmə: “storageState konsepti”İstifadəçi brauzer vasitəsilə giriş etdikdə server kimlik sübutu geri göndərir — adətən bunlardan biri və ya bir neçəsi:
Set-Cookiecavab başlığı ilə təyin edilən sessiya kukisilocalStoragevə ya kukidə saxlanan JWT token- Hər ikisinin birləşməsi
Playwright-in storageState-i həmin sübutu iki üst səviyyəli açarı olan tək bir JSON faylına seriallaşdırır:
{ "cookies": [ { "name": "connect.sid", "value": "s%3Aabc123...", "domain": "localhost", "path": "/", "httpOnly": true } ], "origins": [ { "origin": "http://localhost:3000", "localStorage": [ { "name": "token", "value": "eyJhbGciOi..." } ] } ]}Vəziyyəti saxlamaq uğurlu girişdən sonra edilir:
await page.context().storageState({ path: 'auth/customer.json' });Çağırışın page-də yox, page.context()-də olduğuna diqqət edin — storageState bir BrowserContext metodudur.
Vəziyyəti yükləmək yeni kontekst yaradanda (və ya bunu avtomatik edən konfiqurasiya vasitəsilə) edilir:
const context = await browser.newContext({ storageState: 'auth/customer.json',});Həmin kontekstdə hər hansı səhifə yüklənməzdən əvvəl Playwright kukiləri və localStorage-i fayldan əvvəlcədən doldurur. Tətbiq artıq autentifikasiya edilmiş brauzer görür.
Yadda saxla: storageState cookies + localStorage-in BrowserContext snapshot-udur — girişdən sonra saxlayın, yeni konteksti (və ya layihəni) fayla yönəldin, tətbiq artıq autentifikasiya edilmiş halda yüklənir.
storageState və HTTP-only sessiya kukiləri
Bölmə: “storageState və HTTP-only sessiya kukiləri”Geniş yayılmış bir mif: storageState guya sessiya kukili tətbiqlərlə işləyə bilmir, çünki kuki HttpOnly-dir. Bu yanlışdır — və səbəbini başa düşmək vacibdir, çünki TestMarket Lab məhz belə bir tətbiqdir.
Qarışıqlıq document.cookie-dən gəlir: səhifədəki JavaScript həqiqətən HttpOnly kukini oxuya bilmir. Lakin storageState document.cookie istifadə etmir. O, brauzerin öz kuki anbarını DevTools protokolu vasitəsilə oxuyur, ona görə kontekstdəki bütün kukiləri tutur — HttpOnly, Secure, hamısını.
TestMarket Lab server tərəfli sessiya ilə autentifikasiya edir. O, express-session istifadə edir; onun kukisi (connect.sid) HttpOnly-dir. UI vasitəsilə giriş edin, storageState-i saxlayın və fayl connect.sid-i ehtiva edir; onu təzə kontekstə yükləyin və tətbiq sizi daxil olmuş kimi qəbul edir. Klassik “bir dəfə giriş et, storageState-i saxla, hər yerdə təkrar istifadə et” resepti burada token tətbiqlərində olduğu kimi işləyir.
Özünüz yoxlayın: UI girişindən sonra
console.log(await page.context().storageState())işlədin vəcookiesmassivindəconnect.sid-i"httpOnly": trueilə görəcəksiniz.
Real bir incəlik var, sadəcə fərqlidir. Sessiya kukisi yalnız server tərəfli sessiya anbarına açardır. Saxlanmış fayl həmin sessiya bitdikdə köhnəlir — server yenidən başlayır, sessiya vaxtı keçir və ya istifadəçi çıxış edir. Dünənki işlətmədən saxlanmış storageState bu gün heç nəyə autentifikasiya etməyə bilər. Həll yolu storageState-dən qaçmaq deyil, vəziyyəti hər işlətmənin əvvəlində təzədən yaratmaqdır (setup layihəsi bunu sizin üçün edir).
Yadda saxla: storageState HttpOnly kukiləri də tutur (o, document.cookie-ni yox, kuki anbarını oxuyur), ona görə TestMarket Lab-ın connect.sid-i üçün işləyir — əsl məhdudiyyət köhnəlmədir: fayl yalnız server tərəfli sessiyaya açar olduğu üçün onu hər işlətmədə təzədən yaradın.
Autentifikasiya-fixture nümunəsi (canlı kontekst alternativi)
Bölmə: “Autentifikasiya-fixture nümunəsi (canlı kontekst alternativi)”storageState saxlanmış sessiyanı yenidən oynadır. Bəzən isə canlı sessiya saxlamaq istəyirsiniz: bir BrowserContext daxilində bir dəfə giriş edin, sonra həmin artıq-autentifikasiya-edilmiş konteksti (və onun səhifəsini) fixture vasitəsilə hər testə verin. Kontekst bütün test boyu canlı olduğundan köhnələcək saxlanmış fayl yoxdur — rol dəyişdirmə və lokal iş üçün əlverişlidir.
import { test as base } from '@playwright/test';import type { Page } from '@playwright/test';
async function login(page: Page, email: string, password: string) { await page.goto('/auth/login'); await page.fill('#email', email); await page.fill('#password', password); await page.click('#login-btn'); // Server girişdən sonra yönləndirir və uğur flash-ı göstərir. await page.waitForURL((url) => !url.pathname.startsWith('/auth/login'));}
type AuthFixtures = { customerPage: Page; adminPage: Page;};
export const test = base.extend<AuthFixtures>({ customerPage: async ({ browser }, use) => { const context = await browser.newContext(); const page = await context.newPage(); await login(page, 'customer@test.io', 'customer123'); await use(page); await context.close(); },
adminPage: async ({ browser }, use) => { const context = await browser.newContext(); const page = await context.newPage(); await login(page, 'admin@test.io', 'admin123'); await use(page); await context.close(); },});Testdə istifadə — giriş kodu yoxdur, sadəcə lazım olan rolu istəyin:
import { test } from '../fixtures/auth.fixture';import { expect } from '@playwright/test';
test('daxil olmuş müştəri profil linkini görür', async ({ customerPage }) => { await customerPage.goto('/'); await expect(customerPage.locator('[data-testid="nav-profile"]')).toBeVisible();});
test('admin admin panelinə çata bilir', async ({ adminPage }) => { await adminPage.goto('/admin'); await expect(adminPage.locator('h1')).toContainText('Admin');});
test('müştəri admin panelinə çata bilmir', async ({ customerPage }) => { await customerPage.goto('/admin'); // /unauthorized marşrutu yoxdur — tətbiq admin olmayanları flash xətası ilə ana səhifəyə yönləndirir. await expect(customerPage).toHaveURL('/'); await expect(customerPage.locator('[data-testid="flash-error"]')).toBeVisible();});Hər fixture burada test-scoped-dur: ehtiyacı olan hər test üçün təzə kontekst yaradır. Bu təmiz və izolyasiyalıdır, amma hər test üçün bir dəfə giriş edir. Növbəti bölmə giriş xərcini bütün worker boyu necə amortizasiya etməyi göstərir.
Worker-scoped giriş (worker başına bir dəfə giriş)
Bölmə: “Worker-scoped giriş (worker başına bir dəfə giriş)”Eyni rolu tələb edən çoxlu testiniz varsa, giriş xərcini test başına yox, worker başına bir dəfə ödəyin. Fixture-u { scope: 'worker' } kimi işarələyin və onun kontekstini təkrar istifadə edin:
import { test as base } from '@playwright/test';import type { Page, BrowserContext } from '@playwright/test';
type WorkerAuthFixtures = { customerContext: BrowserContext;};type TestAuthFixtures = { customerPage: Page;};
export const test = base.extend<TestAuthFixtures, WorkerAuthFixtures>({ // Worker prosesi başına bir daxil olmuş kontekst. customerContext: [async ({ browser }, use) => { const context = await browser.newContext(); const page = await context.newPage(); await page.goto('/auth/login'); await page.fill('#email', 'customer@test.io'); await page.fill('#password', 'customer123'); await page.click('#login-btn'); await page.waitForURL((url) => !url.pathname.startsWith('/auth/login')); await page.close(); await use(context); await context.close(); }, { scope: 'worker' }],
// Hər test üçün paylaşılan autentifikasiya kontekstində təzə səhifə. customerPage: async ({ customerContext }, use) => { const page = await customerContext.newPage(); await use(page); await page.close(); },});customerPage-ə qarşı yazılan testlər əvvəlki kimi görünür — sadəcə artıq test başına giriş ödəmir. Sessiya bütün worker-ın ömrü boyu paylaşılan worker kontekstində canlı qalır.
Yadda saxla: autentifikasiya fixture-u saxlanmış fayl yerinə canlı daxil olmuş kontekst saxlayır — zəmanətli təzə vəziyyət və ya asan rol dəyişdirmə istəyəndə ona müraciət edin; test başına yox, worker başına bir dəfə giriş üçün onu worker scope edin.
globalSetup və setup layihələri
Bölmə: “globalSetup və setup layihələri”Əksər paketlər üçün ən təmiz “bir dəfə giriş” digər layihələrin dependencies vasitəsilə elan etdiyi xüsusi setup layihəsidir: o, UI vasitəsilə bir dəfə giriş edir, storageState-i saxlayır və hər asılı layihə həmin faylı yükləyir. TestMarket Lab üçün tövsiyə olunan yanaşma budur — saxlanmış fayl real connect.sid sessiyasını daşıyır.
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({ projects: [ { name: 'setup', testMatch: /auth\.setup\.ts/ }, { name: 'chromium', use: { ...devices['Desktop Chrome'], storageState: 'auth/customer.json' }, dependencies: ['setup'], }, ],});import { test as setup, expect } from '@playwright/test';
setup('müştəri kimi autentifikasiya', async ({ page }) => { await page.goto('/auth/login'); await page.fill('#email', 'customer@test.io'); await page.fill('#password', 'customer123'); await page.click('#login-btn'); await expect(page.locator('.alert-success')).toBeVisible(); // connect.sid-i fayla saxlayır — UI girişi sessiya kukisini təyin etdiyi üçün işləyir. await page.context().storageState({ path: 'auth/customer.json' });});Setup layihəsinin üstünlükləri realdır:
- Setup testi HTML reporter-da görünür — uğursuz olarsa trace və skrinşotları görə bilərsiniz
- Asılılıq qrafı açıqdır:
chromiumyalnızsetupkeçəndən sonra işləyir - Birdən çox layihə eyni setup layihəsindən asılı ola bilər
- O, işlətmə başına bir dəfə işləyir, ona görə hər işlətmədə təzə sessiya da yaradır — köhnəlmə incəliyinin tam əksinə
(globalSetup — konfiqurasiyada tək bir funksiya — eyni şeyi etməyin köhnə yoludur. Setup layihəsi adətən üstündür, çünki reporter-da görünür və asılılıq qrafına inteqrasiya olur.)
Yadda saxla: setup layihəsi bir dəfə giriş edir, storageState-i saxlayır və asılı layihələr onu use.storageState ilə yükləyir — TestMarket Lab üçün tövsiyə olunan yol budur və işlətmə başına bir dəfə işləmək sessiyanı təzə saxlayır.
Çoxsaylı rollar
Bölmə: “Çoxsaylı rollar”Real tətbiqlərin müxtəlif icazələri olan bir neçə istifadəçi rolu var. Setup layihəsi yanaşması ilə hər rol üçün bir setup testi yazır və hər saxlanmış faylı öz layihəsinə bağlayırsınız:
import { test as setup, expect } from '@playwright/test';import path from 'path';
const authDir = path.join(process.cwd(), 'auth');
setup('müştəri kimi autentifikasiya', async ({ page }) => { await page.goto('/auth/login'); await page.fill('#email', 'customer@test.io'); await page.fill('#password', 'customer123'); await page.click('#login-btn'); await expect(page.locator('.alert-success')).toBeVisible(); await page.context().storageState({ path: path.join(authDir, 'customer.json') });});
setup('admin kimi autentifikasiya', async ({ page }) => { await page.goto('/auth/login'); await page.fill('#email', 'admin@test.io'); await page.fill('#password', 'admin123'); await page.click('#login-btn'); await expect(page.locator('.alert-success')).toBeVisible(); await page.context().storageState({ path: path.join(authDir, 'admin.json') });});projects: [ { name: 'setup', testMatch: /auth\.setup\.ts/ }, { name: 'chromium', use: { storageState: 'auth/customer.json' }, dependencies: ['setup'], }, { name: 'admin-chromium', use: { storageState: 'auth/admin.json' }, dependencies: ['setup'], },],(Fixture yanaşması ilə hər rol sadəcə başqa bir fixture-dur — yuxarıda gördüyünüz customerPage və adminPage.)
dependencies-i olmayan layihələr paralel işləyir. dependencies elan edən layihələr başlamazdan əvvəl siyahıdakı hər layihənin bitib keçməsini gözləyir. setup uğursuz olarsa, asılı layihələr ötürülür — çatışmayan auth faylından yaranan yanıldıcı uğursuzluqları görməyəcəksiniz.
Yadda saxla: bir setup testi + bir saxlanmış fayl + hər rol üçün bir layihə rolları izolyasiyalı saxlayır; dependencies rol layihələrini setup-ı gözlətdirir və o uğursuz olarsa təmiz şəkildə ötürür.
Üsullar arasında seçim
Bölmə: “Üsullar arasında seçim”Hər iki üsul TestMarket Lab üçün işləyir. Kuki tipinə görə yox, paketin nəyə ehtiyacı olduğuna görə seçin:
| Məsələ | storageState + setup layihəsi | Autentifikasiya fixture-u |
|---|---|---|
| HTTP-only sessiya kukisi ilə işləyir | Bəli (kuki seriallaşdırılır) | Bəli (canlı kontekst) |
| Token / localStorage auth ilə işləyir | Bəli | Bəli |
| Giriş xərci | İşlətmə başına bir dəfə | Test başına, ya da worker başına bir dəfə |
| Köhnə saxlanmış vəziyyətdən qoruyur | Hər işlətmədə təzələnir | Mövzu deyil — həmişə canlı sessiya |
| Konfiqurasiya dəyişikliyi lazımdır | Bəli (layihələr + dependencies) | Xeyr |
| HTML reporter-da görünür | Bəli (öz setup mərhələsi) | Test başına |
| Çoxrollu dəstək | Rol başına bir layihə | Rol başına bir fixture |
| Üçün ən yaxşı | Böyük CI paketləri, ən az giriş | Rol dəyişdirmə, lokal iş, zəmanətli təzə vəziyyət |
Böyük CI işlətməsi üçün setup-layihəsi + storageState sütunu adətən sürətdə qalib gəlir (bütün işlətmə üçün bir giriş). Ağır rol dəyişdirmə və ya sürətli lokal iş üçün fixture əlverişlidir.
Yadda saxla: TestMarket Lab üçün hər ikisi işləyir — CI-də ən az giriş üçün defolt olaraq storageState + setup layihəsi, canlı kontekst və ya asan rol dəyişdirmə istəyəndə isə fixture seçin.
API girişi
Bölmə: “API girişi”UI girişi əlverişli, amma yavaşdır (~1–3 saniyə). Tətbiq istifadə edilə bilən kimlik qaytaran giriş API-si təqdim edəndə, proqramlı autentifikasiya edib formanı tamamilə ötürə bilərsiniz. Dəqiq mexanizm endpoint-in nə qaytardığından asılıdır:
- Cavab gövdəsində token → onu oxuyun, saxlayın (
localStoragevə ya kuki), sonrastorageState-i saxlayın. - API tərəfindən təyin edilən sessiya kukisi → onu brauzer kontekstindən çağırın ki,
Set-Cookieorada yerləşsin, sonra həmin konteksti istifadə etməyə davam edin.
TestMarket Lab-ın POST /api/auth/login-i heç birini etmir: yalnız istifadəçi məlumatı qaytarır ({ id, email, name, role }) — token yoxdur — və sessiya kukisi təyin etmir. Ona görə API girişi bu tətbiq üçün auth-u toxumlaya bilməz; API davranışını yoxlamaq üçün faydalıdır, amma burada autentifikasiya edilmiş quraşdırma üçün UI vasitəsilə giriş edin (sonra storageState-i saxlayın və ya fixture istifadə edin).
Token əsaslı API mövcud olduqda sürət qazancı realdır:
// İllüstrativ: yalnız /api/auth/login-i token qaytaran tətbiq üçün.const response = await request.post('http://localhost:3000/api/auth/login', { data: { email: 'customer@test.io', password: 'customer123' },});expect(response.ok()).toBeTruthy();const { token } = await response.json(); // yalnız token əsaslı API-lərdə mövcuddur
const context = await browser.newContext();await context.addInitScript((t) => localStorage.setItem('token', t), token);await context.storageState({ path: 'auth/customer.json' });await context.close();API girişinin doğru seçim olduğu hallar:
- Cavabın saxlamağa bir şey verdiyi token əsaslı API-lər
- Quraşdırma vaxtının CI-də ölçülə bildiyi yüksək həcmli quraşdırmalar
- Uzun, çoxaddımlı UI giriş axınları olan tətbiqlər
UI girişində qalmaq lazım olan hallar (storageState ilə saxlanmış, ya da fixture):
- API-si token və ya kuki qaytarmayan server tərəfli sessiya tətbiqləri (TestMarket Lab kimi)
- Birbaşa API endpoint-i olmayan SSO, OAuth2 və ya çoxfaktorlu axınlar
- Real giriş UI-nı yoxlamaq əhatənizin bir hissəsi olduqda
Yadda saxla: API girişi yalnız endpoint saxlaya biləcəyiniz bir şey (token) qaytaranda və ya kuki təyin edəndə kömək edir — TestMarket Lab-ın /api/auth/login-i heç birini etmir, ona görə UI vasitəsilə autentifikasiya edin və storageState-i saxlayın.
Təhlükəsizlik — real kimlik məlumatlarını commit etməyin
Bölmə: “Təhlükəsizlik — real kimlik məlumatlarını commit etməyin”Saxlanmış auth vəziyyəti və kimlik məlumatları həssasdır. Onlara parol kimi yanaşın.
auth/-i .gitignore-a əlavə edin — saxlanmış storageState faylı canlı sessiyadır, parol qədər dəyərlidir:
auth/Kimlik məlumatları üçün .env istifadə edin, heç vaxt sabit kodlamayın:
CUSTOMER_EMAIL=customer@test.ioCUSTOMER_PASSWORD=customer123import 'dotenv/config';
// ...setup daxilində:await page.fill('#email', process.env.CUSTOMER_EMAIL!);await page.fill('#password', process.env.CUSTOMER_PASSWORD!);CI-də kimlik məlumatlarını provayderinizdə şifrələnmiş mühit dəyişənləri kimi təyin edin (GitHub Actions Secrets, GitLab CI/CD Variables və s.). auth/*.json-u hər pipeline işlətməsinin əvvəlində təzədən yaradın və heç vaxt commit etməyin.
Yadda saxla: saxlanmış auth/*.json canlı sessiyadır — auth/ qovluğunu .gitignore edin, kimlik məlumatlarını .env / CI sirlərində saxlayın və vəziyyəti commit etmək yerinə hər işlətmədə təzədən yaradın.
Tapşırıqlar
Bölmə: “Tapşırıqlar”Bu tapşırıqlar lokal klonlanmış TestMarket Lab-a qarşı http://localhost:3000-də işləyir (Modul 2-də qurduğunuz tətbiq). Testləri işlətməzdən əvvəl npm start ilə başladın. Əvvəlcə tövsiyə olunan storageState + setup-layihəsi axınını, sonra canlı-fixture alternativini quracaqsınız.
Tapşırıq 1 — Auth setup layihəsi (storageState)
Bölmə: “Tapşırıq 1 — Auth setup layihəsi (storageState)”tests/starter/tests/setup/auth.setup.ts yaradın və onu playwright.config.ts-ə bağlayın:
testMatch: /auth\.setup\.ts/olan birsetuplayihəsiuse: { storageState: 'auth/customer.json' }vədependencies: ['setup']olan birchromiumlayihəsi- Setup testi giriş edir (
#email/#password/#login-btn),.alert-success-in göründüyünü yoxlayır, sonraawait page.context().storageState({ path: 'auth/customer.json' })
Onu işlədin və auth/customer.json-un yazıldığını və connect.sid kukisini ehtiva etdiyini təsdiqləyin. auth/-i .gitignore-a əlavə edin.
Tapşırıq 2 — Daxil olmuş halda başlayan test (giriş kodu yoxdur)
Bölmə: “Tapşırıq 2 — Daxil olmuş halda başlayan test (giriş kodu yoxdur)”tests/starter/tests/profile.spec.ts yaradın. Setup layihəsi qoşulduqda chromium layihəsi artıq storageState yüklədiyi üçün test autentifikasiya edilmiş halda başlayır:
import { test, expect } from '@playwright/test';
test('müştəri profil linkini görür', async ({ page }) => { await page.goto('/'); await expect(page.locator('[data-testid="nav-profile"]')).toBeVisible();});Test gövdəsində heç bir page.fill('#email', ...) olmamalıdır — saxlanmış vəziyyət girişi idarə etdi.
Tapşırıq 3 — Çoxsaylı rollar
Bölmə: “Tapşırıq 3 — Çoxsaylı rollar”auth/admin.json-u saxlayan admin kimi autentifikasiya setup testi və ondan istifadə edən admin-chromium layihəsi əlavə edin. /admin-ə keçən və h1-in Admin ehtiva etdiyini yoxlayan bir test yazın.
Tapşırıq 4 — Müştəriyə admin paneli qadağandır
Bölmə: “Tapşırıq 4 — Müştəriyə admin paneli qadağandır”Tətbiqin /unauthorized marşrutu yoxdur. Admin olmayan /admin-ə daxil olanda flash xətası ilə /-ə (ana səhifə) yönləndirilir. Müştəri vəziyyətindən istifadə edərək:
import { test, expect } from '@playwright/test';
test('müştəri admin panelinə çata bilmir', async ({ page }) => { await page.goto('/admin'); await expect(page).toHaveURL('/'); await expect(page.locator('[data-testid="flash-error"]')).toBeVisible();});Tapşırıq 5 — Canlı-fixture alternativi
Bölmə: “Tapşırıq 5 — Canlı-fixture alternativi”customerPage və adminPage fixture-larını ixrac edən tests/starter/fixtures/auth.fixture.ts yazın (təzə kontekst → giriş → use(page) → bağla). Saxlanmış fayl yerinə zəmanətli təzə sessiya istədiyiniz test üçün ondan istifadə edin. import type { Page } from '@playwright/test'; yazmağı unutmayın.
Tapşırıq 6 — Bir UI giriş testi saxlayın
Bölmə: “Tapşırıq 6 — Bir UI giriş testi saxlayın”@playwright/test-dən adi test ilə tam brauzer girişi həyata keçirən tests/starter/tests/login.spec.ts-i saxlayın (saxlanmış vəziyyət yox, fixture yox). Bu, sizi giriş formasındakı səssiz pozulmadan qoruyur:
import { test, expect } from '@playwright/test';
test('giriş axını uçdan-uca işləyir', async ({ page }) => { await page.goto('/auth/login'); await page.fill('#email', 'customer@test.io'); await page.fill('#password', 'customer123'); await page.click('#login-btn'); await expect(page.locator('.alert-success')).toBeVisible();});Çağırış — Worker-scoped fixture girişi
Bölmə: “Çağırış — Worker-scoped fixture girişi”customerPage fixture-unu giriş test başına yox, worker başına bir dəfə olacaq şəkildə yenidən düzəldin (onu “Worker-scoped giriş” bölməsində göstərildiyi kimi worker-scoped customerContext və test-scoped customerPage-ə bölün). --workers=1 ilə bir neçə müştəri testi üçün girişin yalnız bir dəfə işlədiyini təsdiqləyin.
Öz-özünü yoxlama sualları
Bölmə: “Öz-özünü yoxlama sualları”storageStateconnect.sidkimiHttpOnlysessiya kukisini tuturmu — və niyə tutur ya da tutmur?- Server tərəfli sessiya tətbiqi üçün
storageStatesaxlamağın əsl incəliyi nədir və setup layihəsi onu necə həll edir? - Autentifikasiya fixture-u saxlanmış
storageStatefaylından nə zaman daha uyğundur? - Test-scoped və worker-scoped auth fixture-u arasındakı fərq nədir?
- Fixture faylında niyə
import type { Page }etməlisiniz? - Admin olmayan
/administəyəndən sonra harada düşür və uğursuzluğu nə sübut edir? auth/niyə.gitignore-da olmalıdır?- TestMarket Lab-ın
POST /api/auth/login-i niyə autentifikasiya vəziyyətini toxumlamaq üçün istifadə edilə bilməz?