Skip to content

Instantly share code, notes, and snippets.

@bartlett705
Created August 18, 2017 07:33
Show Gist options
  • Save bartlett705/7d77be5f835c89c27e4aeade05e137f3 to your computer and use it in GitHub Desktop.
Save bartlett705/7d77be5f835c89c27e4aeade05e137f3 to your computer and use it in GitHub Desktop.

Pre-requisites:

  • Our jest unit and integration testing framework and helpers (link).
  • The enzyme package of React-specific testing utilities (link to enzyme 'getting started docs' or blog post)

I. Behavior-based Unit Tests - ShallowWrapper is your friend. A. Always use our helper setupShallowTest (or the underlying shallow method from enzyme directly) unless you have a really, really good reason not to. Currently accepted 'really good reasons' include: 1. A ComponentClass decorated with @withGraphQL, @withPubSub, or one of their variants. Since the HoC(s) abstract away the vast majority of the data-layer handling, this can still be considered a presentational component if it is essentially rendering data from the back-end(s) with no business logic other than a few notable exceptions. If your component requires more than two of the functionalities below, consider giving it a container to abstract away as much as possible but the actual markup template. a. Loading-state markup, manipulating presentation helpers like Scroll. b. Error-state markup, error reporting, re-fetching on error / user input. c. Reconciling data from multiple back-end services other than our graphql endpoint (find out if it is accurate to call this visage instead?) d. another one. 2. That's it. Export your 'bare' presentational components before applying functional HoCs (ask @prencher if that's the name), and subject those to tests. B. Test the Public API. ShallowWrapper allows you to reach into the component and make assertions against its internal state, or even call setState or lifecycle methods directly. Don't do this. It is probably not a meaningful test, for one. Instead: 1. Simulate the expected behavior of HoCs with mocked props. There are (helpers) for this. 2. Assert that the correct props are passed down to child components based on the initial state (including things like core-ui components). 3. Simulate the expected behavior of child components by invoking the callbacks passed to them by the component under test with every combination of parameters they might actually receive that will create a change to the state of the component under test.
4. Assert that the props passed to children correlate properly to the internal state changes induced in each permutation of the previous step.

Example

We are testing a stateful ComponentClass that is tasked with receiving some video objects from a parent, filtering and sorting them, and mapping them to instances of a presentational VideoCard. It also is tasked with handling input from one child - a filter selector - and updating the order of the VideoCards accordingly. We could start to write tests for it like this:

    /** Standard setup omitted for brevity; more details can be found here (link) */
 
    beforeEach(() => {
       { wrapper, props } = setupShallow(); 
    })
    describe('VideoList should', () => {
      it('render the correct number of videocards in the order provided', () => {
        const renderedVideoCardTitles = wrapper.find(VideoCard).map((card: ShallowWrapper) => card.prop('title'));
        const mockedVideoCardTitles = mockVideos().map((video: Video) => video.title);
        
        expect(renderedVideoCardTitles).toEqual(mockedVideoCardtitles);
      });
      it('handle filter selections by updating the VideoCard sort order', () => {
        const mockedSortedVideoCardTitles =  mockVideos({ sort: FilterSort.TimePosted, ascending: true })
          .map((video: Video) => video.title);
        wrapper.find({ data-test-selector: FILTER_MENU_SELECTOR }).prop('onFilterSelect')({ sort: FilterSort.TimePosted, ascending: true });
        const mockedVideoCardTitles = mockVideos().map((video: Video) => video.title);
 
        expect(renderedVideoCardTitles).toEqual(mockedVideoCardtitles);
    });
      });

II. Container tests, page tests, integration tests - time to mount up. A. B.
C. Don't test the HoCs. They have their own tests. If you find that they don't, bring it up with Browser Clients.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment