Jest

Delightful javascript testing

npm install --save-dev jest #must then run in package.json scripts
npm install jest --global

Most Basic

sum.test.js

const sum = require('./sum');

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
})

package.json

"scripts": {
    "test": "jest"
}

npm run test

Will find any tests in subdirectories

Matchers

expect(2 + 2) - produces expectation object you call matchers on

  • .toBe(4) => Object.is

  • .toEqual(4) => recursively checks fields of object or array, toBe for numbers

  • .toMatchObject(obj) => Check all fields in obj are in

  • .not.toBe(0) => negate matcher

  • .toBeNull => null

  • .toBeUndefined => undefined

  • .toBeDefined => opp of toBeUndefined

  • .toBeTruthy =>if statement treats as true

  • .toBeFalsy => if statement treats as false

  • .toBeGreaterThan(3)

  • .toBeGreaterThanOrEqual(3.5)

  • .toBeLessThan(5)

  • .toBeLessThanOrEqual(4.5)

  • .toBeCloseTo => use instead of equals for jank floating pt

  • .toMatch(/I/) => String regular expressions

  • .toContain('beer') => check array for in

  • .toThrow() => throws errors

Blocks

toplevel before each done first and after each done last compared to blocks

describe('matching cities to foods', () => {
  // Applies only to tests in this describe block
  beforeEach(() => {
    return initializeFoodDatabase();
  });

  test(
  //...

Execution Order

1) Runs down page running code not in test and in describe blocks

2) runs down page again running tests in order found

Async

Can't just expect in callback because test will finish, instead add done argument and test will wait until called or timeout and fail

The ways for using async also work for setup and teardown

Callback

test('the data is peanut butter', done => {
  function callback(data) {
    expect(data).toBe('peanut butter');
    done();
  }

  fetchData(callback);
});

Promises

Just return a promise

test('the data is peanut butter', () => {
  return fetchData().then(data => {
    expect(data).toBe('peanut butter');
  });
//return fetchData().catch(e=>expect(e).toMatch('error'));
});

Async/Await

test('the data is peanut butter', async () => {
  const data = await fetchData();
  expect(data).toBe('peanut butter');
});

Setup

beforeEach(() => {
  initializeCityDatabase();
});

afterEach(() => {
  clearCityDatabase();
});

beforeAll(() => {
  return initializeCityDatabase(); //return for promise
}); 

afterAll(() => {
  return clearCityDatabase();
});

CLI Options

jest my-test --notify --config=config.json

files matching my-test, native OS notification on completion, and config.json as config

Other

To only run one test

change test( to test.only(

test.only('this will be the only test that runs', () => {
  expect(true).toBe(false);
});

Mock

Pretty cool, allows you to specify different returns per time called, check arguments and call count

More Plugins

API Routes

const request = require('supertest');
const server = require('../app.js');

describe('basic route tests', () => {
 test('get home route GET /', async () => {
 const response = await request(server).get('/');
 expect(response.status).toEqual(200);
 expect(response.text).toContain('Hello World!');
 });
});

describe('POST /users', function() {
  it('responds with json', function(done) {
    request(app)
      .post('/users')
      .send({name: 'john'})
      .set('Accept', 'application/json')
      .expect('Content-Type', /json/)
      .expect(200)
      .end(function(err, res) {
        if (err) return done(err);
        done();
      });
  });
});

Last updated