Selenium ve Playwright ile E-posta Doğrulama Kodu Testi

Selenium ya da Playwright ile e-posta doğrulama adımını test etmek için testin, uygulamanızın gönderdiği kodu okuyabileceği gerçek bir gelen kutusuna ihtiyacı vardır. OTPGmail API'siyle test önce bir @gmail.com adresi kiralar, adresi forma yazar, kodu API'den bekler ve kod gelmezse siparişi iptal ederek tutarı geri alır.

Bu rehber, kendi uygulamasının ya da sahibi olduğu test ortamının kayıt akışını otomatikleştiren QA mühendisleri ve geliştiriciler içindir. Ham API çağrılarının ayrıntısı Python ile e-posta onay kodu alma rehberinde; burada çerçevelere özgü kısımlara odaklanıyoruz.

Ne zaman gerçek bir gelen kutusu gerekir?

Birim testlerde ve yerel geliştirmede e-postayı kendi sunucunuzda yakalayan bir araç daha hızlıdır ve her çalıştırmada ücret gerektirmez. Gerçek bir gelen kutusu şu durumlarda anlam kazanır:

Kendi uygulamanız OTPGmail'in hizmet listesinde olmadığı için kod olarak ot (“Herhangi bir site”, uygulamada “Any service”) kullanılır; fiyatı listedeki hizmetlerden yüksektir. Bu seçeneğin Gmail versiyonu adres başına bir kod alır; aynı testte kayıt ve giriş için iki kod gerekiyorsa her biri için ayrı sipariş planlayın. Gmail ve iCloud seçeneklerinin farkları Herhangi bir site sayfasında.

Akış ve kullanacağınız alanlar

  1. POST /v1/orders gövdesi {"service": "ot"}; her yeni sipariş için yeni bir Idempotency-Key (UUID). Yanıt bir dizidir: data[0].orderId ve data[0].email.
  2. email değerini kayıt formuna yazın ve uygulamanızın kodu göndermesini tetikleyin.
  3. GET /v1/orders/{orderId} çağrısını 3–5 saniyede bir yapın. status değeri waiting_code iken bekleyin; completed olduğunda en yeni kod otp[otp.length - 1].code alanındadır.
  4. status değeri cancelled ise kod codeDeadlineAt zamanına kadar gelmemiş, sipariş kendiliğinden iade edilmiştir (en fazla 25 dakika).
  5. Test kod gelmeden biterse POST /v1/orders/{orderId}/cancel çağırın: ilk koddan önce iptal %100 iade edilir.

otp[].code genellikle kısa bir kod ya da bir bağlantıdır. Sistem kodu ayıklayamazsa e-postanın tamamı (HTML ya da metin) aynı alana gelir; değer 80 karakterden uzunsa, satır sonu ya da HTML içeriyorsa kodu kendi biçiminize göre içinden çıkarın.

Playwright (TypeScript): expect.poll ile kod beklemek

Playwright'ın request fikstürü API çağrılarını tarayıcı dışında yapar; anahtar test sürecinde kalır. Örnek, ortam değişkeninde OTPGMAIL_API_KEY ve yapılandırmada baseURL olduğunu varsayar.

// tests/kayit.spec.ts
import { test, expect, type APIRequestContext } from '@playwright/test';
import { randomUUID } from 'node:crypto';

const HOST = 'otpgmail.net';
const API = `https://${HOST}/v1`;
const auth = { Authorization: `Bearer ${process.env.OTPGMAIL_API_KEY}` };

async function rentInbox(request: APIRequestContext) {
  const res = await request.post(`${API}/orders`, {
    headers: { ...auth, 'Idempotency-Key': randomUUID() },
    data: { service: 'ot' },
    timeout: 15_000,
  });
  const body = await res.json();
  if (!body.success) throw new Error(body.error.code); // NO_MAILS_AVAILABLE, INSUFFICIENT_BALANCE...
  return body.data[0] as { orderId: string; email: string };
}

