Pytania rekrutacyjne Jest

55 pytań — 20 odpowiedzi dostępnych od razu

Jest jest popularnym narzędziem do testowania JavaScript i często pojawia się w pytaniach o jakość kodu oraz strategię testów. Ten darmowy podgląd obejmuje przykładowe pytania z zestawu 55 zagadnień.

Materiał porusza konfigurację, asercje i matchery, mockowanie, spy oraz resetowanie mocków. Pozwala powtórzyć, jak projektować czytelne i wiarygodne testy jednostkowe.

Darmowy start

Pierwsze 20 odpowiedzi są dostępne od razu

Przeglądaj pełną listę 55 pytań. Pełne odpowiedzi, przykłady kodu i materiały do nauki odblokujesz w panelu.

Odblokuj 35 odpowiedzi

Podstawy Jest

Czym jest Jest i dlaczego jest tak popularny w ekosystemie JavaScript?

Odpowiedź w 30 sekund: Jest to framework testowy stworzony przez Facebooka (obecnie utrzymywany przez OpenJS Foundation), zaprojektowany jako kompletne rozwiązanie "wszystko w jednym" do testowania kodu JavaScript. Popularność zawdzięcza zerowej konfiguracji, wbudowanym asercjom, mockom i pokryciu kodu oraz świetnej integracji z Reactem i innymi nowoczesnymi narzędziami.

Odpowiedź w 2 minuty: Jest powstał w 2014 roku w Facebooku jako odpowiedź na potrzebę testowania ogromnej bazy kodu React. Jego głównym założeniem było zapewnienie narzędzia, które "po prostu działa" bez konieczności składania ekosystemu z wielu bibliotek (jak w przypadku Mocha + Chai + Sinon + Istanbul). Dziś jest standardem de facto w projektach Reactowych, Next.js, a także często wybierany w aplikacjach Node.js oraz bibliotekach uniwersalnych.

Popularność Jest wynika z kilku czynników: prostej konfiguracji (w wielu projektach wystarczy npm install --save-dev jest), wbudowanego runnera, asercji (expect), mocków (jest.fn, jest.mock), pokrycia kodu (--coverage), a także unikalnych funkcji jak snapshot testing. Dodatkowo Jest działa w izolowanych procesach Node.js, co daje deterministyczne i równoległe wykonywanie testów.

Warto używać Jest, gdy zależy nam na szybkim starcie, dobrej dokumentacji i wsparciu społeczności. Typowe pułapki to: domyślne środowisko jsdom (od Jest 27 zmienione na node — łatwo zapomnieć ustawić testEnvironment: 'jsdom' dla testów DOM-owych), problemy z transformacją ESM/TypeScript wymagające babel-jest lub ts-jest, oraz mockowanie modułów ESM (które do niedawna było eksperymentalne).

Przykład kodu:

// suma.js - prosty moduł do testowania
function suma(a, b) {
  return a + b;
}
module.exports = { suma };

// suma.test.js - test napisany w Jest
const { suma } = require('./suma');

test('dodaje 2 + 3 i zwraca 5', () => {
  // Asercja wbudowana - nie potrzeba Chai ani innej biblioteki
  expect(suma(2, 3)).toBe(5);
});

test('obsługuje liczby ujemne', () => {
  expect(suma(-1, -1)).toBe(-2);
});

Materiały

Jakie są kluczowe cechy Jest, które wyróżniają go na tle innych frameworków testowych?

Odpowiedź w 30 sekund: Jest wyróżnia się modelem "batteries-included" — w jednym pakiecie dostajemy runner, asercje, mocki, snapshot testing oraz raporty pokrycia kodu. Dodatkowo oferuje równoległe wykonywanie testów w izolowanych procesach, tryb watch oraz świetne komunikaty błędów.

Odpowiedź w 2 minuty: Najważniejsze cechy Jest to: zerowa konfiguracja dla większości projektów (zwłaszcza Create React App, Next.js), wbudowane asercje przez API expect (toBe, toEqual, toHaveBeenCalled itd.), system mockowania (jest.fn, jest.spyOn, jest.mock) pozwalający na podmianę całych modułów, oraz snapshot testing — porównywanie wyniku komponentu/struktury z zapisanym wcześniej "zdjęciem".

Kolejne istotne cechy to izolacja testów — każdy plik testowy działa we własnym kontekście (workerze), co eliminuje problemy ze współdzielonym stanem. Równoległość sprawia, że duże suity testów działają znacznie szybciej. Tryb watch (jest --watch) inteligentnie uruchamia tylko testy powiązane ze zmienionymi plikami (poprzez analizę grafu zależności git). Code coverage (--coverage) działa out-of-the-box z wykorzystaniem Istanbul/V8.

Warto wspomnieć o timer mocks (jest.useFakeTimers), które pozwalają testować kod oparty o setTimeout/setInterval bez czekania, oraz o module mocking — możliwości podmiany całego modułu zewnętrznego (np. axios) jedną linią kodu. Pułapką bywa to, że tak rozbudowany framework może maskować problemy projektowe — gdy mockujemy "wszystko", nasze testy przestają cokolwiek weryfikować w realnym świecie.

Przykład kodu:

// Przykład pokazujący kilka kluczowych cech Jest naraz
const axios = require('axios');
jest.mock('axios'); // Automatyczne mockowanie modułu

describe('Pobieranie użytkownika', () => {
  beforeEach(() => {
    // Czyszczenie wywołań mocków przed każdym testem
    jest.clearAllMocks();
  });

  test('pobiera dane i tworzy snapshot', async () => {
    // Mockowanie odpowiedzi HTTP
    axios.get.mockResolvedValue({ data: { id: 1, name: 'Anna' } });

    const response = await axios.get('/api/user/1');

    // Asercja - sprawdzenie wywołania mocka
    expect(axios.get).toHaveBeenCalledWith('/api/user/1');
    // Snapshot - porównanie ze "zdjęciem" zapisanym przy pierwszym uruchomieniu
    expect(response.data).toMatchSnapshot();
  });
});

Materiały

Jaka jest różnica między Jest a Mocha lub Jasmine?

Odpowiedź w 30 sekund: Mocha to minimalistyczny test runner wymagający dodatkowych bibliotek do asercji (Chai) i mocków (Sinon). Jasmine to framework "wszystko w jednym" — zbliżony filozofią do Jest, ale starszy i pozbawiony nowoczesnych funkcji jak snapshot testing czy równoległe wykonywanie. Jest łączy zalety obu: kompletność Jasmine i nowoczesność Mocha.

Odpowiedź w 2 minuty: Mocha (od 2011) to bardzo elastyczny runner, który celowo nie narzuca asercji ani biblioteki mockującej — pozwala dobrać dowolne narzędzia (Chai, Sinon, Should.js, NYC dla coverage). To podejście daje dużą swobodę, ale wymaga większej konfiguracji i znajomości ekosystemu. Mocha jest popularna w bibliotekach Node.js oraz w starszych projektach.

Jasmine (od 2010, stworzony przez Pivotal Labs) to framework BDD oferujący kompletne rozwiązanie: runner, asercje (expect), mocki (spyOn). Składnia (describe, it, beforeEach) była inspiracją dla Jest. Jest najczęściej używany w starszych projektach Angular (przed migracją na Karma+Jasmine, a obecnie często do Jest).

Jest (od 2014) zbudowano bazując na Jasmine, ale dodano: równoległość, snapshoty, lepsze mocki, tryb watch, izolację modułów oraz wbudowane coverage. W praktyce Jest jest dziś najpopularniejszy w świecie React/Next/TypeScript, podczas gdy Mocha utrzymuje silną pozycję w projektach Node.js i bibliotekach niewykorzystujących Reacta.

Wybór zależy od projektu: Jest dla aplikacji frontendowych i monorepo, Mocha dla bibliotek Node.js wymagających minimalnych zależności, Jasmine — głównie w istniejących projektach.

Cecha Jest Mocha Jasmine
Runner tak tak tak
Wbudowane asercje tak (expect) nie (Chai) tak (expect)
Wbudowane mocki tak (jest.fn) nie (Sinon) tak (spyOn)
Snapshot testing tak nie nie
Coverage tak (wbudowany) nie (NYC) nie
Równoległość tak tylko z mocha-parallel nie
Tryb watch tak (smart) tak (--watch) nie
Konfiguracja minimalna wymagana minimalna
Popularność (2024) bardzo wysoka wysoka niska

Przykład kodu:

// Ten sam test w trzech frameworkach

// === MOCHA + CHAI ===
const { expect } = require('chai');
describe('Suma', () => {
  it('dodaje liczby', () => {
    expect(2 + 3).to.equal(5); // Chai - inny styl asercji
  });
});

// === JASMINE ===
describe('Suma', () => {
  it('dodaje liczby', () => {
    expect(2 + 3).toBe(5); // Wbudowane expect
  });
});

// === JEST ===
describe('Suma', () => {
  test('dodaje liczby', () => {
    expect(2 + 3).toBe(5); // Praktycznie identyczne jak Jasmine
  });
});

Materiały

Jak Jest odnajduje pliki testowe w projekcie (testMatch, testPathIgnorePatterns)?

Odpowiedź w 30 sekund: Jest domyślnie wyszukuje pliki w katalogach __tests__ oraz pliki kończące się na .test.js, .spec.js (i ich warianty z TypeScript/JSX). Zachowanie można dostosować poprzez opcje testMatch (lista glob patterns) oraz testPathIgnorePatterns (ścieżki do pominięcia, domyślnie node_modules).

