02 / 10
İlk test ve locator'lar
Test dosyasının yapısı, page fixture'ı, getByRole ve diğer kullanıcı odaklı locator'lar, strict mod, filtreleme, Locator.within() ve codegen ile locator seçmek.
Bir Testin Yapısı
Her test bir başlık ve async bir fonksiyondan oluşur. Fonksiyon ihtiyaç duyduğu araçları parametre olarak alır; bunlara fixture denir. En sık kullanılanı page'dir: test için açılmış, temiz bir tarayıcı sekmesi.1
// tests/login.spec.ts
import { test, expect } from "@playwright/test";
test("hatalı parola hata mesajı gösterir", async ({ page }) => {
await page.goto("/login");
await page.getByLabel("E-posta").fill("yonetici@example.com");
await page.getByLabel("Parola").fill("yanlis");
await page.getByRole("button", { name: "Giriş yap" }).click();
await expect(page.getByRole("alert")).toHaveText("E-posta veya parola hatalı.");
});Üç parça var: sayfaya git, kullanıcı gibi davran, sonucu doğrula. page.goto("/login") yapılandırmadaki baseURL'i kullanır (bkz. Kurulum). Her test kendi tarayıcı bağlamında çalışır; cookie'ler, localStorage ve oturum testler arasında paylaşılmaz.12
Ortak hazırlığı test.beforeEach ile, ilgili testleri test.describe ile gruplayın:1
test.describe("sipariş listesi", () => {
test.beforeEach(async ({ page }) => {
await page.goto("/orders");
});
test("tüm siparişleri listeler", async ({ page }) => {
// ...
});
});Locator Nedir?
Locator, sayfada bir elementi bulmanın tarifidir; elementin kendisi değil. Locator oluşturmak sayfaya dokunmaz. Element ancak bir eylem (click, fill) ya da assertion sırasında aranır ve her seferinde yeniden aranır. Sayfa yeniden render olsa da locator güncel elementi bulur.3
const submit = page.getByRole("button", { name: "Giriş yap" }); // henüz arama yok
await submit.click(); // şimdi aranır, görünür ve tıklanabilir olması beklenirHangi Locator?
Playwright dokümanı kullanıcının gördüğü özellikleri ve açık sözleşmeleri öncelemenizi önerir. Kullanıcı bir butonu sınıf adıyla değil, rolü ve üzerindeki yazıyla tanır:34
| Locator | Ne zaman |
|---|---|
getByRole | Buton, link, başlık, tablo, checkbox; ilk tercih |
getByLabel | Etiketi olan form alanları |
getByPlaceholder | Etiketi olmayan alan (etiket eklemek daha iyi) |
getByText | Etkileşimsiz metin: mesaj, paragraf |
getByAltText | Görseller |
getByTitle | title özelliği olan elementler |
getByTestId | Başka yolu olmayan durumlar için data-testid |
getByRole elementin erişilebilirlik ağacındaki rolünü ve erişilebilir adını kullanır. Yani ekran okuyucunun gördüğünü görür.3 Bir buton getByRole ile bulunamıyorsa çoğu zaman bir erişilebilirlik sorunu vardır (bkz. Erişilebilirlik testi).
page.getByRole("heading", { name: "Siparişler" });
page.getByRole("link", { name: "Çıkış yap" });
page.getByRole("checkbox", { name: "Beni hatırla" });
page.getByRole("table", { name: "Sipariş listesi" }); // <caption> adı verirname varsayılan olarak büyük küçük harf duyarsız ve parça eşleşmesi yapar. "Giriş", "Giriş yap" butonunu da bulur. Tam eşleşme için exact: true verin ya da düzenli ifade kullanın:5
page.getByRole("button", { name: "Giriş yap", exact: true });
page.getByRole("button", { name: /^giriş yap$/i });Don't
CSS sınıfına ya da DOM yapısına bağlı locator yazmayın. Tasarımcı sınıfı değiştirdiğinde test kırılır, oysa kullanıcı için hiçbir şey değişmemiştir.4
page.locator("button.btn-primary.mt-4");
page.locator("//div[2]/form/button");Do
page.getByRole("button", { name: "Giriş yap" });Strict Mod
Locator'lar katıdır: bir eylem tek element bekler. Locator birden fazla elemente uyuyorsa Playwright tahmin etmez, "strict mode violation" hatası verir.3
// Sayfada iki "İptal et" butonu varsa hata verir
await page.getByRole("button", { name: "İptal et" }).click();Çözüm first() değil, aramayı daraltmaktır. first() bugün doğru elementi bulur; yarın sıralama değişince sessizce yanlışına tıklar.
Next.js uygulamalarında sık bir tuzak: sayfada kendi role="alert" mesajınızın yanında Next'in yönlendirme duyurucusu da olabilir. page.getByRole("alert") iki element bulur. Aramayı formun içine daraltın:
const form = page.getByRole("form", { name: "Giriş" });
await expect(form.getByRole("alert")).toHaveText("E-posta veya parola hatalı.");<form> yalnızca erişilebilir bir adı varsa form rolü alır; adı aria-label ya da aria-labelledby ile verin.
Zincirleme ve Filtreleme
Locator'lar zincirlenebilir. Her halka aramayı bir öncekinin içine daraltır:3
page.getByRole("table", { name: "Sipariş listesi" }).getByRole("row");filter bir listeyi metne ya da içerdiği başka bir locator'a göre süzer. Tablodaki belirli bir satırın butonuna basmanın en okunur yolu budur:34
await page
.getByRole("row")
.filter({ hasText: "SP-1001" })
.getByRole("button", { name: "İptal et" })
.click();| Seçenek | Anlamı |
|---|---|
hasText / hasNotText | İçinde bu metin geçen / geçmeyen |
has / hasNot | İçinde bu locator'a uyan element olan / olmayan |
visible | Yalnızca görünür (ya da görünmez) olanlar |
Başlık satırını dışarıda bırakmak için hücre içeren satırları alın: getByRole("row").filter({ has: page.getByRole("cell") }). Başlık hücrelerinin rolü columnheader'dır.
Locator.within()
Playwright 1.64 ile gelen within(), elinizdeki iki locator'ı doğal sırayla birleştirir: "bu buton, şu diyaloğun içinde".6
const save = page.getByRole("button", { name: "Kaydet" });
const dialog = page.getByRole("dialog");
await save.within(dialog).click();Asıl gücü sütun sorgularıdır. nth() ve first() her ebeveynin içinde ayrı ayrı çözülür; böylece "her satırın dördüncü hücresi" yazılabilir:6
const rows = page.getByRole("row").filter({ has: page.getByRole("cell") });
const statusCells = page.getByRole("cell").nth(3).within(rows);
await expect(statusCells).toHaveText(["Kargoda", "Kargoda"]);Warning
within()'e verilen ilk locator bağımsız olmalı. rows.getByRole("cell").nth(3).within(rows) satırların içinde bir kez daha satır arar ve hiçbir şey bulmaz. Bu rehberin projesini yazarken tam olarak bu hatayı yaptık.
Görünür Elementler
visible() (1.63) yalnızca görünür elementlere uyan bir locator döndürür. Eski :visible CSS sözde sınıfının önerilen yerine geçenidir.7 getByRole zaten gizli elementleri atlar; visible() daha çok locator() ve getByText ile işe yarar.
await page.getByText("Kaydedildi").visible().click();Codegen ile Locator Bulmak
Hangi locator'ı yazacağınızdan emin değilseniz Playwright'a sorun. codegen bir tarayıcı açar; tıkladığınız her elemente rol, metin ve test id önceliğiyle bir locator önerir ve birden fazla element eşleşirse locator'ı tekilleştirir:48
$ pnpm dlx playwright codegen localhost:3000"Pick locator" ile bir elementin üzerine gelin; önerilen locator'ı kopyalayın. Kaydedilen testi olduğu gibi kullanmayın; adımları okunur hale getirip assertion ekleyin.
Tip
Next.js dokümanındaki örnek test page.click("text=About") ve page.locator("h1") kullanır. İkisi de çalışır ama eski yazımdır. Aynı testi page.getByRole("link", { name: "About" }).click() ve page.getByRole("heading", { name: "About" }) ile yazın.9
Kendin Dene
Kurulum dersindeki projede bir giriş formu için test yazın. Locator'ları önce
codegenile bulun, sonra elle sadeleştirin.Bir butonu
getByRoleile bulamıyorsanız nedenini araştırın: buton bir<div>mi, adı ikon mu?name: "Gir"vename: "Gir", exact: trueile aynı butonu aramayı deneyin. Hangisi buluyor?Bir tabloda iki satırda aynı butonu bırakın ve
click()çağırın. Strict mod hatasını okuyun, sonrafilterile düzeltin.
Detaylı Öğrenmek İçin
Resmi doküman: Playwright, "Locators"; tüm locator'lar, filtreleme, zincirleme ve strict mod.3
Resmi doküman: Playwright, "Best Practices"; kullanıcı odaklı locator'lar ve CSS'ten kaçınmak.4
Kaynaklar
Test yapısı, eylemler, `beforeEach`, `describe` ve test izolasyonu.
Her testin kendi tarayıcı bağlamında çalışması.
Locator türleri, öncelik, filtreleme, zincirleme ve strict mod.
Kullanıcının gördüğünü test etmek, zincirleme ve codegen.
`name` eşleşmesi, `exact` ve diğer seçenekler.
`Locator.within()` ve ebeveyn içinde çözülen `nth`.
`Locator.visible()`.
Codegen ile test kaydı ve locator seçimi.
Next.js ile ilk Playwright testi.
Last updated: October 22, 2026
