Jest

From bibbleWiki
Jump to navigation Jump to search

Why Not Enzyme

This has over 200+ issues open and 26 of these are bugs. Jest is recommended by the react team.

Naming Test

__tests__/*.js
*.spec.js
*.test.js

Example Test

Describe is the suite, it is the test

describe("The question list ", ()=> {
    it ("should display a list of items", ()=> {
        expect(2+2).toEqual(4);
    })
    it ("should display a list of items", ()=> {
        expect(2+4).toEqual(6);
    })
})

Setup and Teardown

This can be done using

BeforeEach BeforeAll
beforeAll(()=>{
   console.log("Hello");
});

and

AfterEach AfterAll
afterAll(()=>{
   console.log("Hello");
});

Note does not matter what order you write them in.

Skipping and Isolating Tests

Add keyword only to include tests

    it.only ("should display a list of items", ()=> {
        expect(2+2).toEqual(4);
    })

Add keyword skip to exlude tests

    it.skip ("should display a list of items", ()=> {
        expect(2+2).toEqual(4);
    })

Async Tests

it('async test 1', done=> {
    setTimeout(done, 100)
});
it('async test 2',()=> {
    return new Promise(
        resolve => setTimeout(resolve,100)
    );
});
it('async test 1', async ()=>
    await delay(100)
);

Mocking

Create directory __mocking__ at the same level as node_modules

Here is an example for mocking fetch package isomorphic-fetch

 let __value = 42;
 const isomorphicFetch = jest.fn( ()=> __value);
 isomorphicFetch.__setValue = v => __value = v;
 export default  isomorphicFetch;

And the test case. We import the function to be mocked from out __mocks__/isomorphic-fetch.js

import { handleFetchQuestion } from './fetch-question-saga';
import fetch from 'isomorphic-fetch';

 describe("Fetch question s saga", ()=>{
 
     beforeAll( () => {
         fetch.__setValue([{question_id:42}] );
     }); 
 
     it ("should fetch the question saga", async ()=> {
         const gen = handleFetchQuestion({question_id:42});
         const { value } = await gen.next(); 

         expect(value).toEqual( [{question_id:42}] )
         expect(fetch).toHaveBeenCalledWith('/api/questions/42');
     });
 });

Redux and Testing mapStateToProps

You can easily test the map from state to props. e.g.

import { mapStateToProps } from '../QuestionDetail';

it("should map the state to props correctly", () => {

   // Sample App State with sampleQuestion being object in state
   const sampleQuestion {
       question_id:42,
       body: "Space is big"
   };

   const appState = {
       questions: [sampleQuestion]
   };
   
   // Sample Props
   const ownProps = {
       question:42
   });

   const componentState = mapStateToProps(appState, ownProps)
   expect(componentState).toEqual(sampleQuestion);
}


Sample test with state

Bit of a lot of code but here goes

Create component to test

import React from 'react';

export default class extends React.Component {
    constructor)(...args) {
        super(...args);
        this.state = {
            count: -1
        }
    }

    async comonentDidMount () {
        let { count } = await NotificationService.GetNotification();
        this.setState( {
            count
        });
    }

    render() {
       return (
           <section className="mt-3 mb-2">
               <div className="notifications">
                   {this.state.count != -1 ? '${this.state.count} Notifications Awaiting!' : 'Loading...'}
               </div>
           </section>
       )
    }
}

Create a Service

export default {
    async GetNoitifications() {
        console.warning("REAL NOTIFICATION SERVICE!");
        await delay(1000);
        return { count: 42 };
    }
}

Test Case

import NotificationsViewer from '../NotificationsViewer';
import renderer from 'react-test-renderer';
import React from 'react';
import delay from 'redux-saga';

// NOTE Local module you need to pass in url of notification service
jest.mock('../../services/NotificationService');

// NOTE 2 this needs to be a require and needs to be after the jest. Making it
// an import will fail

const notificationService = require('../../services/NotificationService').default; 

  
describe("The notification viewer", () => {

   beforeAll( ()=> {
     notificationService.__setCount(5);
   });

   it("should display the correct number of notifications", async()=> {

       const tree = renderer
           .create(
               <NoticationsViewer/>
            )
       await delay();
       const instance = tree.root;

       // find by className the component
       const component = instance.findByProps( { className: 'notificiations' });  

       const text = component.children[0];
       export(text).toEqual("5 Notifications");

   });
});

Mocked Service src\services\__mocks__\NotificationService.js

let count = 0;
export default {

    __setCount(__count) {
        count = _count;
    },
    async GetNotifications() {
        console.warn("Good Job! Using Mock");
    }
}


Matchers in Jest

These can be found [1]

Some of them for quick reference.

expect(value)
expect.extend(matchers)
expect.anything()
expect.any(constructor)
expect.arrayContaining(array)
expect.assertions(number)
expect.hasAssertions()
expect.not.arrayContaining(array)
expect.not.objectContaining(object)
expect.not.stringContaining(string)
expect.not.stringMatching(string | regexp)
expect.objectContaining(object)
expect.stringContaining(string)
expect.stringMatching(string | regexp)
expect.addSnapshotSerializer(serializer)