Odpowiedź w 2 minuty: Domyślna konfiguracja testMatch w Jest wygląda tak: ["**/__tests__/**/*.[jt]s?(x)", "**/?(*.)+(spec|test).[jt]s?(x)"]. Oznacza to, że Jest znajdzie pliki w katalogach __tests__ (na dowolnym poziomie zagnieżdżenia) oraz wszystkie pliki o rozszerzeniu .test.js, .test.ts, .test.jsx, .test.tsx, .spec.js itd.

testPathIgnorePatterns domyślnie ma wartość ["/node_modules/"], więc Jest nie skanuje zależności. Często dodaje się tu również /dist/, /build/, /.next/ lub inne katalogi build-output, by uniknąć podwójnego uruchamiania testów na skompilowanym kodzie.

Alternatywą dla testMatch jest testRegex (wzajemnie się wykluczają) — wyrażenie regularne dopasowujące ścieżki testów. Generalnie zaleca się testMatch, bo glob jest czytelniejszy.

Warto pamiętać o rootDir (domyślnie katalog z package.json) i roots (lista katalogów, w których Jest szuka testów — domyślnie ["<rootDir>"]). W monorepo często ustawia się roots: ["<rootDir>/packages"] lub używa projects dla wielu konfiguracji.

Pułapki: gdy używamy katalogu __tests__, każdy plik tam trafiający — także helpers.js czy setup.js — zostanie potraktowany jako test (i Jest rzuci błąd "Your test suite must contain at least one test"). Rozwiązaniem jest umieszczanie helperów poza __tests__ albo dodanie ich do testPathIgnorePatterns.

Przykład kodu:

// jest.config.js
module.exports = {
  // Gdzie Jest ma szukać testów
  roots: ['<rootDir>/src', '<rootDir>/tests'],

  // Wzorce dopasowania plików testowych
  testMatch: [
    '**/__tests__/**/*.[jt]s?(x)', // Katalogi __tests__
    '**/?(*.)+(spec|test).[jt]s?(x)' // *.test.js, *.spec.ts itp.
  ],

  // Ścieżki ignorowane (regex, nie glob!)
  testPathIgnorePatterns: [
    '/node_modules/',
    '/dist/',
    '/build/',
    '/__tests__/helpers/' // Pomijamy helpery w __tests__
  ],

  // Alternatywa - testRegex (zamiast testMatch)
  // testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.[jt]sx?$',
};

// Aby zobaczyć, które pliki Jest znajdzie, uruchom:
// npx jest --listTests

Materiały

Jaka jest różnica między test(), it() oraz describe()?

Odpowiedź w 30 sekund: test() i it() to ten sam mechanizm — aliasy definiujące pojedynczy przypadek testowy; różnią się tylko stylem językowym. describe() grupuje powiązane testy w blok logiczny, co poprawia czytelność wyjścia i pozwala dzielić beforeEach/afterEach.

Odpowiedź w 2 minuty: test(name, fn) to podstawowa funkcja Jest definiująca przypadek testowy. it(name, fn) jest jej dokładnym aliasem — istnieje, by umożliwić styl BDD przejęty z Jasmine, gdzie zdanie czytane jest naturalnie: it("should return 5", ...). Wybór między nimi to kwestia konwencji projektu — żadnej różnicy technicznej nie ma.

describe(name, fn) to grupowanie — tworzy blok, w którym możemy zorganizować logicznie powiązane testy. Wyjście Jest pokazuje wtedy hierarchię (zagnieżdżone bullet points), co ułatwia nawigację w dużych plikach. Wewnątrz describe możemy zdefiniować hooki: beforeAll, beforeEach, afterEach, afterAll, które obowiązują tylko w obrębie tego bloku (i jego zagnieżdżonych describe).

Konwencja: nazwa describe opisuje co testujemy (klasa, moduł, funkcja, scenariusz), nazwa test/it opisuje jaki konkretny przypadek. Często stosuje się zagnieżdżone describe dla różnych scenariuszy tej samej funkcji (np. "z poprawnymi danymi", "z błędnymi danymi").

Modyfikatory: test.only / it.only / describe.only uruchamiają tylko zaznaczone testy (przydatne przy debugowaniu); test.skip / describe.skip pomijają je; test.todo("opis") zaznacza testy do napisania.

Przykład kodu:

// Kalkulator - przykład grupowania describe + test/it
const Kalkulator = require('./kalkulator');

describe('Kalkulator', () => {
  let kalkulator;

  // Hook - uruchamiany przed KAŻDYM testem w tym describe
  beforeEach(() => {
    kalkulator = new Kalkulator();
  });

  describe('metoda dodaj()', () => {
    // 'test' i 'it' są identyczne
    test('dodaje dwie liczby dodatnie', () => {
      expect(kalkulator.dodaj(2, 3)).toBe(5);
    });

    it('powinno obsłużyć liczby ujemne', () => {
      // Styl BDD - "it should..."
      expect(kalkulator.dodaj(-1, -1)).toBe(-2);
    });
  });

  describe('metoda podziel()', () => {
    test('dzieli dwie liczby', () => {
      expect(kalkulator.podziel(10, 2)).toBe(5);
    });

    test('rzuca wyjątek przy dzieleniu przez zero', () => {
      expect(() => kalkulator.podziel(10, 0)).toThrow('Dzielenie przez zero');
    });

    test.todo('zaokrąglanie wyniku do 2 miejsc po przecinku');
  });
});

// Wyjście Jest pokazuje hierarchię:
// Kalkulator
//   metoda dodaj()
//     ✓ dodaje dwie liczby dodatnie
//     ✓ powinno obsłużyć liczby ujemne
//   metoda podziel()
//     ✓ dzieli dwie liczby
//     ✓ rzuca wyjątek przy dzieleniu przez zero
//     ✎ todo zaokrąglanie wyniku do 2 miejsc po przecinku

Materiały

Czym jest piramida testów i jak Jest wpisuje się w jej poziomy?

Odpowiedź w 30 sekund: Piramida testów (Mike Cohn, 2009) to model wizualizujący proporcje typów testów: dużo szybkich testów jednostkowych u podstawy, mniej testów integracyjnych pośrodku, niewiele wolnych testów E2E na szczycie. Jest doskonale sprawdza się na poziomie testów jednostkowych i integracyjnych — dla E2E używa się raczej Playwright/Cypress.

Odpowiedź w 2 minuty: Koncepcja piramidy testów zakłada, że dobrze zbalansowana suita testów ma kształt piramidy:

  • Podstawa (~70%): testy jednostkowe — szybkie, izolowane, sprawdzające pojedyncze funkcje/klasy/komponenty;
  • Środek (~20%): testy integracyjne — weryfikujące współpracę kilku modułów (np. komponent + API + store);
  • Wierzchołek (~10%): testy E2E (end-to-end) — uruchamiają całą aplikację w przeglądarce, symulują użytkownika.

Im wyżej, tym testy są wolniejsze, droższe w utrzymaniu i bardziej "kruche" (flaky). Im niżej — szybsze, łatwiejsze do debugowania, ale obejmują mniejszy zakres.

Jest świetnie nadaje się na dwa dolne poziomy: testy jednostkowe (np. czysta funkcja, reducer, hook) oraz testy integracyjne (komponent React z React Testing Library, gdzie sprawdzamy interakcję z DOM, API mockowanym przez MSW itp.). Na poziomie E2E Jest jest rzadziej używany — preferuje się Playwright, Cypress lub WebdriverIO, które uruchamiają realną przeglądarkę.

Alternatywne modele to plaster miodu (Spotify) — więcej testów integracyjnych, mniej jednostkowych, gdy logika biznesowa jest w warstwie integracji; oraz trofeum testowe Kenta C. Doddsa, gdzie integracyjne stanowią największą warstwę. Niezależnie od modelu, Jest pokrywa dolne i środkowe warstwy w stacku JavaScript/TypeScript.

flowchart TD
    E2E["Testy E2E<br/>~10%<br/>Playwright, Cypress<br/>Wolne, drogie"]
    INT["Testy integracyjne<br/>~20%<br/>Jest + RTL + MSW<br/>Współpraca modułów"]
    UNIT["Testy jednostkowe<br/>~70%<br/>Jest<br/>Szybkie, izolowane"]

    E2E --> INT
    INT --> UNIT

    style E2E fill:#ffcccc
    style INT fill:#ffeecc
    style UNIT fill:#ccffcc

Przykład kodu:

// === POZIOM 1: TEST JEDNOSTKOWY (Jest) ===
// formatPrice.js
function formatPrice(amount, currency = 'PLN') {
  return `${amount.toFixed(2)} ${currency}`;
}

// formatPrice.test.js - czysta funkcja, brak zależności
test('formatuje cenę z domyślną walutą', () => {
  expect(formatPrice(19.9)).toBe('19.90 PLN');
});

// === POZIOM 2: TEST INTEGRACYJNY (Jest + React Testing Library) ===
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import CartSummary from './CartSummary';

test('użytkownik dodaje produkt i widzi sumę w PLN', async () => {
  render(<CartSummary />);
  // Symulacja interakcji - test obejmuje komponent, hook i formatPrice
  await userEvent.click(screen.getByRole('button', { name: /dodaj/i }));
  expect(screen.getByText('19.90 PLN')).toBeInTheDocument();
});

