Robot kliknął każdy przycisk. Znalazł osiem luk bezpieczeństwa.
Przestaliśmy testować kawałki, zaczęliśmy testować strony. Prawdziwa przeglądarka, prawdziwy serwer, prawdziwe kliknięcia - na każdym endpoincie, którego dotyka klient.
Nasz kod przechodził sprawdzanie typów, lintera i testy jednostkowe. A mimo to wypuszczał bugi. Nie egzotyczne - formularz resetu, który ignorował potwierdzenie hasła, linki do faktur prowadzące donikąd, feed pokazujący usunięte wątki.
Każdy z nich siedział w szczelinie między kawałkami. Funkcja była dobra. Strona wokół niej - nie. Dlatego zbudowaliśmy framework testowy, który obchodzi tylko jedno: co klient naprawdę widzi i wysyła.
Po co testować prawdziwą stronę?
Każda warstwa testów łapie inny rodzaj błędów. Tylko ostatnia widzi to, co widzą Twoi użytkownicy.
Sprawdza jedną funkcję
Szybki i tani. Ślepy na połączenia: zły URL, zła nazwa pola, przycisk, który nigdy nic nie wysyła.
Sprawdza jedno żądanie
Dowodzi, że serwer odpowiada. Nigdy - że strona to żądanie wysyła albo pokazuje odpowiedź.
Sprawdza całą drogę
Otwiera stronę w Chromium, pisze jak człowiek, klika wyślij, czyta odpowiedź prosto z sieci. Jeśli działa tutaj, działa dla klientów.
Jak działa harness
Playwright sterowany z bun test, zbudowany na definicjach endpointów next-vibe. Definicja zna każde pole - test nie musi.
Otwórz prawdziwą stronę
Test otwiera stronę klienta - /user/login, /story/framework - a nie atrapę. Pisze dopiero wtedy, gdy React przejmie formularz.
Wypełnij typowanymi wartościami
Podajesz wartości, nie selektory. Sterowniki pól czytają definicję i obsługują widoczne UI - piszą, wybierają opcję po etykiecie, dołączają plik.
Złap żądanie z sieci
Submit zwraca prawdę: treść żądania, status i odpowiedź. Harness sprawdza, że żądanie niesie dokładnie to, co wpisano.
Nagraj raz, odtwarzaj zawsze
Płatni dostawcy - modele AI, obraz, muzyka, wideo - są nagrywani per test przy pierwszym uruchomieniu i potem odtwarzani. Zero niespodzianek na rachunku, powtarzalne wyniki.
Raport pokrycia
Raport liczy każdy publiczny endpoint: jeden sukces i jedno odrzucenie. Luki widać, a nie się ich domyśla.
describe("E2E: contact form", () => {
const e2e = useE2E("contact");
e2e.it("sends a message", async ({ open, uniqueEmail }) => {
const form = await open(contactEndpoints.POST, {
path: "/story/framework",
});
await form.fill({
name: "E2E",
email: uniqueEmail("contact"),
subject: ContactSubject.BUG_REPORT,
message: "...",
});
const result = await form.submit();
expect(result.sent).toBe(true);
});
});Cała specyfikacja. Bez selektorów, bez mocków.
Wynik
Pozostałe endpointy potrzebują płatnych kluczy dostawców wyszukiwania, scrapingu i mowy, zanim da się je nagrać.
Luki, które znalazł
Żadna nie wyszła w sprawdzaniu typów ani testach jednostkowych. Każda wyszła, gdy prawdziwa przeglądarka przeszła prawdziwą ścieżkę.
Open redirect na /track
SSRF przez adresy od użytkownika
Cache serwera dzielony między żądaniami
Debug system promptu czytał każdy wątek
Publiczny feed pokazywał ukryte wątki
Opcje logowania zdradzały konta
Reset ignorował potwierdzenie
Prywatne pliki w publicznym cache
I to, co było po prostu zepsute
Nic groźnego - ale po cichu psuło życie prawdziwym ludziom:
- Adresy załączników w czacie i raporty błędów klienta zwracały 404.
- Uprawnienia root nigdy się nie wczytywały - klienci nie mogli pisać w Shared.
- Widget do osadzania nie startował.
- Linki w mailach z fakturami zwracały 404.
- Strona modeli była bezużyteczna.
- Generowanie muzyki przez OpenRouter nie działało.
- Zakres fixture'ów w testach przepuszczał płatne wywołania na żywo.
- Lokalne bazy PGlite zwracały złe wiersze z INSERT…RETURNING.
- Paginacja dla odwiedzających na /tools była zepsuta.
Co to znaczy dla Ciebie
Każda strona, przez którą się rejestrujesz, logujesz, płacisz, czatujesz, generujesz czy zapisujesz, ma teraz test, który otwiera ją w prawdziwej przeglądarce i robi to, co Ty. Gdy coś zmieniamy, robot przechodzi tę drogę, zanim Ty to zrobisz.
Framework jest częścią next-vibe. Budujesz na nim - Twoje endpointy dostają ten sam harness za darmo.
Przeczytaj harness. Użyj go we własnym kodzie.
Framework E2E jest open source i należy do next-vibe. Jeden plik specyfikacji na funkcję, tuż obok definicji.