Sterowanie siecią w Playwright: mock, przerwanie i podstawiona odpowiedź
Użyj routingu Playwright, żeby podstawić, przerwać albo przepuścić wywołanie. Test UI ma paść z powodu, który wybrałeś.
Ten wpis jest częścią serii Podstawy Playwright. Jeśli pominąłeś poprzedni, przeczytaj Część 10 — Praktyki Playwright, które przeżywają wzrost.
Wprowadzenie — test UI czeka na kogoś innego
Test kasy pada, bo magazyn zwrócił 503. Asercja nie doszła do skutku. Raport mówi, że nie było przycisku zapłaty. Przycisku nie było, bo nie przyszła cena.
Playwright może sam odpowiedzieć na sieć. Ty decydujesz, które wywołania są zachowaniem pod testem, a które są dekoracją.
Trzy odpowiedzi na żądanie
page.route działa, zanim żądanie wyjdzie z przeglądarki.
- fulfill — podajesz status, nagłówki i treść. Aplikacja widzi zwykłą odpowiedź.
- abort — żądanie pada w przeglądarce. Offline, urwany transfer, skrypt, który się nie załadował.
- continue / fallback — żądanie idzie na prawdziwy serwer. Wszystko, czego nie chcesz posiadać.
Najpierw rejestruj ogólny route, potem konkretny. Playwright bierze ostatni pasujący, więc catch-all na początku i konkret na końcu to zwykły układ.
await page.route('**/api/**', (route) => route.fallback());
await page.route('**/api/inventory/*', (route) =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ sku: 'book-1', available: 0 }),
}),
);
await page.goto('/checkout');
await expect(page.getByRole('button', { name: 'Pay' })).toBeDisabled();
await expect(page.getByText('Out of stock')).toBeVisible();
Asercja dotyczy UI. Mock jest po to, żeby UI miało znany powód tego stanu.
Nie mockuj tego, co twierdzisz, że testujesz
Jeśli test brzmi „płatność woła usługę płatności”, to wywołanie musi wyjść z testu. Magazyn, podatek i flagi możesz podstawić, jeśli nie są tematem.
Jeśli test brzmi „przycisk zostaje wyłączony, gdy magazyn jest pusty”, podstaw magazyn, a tematem zostaw przycisk.
Test, który mockuje każde wywołanie i sprawdza, że widać nagłówek, jest zrzutem twoich stubów.
Awarie, które umiesz nazwać
test('shows a retry when pricing times out', async ({ page }) => {
await page.route('**/api/pricing', (route) => route.abort('timedout'));
await page.goto('/cart');
await expect(page.getByRole('button', { name: 'Try again' })).toBeVisible();
});
Powody abort to między innymi timedout, failed i internetdisconnected. Wybierz ten, który produkt naprawdę obsługuje. Jeśli wszystkie kończą się tym samym toastem, wystarczy jeden test.
HAR i nagrany ruch
routeFromHAR odtwarza nagrany plik. Przydaje się, gdy trzecia strona nie ma dublera, a odpowiedź jest duża. Aktualizuj HAR, gdy zmienia się kontrakt. Roczny HAR, który wciąż zwraca 200, to sposób na zieloną suite przy przeprojektowanym API.
Wolę małe fulfill, które sam napisałeś pod ten przypadek. Scenariusz widać w teście. HAR go chowa.
Podsumowanie
Przejmij wywołania, przez które test byłby o czymś innym. To, na którym ci zależy, przepuść. Sprawdzaj stan, który widzi użytkownik, a nie fakt, że stub zwrócił 200.
Zadanie na ten tydzień: Znajdź test UI, który w zeszłym miesiącu padł, bo leżała zależność. Przejmij tę zależność routem. Asercję zostaw na ekranie, który użytkownik miał zobaczyć.
Następny wpis w serii: Część 12 — Które przeglądarki naprawdę odpalać.