// === POZIOM 3: TEST E2E (zazwyczaj Playwright, NIE Jest) ===
// e2e/checkout.spec.ts
// import { test, expect } from '@playwright/test';
// test('pełna ścieżka zakupu', async ({ page }) => {
//   await page.goto('/sklep');
//   await page.click('text=Dodaj do koszyka');
//   await expect(page.locator('.cart-total')).toHaveText('19.90 PLN');
// });

Materiały

Konfiguracja i Setup

Jak zainstalować i skonfigurować Jest w projekcie React/TypeScript?

Odpowiedź w 30 sekund: Instalujemy jest, @types/jest, ts-jest oraz @testing-library/react jako devDependencies, a następnie tworzymy plik jest.config.js z presetem ts-jest i środowiskiem jsdom. W projektach opartych na Create React App lub Vite konfiguracja jest często gotowa lub wymaga jedynie drobnych modyfikacji.

Odpowiedź w 2 minuty: W standardowym projekcie React z TypeScript musimy zainstalować kilka kluczowych pakietów: jest jako test runner, ts-jest do transformacji TypeScript, @types/jest dla typowania, jest-environment-jsdom dla symulacji środowiska przeglądarki oraz @testing-library/react i @testing-library/jest-dom do testowania komponentów. Następnie generujemy konfigurację przez npx ts-jest config:init lub tworzymy ręcznie plik jest.config.js.

W konfiguracji ustawiamy preset: 'ts-jest', testEnvironment: 'jsdom', definiujemy ścieżki testów przez testMatch lub testRegex, a dla obsługi importów CSS i assetów konfigurujemy moduleNameMapper. Warto też dodać setupFilesAfterEach z @testing-library/jest-dom żeby uzyskać dodatkowe matchery jak toBeInTheDocument.

Jeśli używamy Create React App, Jest jest już skonfigurowany — wystarczy uruchomić npm test. W projektach Vite zaleca się Vitest, ale można też skonfigurować Jest ręcznie. W Next.js 12+ konfiguracja Jest jest opisana w oficjalnej dokumentacji i wymaga użycia next/jest dla automatycznej obsługi SWC.

Przykład kodu:

// Instalacja pakietów
// npm install --save-dev jest @types/jest ts-jest jest-environment-jsdom
// npm install --save-dev @testing-library/react @testing-library/jest-dom

// jest.config.js - konfiguracja dla React + TypeScript
module.exports = {
  // Preset ts-jest obsługuje transformację TypeScript
  preset: 'ts-jest',
  // Środowisko jsdom symuluje DOM przeglądarki
  testEnvironment: 'jsdom',
  // Pliki uruchamiane po inicjalizacji frameworka testowego
  setupFilesAfterEach: ['<rootDir>/jest.setup.ts'],
  // Mapowanie modułów - obsługa importów CSS i aliasów ścieżek
  moduleNameMapper: {
    '\\.(css|less|scss)$': 'identity-obj-proxy',
    '^@/(.*)$': '<rootDir>/src/$1',
  },
  // Wzorzec wyszukiwania plików testowych
  testMatch: ['**/__tests__/**/*.test.(ts|tsx)'],
};

// jest.setup.ts - dodatkowe matchery z jest-dom
import '@testing-library/jest-dom';

// package.json - skrypty
{
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage"
  }
}

Materiały

Jakie są kluczowe opcje pliku jest.config.js (testEnvironment, transform, moduleNameMapper)?

Odpowiedź w 30 sekund: Najważniejsze opcje to testEnvironment (środowisko wykonania testów — jsdom lub node), transform (mapowanie wzorców plików na transformery jak ts-jest czy babel-jest) oraz moduleNameMapper (regex-mapping importów do mocków lub aliasów). Razem definiują jak Jest interpretuje, transformuje i wykonuje kod testowy.

Odpowiedź w 2 minuty: testEnvironment określa kontekst, w którym uruchamiane są testy. Wartość 'jsdom' symuluje przeglądarkę z dostępem do window, document i DOM, podczas gdy 'node' jest lżejszym środowiskiem dla testów backendowych. Można też ustawić środowisko per-plik przez komentarz @jest-environment na początku pliku testowego.

transform to obiekt mapujący wzorce regex na transformery, które konwertują kod przed wykonaniem. Najczęściej '^.+\\.tsx?$': 'ts-jest' dla TypeScript lub '^.+\\.jsx?$': 'babel-jest' dla JSX. Transformery cache'ują wyniki, więc kolejne uruchomienia są szybsze.

moduleNameMapper rozwiązuje importy przez regex — używany do mockowania CSS ('\\.css$': 'identity-obj-proxy'), assetów statycznych, oraz aliasów ścieżek ('^@/(.*)$': '<rootDir>/src/$1'). Inne ważne opcje to testMatch/testRegex (lokalizacja testów), collectCoverageFrom (zakres pomiaru pokrycia), setupFiles i setupFilesAfterEach (skrypty inicjalizacyjne), globalSetup/globalTeardown (raz przed/po całej suite), moduleDirectories (gdzie szukać modułów) oraz clearMocks: true (auto-czyszczenie mocków między testami).

Przykład kodu:

// jest.config.js - przegląd najważniejszych opcji
module.exports = {
  // Środowisko testowe: 'jsdom' dla frontendu, 'node' dla backendu
  testEnvironment: 'jsdom',

  // Transformacja plików przed wykonaniem
  transform: {
    '^.+\\.tsx?$': ['ts-jest', { tsconfig: 'tsconfig.test.json' }],
    '^.+\\.jsx?$': 'babel-jest',
  },

  // Mapowanie modułów - mocki i aliasy
  moduleNameMapper: {
    // Mockowanie plików CSS/SCSS
    '\\.(css|less|scss|sass)$': 'identity-obj-proxy',
    // Mockowanie obrazów i innych assetów
    '\\.(jpg|jpeg|png|svg)$': '<rootDir>/__mocks__/fileMock.js',
    // Aliasy ścieżek
    '^@components/(.*)$': '<rootDir>/src/components/$1',
  },

  // Wyszukiwanie testów
  testMatch: ['**/*.test.(ts|tsx|js|jsx)'],
  testPathIgnorePatterns: ['/node_modules/', '/dist/'],

  // Pliki konfiguracyjne uruchamiane raz na worker
  setupFiles: ['<rootDir>/jest.polyfills.js'],
  // Pliki uruchamiane po inicjalizacji każdego testu
  setupFilesAfterEach: ['<rootDir>/jest.setup.ts'],

  // Pokrycie kodu
  collectCoverageFrom: ['src/**/*.{ts,tsx}', '!src/**/*.d.ts'],
  coverageThreshold: {
    global: { branches: 80, functions: 80, lines: 80 },
  },

  // Auto-czyszczenie mocków między testami
  clearMocks: true,
  restoreMocks: true,
};

Materiały

Czym jest różnica między środowiskami jsdom a node i kiedy wybrać które?

Odpowiedź w 30 sekund: jsdom symuluje przeglądarkę z DOM, window, document i większością Web API — idealne dla testów komponentów React i kodu używającego DOM. node to lekkie środowisko bez DOM, szybsze i mniej zasobożerne — odpowiednie dla testów logiki biznesowej, funkcji utility i kodu serwerowego.

Odpowiedź w 2 minuty: jsdom to czysto-JavaScriptowa implementacja standardów DOM i HTML, która tworzy wirtualne środowisko przeglądarki w Node.js. Daje dostęp do window, document, localStorage, fetch (od jsdom 16+ z polyfillem), eventów DOM oraz wielu Web API. Jest niezbędne do testowania komponentów React, manipulacji DOM, hooks używających DOM oraz interakcji użytkownika. Ma jednak narzut — testy są wolniejsze, a inicjalizacja środowiska zajmuje czas.

node to natywne środowisko Node.js bez żadnej symulacji przeglądarki. Brak window, document, ale dostępne są wszystkie Node.js API jak fs, path, process. Jest znacznie szybsze, idealne dla testów funkcji pure, klas, parserów, walidatorów, kodu Express/NestJS oraz logiki biznesowej niezależnej od UI.

Wybór zależy od testowanego kodu. W projekcie hybrydowym (np. Next.js) można mieszać środowiska per-plik przez komentarz /** @jest-environment node */ lub /** @jest-environment jsdom */ na początku pliku testowego. Niektóre projekty konfigurują nawet osobne projekty Jest dla różnych typów testów przez opcję projects w jest.config.js.

Cecha jsdom node
DOM API Tak (window, document) Nie
localStorage / sessionStorage Tak Nie
fetch API Tak (jsdom 16+) Tak (Node 18+)
Wydajność Wolniejsze (narzut DOM) Szybsze
Rozmiar pamięci Większy Mniejszy
Testy komponentów React Tak Nie
Testy Express/API Słabo Idealne
Testy logiki/utili Działa, ale narzut Idealne
Domyślne w CRA Tak Nie

Przykład kodu:

// jest.config.js - środowisko globalne
module.exports = {
  testEnvironment: 'jsdom', // domyślnie dla projektów frontendowych
};

// Nadpisanie środowiska per plik testowy
/**
 * @jest-environment node
 */
// validator.test.ts - test logiki bez DOM
import { validateEmail } from './validator';

describe('validateEmail', () => {
  it('powinien zwrócić true dla poprawnego emaila', () => {
    expect(validateEmail('test@example.com')).toBe(true);
  });
});

// Inny plik - test komponentu React (jsdom)
/**
 * @jest-environment jsdom
 */
import { render, screen } from '@testing-library/react';
import { Button } from './Button';

