Kontrolki wewnątrz ramki
Gdy kontrolka leży w ramce iframe, wskaż ramkę przez frameLocator. Lokator na obiekcie page przeszukuje tylko główny dokument i nie widzi pola.
Ten wpis jest częścią serii Podstawy Playwright. Jeśli pominąłeś poprzedni, przeczytaj Część 15 — Sprawdzaj stronę, którą otworzyło kliknięcie.
Wprowadzenie — pole widać na ekranie
Test widzi pole numeru karty na ekranie kasy. Wywołanie page.getByLabel('Card number') czeka do timeoutu i kończy się błędem. Pole leży wewnątrz elementu iframe od operatora płatności, a obiekt page przeszukuje tylko główny dokument.
Część 15 przełączała asercję na nowe okno, bo kliknięcie otwierało osobny popup. Element iframe zostaje w tej samej karcie, ale trzyma osobny dokument. Lokator musi wejść do tej ramki, zanim zacznie szukać kontrolki.
Wejdź do ramki przez frameLocator
Metoda page.frameLocator() kieruje kolejny lokator do dokumentu wewnątrz elementu iframe. Działa jak zwykły lokator: czeka, aż ramka pojawi się w DOM, i przetrwa ponowne przeładowanie tej ramki.
test('fills the card number inside the payment frame', async ({ page }) => {
await page.goto('/checkout');
const paymentFrame = page.frameLocator('iframe[title="Secure payment"]'); // dokument z polami karty
await paymentFrame.getByLabel('Card number').fill('4242424242424242');
await page.getByRole('button', { name: 'Pay 49.00' }).click();
await expect(page.getByRole('heading', { name: 'Payment received' })).toBeVisible();
});
Decyzją jest frameLocator. W ramce leży tylko pole numeru karty. Przycisk płatności oraz nagłówek potwierdzenia należą do strony kasy, więc te dwa wywołania zostają na obiekcie page.
Wewnątrz ramki zachowaj kolejność lokatorów z części 2: najpierw rola, potem etykieta, na końcu test ID. Wejście do elementu iframe zmienia przeszukiwany dokument, ale nie zmienia sposobu wyboru selektorów.
Wybieraj frameLocator zamiast page.frame()
Wywołanie page.frame({ name: 'payment' }) zwraca obiekt ramki z tej konkretnej chwili albo null, jeśli element iframe jeszcze się nie załadował. Gdy widget płatności przeładuje swoją ramkę po zmianie adresu dostawy, taka zapisana referencja wskazuje już odłączony dokument.
Obiekt frameLocator odnajduje ramkę przy każdej akcji. Sięgaj po frameLocator, gdy klikasz kontrolkę, wpisujesz tekst albo sprawdzasz asercję. Po metodę page.frame() sięgaj tylko wtedy, gdy potrzebujesz wywołania niedostępnego na lokatorze, na przykład odczytu adresu URL ramki.
Sam znacznik iframe nie zastępuje asercji
Sprawdzenie, że page.locator('iframe[title="Secure payment"]') jest widoczny, dowodzi tylko tego, że strona główna wstawiła pusty kontener. Dokument wewnątrz tej ramki może być pusty, zablokowany przez nagłówek bezpieczeństwa albo zatrzymany na ekranie błędu.
Sprawdzaj kontrolkę albo komunikat wewnątrz paymentFrame. Gdy operator płatności osadza każde pole w osobnej ramce — osobny iframe na numer karty, osobny na datę ważności i osobny na kod CVC — wskaż każdą ramkę przez własny frameLocator nazwany po atrybucie title. Unikaj .first() na znacznikach iframe, bo wcześniejsza ramka narzędzia analitycznego w drzewie DOM przejmie to dopasowanie.
Podsumowanie
Gdy formularz albo zewnętrzny widget renderuje się wewnątrz elementu iframe, zacznij łańcuch od page.frameLocator(), a dalej używaj zwykłych lokatorów opartych na rolach i etykietach. Obiekt page zostaw kontrolkom z dokumentu głównego i nie traktuj widocznego znacznika iframe jako dowodu, że osadzony formularz się wczytał.
Zadanie na ten tydzień: Znajdź jeden test, który przy osadzonym formularzu płatności, oknie czatu albo zabezpieczeniu captcha sprawdza tylko stronę główną, albo omija ten krok. Wskaż tę ramkę przez frameLocator po atrybucie title i dopisz asercję na kontrolkę wewnątrz ramki.