diff --git a/src/www/js/jest/__tests__/async.solution.spec.js b/src/www/js/jest/__tests__/async.solution.spec.js new file mode 100644 index 0000000..e63da89 --- /dev/null +++ b/src/www/js/jest/__tests__/async.solution.spec.js @@ -0,0 +1,77 @@ +const { find, propEq } = require('ramda') + +const todos = [ + { id: 1, text: 'Learn Jest' }, + { id: 2, text: 'Learn async' }, + { id: 3, text: '???' }, + { id: 4, text: 'Profit 💸' }, +] + +const getTodos = () => ( + new Promise((res) => { + process.nextTick(() => { + res(todos) + }) + }) +) + +const getTodo = async (id) => { + const todos = await getTodos() + const todo = find(propEq('id', id), todos) + + if (!todo) throw new Error(`Todo ID ${id} not found`) + // if (!todo) return Promise.reject(`Todo ID ${id} not found`) + + return todo +} + +const getTodoInBackground = (id, cb) => { + getTodos() + .then((todos) => cb(find(propEq('id', id), todos))) + return true +} + +describe('Async tests', () => { + describe('#getTodos', () => { + it('should work with async/await', async () => { + const res = await getTodos() + expect(res).toEqual(todos) + }) + + it('should work with await + resolves', async () => { + await expect(getTodos()).resolves.toEqual(todos) + }) + + it('should work by returning a promise', () => { + return getTodos() + .then((res) => { + expect(res).toEqual(todos) + }) + }) + }) + + describe('#getTodo', () => { + it('should find a todo', async () => { + await expect(getTodo(1)).resolves.toEqual(todos[0]) + }) + + it('should throw error when todo not found', async () => { + return await expect(getTodo(42)).rejects.toThrow('Todo ID 42 not found') + }) + + // TODO what's wrong with this test? + it('should throw an error for missing todo', async () => { + await expect(getTodo(42)).rejects.toThrow('Todo ID 42 not found') + }) + }) + + describe('#getTodoInBackground', () => { + it('should get a todo in background and pass to callback', async () => { + const flushPromises = () => new Promise(process.nextTick) + const mock = jest.fn() + getTodoInBackground(1, mock) + await flushPromises() + expect(mock).toHaveBeenCalledWith(todos[0]) + }) + }) +}) diff --git a/src/www/js/jest/__tests__/async.spec.js b/src/www/js/jest/__tests__/async.spec.js index b01917a..ab48c8c 100644 --- a/src/www/js/jest/__tests__/async.spec.js +++ b/src/www/js/jest/__tests__/async.spec.js @@ -20,14 +20,13 @@ const getTodo = async (id) => { const todo = find(propEq('id', id), todos) if (!todo) throw new Error(`Todo ID ${id} not found`) - // if (!todo) return Promise.reject(`Todo ID ${id} not found`) return todo } const getTodoInBackground = (id, cb) => { getTodos() - .then((todos) => find(propEq('id', id), todos)) + .then((todos) => cb(find(propEq('id', id), todos))) return true } @@ -43,13 +42,9 @@ describe('Async tests', () => { describe('#getTodo', () => { it.todo('should find a todo') - // it.todo('should throw error when todo not found') - it('should throw error when todo not found', async () => { - return await expect(getTodo(42)) - .rejects.toThrow('Todo ID 42 not found') - }) + it.todo('should throw error when todo not found') - // TODO what's wrong with this test? + // TODO what's wrong with this test? Rewrite it so it doesn't silently fail it('should throw an error for missing todo', async () => { try { await getTodo(1) diff --git a/src/www/js/jest_mocks/__tests__/coin.solution.test.js b/src/www/js/jest_mocks/__tests__/coin.solution.test.js new file mode 100644 index 0000000..f406b62 --- /dev/null +++ b/src/www/js/jest_mocks/__tests__/coin.solution.test.js @@ -0,0 +1,39 @@ +import { coinFlip, winJackpot } from '../coin' +import { getRandomInt } from '../random' +import { resetJackpot } from '../store' + +jest.mock('../random') + +describe('#coinFlip', () => { + it('should return Heads or Tails based on random generator', () => { + /** + * TODO these will fail randomly. Use `jest.mock` to control the output + * of the random number generator and test the coin flip behavior. + * You should not have to change the implementation files. + */ + getRandomInt.mockReturnValueOnce(true) + expect(coinFlip()).toEqual('Heads') + getRandomInt.mockReturnValueOnce(false) + expect(coinFlip()).toEqual('Tails') + }) +}) + +jest.mock('../store', () => ({ + getCurrentJackpot: jest.fn().mockReturnValue(100), + resetJackpot: jest.fn() +})) + +describe('#winJackpot', () => { + it('should reset the jackpot and return the winnings message', () => { + /** + * TODO + * Using an inline mock `jest.mock('./dep', () => { ... }) to mock + * the behavior of the store. + * 1. Test that a message of "You won $...!" is returned based off + * the current jackpot. + * 2. Test that the jackpot is told to reset. + */ + expect(winJackpot()).toEqual('You won $100!') + expect(resetJackpot).toHaveBeenCalled() + }) +})