describe('Button', () => {
  it('powinien wyrenderować tekst', () => {
    // Wymaga DOM - jsdom dostarcza document
    render(<Button>Kliknij mnie</Button>);
    expect(screen.getByText('Kliknij mnie')).toBeInTheDocument();
  });
});

// Konfiguracja wielu projektów - osobne środowiska
// jest.config.js
module.exports = {
  projects: [
    {
      displayName: 'frontend',
      testMatch: ['<rootDir>/src/components/**/*.test.tsx'],
      testEnvironment: 'jsdom',
    },
    {
      displayName: 'backend',
      testMatch: ['<rootDir>/src/api/**/*.test.ts'],
      testEnvironment: 'node',
    },
  ],
};

Materiały

Jak skonfigurować Jest do pracy z TypeScript za pomocą ts-jest lub Babela?

Odpowiedź w 30 sekund: ts-jest używa kompilatora TypeScript do transformacji i sprawdzania typów podczas testów — wolniejsze, ale dokładne. Babel (z @babel/preset-typescript) tylko usuwa typy bez sprawdzania — znacznie szybsze, ale bez bezpieczeństwa typów. Wybór zależy od priorytetu: bezpieczeństwo typów vs wydajność.

Odpowiedź w 2 minuty: ts-jest to transformer dla Jest, który używa oficjalnego kompilatora TypeScript (tsc) do transformacji plików .ts/.tsx na JavaScript. Zachowuje pełne sprawdzanie typów podczas testów, co oznacza, że błąd typu spowoduje niepowodzenie testu. Konfiguracja jest prosta: npm install --save-dev ts-jest, potem npx ts-jest config:init generuje konfigurację. Można go dostrajać przez opcję globals lub przekazywanie konfiguracji w transform. W nowszych wersjach (29+) zalecane jest użycie funkcji createDefaultPreset() zamiast preset: 'ts-jest'.

Babel z @babel/preset-typescript traktuje TypeScript jak JavaScript z dodatkową składnią — usuwa typy bez ich weryfikacji. Jest znacznie szybszy, bo nie wykonuje pełnej kompilacji TS. Wymaga @babel/preset-env, @babel/preset-react i @babel/preset-typescript. Wadą jest brak sprawdzania typów w czasie testów — błędy typów wykryjesz dopiero przez osobne tsc --noEmit. Tej ścieżki używa domyślnie Create React App oraz next/jest.

Cecha ts-jest Babel + preset-typescript
Sprawdzanie typów Tak Nie (tylko usuwa typy)
Wydajność Wolniejsze Szybsze
Konfiguracja Mniej kroków Wymaga babel.config
Source maps Dobre Bardzo dobre
Wsparcie dla const enum Tak Nie (bez plugin)
Wsparcie decoratorów Pełne Eksperymentalne
Dekrety dekoratorów Tak (z tsconfig) Wymaga pluginu
Używane w CRA Nie Tak
Używane w Next.js Nie Tak (SWC)

Praktyczna rekomendacja: dla bibliotek i projektów wymagających ścisłej typizacji wybierz ts-jest. Dla aplikacji frontendowych z dużą liczbą testów, gdzie liczy się szybkość, użyj Babela i osobno uruchamiaj tsc --noEmit w CI dla sprawdzania typów. W projektach Next.js i CRA decyzja jest już podjęta — używaj Babela/SWC.

Przykład kodu:

// === OPCJA 1: ts-jest ===
// npm install --save-dev ts-jest @types/jest

// jest.config.js
const { createDefaultPreset } = require('ts-jest');

module.exports = {
  // Nowoczesna konfiguracja ts-jest (v29+)
  ...createDefaultPreset(),
  testEnvironment: 'jsdom',
  // Opcjonalna konfiguracja per-transform
  transform: {
    '^.+\\.tsx?$': [
      'ts-jest',
      {
        tsconfig: 'tsconfig.test.json',
        // Wyłączenie sprawdzania typów dla szybkości
        isolatedModules: false,
        // Diagnostyka - wyświetlanie błędów TS
        diagnostics: true,
      },
    ],
  },
};

// === OPCJA 2: Babel ===
// npm install --save-dev @babel/preset-env @babel/preset-react @babel/preset-typescript babel-jest

// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', { targets: { node: 'current' } }],
    ['@babel/preset-react', { runtime: 'automatic' }],
    '@babel/preset-typescript', // Usuwa typy, nie sprawdza
  ],
};

// jest.config.js dla Babela
module.exports = {
  testEnvironment: 'jsdom',
  // Babel jest używany automatycznie przez babel-jest
  transform: {
    '^.+\\.(t|j)sx?$': 'babel-jest',
  },
};

// package.json - osobne sprawdzanie typów w CI
{
  "scripts": {
    "test": "jest",
    "type-check": "tsc --noEmit",
    "ci": "npm run type-check && npm test"
  }
}

Materiały

Jak używać setupFiles oraz setupFilesAfterEach i czym się różnią?

Odpowiedź w 30 sekund: setupFiles uruchamia się przed załadowaniem frameworka testowego — używany do polyfilli i konfiguracji środowiska. setupFilesAfterEach (właściwa nazwa to setupFilesAfterEach) uruchamia się po załadowaniu frameworka — używany do globalnych matcherów (jest-dom), mocków i hooków beforeEach/afterEach.

Odpowiedź w 2 minuty: Jest oferuje kilka opcji konfiguracyjnych dla skryptów uruchamianych przed testami, a każda działa na innym etapie cyklu życia. setupFiles to tablica skryptów uruchamianych przed inicjalizacją frameworka testowego w każdym pliku testowym. Na tym etapie nie są jeszcze dostępne globalne API Jest jak expect, beforeEach, jest.mock — używamy go więc dla polyfilli (whatwg-fetch, intersection-observer), ustawiania zmiennych środowiskowych, czy konfiguracji globalnych obiektów.

setupFilesAfterEach (uwaga: właściwa nazwa to setupFilesAfterEach) działa po załadowaniu frameworka. Mamy tu dostęp do całego API Jest — można rejestrować globalne hooki beforeAll/beforeEach/afterEach/afterAll, rozszerzać expect o customowe matchery (np. @testing-library/jest-dom), konfigurować Testing Library (np. configure({ asyncUtilTimeout: 5000 })) oraz mockować moduły globalne.

Dodatkowo Jest oferuje globalSetup i globalTeardown — pliki uruchamiane raz przed/po całej suite testowej (nie per plik). Używane do startu bazy danych, generowania danych testowych, czy uruchomienia serwera mockowego.

Opcja Kiedy Dostęp do API Jest Typowe użycie
globalSetup Raz przed wszystkimi testami Nie Start DB, init serwera
setupFiles Przed frameworkiem, per plik Nie Polyfille, env vars
setupFilesAfterEach Po frameworku, per plik Tak jest-dom, globalne mocki
globalTeardown Raz po wszystkich testach Nie Cleanup DB, stop serwera

Przykład kodu:

// jest.config.js
module.exports = {
  // Uruchamiane RAZ przed wszystkimi testami
  globalSetup: '<rootDir>/jest.global-setup.ts',
  globalTeardown: '<rootDir>/jest.global-teardown.ts',

  // Uruchamiane PRZED frameworkiem, dla każdego pliku testowego
  setupFiles: ['<rootDir>/jest.polyfills.ts'],

  // Uruchamiane PO frameworku, dla każdego pliku testowego
  setupFilesAfterEach: ['<rootDir>/jest.setup.ts'],
};

// === jest.polyfills.ts - setupFiles ===
// Tu NIE MAMY dostępu do API Jest (expect, beforeEach, jest.mock)
// Tylko polyfille i konfiguracja środowiska

// Polyfill dla fetch w środowisku jsdom
import 'whatwg-fetch';

// Polyfill dla IntersectionObserver
import 'intersection-observer';

// Ustawianie zmiennych środowiskowych
process.env.API_URL = 'http://localhost:3000';
process.env.NODE_ENV = 'test';

// Globalna konfiguracja - np. timezone
process.env.TZ = 'UTC';

// === jest.setup.ts - setupFilesAfterEach ===
// Tu MAMY pełen dostęp do API Jest
import '@testing-library/jest-dom'; // Rozszerza expect o matchery DOM
import { configure } from '@testing-library/react';
import { server } from './mocks/server';

// Konfiguracja Testing Library
configure({ asyncUtilTimeout: 5000 });

// Globalne hooki dla wszystkich testów
beforeAll(() => {
  // Start MSW (Mock Service Worker) przed wszystkimi testami
  server.listen({ onUnhandledRequest: 'error' });
});

afterEach(() => {
  // Reset handlerów po każdym teście
  server.resetHandlers();
  // Czyszczenie mocków
  jest.clearAllMocks();
});

afterAll(() => {
  // Zatrzymanie MSW po wszystkich testach
  server.close();
});

// Mockowanie globalnego obiektu window.matchMedia
Object.defineProperty(window, 'matchMedia', {
  writable: true,
  value: jest.fn().mockImplementation((query) => ({
    matches: false,
    media: query,
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
  })),
});

// === jest.global-setup.ts - uruchamia się RAZ ===
module.exports = async () => {
  // Np. start testowej bazy danych
  console.log('Uruchamianie środowiska testowego...');
  // await startTestDatabase();
};

Materiały

Asercje i Matchery

Jakie są najczęściej używane matchery w Jest (toBe, toEqual, toContain, toMatch)?

