Test Renderer

Importowanie

import TestRenderer from 'react-test-renderer'; // ES6
const TestRenderer = require('react-test-renderer'); // ES5 z zainstalowanym npm

Ogólne informacje

Paczka ta udostępnia narzędzie, które renderuje komponenty reactowe do czysto javascriptowych obiektów, bez użycia drzewa DOM czy natywnego środowiska mobilnego.

Istotą tej paczki jest łatwość wygenerowania “migawki” (ang. snapshot) hierarchii widoków (podobnej do drzewa DOM), wyrenderowanej przez komponent z React DOM lub React Native bez pomocy przeglądarki czy jsdom.

Przykład:

import TestRenderer from 'react-test-renderer';

function Link(props) {
  return <a href={props.page}>{props.children}</a>;
}

const testRenderer = TestRenderer.create(
  <Link page="https://www.facebook.com/">Facebook</Link>
);

console.log(testRenderer.toJSON());
// { type: 'a',
//   props: { href: 'https://www.facebook.com/' },
//   children: [ 'Facebook' ] }

Przy pomocy funkcjonalności biblioteki Jest do generowania snapshotów można automatycznie zapisać do pliku kopię drzewa w formacie JSON, a w teście sprawdzać, czy się ono nie zmieniło (Więcej informacji na ten temat).

Zwrócone drzewo można również przeszukiwać w celu znalezienia konkretnych węzłów i sprawdzenia ich właściwości.

import TestRenderer from 'react-test-renderer';

function MyComponent() {
  return (
    <div>
      <SubComponent foo="bar" />
      <p className="my">Cześć</p>
    </div>
  )
}

function SubComponent() {
  return (
    <p className="sub">Potomek</p>
  );
}

const testRenderer = TestRenderer.create(<MyComponent />);
const testInstance = testRenderer.root;

expect(testInstance.findByType(SubComponent).props.foo).toBe('bar');
expect(testInstance.findByProps({className: "sub"}).children).toEqual(['Potomek']);

TestRenderer

Instancja TestRenderer

TestInstance

Dokumentacja

TestRenderer.create()

TestRenderer.create(element, options);

Tworzy instancję TestRenderer przy użyciu przekazanego elementu reactowego. Nie korzysta z prawdziwego drzewa DOM, lecz renderuje całe drzewo komponentów do pamięci, aby można było wykonać na nim asercje. Zwracana instancja posiada następujące metody i właściwości:

testRenderer.toJSON()

testRenderer.toJSON()

Zwraca obiekt reprezentujący wyrenderowane drzewo. W drzewie znajdą się wyłącznie węzły specyficzne dla platformy, np. <div> lub <View>, wraz ze swoimi właściwościami. Nie zostaną wyrenderowane natomiast żadne niestandardowe komponenty użytkownika. Funkcja przydaje się przy testowaniu za pomocą snapshotów.

testRenderer.toTree()

testRenderer.toTree()

Zwraca obiekt reprezentujący wyrenderowane drzewo. W przeciwieństwie do toJSON(), ta reprezentacja jest bardziej szczegółowa i zawiera również niestandardowe komponenty użytkownika. Prawdopodobnie ta funkcja nigdy ci się nie przyda, chyba że piszesz w oparciu o tę paczkę własną bibliotekę do testów.

testRenderer.update()

testRenderer.update(element)

Przy użyciu nowego elementu głównego ponownie renderuje drzewo przechowywane w pamięci. Symuluje aktualizację przeprowadzaną przez Reacta na korzeniu drzewa. Jeśli nowy element ma ten sam typ i klucz, co poprzedni, drzewo zostanie zaktualizowane; w przeciwnym wypadku drzewo zostanie odmontowane i zamontowane ponownie.

testRenderer.unmount()

testRenderer.unmount()

Odmontowuje drzewo przechowywane w pamięci, wywołując odpowiednie zdarzenia z cyklu życia komponentów.

testRenderer.getInstance()

testRenderer.getInstance()

Zwraca instancję korzenia drzewa, jeśli takowy istnieje. Nie zadziała, jeśli komponent główny jest funkcją, ponieważ funkcje nie mają własnych instancji.

testRenderer.root

testRenderer.root

Zwraca “instancję testową” korzenia drzewa. Przydatne do wykonywania asercji na poszczególnych węzłach drzewa, a także do wyszukiwania innych “instancji testowych” w poddrzewach.

testInstance.find()

testInstance.find(test)

Wyszukuje w poddrzewie dokładnie jedną instancję testową, dla której wywołanie test(testInstance) zwróci true. Jeśli funkcja test(testInstance) nie zwróci true dla dokładnie jednej instancji, rzucony zostanie wyjątek.

testInstance.findByType()

testInstance.findByType(type)

Wyszukuje w poddrzewie dokładnie jedną instancję testową o podanym typie type. Jeśli funkcja znajdzie inną liczbę instancji, rzucony zostanie wyjątek.

testInstance.findByProps()

testInstance.findByProps(props)

Wyszukuje w poddrzewie dokładnie jedną instancję testową o podanych właściwościach props. Jeśli funkcja znajdzie inną liczbę instancji, rzucony zostanie wyjątek.

testInstance.findAll()

testInstance.findAll(test)

Wyszukuje w poddrzewie wszystkie instancje testowe, dla których funkcja test(testInstance) zwraca true.

testInstance.findAllByType()

testInstance.findAllByType(type)

Wyszukuje w poddrzewie wszystkie instancje testowe o podanym typie type.

testInstance.findAllByProps()

testInstance.findAllByProps(props)

Wyszukuje w poddrzewie wszystkie instancje testowe o podanych właściwościach props.

testInstance.instance

testInstance.instance

Zwraca instancję komponentu powiązanego z daną instancją testową. Działa tylko dla komponentów klasowych, ponieważ funkcyjne nie mają instancji. Wynik jest referencją odpowiadającą this w danym komponencie.

testInstance.type

testInstance.type

Zwraca typ komponentu powiązanego z daną instancją testową. Przykładowo, typem komponentu <Button /> jest Button.

testInstance.props

testInstance.props

Zwraca atrybuty powiązane z daną instancją testową. Przykładowo, właściwościami komponentu <Button size="small" /> są: {size: 'small'}.

testInstance.parent

testInstance.parent

Zwraca instancję rodzica dla danej instancji testowej.

testInstance.children

testInstance.children

Zwraca instancje potomków dla danej “instancji testowej”.

Pomysły

Do metody TestRenderer.create jako argument można przekazać funkcję createNodeMock, która pozwala na tworzenie własnych atrap referencji (ang. mock refs). createNodeMock jako argument przyjmuje element, a zwraca obiekt będący atrapą referencji. Przydaje się to w testach komponentów, które korzystają z referencji (ang. refs) do innych komponentów.

import TestRenderer from 'react-test-renderer';

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.input = null;
  }
  componentDidMount() {
    this.input.focus();
  }
  render() {
    return <input type="text" ref={el => this.input = el} />
  }
}

let focused = false;
TestRenderer.create(
  <MyComponent />,
  {
    createNodeMock: (element) => {
      if (element.type === 'input') {
        // atrapa funkcji "focus"
        return {
          focus: () => {
            focused = true;
          }
        };
      }
      return null;
    }
  }
);
expect(focused).toBe(true);