From f87efac951079f3b7053a253dcb6229c328e889d Mon Sep 17 00:00:00 2001 From: Andrew Smith Date: Fri, 12 Mar 2021 15:42:32 -0800 Subject: [PATCH 1/3] Clean up async exercise. --- .../js/jest/__tests__/async.solution.spec.js | 77 +++++++++++++++++++ src/www/js/jest/__tests__/async.spec.js | 11 +-- 2 files changed, 80 insertions(+), 8 deletions(-) create mode 100644 src/www/js/jest/__tests__/async.solution.spec.js 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..4c0de87 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) From cb6c8c15884c2d515cd5c2daa6a8aec967e7aa76 Mon Sep 17 00:00:00 2001 From: Andrew Smith Date: Fri, 12 Mar 2021 15:43:51 -0800 Subject: [PATCH 2/3] Fix syntax. --- src/www/js/jest/__tests__/async.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/www/js/jest/__tests__/async.spec.js b/src/www/js/jest/__tests__/async.spec.js index 4c0de87..ab48c8c 100644 --- a/src/www/js/jest/__tests__/async.spec.js +++ b/src/www/js/jest/__tests__/async.spec.js @@ -42,7 +42,7 @@ describe('Async tests', () => { describe('#getTodo', () => { it.todo('should find a todo') - it.todo('should throw error when todo not found')}) + it.todo('should throw error when todo not found') // TODO what's wrong with this test? Rewrite it so it doesn't silently fail it('should throw an error for missing todo', async () => { From 135c8500544a2ad89f8d7c3674b8448ea90b6092 Mon Sep 17 00:00:00 2001 From: Andrew Smith Date: Fri, 12 Mar 2021 15:46:44 -0800 Subject: [PATCH 3/3] Add mocks exercise solution. --- .../__tests__/coin.solution.test.js | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/www/js/jest_mocks/__tests__/coin.solution.test.js 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() + }) +})