Odpowiedź w 30 sekund: Jest oferuje bogaty zestaw matcherów do weryfikacji wartości. Najczęściej używane to toBe() dla porównań prymitywów przez referencję, toEqual() dla głębokiego porównania obiektów i tablic, toContain() do sprawdzania zawartości tablic lub ciągów oraz toMatch() do dopasowania ciągów do wyrażenia regularnego lub podciągu.

Odpowiedź w 2 minuty: Matchery (ang. matchers) to metody dołączone do obiektu zwracanego przez expect(), które pozwalają opisać oczekiwany wynik testu. Każdy matcher wykonuje konkretny rodzaj porównania, a w razie niezgodności generuje czytelny komunikat o błędzie. Dzięki temu nie musimy pisać własnych warunków if ani rzucać błędów ręcznie — Jest robi to za nas.

Najpopularniejsze matchery to: toBe() (porównanie przez Object.is, idealne dla liczb, stringów, booleanów), toEqual() (rekurencyjne porównanie struktury — używane do obiektów i tablic), toContain() (sprawdza czy element jest w tablicy lub czy podciąg występuje w stringu), toMatch() (porównuje string z regexem lub innym stringiem), toBeTruthy() / toBeFalsy() (sprawdzają wartość logiczną), toBeNull(), toBeUndefined(), toBeDefined() (sprawdzają wartości specjalne), toBeGreaterThan() / toBeLessThan() (porównania liczbowe) oraz toHaveLength() (długość tablicy/stringa).

Każdy matcher można zanegować przez .not, np. expect(value).not.toBe(5). Dla operacji asynchronicznych dostępne są dodatkowe modyfikatory .resolves i .rejects. Dobrym zwyczajem jest wybieranie najbardziej specyficznego matchera dla danej sytuacji — daje to lepsze komunikaty błędów i czytelniejsze testy.

Przykład kodu:

// toBe - porównanie przez referencję (Object.is)
test('toBe dla wartości prymitywnych', () => {
  expect(2 + 2).toBe(4);
  expect('hello').toBe('hello');
  expect(true).toBe(true);
});

// toEqual - głębokie porównanie struktury
test('toEqual dla obiektów i tablic', () => {
  const uzytkownik = { imie: 'Anna', wiek: 30 };
  expect(uzytkownik).toEqual({ imie: 'Anna', wiek: 30 });

  const liczby = [1, 2, 3];
  expect(liczby).toEqual([1, 2, 3]);
});

// toContain - sprawdzenie zawartości
test('toContain dla tablic i stringów', () => {
  const owoce = ['jablko', 'banan', 'gruszka'];
  expect(owoce).toContain('banan');

  const tekst = 'Witaj w Jest';
  expect(tekst).toContain('Jest');
});

// toMatch - dopasowanie do regexa lub podciągu
test('toMatch dla stringów', () => {
  expect('team').not.toMatch(/I/);
  expect('Christoph').toMatch(/stop/);
  expect('numer-123').toMatch(/\d+/);
});

// Negacja przez .not
test('uzycie .not', () => {
  expect(5).not.toBe(10);
  expect([1, 2, 3]).not.toContain(4);
});

Materiały

Jaka jest różnica między toBe(), toEqual() oraz toStrictEqual()?

Odpowiedź w 30 sekund: toBe() porównuje wartości przez referencję (Object.is), działa dobrze dla prymitywów. toEqual() wykonuje głębokie porównanie struktury i ignoruje undefined w polach obiektu. toStrictEqual() jest najściślejszy — sprawdza również typ obiektu (klasę) oraz obecność pól z wartością undefined.

Odpowiedź w 2 minuty: Wybór odpowiedniego matchera do porównania równości jest jednym z najczęstszych źródeł pomyłek w testach Jest. Trzy najważniejsze opcje to toBe(), toEqual() i toStrictEqual(), a różnice między nimi mają realny wpływ na precyzję testów.

toBe() używa Object.is() do porównania. Dla prymitywów (liczby, stringi, booleany) działa zgodnie z intuicją, ale dla obiektów i tablic porówna jedynie referencje — dwa różne obiekty o tej samej zawartości nie będą równe. Dlatego do struktur danych używamy toEqual(), który wykonuje rekurencyjne porównanie pól.

toEqual() ignoruje jednak pola z wartością undefined i nie sprawdza typu obiektu — instancja klasy User z polami {name: 'Anna'} będzie równa zwykłemu obiektowi {name: 'Anna'}. Jeśli potrzebujemy najściślejszej kontroli, używamy toStrictEqual(), który dodatkowo weryfikuje że oba obiekty są instancjami tej samej klasy (sprawdza prototyp) oraz rozróżnia {a: undefined} od {}. Jest też świadomy elementów rzadkich tablic — [, , 1] nie będzie równe [undefined, undefined, 1].

Matcher Mechanizm Obiekty Typ/klasa Pola undefined
toBe() Object.is tylko referencja nie sprawdza nie dotyczy
toEqual() głębokie porównanie po wartości ignoruje ignoruje
toStrictEqual() głębokie + ścisłe po wartości sprawdza rozróżnia

Przykład kodu:

// toBe - referencyjne porównanie
test('toBe dla prymitywow vs obiektow', () => {
  expect(42).toBe(42); // OK - prymityw
  expect({ a: 1 }).not.toBe({ a: 1 }); // rozne referencje
});

// toEqual - gleboke porownanie, ale liberalne
test('toEqual ignoruje undefined i typ', () => {
  expect({ a: 1, b: undefined }).toEqual({ a: 1 }); // PRZECHODZI
  expect({ a: 1 }).toEqual({ a: 1, b: undefined }); // PRZECHODZI

  class Uzytkownik {
    constructor(imie) { this.imie = imie; }
  }
  expect(new Uzytkownik('Anna')).toEqual({ imie: 'Anna' }); // PRZECHODZI
});

// toStrictEqual - najscislejszy
test('toStrictEqual wykrywa subtelne roznice', () => {
  // Roznica w polach undefined
  expect({ a: 1, b: undefined }).not.toStrictEqual({ a: 1 });

  // Roznica w klasie (prototypie)
  class Uzytkownik {
    constructor(imie) { this.imie = imie; }
  }
  expect(new Uzytkownik('Anna')).not.toStrictEqual({ imie: 'Anna' });

  // Rozne instancje tej samej klasy z tymi samymi polami - OK
  expect(new Uzytkownik('Anna')).toStrictEqual(new Uzytkownik('Anna'));

  // Rzadkie tablice
  expect([, , 1]).not.toStrictEqual([undefined, undefined, 1]);
});

Materiały

Jak testować rzucanie wyjątków za pomocą toThrow()?

Odpowiedź w 30 sekund: Aby przetestować rzucanie wyjątków, należy przekazać do expect() funkcję (lub wrap w arrow function), a następnie użyć matchera .toThrow(). Można sprawdzić sam fakt rzucenia, konkretny komunikat (string lub regex), instancję klasy błędu albo obiekt z polami błędu.

Odpowiedź w 2 minuty: Matcher .toThrow() (alias .toThrowError()) służy do weryfikacji, że dany kod rzuca wyjątek. Kluczowa zasada: kod, który może rzucić wyjątek, musi być przekazany do expect() jako funkcja — w przeciwnym razie wyjątek zostanie rzucony zanim Jest zdąży go przechwycić, a test się wywali.

.toThrow() przyjmuje opcjonalny argument, który pozwala na precyzyjną weryfikację: bez argumentu sprawdza tylko, że dowolny wyjątek został rzucony; jako string — czy komunikat błędu zawiera dany podciąg; jako wyrażenie regularne — czy komunikat pasuje do wzorca; jako klasa błędu (np. TypeError) — czy rzucono instancję tej klasy; jako instancja błędu — czy komunikat jest dokładnie taki sam; jako obiekt — porównuje wybrane pola błędu.

W przypadku funkcji asynchronicznych używamy .rejects.toThrow() w połączeniu z await. Można też testować negację przez .not.toThrow() — przydatne, gdy chcemy potwierdzić, że konkretne wywołanie jest bezpieczne. W praktyce warto testować zarówno typ wyjątku, jak i jego treść, aby mieć pewność, że obsługujemy właściwy przypadek brzegowy.

Przykład kodu:

function podziel(a, b) {
  if (b === 0) {
    throw new Error('Nie mozna dzielic przez zero');
  }
  if (typeof a !== 'number' || typeof b !== 'number') {
    throw new TypeError('Argumenty musza byc liczbami');
  }
  return a / b;
}

test('rzuca jakikolwiek wyjatek', () => {
  // WAZNE: przekazujemy funkcje, nie wynik wywolania!
  expect(() => podziel(10, 0)).toThrow();
});

test('sprawdzenie komunikatu jako string (substring)', () => {
  expect(() => podziel(10, 0)).toThrow('dzielic przez zero');
});

test('sprawdzenie komunikatu przez regex', () => {
  expect(() => podziel(10, 0)).toThrow(/przez zero$/);
});

test('sprawdzenie klasy bledu', () => {
  expect(() => podziel('a', 2)).toThrow(TypeError);
});

test('sprawdzenie instancji bledu', () => {
  expect(() => podziel(10, 0)).toThrow(
    new Error('Nie mozna dzielic przez zero')
  );
});

test('kod, ktory nie rzuca wyjatku', () => {
  expect(() => podziel(10, 2)).not.toThrow();
});

// Funkcje asynchroniczne
async function pobierzDane(id) {
  if (!id) throw new Error('Brak ID');
  return { id };
}