function extractCode(raw: string): string {
  if (raw.length <= 80 && !raw.includes('\n') && !raw.includes('<')) return raw;
  return raw.match(/\b\d{6}\b/)?.[0] ?? raw; // tam e-posta geldiyse: kendi kod biçiminiz
}

test('e-posta doğrulama kodlu kayıt', async ({ page, request }) => {
  test.setTimeout(6 * 60_000);
  const inbox = await rentInbox(request);
  let order: { status: string; otp: { code: string }[] } | undefined;
  try {
    await page.goto('/kayit');
    await page.getByLabel('E-posta').fill(inbox.email);
    await page.getByRole('button', { name: 'Kod gönder' }).click();

    await expect.poll(async () => {
      const r = await request.get(`${API}/orders/${inbox.orderId}`, { headers: auth });
      order = (await r.json()).data;
      return order?.status;
    }, { message: 'doğrulama kodu bekleniyor', intervals: [4_000], timeout: 5 * 60_000 })
      .not.toBe('waiting_code');

    expect(order?.status).toBe('completed');
    const code = extractCode(order!.otp[order!.otp.length - 1].code);
    await page.getByLabel('Doğrulama kodu').fill(code);
    await page.getByRole('button', { name: 'Doğrula' }).click();
    await expect(page.getByText('Hesabınız doğrulandı')).toBeVisible();
  } finally {
    if (order?.status !== 'completed') {
      await request.post(`${API}/orders/${inbox.orderId}/cancel`, { headers: auth }); // iade
    }
  }
});

Playwright'ın varsayılan test süresi yavaş bir e-postadan kısadır; bu yüzden test süreyi kendisi uzatır. Etiketler ve metinler (“Kod gönder”, “Hesabınız doğrulandı”) sizin uygulamanıza aittir; kendi seçicilerinizle değiştirin.

Selenium e-posta doğrulama testi (Python): WebDriverWait ile API

WebDriverWait.until yalnızca sayfa öğelerini değil, sürücüyü alan herhangi bir fonksiyonu bekleyebilir. poll_frequency=4 ile API her dört saniyede bir sorgulanır; temizliği pytest fikstürü yapar.

# test_kayit.py
import os, uuid, requests, pytest
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

HOST = "otpgmail.net"
API = f"https://{HOST}/v1"
AUTH = {"Authorization": f"Bearer {os.environ['OTPGMAIL_API_KEY']}"}

@pytest.fixture
def driver():
    d = webdriver.Chrome()
    yield d
    d.quit()

@pytest.fixture
def inbox():
    r = requests.post(f"{API}/orders", json={"service": "ot"},
                      headers={**AUTH, "Idempotency-Key": str(uuid.uuid4())}, timeout=15)
    body = r.json()
    if not body["success"]:
        pytest.skip(body["error"]["code"])  # ör. NO_MAILS_AVAILABLE: ücret kesilmez
    order = body["data"][0]
    yield order
    # temizlik: ilk koddan önce iptal %100 iade; kod geldiyse API iptali reddeder
    requests.post(f"{API}/orders/{order['orderId']}/cancel", headers=AUTH, timeout=15)

def latest_code(order_id):
    o = requests.get(f"{API}/orders/{order_id}", headers=AUTH, timeout=15).json()["data"]
    if o["status"] == "cancelled":
        raise AssertionError("kod gelmedi, sipariş iade edildi")
    return o["otp"][-1]["code"] if o["otp"] else False

def test_kayit(driver, inbox):
    driver.get("https://staging.ornek.com.tr/kayit")
    driver.find_element(By.NAME, "email").send_keys(inbox["email"])
    driver.find_element(By.CSS_SELECTOR, "button[type=submit]").click()
    code = WebDriverWait(driver, timeout=300, poll_frequency=4).until(
        lambda d: latest_code(inbox["orderId"]))
    driver.find_element(By.NAME, "code").send_keys(code)
    driver.find_element(By.CSS_SELECTOR, "button[type=submit]").click()

