Testowanie React.js w Enzyme — props, state i interakcje

Ten wpis jest 15 częścią z 16 w kursie React.js

Pokazałem już jak pisać proste testy do aplikacji React.js z użyciem Enzyme. Sprawdzanie czy coś się renderuje, czy zawiera tekst, czy dobrze pokazuje elementy… W tym wpisie idę o krok dalej. Pokazuję jak w Enzyme testować interakcje z komponentami, odczytywać i zmieniać propsy a także state.

Pobieranie i ustawianie propsów oraz state

Na elementach (selektorach) Enzyme można wywołać kilka ciekawych metod. W tym momencie interesują Cię te służące do odczytywania i ustawiania propsów i stanu:

  • props() — zwraca wszystkie propsy danego elementu
  • prop(key) — zwraca prop o nazwie key
  • state([key]) — zwraca cały state lub (opcjonalnie) to co kryje się pod kluczem key
  • setProps(nextProps) — ustawia propsy komponentu (podany obiekt zostanie połączony z istniejącymi już propsami)
  • setState(nextState) — ustawia state komponentu (j.w.)

A więc przetestujmy teraz czy, w naszej ulubionej liście kontaktów, komponent <App> przekazuje do <UsersList> prop o nazwie users z tablicą imion:

it('passes all users to the UsersList', () => {
  const app = shallow();
  expect(app.find('UsersList').prop('users')).toEqual(['Michal', 'Kasia', 'Jacek', 'Marta', 'Tomek', 'Ania']);
})

Po kolei: Płytkie renderowanie komponentu App. Następnie znajdź komponent UsersList, pobierz jego prop o nazwie users i porównaj z podaną tablicą.

Następnie można by się pokusić o przetestowanie czy komponent UsersList poprawnie reaguje na zmianę propsów. A więc pierwszy render, a następnie zmiana propsów i test (jest to trochę test na siłę, ale to w tym momencie nieistotne):

describe('change props', () => {
    const users = ['Jan', 'Maria'];
    const usersList = shallow(<UsersList users={['Ktoś tam', 'Nieważne']} />);
    usersList.setProps({ users });
    
    users.forEach(user => {
        it(`includes name ${user} on the list`, () => {
            expect(usersList).toContainReact(<li>{user}</li>)
        });
    });
});

W analogiczny sposób można pobierać i ustawiać state, a następnie sprawdzać czy komponent się poprawnie renderuje.

Interakcje

Jedyny brakujący element układanki to testowanie interakcji z komponentami. W tym przykładzie chcesz sprawdzić czy wpisywanie czegoś w pole tekstowe powoduje rzeczywiście filtrowanie tablicy z imionami.

W bardziej realnym przykładzie zamockowałbym najpierw źródło danych, aby mieć 100% kontrolę nad przebiegiem testu. Tutaj ten krok pomijam i na razie zakładam, że lista imion jest mi po prostu znana i niezmienna.

Przyda się tutaj funkcja simulate z Enzyme. Przyjmuje ona dwa argumenty:

  • nazwę zdarzenia np. click albo input
  • mock obiektu zdarzenia (opcjonalnie)

W tym przypadku chcę przetestować wpisanie literki „M”. Muszę więc zasymulować zdarzenie input i podać obiekt zdarzenia z ustawionym value na wartość "M":

it('filters names on input', () => {
  const app = shallow(<App />);
  expect(app.find('UsersList').prop('users')).toEqual(['Michal', 'Kasia', 'Jacek', 'Marta', 'Tomek', 'Ania']);

  app.find('input').simulate('input', {currentTarget: {value: 'M'}})
  expect(app.find('UsersList').prop('users')).toEqual(['Michal', 'Marta', 'Tomek']);
});

Po kolei: Renderuje się aplikacja. Następnie upewniam się, że lista kontaktów jest taka, jak mi się wydaje, że jest (to krok w sumie zbędny). Następnie symuluję zdarzenie input i ponownie sprawdzam listę kontaktów — teraz jest już inna.

Podobnie można testować inne zdarzenia, np. click czy nawet focus.

Podsumowanie

Tym sposobem masz już pełen zestaw narzędzi potrzebny do testowania nawet najbardziej rozbudowanych komponentów. Enzyme jest świetną biblioteką i warto zapoznać się z jego pełną dokumentacją! Cały kod jest dostępny na moim GitHubie: https://github.com/mmiszy/typeofweb-kurs-react/tree/part-3

Jeśli chcesz na bieżąco dowiadywać się o kolejnych częściach kursu React.js to koniecznie śledź mnie na Facebooku i zapisz się na newsletter.

Ćwiczenie

Ćwiczenie:  Przetestuj czy po skasowaniu literki „M” z inputa lista kontaktów wróci do stanu pierwotnego.

  • kensshin985

    Hej, dobra robota z tym kursem.
    Pierwsze kilka rozdziałów było krótko, konkretnie wytłumaczone – co zachęcało do przerabiania kolejnych. Lecz jakoś od 10 się pogubiłem – wyszły prawdopodobnie moje braki w js.
    Ogólnie bardziej interesuje mnie back-end(java/spring/hibernate), aczkolwiek w celach pisania pracy inżynierskiej oraz ogólnie nauczenia się czegoś nowego chciałbym liznąć trochę front’u. Przerobiłem książkę head first javascript ale nie czuję się po niej zbyt pewnie. Może mógłby mi ktoś polecić jakiś dobry kurs/blog traktujący o js.

    Jeszcze jedna rzecz, którą zauważyłem. Z rozdziału 1 oraz 14(a może i innych) nie wyświetla się w nawigacji kursu rozdział 15 – prawdopodobnie wkradł się jakiś błąd 😀

    • Niestety nie znam żadnych kursów JS 😉 Jedyne co mi przychodzi do głowy to seria książek „You Don’t Know JS”.
      A masz jakieś konkretne pytania? 🙂