test('async - rzucanie wyjatku', async () => {
  await expect(pobierzDane(null)).rejects.toThrow('Brak ID');
});

Materiały

Czym są asymmetric matchery (expect.any, expect.arrayContaining, expect.objectContaining)?

Odpowiedź w 30 sekund: Asymetryczne matchery to specjalne obiekty, których używamy wewnątrz toEqual() lub innych matcherów do częściowego/elastycznego dopasowania zamiast dokładnej równości. Pozwalają porównać tylko wybrane pola obiektu (expect.objectContaining), sprawdzić obecność elementów w tablicy (expect.arrayContaining) lub typ wartości (expect.any).

Odpowiedź w 2 minuty: Asymetryczne matchery (ang. asymmetric matchers) są jednym z najpotężniejszych narzędzi w Jest do testowania struktur danych, gdy nie znamy lub nie chcemy znać wszystkich wartości z góry. Nazwa "asymetryczne" wynika z tego, że nie są one porównaniem dwóch konkretnych wartości — to obiekty, które same definiują warunek dopasowania.

Najczęściej używane to: expect.any(Constructor) — sprawdza, czy wartość jest instancją danego typu (Number, String, Function, klasa); expect.anything() — pasuje do wszystkiego oprócz null i undefined; expect.objectContaining(obj) — sprawdza, czy obiekt zawiera dane pola (pozostałe pola mogą istnieć i mieć dowolne wartości); expect.arrayContaining(arr) — sprawdza, czy tablica zawiera wszystkie wymienione elementy w dowolnej kolejności; expect.stringContaining(str) i expect.stringMatching(regex) — częściowe dopasowanie stringów.

Te matchery można dowolnie zagnieżdżać — np. objectContaining może mieć pole opisane przez arrayContaining, które z kolei zawiera expect.any(Object). Szczególnie przydają się przy testowaniu wywołań mocków (toHaveBeenCalledWith), gdzie często chcemy sprawdzić tylko fragment przekazanego argumentu, oraz przy testowaniu odpowiedzi API, gdzie pola jak id czy createdAt są generowane dynamicznie.

Przykład kodu:

// expect.any - sprawdzenie typu
test('expect.any sprawdza typ wartosci', () => {
  function uzytkownik(imie) {
    return { id: Math.random(), imie, utworzono: new Date() };
  }

  expect(uzytkownik('Anna')).toEqual({
    id: expect.any(Number),
    imie: 'Anna',
    utworzono: expect.any(Date),
  });
});

// expect.objectContaining - czesciowe dopasowanie obiektu
test('expect.objectContaining ignoruje dodatkowe pola', () => {
  const odpowiedz = {
    status: 200,
    dane: { imie: 'Anna', wiek: 30 },
    timestamp: Date.now(),
  };

  expect(odpowiedz).toEqual(
    expect.objectContaining({
      status: 200,
      dane: expect.objectContaining({ imie: 'Anna' }),
    })
  );
});

// expect.arrayContaining - elementy w dowolnej kolejnosci
test('expect.arrayContaining sprawdza obecnosc elementow', () => {
  const tagi = ['javascript', 'jest', 'testing', 'node'];

  expect(tagi).toEqual(
    expect.arrayContaining(['jest', 'javascript'])
  );
});

// expect.stringMatching - dopasowanie stringa
test('expect.stringMatching z regexem', () => {
  const email = 'anna@example.com';
  expect(email).toEqual(expect.stringMatching(/^.+@.+\..+$/));
});

// Uzycie z mockami
test('asymmetric matchery z mockami', () => {
  const mockFn = jest.fn();
  mockFn({ uzytkownik: 'Anna', timestamp: Date.now() });

  expect(mockFn).toHaveBeenCalledWith(
    expect.objectContaining({
      uzytkownik: 'Anna',
      timestamp: expect.any(Number),
    })
  );
});

// Zagniezdzanie matcherow
test('zagniezdzone asymmetric matchery', () => {
  const dane = {
    uzytkownicy: [
      { id: 1, imie: 'Anna' },
      { id: 2, imie: 'Jan' },
    ],
  };

  expect(dane).toEqual({
    uzytkownicy: expect.arrayContaining([
      expect.objectContaining({ imie: 'Anna' }),
    ]),
  });
});

Materiały

Jak tworzyć własne matchery w Jest (expect.extend)?

Odpowiedź w 30 sekund: Własne matchery tworzymy przez expect.extend({ nazwaMatchera(received, ...args) { ... } }). Funkcja matchera musi zwrócić obiekt z polami pass (boolean) oraz message (funkcja zwracająca string komunikatu błędu). Po rejestracji można używać expect(x).nazwaMatchera().

Odpowiedź w 2 minuty: Mimo bogatego zestawu wbudowanych matcherów, czasem potrzebujemy testować specyficzne reguły domenowe — np. że obiekt jest prawidłowym numerem PESEL, że data mieści się w danym zakresie, albo że odpowiedź API ma określoną strukturę. Jest pozwala rozszerzać API expect przez expect.extend().

Funkcja matchera otrzymuje jako pierwszy argument received (wartość przekazaną do expect()), a kolejne argumenty to wartości podane przy wywołaniu matchera. Musi zwrócić obiekt z dwoma polami: pass (czy test przeszedł) oraz message (funkcja zwracająca komunikat błędu — jest wywoływana tylko wtedy, gdy test się nie powiódł lub gdy używamy .not). Wewnątrz matchera dostępny jest też kontekst this, który zawiera m.in. this.isNot (czy użyto .not), this.utils (helpery do formatowania) i this.equals (funkcja głębokiego porównania).

Dobrze napisany matcher: ma znaczącą nazwę (toBeValidPesel, a nie customMatcher1), zwraca czytelny komunikat błędu z informacją o oczekiwaniu i otrzymanej wartości, używa this.utils.printReceived/printExpected do formatowania oraz obsługuje przypadek .not (komunikat różni się zależnie od this.isNot). Matchery można też pisać asynchronicznie — wystarczy zwrócić Promise z obiektem {pass, message}. W projekcie TypeScript warto dodatkowo zadeklarować typy w pliku .d.ts, aby IDE rozpoznawało nowe metody.

Przykład kodu:

// Prosty matcher sprawdzajacy zakres liczbowy
expect.extend({
  toBeWithinRange(received, floor, ceiling) {
    const pass = received >= floor && received <= ceiling;

    if (pass) {
      return {
        message: () =>
          `oczekiwano, ze ${received} NIE bedzie w zakresie ${floor}-${ceiling}`,
        pass: true,
      };
    } else {
      return {
        message: () =>
          `oczekiwano, ze ${received} bedzie w zakresie ${floor}-${ceiling}`,
        pass: false,
      };
    }
  },
});

test('uzycie wlasnego matchera', () => {
  expect(50).toBeWithinRange(10, 100);
  expect(5).not.toBeWithinRange(10, 100);
});

// Bardziej zaawansowany matcher z this.utils
expect.extend({
  toBeValidPesel(received) {
    const isString = typeof received === 'string';
    const hasCorrectLength = isString && received.length === 11;
    const isNumeric = isString && /^\d+$/.test(received);
    const pass = hasCorrectLength && isNumeric;

    return {
      pass,
      message: () =>
        this.isNot
          ? `oczekiwano, ze ${this.utils.printReceived(received)} NIE bedzie prawidlowym PESEL`
          : `oczekiwano, ze ${this.utils.printReceived(received)} bedzie prawidlowym PESEL (11 cyfr)`,
    };
  },
});

test('walidacja PESEL', () => {
  expect('12345678901').toBeValidPesel();
  expect('abc').not.toBeValidPesel();
  expect('123').not.toBeValidPesel();
});

// Asynchroniczny matcher
expect.extend({
  async toResolveWithStatus(receivedPromise, expectedStatus) {
    const response = await receivedPromise;
    const pass = response.status === expectedStatus;

    return {
      pass,
      message: () =>
        `oczekiwano statusu ${expectedStatus}, otrzymano ${response.status}`,
    };
  },
});

test('async matcher', async () => {
  const promise = Promise.resolve({ status: 200 });
  await expect(promise).toResolveWithStatus(200);
});

W projekcie TypeScript dodajemy typy w jest.d.ts:

declare global {
  namespace jest {
    interface Matchers<R> {
      toBeWithinRange(floor: number, ceiling: number): R;
      toBeValidPesel(): R;
    }
  }
}

Materiały

Mockowanie - jest.fn i jest.mock

Czym jest mock i kiedy warto go używać w testach?

Odpowiedź w 30 sekund: Mock to obiekt zastępczy, który imituje zachowanie prawdziwej zależności (funkcji, modułu, klasy) w testach. Używamy go, gdy chcemy odizolować testowany kod od zewnętrznych zależności (API, baza danych, czas, losowość) lub gdy chcemy zweryfikować interakcje między obiektami (czy funkcja została wywołana z odpowiednimi argumentami).

Odpowiedź w 2 minuty: Mock to ogólne pojęcie z rodziny "test doubles" (zamienników testowych), które obejmuje także stuby, spies, fakes i dummies. W kontekście Jest, mock to obiekt, który zapamiętuje wszystkie swoje wywołania (argumenty, kontekst, wartości zwracane) i pozwala na kontrolowanie tego, co zwraca w trakcie testu. Dzięki temu możemy testować kod w izolacji, bez polegania na rzeczywistych implementacjach.

Kiedy warto używać mocków? Po pierwsze, gdy testujemy kod komunikujący się z zewnętrznymi serwisami (HTTP API, baza danych, system plików) – nie chcemy w testach jednostkowych wykonywać prawdziwych żądań sieciowych. Po drugie, gdy zależność jest niedeterministyczna (czas, Math.random, generator UUID) – mockowanie daje przewidywalność. Po trzecie, gdy testujemy interakcje – chcemy sprawdzić, czy nasz kod wywołał określoną funkcję z odpowiednimi argumentami (np. czy logger został wywołany przy błędzie).

Kiedy NIE używać mocków? Nadmierne mockowanie prowadzi do testów, które weryfikują implementację zamiast zachowania – każda zmiana w kodzie wymaga aktualizacji testów. Mockujemy granice systemu (I/O), a nie czystą logikę biznesową. Jeśli mockujemy 90% kodu, prawdopodobnie testujemy tylko mocki, a nie rzeczywiste zachowanie aplikacji.

Przykład kodu:

// Kod produkcyjny - serwis użytkownika
class UserService {
  constructor(httpClient, logger) {
    this.httpClient = httpClient;
    this.logger = logger;
  }

  async fetchUser(id) {
    try {
      const response = await this.httpClient.get(`/api/users/${id}`);
      return response.data;
    } catch (error) {
      this.logger.error('Nie udało się pobrać użytkownika', error);
      throw error;
    }
  }
}

// Test z użyciem mocków - izolacja od HTTP i loggera
test('pobiera użytkownika i zwraca dane', async () => {
  // Mock zależności - zastępujemy prawdziwy HTTP klient i logger
  const mockHttpClient = {
    get: jest.fn().mockResolvedValue({ data: { id: 1, name: 'Anna' } })
  };
  const mockLogger = { error: jest.fn() };

  const service = new UserService(mockHttpClient, mockLogger);
  const user = await service.fetchUser(1);

  // Weryfikujemy zachowanie - czy zostały wywołane odpowiednie metody
  expect(user).toEqual({ id: 1, name: 'Anna' });
  expect(mockHttpClient.get).toHaveBeenCalledWith('/api/users/1');
  expect(mockLogger.error).not.toHaveBeenCalled();
});

Materiały

Jak tworzyć mock funkcji za pomocą jest.fn() i sprawdzać jej wywołania?

Odpowiedź w 30 sekund: jest.fn() tworzy nową funkcję mockującą, która zapamiętuje wszystkie wywołania w obiekcie .mock. Możemy kontrolować jej zachowanie metodami mockReturnValue, mockResolvedValue, mockImplementation, a następnie weryfikować wywołania matcherami toHaveBeenCalled, toHaveBeenCalledWith, toHaveBeenCalledTimes.

Odpowiedź w 2 minuty: jest.fn() to fabryka funkcji mockujących. Wywołanie bez argumentów tworzy funkcję, która zwraca undefined i niczego nie robi, ale rejestruje wszystkie swoje wywołania. Każda taka funkcja ma właściwość .mock, która zawiera m.in. calls (tablica argumentów wszystkich wywołań), results (zwrócone wartości lub rzucone wyjątki), instances (kontekst this) i contexts.

Konfiguracja zachowania mocka odbywa się przez metody łańcuchowe:

  • mockReturnValue(value) – synchroniczna wartość zwracana
  • mockResolvedValue(value) – Promise.resolve dla testów asynchronicznych
  • mockRejectedValue(error) – Promise.reject dla testowania błędów
  • mockImplementation(fn) – dowolna implementacja
  • mockReturnValueOnce(value) – wartość tylko dla pierwszego wywołania (kolejkowanie)

Weryfikacja wywołań używa matcherów Jest:

  • toHaveBeenCalled() – czy w ogóle wywołane
  • toHaveBeenCalledTimes(n) – ile razy
  • toHaveBeenCalledWith(arg1, arg2) – z jakimi argumentami
  • toHaveBeenLastCalledWith(...) – ostatnie wywołanie
  • toHaveBeenNthCalledWith(n, ...) – n-te wywołanie

Pamiętaj o czyszczeniu mocków między testami przez jest.clearAllMocks() w beforeEach lub konfigurację clearMocks: true w jest.config.js, inaczej stan z poprzednich testów może wpływać na asercje.

Przykład kodu:

test('jest.fn() - tworzenie i weryfikacja mocka', () => {
  // Tworzenie prostego mocka
  const callback = jest.fn();

  // Wywołanie mocka kilka razy z różnymi argumentami
  callback('Anna', 25);
  callback('Jan', 30);

  // Weryfikacja wywołań
  expect(callback).toHaveBeenCalled();
  expect(callback).toHaveBeenCalledTimes(2);
  expect(callback).toHaveBeenCalledWith('Anna', 25);
  expect(callback).toHaveBeenLastCalledWith('Jan', 30);
  expect(callback).toHaveBeenNthCalledWith(1, 'Anna', 25);

  // Dostęp do surowych danych o wywołaniach
  expect(callback.mock.calls).toEqual([['Anna', 25], ['Jan', 30]]);
});

test('konfiguracja wartości zwracanych', async () => {
  // mockReturnValue - synchroniczne wartości
  const sumator = jest.fn().mockReturnValue(42);
  expect(sumator()).toBe(42);

  // mockReturnValueOnce - kolejkowanie wartości
  const licznik = jest.fn()
    .mockReturnValueOnce(1)
    .mockReturnValueOnce(2)
    .mockReturnValue(99); // domyślna wartość dla pozostałych

  expect(licznik()).toBe(1);
  expect(licznik()).toBe(2);
  expect(licznik()).toBe(99);
  expect(licznik()).toBe(99);

  // mockResolvedValue - dla funkcji asynchronicznych
  const pobierzDane = jest.fn().mockResolvedValue({ id: 1 });
  await expect(pobierzDane()).resolves.toEqual({ id: 1 });

  // mockImplementation - pełna kontrola nad zachowaniem
  const mnożenie = jest.fn().mockImplementation((a, b) => a * b);
  expect(mnożenie(3, 4)).toBe(12);
});

Materiały

Jaka jest różnica między jest.fn(), jest.spyOn() a jest.mock()?

Odpowiedź w 30 sekund: jest.fn() tworzy nową, samodzielną funkcję mockującą. jest.spyOn(obj, 'metoda') "podsłuchuje" istniejącą metodę obiektu – domyślnie zachowuje oryginalną implementację, ale rejestruje wywołania. jest.mock('moduł') zastępuje cały moduł automatycznie wygenerowanym (lub ręcznym) mockiem – to operacja na poziomie modułu, nie pojedynczej funkcji.

Odpowiedź w 2 minuty: To trzy różne narzędzia o różnym zasięgu i przeznaczeniu. Wybór zależy od tego, co i jak chcemy zastąpić.

jest.fn() tworzy izolowaną funkcję mockującą "z powietrza" – używamy jej do przekazania jako callback, dependency injection lub do budowania mock obiektów. Nie modyfikuje żadnego istniejącego kodu, jest samodzielna.

jest.spyOn(obiekt, 'nazwaMetody') to mock zachowujący oryginał. Tworzy "szpiega" – metoda nadal działa normalnie, ale wszystkie wywołania są rejestrowane. Idealna do weryfikacji efektów ubocznych bez zmiany zachowania. Można ją łączyć z mockImplementation() lub mockReturnValue() żeby zmienić zachowanie. Ważne: spy MUSI być przywrócony przez mockRestore() po teście, inaczej zmiana pozostaje globalna i wpływa na kolejne testy.

jest.mock('ścieżka/do/modułu') działa na poziomie modułu – zastępuje cały import. Automatycznie generuje mock dla wszystkich eksportów (funkcje stają się jest.fn() zwracającymi undefined). Można podać drugi argument – factory funkcję zwracającą custom mock. Wywołanie jest.mock() jest hoistowane na początek pliku przez Jest babel transform.

Cecha jest.fn() jest.spyOn() jest.mock()
Zasięg Pojedyncza funkcja Metoda obiektu Cały moduł
Tworzy nowy mock Tak Nie - opakowuje istniejący Tak - dla całego modułu
Zachowuje oryginał Nie Tak (domyślnie) Nie (domyślnie)
Wymaga mockRestore() Nie Tak Nie (auto przy restoreMocks)
Hoisting Nie Nie Tak (na początek pliku)
Typowe użycie Callback, DI Podsłuch metod, console.log Mock całych modułów

Przykład kodu:

// 1. jest.fn() - samodzielny mock jako callback
test('jest.fn() jako callback', () => {
  const mockCallback = jest.fn(x => x * 2);
  [1, 2, 3].forEach(mockCallback);

  expect(mockCallback).toHaveBeenCalledTimes(3);
  expect(mockCallback.mock.results[0].value).toBe(2);
});

// 2. jest.spyOn() - podsłuchiwanie istniejącej metody
test('jest.spyOn() - weryfikacja bez zmiany zachowania', () => {
  const użytkownik = {
    powitaj(imie) { return `Witaj, ${imie}!`; }
  };

  const spy = jest.spyOn(użytkownik, 'powitaj');
  const wynik = użytkownik.powitaj('Anna');

  // Oryginalna metoda nadal działa, ale wywołanie jest zarejestrowane
  expect(wynik).toBe('Witaj, Anna!');
  expect(spy).toHaveBeenCalledWith('Anna');

  spy.mockRestore(); // KLUCZOWE - przywróć oryginał
});

