Jeśli testy Cypressa zaczynają rozjeżdżać się z zachowaniem aplikacji, zwykle problem nie leży w samym asercie, tylko w tym, że przeglądarka nie reaguje tak samo na zdarzenie symulowane i natywne. W praktyce chodzi o to, kiedy używać cypress real events zamiast klasycznych, symulowanych komend Cypressa. Poniżej rozkładam to na konkretne przypadki: co ta wtyczka faktycznie robi, jak ją wdrożyć, gdzie daje największy efekt i gdzie lepiej jej nie nadużywać.
Najważniejsze informacje w skrócie
- Wtyczka `cypress-real-events` wysyła natywne zdarzenia przeglądarki, a nie tylko zdarzenia tworzone przez JavaScript.
- Najbardziej pomaga tam, gdzie liczy się `:hover`, fokus, skróty klawiaturowe, przewijanie kółkiem myszy albo inne zachowania zależne od prawdziwej interakcji.
- Działa tylko w przeglądarkach opartych na Chromium, więc nie jest rozwiązaniem uniwersalnym dla całego stacku testów.
- Instalacja jest prosta: pakiet, import w pliku support i ewentualnie dopisanie typu do `tsconfig.json`.
- To narzędzie uzupełniające, a nie zamiennik wszystkich standardowych komend Cypressa.
- Najlepiej traktować je selektywnie, bo tam, gdzie wystarczą zwykłe komendy, prostota nadal wygrywa.
Czym są natywne zdarzenia i kiedy robią różnicę
Standardowe komendy Cypressa, takie jak kliknięcie czy wpisywanie tekstu, są w dużej mierze symulowane przez JavaScript. To zwykle wystarcza, ale nie zawsze oddaje zachowanie realnego użytkownika. Niektóre komponenty reagują inaczej na zdarzenia „niezaufane”, inne wymagają prawdziwego fokusu, a jeszcze inne odsłaniają menu dopiero po natywnym hoverze albo dopiero wtedy, gdy przeglądarka widzi rzeczywistą sekwencję klawiszy.
Właśnie w takich miejscach realne zdarzenia mają sens. Ja traktuję je jako narzędzie do testowania granicznych, bardziej „ludzkich” interakcji, a nie jako domyślny sposób klikania wszystkiego. Jeśli aplikacja działa dobrze na symulacji, ale sypie się na prawdziwym focusie, skrócie klawiszowym albo zachowaniu `beforeunload`, to nie jest drobny detal. To sygnał, że test pokrywa zły poziom interakcji.
W praktyce najczęściej chodzi o trzy rzeczy: zgodność z zachowaniem przeglądarki, lepsze odwzorowanie flow użytkownika i mniejszą liczbę obejść w testach. Zanim jednak uznasz to za lepszą wersję wszystkich komend, warto zobaczyć, jak ta wtyczka działa pod spodem i czym różni się od zwykłego `trigger()`.
Jak działa wtyczka i czym różni się od `cy.trigger()`
Według dokumentacji Cypressa `cy.trigger()` jest niskopoziomowym narzędziem do ręcznego wywoływania zdarzeń. To dobre rozwiązanie, gdy chcesz precyzyjnie ustawić typ eventu i jego parametry. Problem zaczyna się wtedy, gdy biblioteka frontendowa oczekuje zachowania przeglądarki, a nie tylko samego eventu w DOM. Wtyczka `cypress-real-events` idzie inną drogą: wykorzystuje Chrome DevTools Protocol i emuluje natywne działania przeglądarki, podobnie jak robią to narzędzia działające nad CDP.
| Obszar | Standardowy Cypress | `cypress-real-events` | Kiedy to ma znaczenie |
|---|---|---|---|
| Źródło zdarzenia | Symulacja przez JavaScript | Natywne zdarzenie przeglądarki | Gdy komponent sprawdza prawdziwą interakcję użytkownika |
| `:hover` | Często wymaga obejścia | Obsługiwany naturalnie | Menu, tooltipy, elementy ujawniane po najechaniu |
| Fokus i tabowanie | Da się testować, ale nie zawsze realistycznie | Lepsze odwzorowanie natywnego przechodzenia po polach | Formularze, a11y, skróty klawiaturowe |
| Debugowanie | Zwykle bardziej przewidywalne | Bywa mniej „gadatliwe”, gdy zdarzenie się nie powiedzie | Gdy zależy Ci na czytelnych błędach i prostym utrzymaniu testów |
To ważne rozróżnienie: `cy.trigger()` nadal jest przydatny, ale działa bardziej jak precyzyjny instrument diagnostyczny. Z kolei `cypress-real-events` jest bliżej tego, co robi człowiek przy klawiaturze i myszce. Ta różnica najlepiej wychodzi w testach interaktywnych, więc następny krok to konfiguracja i pierwszy sensowny scenariusz użycia.
Jak ją dodać do projektu bez zbędnej konfiguracji
Instalacja jest prosta i nie wymaga rozbudowanego setupu. Najczęściej wystarczą trzy kroki: doinstalowanie paczki, import w pliku wsparcia i ewentualne dopisanie typów TypeScript, jeśli projekt z nich korzysta. W praktyce robię to od razu w warstwie testowej, żeby nie rozciągać konfiguracji po kilku plikach.
npm install cypress-real-events
import "cypress-real-events";
{
"compilerOptions": {
"types": ["cypress", "node", "cypress-real-events"]
}
}
Po tym możesz używać komend zaczynających się od `real`, na przykład `realClick`, `realHover`, `realPress`, `realType` czy `realMouseWheel`. W repozytorium wtyczki widać też, że zestaw obejmuje m.in. `realTouch`, `realSwipe`, `realMouseMove`, `realMouseDown` i `realMouseUp`, więc to nie jest jednorazowy trik do hovera, tylko pełniejszy zestaw natywnych interakcji.
W CI trzeba pamiętać o jednym: testy muszą uruchamiać się w prawdziwej przeglądarce opartej na Chromium. Sama wtyczka nie rozwiązuje problemu środowiska, jeśli pipeline jest zbudowany tak, że nie ma gdzie wykonać natywnych zdarzeń. To prowadzi prosto do pytania, gdzie ta wtyczka daje realny zwrot, a gdzie tylko dokłada złożoność.
W jakich scenariuszach daje największy efekt
Najlepsze zastosowania są zwykle bardzo konkretne. Nie chodzi o to, by przerabiać cały zestaw testów e2e na natywne zdarzenia, tylko o to, by sięgać po nie tam, gdzie zwykłe komendy są zbyt „płaskie”. Ja najczęściej widzę sens w czterech obszarach.
- Menu i tooltippy po hoverze - jeśli UI otwiera panel dopiero po prawdziwym najechaniu kursorem, zwykła symulacja bywa niewystarczająca. Tu realny hover skraca obejścia i lepiej odtwarza zachowanie użytkownika.
- Nawigacja klawiaturą - testy dostępności i flow formularzy z `Tab`, skrótami oraz zmianą fokusu wychodzą naturalniej, bo przeglądarka widzi rzeczywiste naciśnięcia klawiszy.
- Dialogi i zachowania systemowe - alerty, potwierdzenia i scenariusze związane z opuszczeniem strony potrafią zachowywać się inaczej, gdy aplikacja dostaje rzeczywistą interakcję, a nie tylko event z DOM.
- Interakcje zależne od przewijania i kursora - kółko myszy, ruch kursora czy precyzyjne kliknięcie w określonym punkcie są przydatne przy bardziej złożonych widgetach.
Dobry test z użyciem tej wtyczki zwykle wygląda tak, że najpierw ustawiasz stan bazowy, potem wykonujesz natywną interakcję i od razu sprawdzasz skutek w UI. Na przykład:
cy.get("[aria-label='Menu']").realHover();
cy.contains("Ustawienia").should("be.visible");
cy.get("input").focus();
cy.realPress("Tab");
cy.focused().should("have.attr", "type", "button");
To są proste przykłady, ale właśnie w nich widać przewagę: mniej sztucznych obejść, mniej kombinowania z `trigger()` i mniej sporów z biblioteką frontendową. Dalej trzeba jednak uczciwie powiedzieć, gdzie ta wygoda się kończy.
Jakie ma ograniczenia i gdzie lepiej jej nie nadużywać
Największe ograniczenie jest techniczne: natywne zdarzenia działają tylko w przeglądarkach opartych na Chromium. Firefox nie jest wspierany, więc jeśli Twoja strategia testowa zakłada szeroki cross-browser, ta wtyczka nie może być jedynym rozwiązaniem. Drugi temat to CI. Jeżeli pipeline uruchamia testy w obrazie, który źle współpracuje z CDP, natywne eventy potrafią działać niestabilnie. W repozytorium wtyczki wyraźnie widać zalecenie, by korzystać z typowego środowiska Cypressa albo z obrazu opartego o `node:lts` i doinstalować realną przeglądarkę.
| Ograniczenie | Skutek | Co robić w praktyce |
|---|---|---|
| Tylko Chromium | Brak wsparcia dla Firefox | Traktować wtyczkę jako rozszerzenie, nie fundament całej strategii |
| Środowisko CI | Ryzyko problemów z CDP | Testować na stabilnym obrazie i realnej przeglądarce |
| Zgodność wersji | Możliwy konflikt zależności | Sprawdzać peer dependencies przed aktualizacją Cypressa |
| Diagnostyka błędów | Uboższy komunikat, gdy event nie przejdzie | Utrzymywać osobne testy sanity i nie zastępować wszystkiego natywnymi eventami |
Warto też pamiętać o zgodności wersji. W publicznym wątku dotyczącym Cypressa pojawił się konflikt `cypress-real-events` z Cypress 15, więc przed większą aktualizacją dobrze jest sprawdzić, czy dana wersja pakietu nadal pasuje do Twojego stacku. To nie jest powód, by z tej wtyczki rezygnować, ale wystarczający, by nie zakładać bezrefleksyjnie, że każda nowa wersja Cypressa zadziała tak samo.
W praktyce moja rekomendacja jest prosta: używaj natywnych zdarzeń tam, gdzie naprawdę testujesz zachowanie użytkownika, a nie tylko „kliknięcie elementu”. Jeśli komponent jest prosty, klasyczne komendy Cypressa pozostają czytelniejsze, szybsze w utrzymaniu i mniej wrażliwe na wersje przeglądarki.
Co warto ustalić w zespole przed wdrożeniem
Jeśli miałbym wdrażać tę wtyczkę w zespole produktowym, ustaliłbym trzy rzeczy jeszcze przed napisaniem pierwszego testu. Po pierwsze, spis użyć: tylko hover, tylko keyboard flow, tylko przypadki, w których standardowy Cypress faktycznie nie daje rady. Po drugie, matrycę uruchomień: które testy lecą na Chromium, które muszą pozostać cross-browser, a które w ogóle nie powinny dotykać natywnych eventów. Po trzecie, politykę wersji: przypięty zakres Cypressa, kontrola paczki w lockfile i szybki przegląd zmian po aktualizacji frameworka.
To podejście zwykle oszczędza więcej czasu niż samo „dodanie kolejnej wtyczki”. `cypress-real-events` jest mocnym narzędziem, ale tylko wtedy, gdy używasz go selektywnie i z jasnym celem. Właśnie tak buduje się stabilne testy automatyczne: nie przez mnożenie sztuczek, tylko przez dobranie właściwego narzędzia do konkretnego zachowania aplikacji.