Cypress Component Testing w React i Next.js — kiedy naprawdę ma sens
Cypress Component Testing w React i Next.js bez marketingowej mgły. Kiedy daje przewagę nad RTL, jak go skonfigurować i gdzie kończą się jego możliwości.
Cypress Component Testing (CT) daje nam przydatną warstwę testów, kiedy chcemy wyłapać problemy z DOM, CSS i interakcjami, których nie widać w samym jsdom. Testując komponet odpalamy go w przeglądarce, ale bez uruchamiania całej aplikacji.
Krótka odpowiedź: Cypress CT = prawdziwa przeglądarka oraz izolowany komponent bez uruchamiania całej aplikacji. Użyj go dla: CSS-zależnych komponentów, drag & drop, focus states. Użyj RTL dla logiki, hooków i szybkich unit testów, a E2E dla: routingu, auth, pełnych flow. Pamiętaj: CT nie zastępuje ani React Testing Library ani pełnych testów E2E. W projektach Next.js najlepiej radzi sobie z client components, design systemu, formularzy, interakcji z DOM i przypadków, w których chcesz zobaczyć prawdziwy CSS. Z kolei dla całych stron, Server Components, redirectów, autoryzacji i przepływów między widokami, dalej wygrywają testy E2E.
Czym Component Testing różni się od E2E?
Różnica jest zasadnicza: w tradycyjnym Cypress E2E musisz mieć uruchomiony serwer dev, cała aplikacja jest włączona i działa, a Cypress nawiguje po stronach jak użytkownik. Z kolei w Component Testing montujesz pojedynczy komponent (lub drzewo komponentów) bezpośrednio w przeglądarce Cypress.
W ten sposób, testy CT są szybsze, bardziej izolowane i łatwiejsze do debugowania.
Setup: Next.js + TypeScript + Cypress CT
Instalacja
Code
npm install -D cypressnpx cypress open
Przy pierwszym uruchomieniu Cypress daje nam wybór pomiędzy E2E Testing, a Component Testing - wybierz Component Testing i pozwól mu wygenerować bazową konfigurację. W przypadku Next.js Component Testing, opiera się zwykle na integracji z Webpackiem, więc warto potraktować to jako osobną warstwę testów dla komponentów, a nie próbę uruchamiania całej aplikacji App Router 1:1 wewnątrz Cypressa.
// cypress/component/SearchInput.cy.tsximport { SearchInput } from "@/components/SearchInput";describe("SearchInput", () => { it("calls onSearch after debounce", () => { cy.clock(); // przejmuje kontrolę nad timerami przeglądarki const onSearch = cy.stub().as("searchHandler"); cy.mount(<SearchInput onSearch={onSearch} debounceMs={200} />); cy.get("[aria-label='Pole wyszukiwania']").type("React"); // Przed debounce – onSearch nie powinien być wywołany cy.get("@searchHandler").should("not.have.been.called"); // Przesuń czas o 200 ms – debounce odpala się dokładnie teraz cy.tick(200); cy.get("@searchHandler").should("have.been.calledWith", "React"); }); it("renders custom placeholder", () => { cy.mount( <SearchInput onSearch={cy.stub()} placeholder="Znajdź produkt..." /> ); cy.get("input").should("have.attr", "placeholder", "Znajdź produkt..."); });});
Testowanie z kontekstem i providerami
Wiele komponentów React zależy od kontekstu (Theme, Auth, Router), natomiast w CT musisz dostarczyć te providery ręcznie.
Code
// cypress/support/component.ts – rozszerzonyimport { mount } from "cypress/react";import { ThemeProvider } from "@/context/ThemeContext";import { QueryClient, QueryClientProvider } from "@tanstack/react-query";function createWrapper() { const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false }, }, }); return function Wrapper({ children }: { children: React.ReactNode }) { return ( <QueryClientProvider client={queryClient}> <ThemeProvider>{children}</ThemeProvider> </QueryClientProvider> ); };}Cypress.Commands.add("mount", (component, options = {}) => { const Wrapper = createWrapper(); return mount(<Wrapper>{component}</Wrapper>, options);});
Teraz każdy cy.mount() automatycznie opakowuje komponent w potrzebne providery.
Cypress CT vs Jest + React Testing Library
Aspekt
Cypress CT
Jest + RTL
Środowisko
Prawdziwa przeglądarka
jsdom (symulacja)
CSS
Działa (widoczne wizualnie)
Ignorowane
Visual debugging
Time-travel, snapshoty
Console.log
Szybkość
Wolniejsze (przeglądarka)
Szybsze (Node.js)
Event handling
Natywne eventy przeglądarki
Symulowane
Setup
Wymaga konfiguracji webpack
Prosta konfiguracja
CI
Wymaga headless browser
Nie wymaga
Kiedy Cypress CT wygrywa?
W telegraficznym skrócie:
Komponent intensywnie korzysta z CSS (animacje, responsive layout),
Zależy Ci na wizualnym debugowaniu,
Testujesz interakcje drag & drop, scroll, resize,
Chcesz spójności z istniejącymi testami Cypress E2E.
Kiedy Jest + RTL wygrywa?
Kiedy szybkość jest priorytetem (CI/CD to praktyka automatyzacji testów, buildów i wdrożeń w procesie dostarczania oprogramowania.),
Testujesz logikę, a nie wygląd i masz prosty setup bez ciężkich zależności CSS,
Twój zespół już zna i używa z powodzeniem RTL.
Interceptowanie requestów w CT
Cypress CT wspiera cy.intercept() tak samo jak E2E:
Code
// cypress/component/UserProfile.cy.tsximport { UserProfile } from "@/components/UserProfile";describe("UserProfile", () => { it("displays user data from API", () => { cy.intercept("GET", "/api/user/1", { statusCode: 200, body: { name: "Jan Kowalski", email: "jan@example.com" }, }).as("getUser"); cy.mount(<UserProfile userId="1" />); cy.wait("@getUser"); cy.contains("Jan Kowalski"); cy.contains("jan@example.com"); }); it("shows error state on API failure", () => { cy.intercept("GET", "/api/user/1", { statusCode: 500, body: { error: "Internal Server Error" }, }); cy.mount(<UserProfile userId="1" />); cy.contains(/nie udało się załadować/i); });});
Ograniczenia w projektach Next.js
To jest miejsce, w którym wiele osób próbuje wycisnąć z CT za dużo.
Client Components nadają się bardzo dobrze do CT, poniważ posiadają lokalny stan, eventy i zależności od DOM.
Server Components lepiej testować przez integrację lub E2E, ponieważ ich wartość wynika z renderowania po stronie serwera, cachingu i kompozycji z resztą aplikacji.
Routing App Routera nie jest celem CT. Jeśli chcesz testować przejścia między stronami, middleware, auth guardy czy redirect(), pisz testy E2E.
generateMetadata, generateStaticParams, route handlers i cache Next.js to nie są "zachowania komponentu" i nie warto na siłę wrzucać ich do CT.
Dobry podział odpowiedzialności wygląda zwykle tak:
Vitest/RTL: czysta logika, hooki, komponenty bez ciężkiego CSS,
Cypress CT: komponenty interaktywne, layout zależny od przeglądarki, drag and drop, focus states,
Data-testid vs role – preferuj role i aria-label (jak RTL), ale data-testid to pragmatyczny fallback.
Nie testuj w CT tego, co lepiej sprawdzi E2E – nawigacja między stronami, pełne flow użytkownika i integracja wielu komponentów to domena testów E2E.
FAQ
Czym jest Cypress Component Testing?
Cypress Component Testing (CT) to tryb testowania, w którym montujesz pojedynczy komponent React bezpośrednio w przeglądarce Cypress i to bez uruchamiania całej aplikacji i serwera dev. Otrzymujesz w ten sposób prawdziwe środowisko przeglądarki, działający CSS, natywne eventy DOM, time-travel debugging. To dodatkowa warstwa między unit testami (jsdom), a pełnymi testami E2E.
Jaka różnica między Cypress CT, a Jest + React Testing Library?
Cypress CT działa w prawdziwej przeglądarce, co oznacza, że CSS jest aplikowany, eventy są natywne, a animacje działają - daje pewność, że komponent zachowuje się jak w produkcji, co jest wartościowe dla komponentów CSS-intensywnych i złożonych interakcji DOM. Jest + RTL używa jsdom, czyli symuluje przeglądarkę bez prawdziwego renderowania CSS, natomiast sam RTL jest szybszy (Node.js, nie przeglądarka) i prostszy w konfiguracji.
Kiedy wybrać Cypress CT zamiast RTL?
Cypress CT wygrywa gdy: (1) komponent intensywnie używa CSS (animacje, media queries, focus states); (2) testujesz interakcje drag & drop, scroll, resize; (3) zależy Ci na wizualnym debugowaniu i inspekcji w przeglądarce; (4) już używasz Cypress E2E i chcesz spójnego workflow. RTL wygrywa gdy: (1) szybkość w CI jest priorytetem; (2) testujesz logikę i hooki; (3) masz prosty stack bez CSS dependencies.
Czy można testować Next.js Server Components w Cypress CT?
Nie bezpośrednio. Server Components wykonują się po stronie serwera i zwracają serialized payload — nie są komponentami React, które można zamontować w przeglądarce. Do testowania Server Components używaj testów integracyjnych lub E2E. Cypress CT najlepiej sprawdza się dla Client Components z 'use client', które mają lokalny stan, handlery zdarzeń i bezpośrednie interakcje z DOM.
Jak skonfigurować Cypress Component Testing w Next.js?
Instalacja: npm install -D cypress. Przy pierwszym npx cypress open wybierz "Component Testing" i framework Next.js — Cypress wygeneruje bazową konfigurację. W cypress.config.ts ustaw component.devServer.framework: 'next' i bundler: 'webpack'. Dodaj support file z Cypress.Commands.add('mount', mount). Dla komponentów zależnych od kontekstu (React Query, Theme) stwórz wrapper w support file.
Czy Cypress CT zastępuje testy E2E?
Nie. CT i E2E testują różne rzeczy, ponieważ CT oznacza izolowany komponent, szybkie wykonanie, bez routingu ani serwera. E2E wiąże się z pełną aplikacją uruchomioną jak w produkcji, realne przepływy użytkownika przez wiele stron. Co wymaga E2E? Routing, middleware, auth, redirecty, generateMetadata czy Server Actions. Optymalny podział to RTL dla logiki, CT dla interaktywnych komponentów z realnym DOM, a E2E dla krytycznych flow.
Jak mockować API w Cypress Component Testing?
Cypress CT wspiera cy.intercept() tak samo jak E2E, czyli przechwytuje requesty HTTP i zwraca mock response. W teście: cy.intercept('GET', '/api/user', { body: mockUser }), potem montuj komponent i weryfikuj render. Możesz też używać cy.stub() do mockowania propsów będących callbackami. Dla komponentów używających React Query warto skonfigurować QueryClient z retry: false w wrapperze testowym.
Cypress Component Testing to potężne narzędzie, które wypełnia lukę między unit testami, a testami E2E. Daje Ci pewność prawdziwej przeglądarki z szybkością izolowanego testu, co w połączeniu z Next.js i TypeScript tworzy bardzo solidny fundament jakości kodu w projekcie.
Jeśli już korzystasz z Cypress do E2E, CT jest Twoim naturalnym następnym krokiem. Z kolei, jeśli zaczynasz od zera, traktuj go jako narzędzie do konkretnych problemów: realnego DOM, CSS i trudnych interakcji.
Najlepszy setup? Rozsądny podział między CT, RTL i E2E...
Pracuję z tym zawodowo.
Jeśli chcesz przełożyć ten temat na lepszą architekturę frontendu, uporządkować React lub Next.js i podnieść jakość pracy zespołu, skontaktuj się ze mną. Pomagam zamieniać wiedzę z artykułów w praktyczne decyzje technologiczne.
Maciej Sala — project manager i frontendowiec z doświadczeniem w marketingu internetowym. Na co dzień pracuję z Reactem, Next.js i TypeScriptem, łącząc perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat związany z branżą gier wideo jako project manager i game designer.
Absolwent historii na Uniwersytecie Jagiellońskim i studiów podyplomowych z marketingu internetowego na Akademii Górniczo-Hutniczej w Krakowie. Poza pracą trenuje na siłowni, maluje figurki i realizuje własne projekty.
Astro.js vs Next.js — które narzędzie wybrać w 2026 roku?
Fachowe porównanie Astro.js i Next.js z perspektywy developera pracującego na co dzień w Next.js. Architektura, wydajność, SEO, DX, koszty i konkretne use case — z benchmarkami i przykładami kodu.
WordPress → Next.js — migracja treści, redirecty 301 i zachowanie pozycji SEO
Jak przenieść stronę z WordPress na Next.js bez utraty pozycji w Google? Eksport treści, mapowanie URL, redirecty 301, migracja obrazów i weryfikacja indeksacji.
Google Search Console + Next.js — indeksacja, błędy, performance i co z nimi robić
Jak korzystać z Google Search Console dla strony Next.js? Weryfikacja, sitemap, indeksacja, Core Web Vitals, crawl budget i najczęstsze problemy — praktyczny poradnik.