test('jest.spyOn() z podmianą implementacji', () => {
  // Częsty przypadek - wyciszenie console.error w testach
  const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});

  console.error('Ten błąd nie zostanie wypisany');
  expect(errorSpy).toHaveBeenCalledWith('Ten błąd nie zostanie wypisany');

  errorSpy.mockRestore();
});

// 3. jest.mock() - mockowanie całego modułu
jest.mock('./apiClient'); // Hoistowane na górę pliku!
import { pobierzUżytkownika } from './apiClient';

test('jest.mock() - cały moduł zastąpiony', async () => {
  pobierzUżytkownika.mockResolvedValue({ id: 1, name: 'Anna' });

  const dane = await pobierzUżytkownika(1);
  expect(dane).toEqual({ id: 1, name: 'Anna' });
  expect(pobierzUżytkownika).toHaveBeenCalledWith(1);
});

Materiały

Jak mockować cały moduł za pomocą jest.mock() i __mocks__?

Odpowiedź w 30 sekund: jest.mock('./moduł') automatycznie zastępuje moduł – wszystkie eksporty stają się funkcjami mockującymi. Można podać factory function jako drugi argument dla custom implementacji. Folder __mocks__ obok mockowanego pliku pozwala na trwałe ręczne mocki (manual mocks) używane w wielu testach.

Odpowiedź w 2 minuty: Jest oferuje trzy poziomy mockowania modułów, od najprostszego do najbardziej zaawansowanego.

1. Automatyczny mock (jest.mock('./ścieżka')): Jest sam analizuje moduł i tworzy zamiennik – funkcje stają się jest.fn() zwracającymi undefined, klasy są auto-mockowane (konstruktor + metody to mocki), prymitywy zachowują wartości. To wystarczy, gdy nie zależy nam na zwracanych wartościach, a tylko chcemy zweryfikować wywołania.

2. Mock z factory function: jest.mock('./moduł', () => ({ ... })) daje pełną kontrolę – możemy zwrócić dowolną strukturę. UWAGA: factory nie ma dostępu do zmiennych ze scope'u (przez hoisting), z wyjątkiem zmiennych z prefiksem mock (np. mockFoo). To częsta pułapka.

3. Manual mocks w folderze __mocks__: Tworzymy folder __mocks__ obok mockowanego modułu (lub w korzeniu projektu dla node_modules). Plik wewnątrz definiuje stałą implementację mocka. Aby aktywować, wywołujemy jest.mock('./moduł') bez factory – Jest automatycznie podstawi __mocks__/moduł.js. Dla modułów z node_modules (np. lodash, axios) mock w __mocks__/lodash.js w korzeniu jest aktywowany automatycznie (lub przez jest.mock('lodash') w teście).

Częściowy mock: jest.mock('./moduł', () => ({ ...jest.requireActual('./moduł'), specyficznaFunkcja: jest.fn() })) pozwala zachować większość modułu i zmockować tylko wybrane funkcje – bardzo użyteczne dla bibliotek narzędziowych.

Strategia Kiedy używać Konfiguracja
Auto mock Testy, gdzie wartości zwracane nie mają znaczenia jest.mock('./moduł')
Factory mock Custom zachowanie dla jednego testu jest.mock('./moduł', () => ({...}))
Manual mock __mocks__ Wielokrotne użycie tego samego mocka Plik w __mocks__/nazwa.js
Częściowy mock Mock tylko fragmentu modułu jest.requireActual + spread

Przykład kodu:

// 1. AUTO MOCK - cały moduł automatycznie zmockowany
// plik: services/database.js
export const zapiszUżytkownika = (user) => { /* prawdziwa logika */ };
export const pobierzUżytkownika = (id) => { /* prawdziwa logika */ };

// plik: user.test.js
import { zapiszUżytkownika, pobierzUżytkownika } from './services/database';

jest.mock('./services/database'); // wszystko staje się jest.fn()

test('automatyczny mock modułu', () => {
  pobierzUżytkownika.mockReturnValue({ id: 1, name: 'Anna' });

  expect(pobierzUżytkownika(1)).toEqual({ id: 1, name: 'Anna' });
  expect(zapiszUżytkownika).not.toHaveBeenCalled();
});

// 2. FACTORY MOCK - custom implementacja
jest.mock('./services/api', () => ({
  fetchData: jest.fn(() => Promise.resolve({ success: true })),
  postData: jest.fn(() => Promise.resolve({ id: 123 })),
  // PUŁAPKA: nie możesz odwołać się do zewnętrznych zmiennych!
  // const dane = { foo: 'bar' }; - to NIE zadziała przez hoisting
}));

// 3. MANUAL MOCK w __mocks__
// Struktura folderów:
// project/
//   services/
//     api.js
//     __mocks__/
//       api.js      <- mock automatycznie używany
//   user.test.js

// services/__mocks__/api.js
export const fetchData = jest.fn(() =>
  Promise.resolve({ użytkownicy: [{ id: 1, name: 'Anna' }] })
);
export const postData = jest.fn(() => Promise.resolve({ id: 999 }));

// W teście wystarczy:
jest.mock('./services/api'); // użyje __mocks__/api.js

// 4. CZĘŚCIOWY MOCK - zmockuj tylko wybrane funkcje
jest.mock('./utils/format', () => {
  const oryginalny = jest.requireActual('./utils/format');
  return {
    ...oryginalny, // zachowaj wszystkie oryginalne funkcje
    formatujDate: jest.fn(() => '2024-01-01'), // zmockuj tylko jedną
  };
});

// 5. MOCK BIBLIOTEKI Z NODE_MODULES
// Plik w korzeniu: __mocks__/axios.js
export default {
  get: jest.fn(() => Promise.resolve({ data: {} })),
  post: jest.fn(() => Promise.resolve({ data: {} })),
};
// W teście:
jest.mock('axios'); // automatycznie podstawi __mocks__/axios.js

Materiały

21. Czym różni się manual mock od automock w Jest?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
22. Jak mockować ES Modules (import) i pułapki związane z hoistingiem jest.mock()?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Spies i Reset Mocków

23. Czym jest spy i kiedy używać jest.spyOn() zamiast jest.fn()?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
24. Jaka jest różnica między mockClear, mockReset a mockRestore?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
25. Jak globalnie resetować mocki za pomocą clearMocks, resetMocks i restoreMocks w konfiguracji?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Testy Asynchroniczne

26. Jak testować kod asynchroniczny używając async/await i Promises?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
27. Jak używać resolves i rejects w asercjach asynchronicznych?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
28. Jak testować callbacki za pomocą parametru done i jakie są tego pułapki?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
29. Jak mockować i testować fetch oraz wywołania API w Jest?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
30. Jak mockować timery (setTimeout, setInterval) za pomocą jest.useFakeTimers()?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Hooks i Lifecycle

31. Jakie są dostępne hooki lifecycle (beforeEach, afterEach, beforeAll, afterAll)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
32. Jaka jest kolejność wykonywania hooków w zagnieżdżonych blokach describe?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
33. Jak unikać wycieku stanu pomiędzy testami za pomocą hooków?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
34. Jak używać --testNamePattern oraz modyfikatorów test.only, test.skip, test.todo?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Snapshot Testing

35. Czym jest snapshot testing w Jest i jak działa?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
36. Kiedy snapshot testing jest dobrym rozwiązaniem, a kiedy się nie sprawdza?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
37. Jak aktualizować nieaktualne snapshoty (--updateSnapshot, -u)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
38. Czym są inline snapshots i kiedy warto ich używać?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Code Coverage

39. Jak generować raport pokrycia kodu (--coverage) i co oznaczają metryki branches, statements, functions, lines?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
40. Jak ustawić progi pokrycia (coverageThreshold) i wymusić ich spełnienie w CI?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
41. Czym jest collectCoverageFrom i dlaczego nie wystarczy samo --coverage?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Testy Parametryzowane i Strukturyzacja

42. Jak używać test.each() i describe.each() do testów parametryzowanych?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
43. Jak organizować pliki testowe w projekcie (__tests__, sąsiadujące .test.js, struktura katalogów)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
44. Jak współdzielić logikę między testami za pomocą fixtures i factory functions?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Wydajność i Debugowanie

45. Jak Jest uruchamia testy równolegle i jak kontrolować workerów (--maxWorkers)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
46. Jak debugować pojedynczy test w Jest (Node Inspector, VS Code, --runInBand)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
47. Jakie są typowe przyczyny wolnych testów w Jest i jak je optymalizować?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
48. Czym jest tryb --watch i jak różni się od --watchAll?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Best Practices i Wzorce

49. Jakie są zasady AAA (Arrange-Act-Assert) i jak je stosować w testach Jest?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
50. Jakie są najczęstsze antywzorce w testach Jest (over-mocking, testowanie szczegółów implementacji)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
51. Jak pisać testy odporne na refaktoring (test behavior, not implementation)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
52. Jak testować błędy i edge case'y w sposób kompleksowy?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
53. Jakie są dobre praktyki pisania nazw testów (czytelność, konwencje)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
54. Jak integrować Jest z CI/CD (GitHub Actions, GitLab CI) i co warto uruchamiać?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi
55. Jakie biblioteki uzupełniają Jest w typowym projekcie frontend (RTL, MSW, jest-dom)?

Odpowiedź dostępna w pełnej wersji. Odblokuj 35 pozostałych odpowiedzi i ucz się z pełnego zestawu.

Odblokuj odpowiedzi

Chcesz poznać wszystkie odpowiedzi?

Uzyskaj pełny dostęp do 55 pytań rekrutacyjnych z Jest oraz pozostałych technologii.

Zobacz plany cenowe