Sink Testing

redux-sink provide a simple testing flow, here is the example of testing with `jest` along with `enzyme` and `typescript`

Test sink class

Testing sink classes are simple because sink provides the injections based on containers, simply inject mock objects then you can test the logic of sink

import { mocked } from 'ts-jest/utils';

import { HttpClient } from './http-client';
import { PatientAddSink } from './patient-add-sink';

jest.mock('./http-client');

// create mock object of httpclient which does external requests
const mockHttpClient = mocked(new HttpClient(), true);

describe('sink:: patient-add-sink', () => {
  beforeEach(() => {
    // create mock implementation of post to return a promise object
    // which is the same behavior as normal request call
    mockHttpClient.post.mockImplementation(x => {
      return Promise.resolve({} as any);
    });
  });

  it('should call api when submit', async () => {
    // create sink with mock httpclient
    const sink = new PatientAddSink(mockHttpClient as any);
    
    // set starting state
    sink.hospital = { name: 'test', id: 1, waitTime: 1 };
    sink.illness = { name: 'test', id: 1 };
    
    // run sink effect
    const promise = sink.submit();
    
    // check state before request finishes
    expect(sink.submitting).toBeTruthy();
    await promise;
    
    // check state after request completed
    expect(sink.submitting).toBeFalsy();
    expect(mockHttpClient.post.mock.calls).toHaveLength(1);
  });
});

Test react component

Test the components by mock the useSink and SinkContainer without Provider wrapper

import { shallow } from 'enzyme';
import * as React from 'react';
import { SinkContainer } from 'redux-sink';

import { PatientAddSection } from '../patient-add-section';
import { PatientAddSubmit } from '../patient-add-submit';
import { PatientAdd } from './patient-add';
import { PatientAddSink } from './patient-add-sink';

// mock original useSink by jest function
// return the sink from custom SinkContainer instead of SinkFactory
const reduxSink = require('redux-sink');
const sinkContainer = new SinkContainer();
reduxSink.useSink = jest.fn((sink) => sinkContainer.getSink(sink));

// create the container store, which has dispatch and event capability
sinkContainer.createStore();

describe('component:: patient-add', () => {
  it('should mount', () => {
    const container = shallow(<PatientAdd />);
    expect(container.html()).toBeTruthy();
  });
  
  it('should display hospital when illness selected', () => {
    // get the sink that used by component
    const sink = sinkContainer.getSink(PatientAddSink);
    // update the sink state
    sink.illness = { name: 'test', id: 1 };
    
    // shallow render the component by enzyme
    // component will updated according to sink state
    const container = shallow(<PatientAdd />);
    const sections = container.find(PatientAddSection);
    
    expect(sections.length).toEqual(2);
  });
});

Last updated