Modul 1: QA üçün JavaScript və TypeScript
Bu modul Playwright testlərini yazmaq üçün lazım olan TypeScript və JavaScript biliklərini verir — nə çox, nə az. Əgər daha əvvəl kod yazmamısınızsa, problem deyil. Əgər daha əvvəl JS yazmısınızsa, bu modul gündəlik istifadə edəcəyiniz şablonları möhkəmləndirəcək.
Kurs boyu TypeScript istifadə edirik — Modul 0-da npm init playwright@latest bunu sizin üçün qurub. TypeScript ixtiyari tiplərlə JavaScript-dir, ona görə də aşağıdakı hər bir JavaScript nümunəsi eyni zamanda etibarlı TypeScript-dir.
🎬 Video tezliklə əlavə olunacaq
const və let — var heç vaxt istifadə etməyin
Bölmə: “const və let — var heç vaxt istifadə etməyin”Hər test faylında iki dəyişən açar sözü görəcəksiniz: const və let.
const baseURL = 'http://localhost:3000'; // yenidən mənimsədilməyəcəklet retryCount = 0; // sonra dəyəri dəyişəcəkQayda: standart olaraq const istifadə edin. Dəyişənə yeni dəyər mənimsətməli olduqda let-ə keçin.
// ✅ Düzgünconst TIMEOUT = 30000;let attempts = 0;attempts = attempts + 1; // yaxşıdır — let yenidən mənimsətməyə icazə verir
// ❌ Xəta verirconst MAX = 5;MAX = 10; // TypeError: Assignment to constant variableVacib bir məqam: const dəyişməzlik demək deyil. Obyekt xüsusiyyətlərini dəyişdirmək mümkündür:
const config = { retries: 1 };config.retries = 2; // ✅ buna icazə verilirconfig = { retries: 3 }; // ❌ buna icazə verilmir — referansı yenidən mənimsədə bilməzsinizvar haqqında: mövcuddur, amma çaşdırıcı scope xətaları yaradır. Bütün müasir linter-lər bunu işarələyir. Playwright layihəsində heç vaxt var-a ehtiyac olmayacaq.
Blok scope
Bölmə: “Blok scope”const və let blok-scoped-dır — yalnız elan edildikləri { } blokunun daxilindən əlçatandır. Aşağıdakı nümunədə message yalnız if bloku daxilindədir; blokundan kənarda ReferenceError atılır:
if (true) { let message = 'Salam!';}console.log(message); // ❌ ReferenceError: message is not definedTapşırıq 1-də məhz bu xətanı düzəldəcəksiniz.
Tapşırıqlara hazırlıq
Bölmə: “Tapşırıqlara hazırlıq”Bütün tapşırıqlar sadə Node.js ilə işləyir — brauzerlərə ehtiyac yoxdur.
- Modul 0-da qurduğunuz Playwright layihəsini VS Code-da açın.
- Layihənin kökündə
exercises/mod1/qovluğunu yaradın (Explorer panelində sağ klik → New Folder). - Hər tapşırıq üçün ayrı fayl yaradın:
exercise-1.ts,exercise-2.ts…exercise-6.ts. - İnteqrasiya olunmuş terminalı açın (Ctrl + `) — yolun layihə kökü olduğundan əmin olun.
- Faylı işlədin:
npx tsx exercises/mod1/exercise-1.ts
tsx tapılmırsa: npm install -D tsx
Tapşırıq 1: Dəyişənlər — xətaları tapın
Bölmə: “Tapşırıq 1: Dəyişənlər — xətaları tapın”Aşağıdakı kodda bir neçə problem var. Onları düzəldin və faylı işlədin.
// ❌ Bu kodda problemlər var. Düzəldin.var baseURL = 'http://localhost:3000';const TIMEOUT = 30000;TIMEOUT = 50000; // Bu icazəlidirmi?
if (true) { let message = 'Salam!';}console.log(message); // Niyə xəta var?
console.log('Tapşırıq 1 tamamlandı');Addımlar:
var baseURL-ıconstilə əvəzləyinTIMEOUTyenidən mənimsətməni düzəldin — yeni dəyişən istifadə edin (məs.TIMEOUT_EXTENDED)user = {...}—constdəyişəninə mənimsətmə xətasıdır;let userilə elan edinmessagescope xətasını düzəldin —console.log-u blokun içinə köçürün- Düzəldilmiş faylı işlədin və xəta olmadığını yoxlayın
Gözlənilən nəticə:
Salam!Tapşırıq 1 tamamlandıString, rəqəm və boolean
Bölmə: “String, rəqəm və boolean”Bu üç primitiv tip test fayllarında istifadə edəcəklərinizin böyük hissəsini əhatə edir.
String-lər
Bölmə: “String-lər”const url = 'http://localhost:3000/login';const selector = '#email-input';
// Template literal (backtick) — dəyər yerləşdirəndə bunları istifadə edinconst message = `Keçildi: ${url}`;const fullSelector = `[data-testid="${selector}"]`;Template literal-lar (backtick-li string-lər) Playwright-də çox istifadə olunur — konfiqurasiya fayllarında, page object-lərdə və iddia ifadələrində.
Rəqəmlər
Bölmə: “Rəqəmlər”const timeout = 5000; // millisaniyəconst retries = 3;const price = 19.99;Tip çevrilmələrinə diqqət edin (aşağıdakı nümunələr xalis JavaScript davranışını göstərir — TypeScript tipləri yoxdur):
'5' - 3 // → 2 (JS string-i rəqəmə çevirir)'5' + 3 // → '53' (JS 3-ü string-ə çevirir — tələ!)Praktikada açıq çevirmədən istifadə edin: Number('5') və ya parseInt('5', 10).
Boolean
Bölmə: “Boolean”const isLoggedIn = true;const hasErrors = false;// Həmişə === (ciddi bərabərlik), heç vaxt =='5' === 5 // → false (fərqli tiplər)'5' == 5 // → true (tip çevrilməsi — bundan qaçın)Playwright-də boolean-lar iddia ifadələrində (expect(isVisible).toBe(true)) və konfiqurasiyada (headless: true) görünür.
Array-lər və obyektlər
Bölmə: “Array-lər və obyektlər”Array-lər
Bölmə: “Array-lər”const browsers = ['chromium', 'firefox', 'webkit'];const prices = [9.99, 14.99, 29.99];
// Ümumi əməliyyatlarbrowsers.length; // 3browsers[0]; // 'chromium'browsers.push('electron'); // sona əlavə edirbrowsers.filter(b => b !== 'webkit'); // 'webkit' olmadan yeni array qaytarırbrowsers.map(b => b.toUpperCase()); // ['CHROMIUM', 'FIREFOX', 'WEBKIT']Obyektlər
Bölmə: “Obyektlər”const user = { password: 'customer123', role: 'admin',};
// Xüsusiyyətlərə girişuser['role']; // 'admin' — dinamik açarlar üçün mötərizə notasiyasıDestructuring
Bölmə: “Destructuring”Destructuring, obyekt və array-lərdən dəyərləri təmiz şəkildə çıxarmağa imkan verir:
const { email, password } = user;// eyni məna daşıyır: const email = user.email; const password = user.password;
const [first, second] = browsers;// eyni məna daşıyır: const first = browsers[0]; const second = browsers[1];Playwright-də bunu daim görəcəksiniz — məsələn, freymvorkdan test və expect-i çıxararkən:
import { test, expect } from '@playwright/test';Spread operatoru
Bölmə: “Spread operatoru”Spread operatoru (...) obyekt və array-ləri kopyalayır və birləşdirir:
const defaultOptions = { headless: true, slowMo: 0 };const debugOptions = { ...defaultOptions, headless: false, slowMo: 500 };// → { headless: false, slowMo: 500 }Test konfiqurasiyalarını birləşdirmək və dəyişdirilmiş test data obyektləri qurmaq üçün geniş istifadə olunur.
Tapşırıq 2: Test data obyektlərini qurun
Bölmə: “Tapşırıq 2: Test data obyektlərini qurun”testData obyektini tamamlayın:
const testData = { validCustomer: { password: 'customer123', name: 'Test Müştərisi', },
validAdmin: { // TODO: bu xüsusiyyətləri əlavə edin: // email: '[email protected]', password: 'admin123', name: 'Test Admini' },
newProduct() { // TODO: { name: `Test Məhsulu ${Date.now()}`, price: 19.99, category: 'aksesuarlar' } qaytarın },
shippingDetails() { // TODO: { name: '...', address: '...', city: '...', zip: '...' } qaytarın — öz test dəyərlərinizi istifadə edin },};
console.log('Müştəri:', testData.validCustomer);console.log('Admin:', testData.validAdmin);console.log('Məhsul:', testData.newProduct());console.log('Göndərmə:', testData.shippingDetails());Gözlənilən nəticə:
Müştəri: { email: '[email protected]', password: 'customer123', name: 'Test Müştərisi' }Admin: { email: '[email protected]', password: 'admin123', name: 'Test Admini' }Məhsul: { name: 'Test Məhsulu 1712345678901', price: 19.99, category: 'aksesuarlar' }Göndərmə: { name: '...', address: '...', city: '...', zip: '...' }Funksiyalar və arrow funksiyalar
Bölmə: “Funksiyalar və arrow funksiyalar”Adi funksiyalar
Bölmə: “Adi funksiyalar”function formatPrice(price: number): string { return `$${price.toFixed(2)}`;}price-dakı : number annotasiyası və mötərizələrdən sonrakı : string TypeScript tipləridir — onlar redaktora nəyin daxil ola biləcəyini və nəyin çıxdığını bildirir. Onları hər yerdə görəcəksiniz.
Arrow funksiyalar
Bölmə: “Arrow funksiyalar”Arrow funksiyalar daha qısa, müasir sintaksisdir — Playwright-də hər yerdə görünür:
const formatPrice = (price: number): string => `$${price.toFixed(2)}`;
// Çox sətirli arrow funksiya { } və açıq return tələb edirconst generateUser = (role: string) => { const timestamp = Date.now(); return { email: `${role}_${timestamp}@test.io`, role };};Hər Playwright testi arrow funksiyadan istifadə edir:
test('istifadəçi daxil ola bilər', async ({ page }) => { await page.goto('/login'); // ...});Nəyi nə vaxt istifadə etməli:
- Arrow funksiyalar: callback-lər, test gövdələri, qısa köməkçi funksiyalar
- Adi
function: class metodları (məsələn,thisistifadə edən Page Object metodları)
Gizli return tələsi
Bölmə: “Gizli return tələsi”Tək ifadəli arrow funksiyalar dəyəri gizli qaytarır — return açar sözü lazım deyil:
const double = x => x * 2; // gizli return — x * 2 qaytarırconst triple = x => { x * 3 }; // ❌ return yoxdur — undefined qaytarırconst triple = x => { return x * 3 }; // ✅ açıq returnTapşırıq 3: Köməkçi funksiyalar yazın
Bölmə: “Tapşırıq 3: Köməkçi funksiyalar yazın”Bu dörd arrow funksiyanı ehtiva edən exercise-3.ts hazırlayın:
// 1. formatPrice(price) — $ və 2 onluq rəqəm ilə string qaytarır// formatPrice(19.99) → "$19.99"
// 2. isEmail(email) — string '@' və '.' ehtiva edirsə true qaytarır// isEmail('[email protected]') → true// isEmail('e-poçt-deyil') → false
// 3. generateUser(role) — timestamp-li email ilə obyekt qaytarır// generateUser('admin') → { email: '[email protected]', role: 'admin' }
// 4. filterByCategory(products, category) — array-i kateqoriyaya görə süzür// filterByCategory([{name:'Siçan',category:'aksesuarlar'},...], 'aksesuarlar')// → [{name:'Siçan',category:'aksesuarlar'}]İpuclar: template literal, .toFixed(2), .includes(), Date.now(), .filter() istifadə edin. Hər parametrə əsas tip annotasiyası əlavə edin.
Gözlənilən nəticə:
$19.99truefalse{ email: '[email protected]', role: 'admin' }[ { name: 'Siçan', category: 'aksesuarlar' } ]Import və export (ESM)
Bölmə: “Import və export (ESM)”Playwright ES modulları (ESM) istifadə edir — import / export sintaksisi. Yazacağınız hər .ts faylı ən azı bir import ilə başlayacaq.
Import etmək
Bölmə: “Import etmək”// Moduldan adlandırılmış export-ları import etimport { test, expect } from '@playwright/test';
// Bir neçə şeyi import edinimport { chromium, firefox } from '@playwright/test';
// Öz faylınızı import edin (default export)import LoginPage from './pages/LoginPage';
// Öz faylınızı import edin (adlandırılmış export)import { LoginPage } from './pages/LoginPage';Qeyd: öz faylınızı import edəndə yola .ts uzantısı əlavə etmirsiniz.
Export etmək
Bölmə: “Export etmək”// LoginPage.ts — adlandırılmış exportimport { Page } from '@playwright/test';
export class LoginPage { constructor(public page: Page) {}}
// LoginPage.ts — default export (fayl başına yalnız bir dənə)import { Page } from '@playwright/test';
class LoginPage { constructor(public page: Page) {}}export default LoginPage;export açar sözünü unutsanız, import undefined qaytaracaq və TypeError: LoginPage is not a constructor kimi xətalar görəcəksiniz.
CommonJS-i hələ də görə bilərsiniz
Bölmə: “CommonJS-i hələ də görə bilərsiniz”Köhnə Node.js və Playwright nümunələri CommonJS sintaksisindən istifadə edir — const { test } = require('@playwright/test') və module.exports = LoginPage. Hər iki üsul Node.js-də işləyir, amma rəsmi Playwright generatoru və bu kurs hər yerdə ESM import / export istifadə edir. Bir təlimatda ya köhnə repo-da require() görsəniz, eyni ideya, fərqli sintaksis kimi qəbul edin.
Promise-lər və async/await
Bölmə: “Promise-lər və async/await”Bu bölmə flaky testlərdən qaçmaq üçün ən vacibdir. await unutmaq test uğursuzluqlarının 1 nömrəli səbəbidir.
Asinxron əməliyyatları anlamaq üçün qəhvə sifariş etməyi təsəvvür edin: kassaya pul verirsiniz və çek alırsınız — bu sizin Promise-inizdir. await isə piştaxtanın yanında dayanıb qəhvə hazır olana qədər gözləməkdir. Çek (Promise) dərhal əlinizdədir, nəticə isə bir az sonra gəlir.
Promise nədir?
Bölmə: “Promise nədir?”Promise hələ mövcud olmayan bir dəyəri təmsil edir — asinxron əməliyyatın nəticəsidir. Playwright demək olar ki, hər əməliyyatdan Promise qaytarır:
// page.goto() Promise qaytarırconst promise = page.goto('/login'); // naviqasiyanı başladır amma gözləmirawait dayanır və gözləyir
Bölmə: “await dayanır və gözləyir”async function login() { await page.goto('/login'); // naviqasiyanın tamamlanmasını gözləyir await page.fill('#email', '...'); // doldurmağın tamamlanmasını gözləyir await page.click('button'); // klikləmənin tamamlanmasını gözləyir}await olmadan test əməliyyat bitmədən növbəti sətirə keçir:
// ❌ await yoxdur — test dərhal davam edirpage.goto('/login');expect(page).toHaveURL('/dashboard'); // login olmadan işləyir!async açar sözü
Bölmə: “async açar sözü”await istifadə edən hər funksiya async ilə elan edilməlidir:
// ✅ Düzgünasync function runTest() { await page.goto('/');}
// Arrow funksiya kimi də işləyirconst runTest = async () => { await page.goto('/');};async funksiya həmişə Promise qaytarır. Əgər async funksiyadan 'salam' qaytarsanız, çağıran tərəf Promise<string> alır — onlar da await etməlidir.
Promise.all — paralel əməliyyatlar
Bölmə: “Promise.all — paralel əməliyyatlar”Eyni anda bir neçə şeyi gözləmək lazım olduqda:
// Naviqasiya VƏ başqa bir şeyi eyni anda gözləyinconst [response] = await Promise.all([ page.waitForResponse('/api/login'), page.click('button[type="submit"]'),]);Bu, klik etdikdə şəbəkə sorğusunu gözləmək lazım olan naviqasiya şablonları üçün istifadə olunur.
Tapşırıq 4: Xətalı asinxron kodu düzəldin
Bölmə: “Tapşırıq 4: Xətalı asinxron kodu düzəldin”Aşağıdakı kodda 6 əksik await açar sözü var. Onları tapın və düzəldin.
const fakePage = { goto: (url: string) => new Promise<void>(r => setTimeout(() => { console.log(`Keçildi: ${url}`); r(); }, 50)), fill: (selector: string, value: string) => new Promise<void>(r => setTimeout(() => { console.log(`${selector} dolduruldu: ${value}`); r(); }, 50)), click: (selector: string) => new Promise<void>(r => setTimeout(() => { console.log(`Klik edildi: ${selector}`); r(); }, 50)), waitForSelector: (selector: string) => new Promise<void>(r => setTimeout(() => { console.log(`Gözlənildi: ${selector}`); r(); }, 50)), screenshot: () => new Promise<void>(r => setTimeout(() => { console.log('Ekran görüntüsü alındı'); r(); }, 50)),};
async function runTest() { console.log('Test başlayır...');
fakePage.goto('/auth/login'); // ❌ await yoxdur console.log('Login səhifəsinə keçildi');
fakePage.waitForSelector('#email'); // ❌ await yoxdur fakePage.fill('#password', 'customer123'); // ❌ await yoxdur fakePage.click('button[type="submit"]'); // ❌ await yoxdur
console.log('Login formu göndərildi'); fakePage.screenshot(); // ❌ await yoxdur
console.log('Test tamamlandı!');}
runTest();Əvvəlcə xətalı versiyanı işlədin — çıxış sırasının yanlış olduğunu görəcəksiniz. Sonra await əlavə edib yenidən işlədin.
TypeScript əsasları
Bölmə: “TypeScript əsasları”Bu modul boyu artıq TypeScript yazırsınız — hər annotasiya edilmiş parametr (price: number, role: string) iş başında olan TypeScript-dir. Bu bölmə sadəcə “tip annotasiyaları olan JS” hissələri bir araya gətirmir: interface-lər, istəyə bağlı xüsusiyyətlər və JSDoc.
Niyə tiplər kömək edir
Bölmə: “Niyə tiplər kömək edir”Tiplər kodu işlətməzdən əvvəl xətaları aşkar edir:
// JavaScript — xəta yalnız işləmə zamanı baş verirfunction formatPrice(price) { return `$${price.toFixed(2)}`;}formatPrice('rəqəm-deyil'); // işləmə zamanı çöküş
// TypeScript — xəta dərhal redaktorda görünürfunction formatPrice(price: number): string { return `$${price.toFixed(2)}`;}formatPrice('rəqəm-deyil'); // ❌ TypeScript xətası: Argument of type 'string' is not assignable to parameter of type 'number'VS Code-dakı qırmızı dalğalı xətt — siqnaldır. İşə salmadan öncə xətanı düzəldirsiniz.
Interface-lər
Bölmə: “Interface-lər”Interface-lər obyektin formasını təsvir edir. Test data üçün istifadə edin:
interface User { email: string; password: string; role: 'admin' | 'customer'; // union type — yalnız bu iki dəyər}
interface Product { name: string; price: number; category: string;}
const user: User = { password: 'customer123', role: 'customer',};İstəyə bağlı xüsusiyyətlər
Bölmə: “İstəyə bağlı xüsusiyyətlər”Xüsusiyyəti istəyə bağlı etmək üçün ? əlavə edin:
interface ShippingDetails { name: string; address: string; city: string; zip: string; country?: string; // istəyə bağlı — undefined ola bilər}JSDoc — .ts faylları olmadan TypeScript faydaları
Bölmə: “JSDoc — .ts faylları olmadan TypeScript faydaları”Sadə .js faylında tip yoxlaması lazım olarsa, JSDoc annotasiyalarından istifadə edin. VS Code onları oxuyur və sizə avtomatik tamamlama və tip xətaları göstərir — TypeScript kimi, amma heç bir build addımı olmadan.
/** * @param {number} price * @returns {string} */const formatPrice = (price) => `$${price.toFixed(2)}`;
class LoginPage { /** @param {import('@playwright/test').Page} page */ constructor(page) { this.page = page; }}Tez-tez ehtiyacınız olmayacaq — kurs .ts faylları istifadə edir — amma köhnə kod bazalarında görəcəksiniz.
Xətaları və stack trace-ləri oxumaq
Bölmə: “Xətaları və stack trace-ləri oxumaq”Test uğursuz olduqda, xəta mesajı nə baş verdiyini dəqiq deyir — əgər oxumağı bilsəniz.
Playwright xətasının anatomiyası
Bölmə: “Playwright xətasının anatomiyası” 1) [chromium] › login.spec.ts:10:3 › admin can login to dashboard ───────────
TypeError: Cannot read properties of undefined (reading 'click')
16 | async login(email: string, password: string) { 17 | await this.emailInput.fill(email); > 18 | await this.loginButton.click(); | ^ 19 | }
at LoginPage.login (tests/pages/LoginPage.ts:18:28) at tests/login.spec.ts:15:12Yuxarıdan aşağı oxuyun:
- Test başlığı —
[chromium] › login.spec.ts:10:3 › admin can login to dashboardbrauzer proyektini, testin başladığı fayl və sətri, və test adını göstərir. - Xəta tipi və mesajı —
TypeError: Cannot read properties of undefined (reading 'click'). Bir şeyundefined-dir və siz onun üzərində.click()çağırmağa cəhd etdiniz. - Kod çərçivəsi — xətanın ətrafındakı sətirlər. 18-ci sətirdəki
>oxu uğursuz sətri işarələyir;^işarəsi tam olaraq pozulan ifadəni göstərir — buradathis.loginButtonundefined-dir. - Stack sətirləri — hər çağırışın öz fayllarınızda haradan gəldiyi. Stack-in başı — xətanın baş verdiyi yer; aşağıda — onu çağıran kod.
node_modules stack sətirlərinə məhəl qoymayın — bunlar Playwright-in daxili işləridir. Öz fayllarınıza diqqət edin.
Ümumi xətalar və mənası
Bölmə: “Ümumi xətalar və mənası”| Xəta | Məna | Həll |
|---|---|---|
Cannot read properties of null (reading 'click') | Bir dəyişən və ya handle null-dur — gözlənilən obyekt tapılmadı | Dəyişənin düzgün başladıldığını və selector-un düzgün yazıldığını yoxlayın |
Cannot read properties of undefined | Dəyişən mənimsədilməyib | Import-ları, dəyişən scope-unu yoxlayın |
ReferenceError: X is not defined | Dəyişən scope-da elan edilməyib | Yazılışı, elan yerini yoxlayın |
TypeError: X is not a function | Yanlış şey import edilib ya export unudulub | console.log(typeof X) yoxlayın |
| Nəticə sırası yanlışdır | await yoxdur | Asinxron çağırışlardan əvvəl await əlavə edin |
Tapşırıq 5: Stack trace-i oxuyun
Bölmə: “Tapşırıq 5: Stack trace-i oxuyun”Bu xətanı oxuyun və aşağıdakı sualları cavablayın:
1) [chromium] › login.spec.ts:10:3 › admin can login to dashboard ───────────
TypeError: Cannot read properties of undefined (reading 'click')
16 | async login(email: string, password: string) { 17 | await this.emailInput.fill(email); > 18 | await this.loginButton.click(); | ^ 19 | }
at LoginPage.login (tests/pages/LoginPage.ts:18:28) at tests/login.spec.ts:15:12Suallar:
- Xəta faktiki olaraq harada baş verdi? (fayl, sətir, sütun)
- Uğursuz olan testin adı nədir?
- “Cannot read properties of undefined” bu kontekstdə nə deməkdir — nə undefined-dir?
- Bunu düzəltmək üçün ilk nəyi yoxlayardınız?
Cavablarınızı exercise-5.ts faylında şərh kimi yazın.
Mühit dəyişənləri
Bölmə: “Mühit dəyişənləri”URL-ləri, parolları və ya tokenləri test fayllarına heç vaxt birbaşa yazmayın. Bunun əvəzinə mühit dəyişənlərindən istifadə edin.
process.env-dən oxumaq
Bölmə: “process.env-dən oxumaq”const baseURL = process.env.BASE_URL;const adminEmail = process.env.ADMIN_EMAIL;Standart dəyərlər və məcburi dəyişənlər
Bölmə: “Standart dəyərlər və məcburi dəyişənlər”function getConfig() { const baseUrl = process.env.BASE_URL ?? 'http://localhost:3000'; // standart dəyər
const adminEmail = process.env.ADMIN_EMAIL; if (!adminEmail) { throw new Error('ADMIN_EMAIL mühit dəyişəni tələb olunur'); }
const isCI = process.env.CI === 'true'; // string-i boolean-a çevir
return { baseUrl, adminEmail, isCI };}.env faylları
Bölmə: “.env faylları”Layihə kökündə .env faylı hazırlayın:
BASE_URL=http://localhost:3000ADMIN_PASSWORD=admin123CI=falseSonra konfiqurasiyanın başında yükləyin:
import 'dotenv/config';// İndi process.env.BASE_URL, process.env.ADMIN_EMAIL və s. mövcuddur.env-i həmişə .gitignore-a əlavə edin — sirrləri heç vaxt version control-a göndərməyin.
Bu şablonu playwright.config.ts-də görəcəksiniz:
import { defineConfig } from '@playwright/test';import 'dotenv/config';
export default defineConfig({ use: { baseURL: process.env.BASE_URL ?? 'http://localhost:3000', }, forbidOnly: !!process.env.CI, // !! string-i boolean-a çevirir});Tapşırıq 6: Mühit dəyişənləri
Bölmə: “Tapşırıq 6: Mühit dəyişənləri”process.env-dən oxuyan getConfig() funksiyasını tətbiq edin:
// dotenv-i simulyasiya edirikprocess.env.BASE_URL = 'http://localhost:3000';process.env.ADMIN_PASSWORD = 'admin123';process.env.CI = 'true';
function getConfig() { // Qaytarın: // - baseUrl (BASE_URL-dən, standart 'http://localhost:3000') // - adminEmail (ADMIN_EMAIL-dən, yoxdursa Error at) // - adminPassword (ADMIN_PASSWORD-dən, yoxdursa Error at) // - isCI (CI-dən, 'true' string-ini boolean true-ya çevirin)}
console.log(getConfig());Bonus: process.env.ADMIN_EMAIL-i silin və xətanı try/catch ilə idarə edin.
Əsas nəticələr
Bölmə: “Əsas nəticələr”Yapışqan kağıza yazacağınız dörd qayda:
- Standart olaraq
const, yenidən mənimsətmək üçünlet, heç vaxtvar - Hər Playwright əməliyyatını
awaitedin —awaitunudulması = flaky test - Stack trace-ləri yuxarıdan aşağı oxuyun — başlıq, xəta mesajı, kod çərçivəsi, sonra öz fayllarınıza işarə edən stack sətirləri
- Sirrləri heç vaxt kodda yazmayın —
process.envvə.envfayllarından istifadə edin
Modul 2-də bu modulun hər bir anlayışı real Page Object class-larında istifadə olunacaq.