latest_code kod yokken False döndürür; WebDriverWait bu sırada beklemeye devam eder, sipariş iptal olduysa hata testi hemen durdurur. Python'da requests kullanın: standart urllib kütüphanesinin varsayılan kullanıcı aracısı API'nin önündeki CDN tarafından reddedilebilir.

Türkçe yerel ayarda gizli hata: büyük “I”

Türkçe yerel ayarda büyük “I” harfinin küçüğü “ı”dır. E-posta adresini küçük harfe çevirirken yerel ayara bağlı bir fonksiyon kullanan bir sunucu, “INFO@…” adresini “ınfo@…” yapar ve kod hiç gönderilmez ya da yanlış yere gider. Java'da varsayılan yerel ayarla çalışan toLowerCase(), C#'ta ToLower() ve JavaScript'te toLocaleLowerCase('tr-TR') bu davranışa açıktır; toLowerCase(Locale.ROOT), ToLowerInvariant() ve JavaScript'in düz toLowerCase() fonksiyonu ise yerel ayardan bağımsızdır.

Bu hatayı yalnızca gerçek teslimat yakalar. Gmail adreslerinde büyük-küçük harf fark etmediği için kiraladığınız adresi forma inbox.email.toUpperCase() olarak yazan ikinci bir test ekleyin; Playwright yapılandırmasında locale: 'tr-TR' kullanın ve sunucuyu Türkçe yerel ayarla çalıştırın. Kod geliyorsa normalleştirme doğrudur.

CI'da sınırlar, paralel testler ve temizlik

Sınırlar

Kiralık gelen kutusu yalnızca e-posta almak içindir: e-posta gönderemezsiniz, gelen kutusuna giriş yapamazsınız ve adres kalıcı değildir. Bu test düzenini kendi uygulamanızın ya da test etme izniniz olan bir ortamın kayıt akışı için kullanın; başkalarının platformlarında betikle hesap açmak için değil. Akışın genel resmi OTPGmail nasıl çalışır sayfasında.

Sıkça sorulan sorular

Kod gelmezse ücret öder miyim?

Hayır. Kod codeDeadlineAt zamanına kadar gelmezse sipariş kendiliğinden iptal olur ve tutarın %100'ü bakiyenize döner; testiniz daha erken bitiyorsa iptal çağrısıyla aynı iadeyi hemen alırsınız.

Kiralık adresin gelen kutusunu IMAP ile okuyabilir miyim?

Hayır. Kiralamada şifre ve IMAP erişimi yoktur; kod yalnızca API'de ve sipariş sayfasında görünür. Testiniz IMAP'e bağlıysa okuma adımını API çağrısıyla değiştirin.

iCloud adresi mi, Gmail mi kullanmalıyım?

Kayıt formunuzu sıradan kullanıcılar gibi test etmek için ikisi de gerçek adreslerdir. Fiyat ve kod kuralı seçeneğe göre değişir; ikisini ayrı testlerde denemek, kodlarınızın iki posta sağlayıcısına da ulaştığını gösterir.

Bir test ortamı için anahtarı nereden alırım?

Giriş yaptıktan sonra API belgeleri sayfasındaki “API anahtarınız” kutusundan ya da “Hesabım” sayfasından. Anahtarı CI gizli değişkeninde tutun; yeni anahtar oluşturduğunuzda eskisi hemen çalışmaz hale gelir.

İlgili rehberler

Doğrulama kodunuzu şimdi alın

Kayıt ücret gerektirmez. Ücret yalnızca gelen kutusu teslim edildiğinde kesilir; bekleme süresinde (en fazla 25 dakika) kod gelmezse tutarın %100'ü otomatik olarak iade edilir.

Aradığınız hizmet listede yok mu? Kiralama sayfasındaki Hizmet ekle düğmesiyle istekte bulunun; yönetici isteği inceler ve altyapı destekliyorsa hizmeti ekler.

Yalnızca kod değil, giriş yapabileceğiniz bir Gmail hesabı mı lazım? Kısa ömürlü Gmail hesabı sayfasına göz atın · İade ve garanti