From 5c98bc7310be01a1106b379432960f4f7b873453 Mon Sep 17 00:00:00 2001 From: "@a.schepkivsky" Date: Mon, 5 Feb 2024 21:26:00 +0500 Subject: [PATCH 1/5] feat: 01, 02, 03 --- src/01-simple-tests/index.test.ts | 20 +++++++----- src/02-table-tests/index.test.ts | 37 ++++++++++++++++------- src/03-error-handling-async/index.test.ts | 27 +++++++++++++---- 3 files changed, 59 insertions(+), 25 deletions(-) diff --git a/src/01-simple-tests/index.test.ts b/src/01-simple-tests/index.test.ts index fbbea85de..910b66487 100644 --- a/src/01-simple-tests/index.test.ts +++ b/src/01-simple-tests/index.test.ts @@ -1,32 +1,36 @@ // Uncomment the code below and write your tests -// import { simpleCalculator, Action } from './index'; +import { simpleCalculator, Action } from './index'; describe('simpleCalculator tests', () => { test('should add two numbers', () => { - // Write your test here + expect(simpleCalculator({ a: 1, b: 2, action: Action.Add })).toBe(3); }); test('should subtract two numbers', () => { - // Write your test here + expect(simpleCalculator({ a: 10, b: 7, action: Action.Subtract })).toBe(3); }); test('should multiply two numbers', () => { - // Write your test here + expect(simpleCalculator({ a: 3, b: 4, action: Action.Multiply })).toBe(12); }); test('should divide two numbers', () => { - // Write your test here + expect(simpleCalculator({ a: 10, b: 2, action: Action.Divide })).toBe(5); }); test('should exponentiate two numbers', () => { - // Write your test here + expect(simpleCalculator({ a: 2, b: 3, action: Action.Exponentiate })).toBe( + 8, + ); }); test('should return null for invalid action', () => { - // Write your test here + expect(simpleCalculator({ a: 1, b: 2, action: 'invalid' })).toBeNull(); }); test('should return null for invalid arguments', () => { - // Write your test here + expect( + simpleCalculator({ a: 1, b: 'invalid', action: Action.Add }), + ).toBeNull(); }); }); diff --git a/src/02-table-tests/index.test.ts b/src/02-table-tests/index.test.ts index 4f36e892e..c5f963d98 100644 --- a/src/02-table-tests/index.test.ts +++ b/src/02-table-tests/index.test.ts @@ -1,17 +1,32 @@ // Uncomment the code below and write your tests -/* import { simpleCalculator, Action } from './index'; +import { simpleCalculator, Action } from './index'; const testCases = [ - { a: 1, b: 2, action: Action.Add, expected: 3 }, - { a: 2, b: 2, action: Action.Add, expected: 4 }, - { a: 3, b: 2, action: Action.Add, expected: 5 }, - // continue cases for other actions -]; */ + { a: 1, b: 2, action: Action.Add, expected: 3 }, + { a: 2, b: 2, action: Action.Add, expected: 4 }, + { a: 3, b: 2, action: Action.Add, expected: 5 }, + { a: 4, b: 2, action: Action.Subtract, expected: 2 }, + { a: 9, b: 3, action: Action.Subtract, expected: 6 }, + { a: 6, b: 2, action: Action.Subtract, expected: 4 }, + { a: 4, b: 2, action: Action.Multiply, expected: 8 }, + { a: 5, b: 2, action: Action.Multiply, expected: 10 }, + { a: 6, b: 2, action: Action.Multiply, expected: 12 }, + { a: 8, b: 4, action: Action.Divide, expected: 2 }, + { a: 10, b: 2, action: Action.Divide, expected: 5 }, + { a: 12, b: 3, action: Action.Divide, expected: 4 }, + { a: 2, b: 4, action: Action.Exponentiate, expected: 16 }, + { a: 3, b: 3, action: Action.Exponentiate, expected: 27 }, + { a: 10, b: 2, action: Action.Exponentiate, expected: 100 }, + { a: 'invalid', b: 2, action: Action.Exponentiate, expected: null }, + { a: 2, b: 'invalid', action: Action.Add, expected: null }, + { a: 3, b: 2, action: 'invalid', expected: null }, +]; describe('simpleCalculator', () => { - // This test case is just to run this test suite, remove it when you write your own tests - test('should blah-blah', () => { - expect(true).toBe(true); - }); - // Consider to use Jest table tests API to test all cases above + test.each(testCases)( + 'should calculate $a $action $b and return $expected, or return null on invalid input', + ({ expected, ...input }) => { + expect(simpleCalculator(input)).toBe(expected); + }, + ); }); diff --git a/src/03-error-handling-async/index.test.ts b/src/03-error-handling-async/index.test.ts index 6e106a6d6..016e4508f 100644 --- a/src/03-error-handling-async/index.test.ts +++ b/src/03-error-handling-async/index.test.ts @@ -1,30 +1,45 @@ // Uncomment the code below and write your tests -// import { throwError, throwCustomError, resolveValue, MyAwesomeError, rejectCustomError } from './index'; +import { + throwError, + throwCustomError, + resolveValue, + MyAwesomeError, + rejectCustomError, +} from './index'; describe('resolveValue', () => { test('should resolve provided value', async () => { - // Write your test here + const value = await resolveValue(1); + expect(value).toBe(1); }); }); describe('throwError', () => { test('should throw error with provided message', () => { - // Write your test here + expect(() => throwError('errorMsg')).toThrow('errorMsg'); }); test('should throw error with default message if message is not provided', () => { - // Write your test here + expect(() => throwError()).toThrow('Oops!'); }); }); describe('throwCustomError', () => { test('should throw custom error', () => { - // Write your test here + try { + throwCustomError(); + } catch (error) { + expect(error instanceof MyAwesomeError).toBeTruthy(); + } }); }); describe('rejectCustomError', () => { test('should reject custom error', async () => { - // Write your test here + try { + await rejectCustomError(); + } catch (error) { + expect(error instanceof MyAwesomeError).toBeTruthy(); + } }); }); From 4cff8fa08362aec266a37e9907ae436699f85291 Mon Sep 17 00:00:00 2001 From: "@a.schepkivsky" Date: Mon, 12 Feb 2024 21:31:56 +0500 Subject: [PATCH 2/5] feat: 04 --- src/04-test-class/index.test.ts | 54 +++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/src/04-test-class/index.test.ts b/src/04-test-class/index.test.ts index 937490d82..8a24a7861 100644 --- a/src/04-test-class/index.test.ts +++ b/src/04-test-class/index.test.ts @@ -1,44 +1,74 @@ -// Uncomment the code below and write your tests -// import { getBankAccount } from '.'; +import lodash from 'lodash'; +import { + BankAccount, + InsufficientFundsError, + SynchronizationFailedError, + getBankAccount, +} from '.'; describe('BankAccount', () => { test('should create account with initial balance', () => { - // Write your test here + const account = getBankAccount(10); + expect(account instanceof BankAccount).toBe(true); + expect(account.getBalance()).toBe(10); }); test('should throw InsufficientFundsError error when withdrawing more than balance', () => { - // Write your test here + try { + getBankAccount(10).withdraw(20); + } catch (error) { + expect(error instanceof InsufficientFundsError).toBe(true); + } }); test('should throw error when transferring more than balance', () => { - // Write your test here + expect(() => getBankAccount(10).transfer(20, getBankAccount(5))).toThrow(); }); test('should throw error when transferring to the same account', () => { - // Write your test here + const account = getBankAccount(10); + expect(() => account.transfer(20, account)).toThrow(); }); test('should deposit money', () => { - // Write your test here + const account = getBankAccount(10); + account.deposit(20); + expect(account.getBalance()).toBe(30); }); test('should withdraw money', () => { - // Write your test here + const account = getBankAccount(30); + account.withdraw(20); + expect(account.getBalance()).toBe(10); }); test('should transfer money', () => { - // Write your test here + const fromAccount = getBankAccount(30); + const toAccount = getBankAccount(10); + fromAccount.transfer(15, toAccount); + expect(fromAccount.getBalance()).toBe(15); + expect(toAccount.getBalance()).toBe(25); }); test('fetchBalance should return number in case if request did not failed', async () => { - // Write your tests here + jest.spyOn(lodash, 'random').mockReturnValue(10); + expect(await getBankAccount(0).fetchBalance()).toBe(10); }); test('should set new balance if fetchBalance returned number', async () => { - // Write your tests here + const account = getBankAccount(0); + jest.spyOn(account, 'fetchBalance').mockResolvedValue(10); + await account.synchronizeBalance(); + expect(account.getBalance()).toBe(10); }); test('should throw SynchronizationFailedError if fetchBalance returned null', async () => { - // Write your tests here + const account = getBankAccount(0); + jest.spyOn(account, 'fetchBalance').mockResolvedValue(null); + try { + await account.synchronizeBalance(); + } catch (error) { + expect(error instanceof SynchronizationFailedError).toBe(true); + } }); }); From 492dc05b708505ec82b24c079d16122ad1740023 Mon Sep 17 00:00:00 2001 From: "@a.schepkivsky" Date: Mon, 12 Feb 2024 23:16:18 +0500 Subject: [PATCH 3/5] feat: 05 --- src/05-partial-mocking/index.test.ts | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/05-partial-mocking/index.test.ts b/src/05-partial-mocking/index.test.ts index 9d8a66cbd..2326a45e5 100644 --- a/src/05-partial-mocking/index.test.ts +++ b/src/05-partial-mocking/index.test.ts @@ -1,8 +1,13 @@ -// Uncomment the code below and write your tests -// import { mockOne, mockTwo, mockThree, unmockedFunction } from './index'; +import { mockOne, mockTwo, mockThree, unmockedFunction } from './index'; jest.mock('./index', () => { - // const originalModule = jest.requireActual('./index'); + const module = jest.requireActual('./index'); + return { + ...module, + mockOne: jest.fn(), + mockTwo: jest.fn(), + mockThree: jest.fn(), + }; }); describe('partial mocking', () => { @@ -11,10 +16,16 @@ describe('partial mocking', () => { }); test('mockOne, mockTwo, mockThree should not log into console', () => { - // Write your test here + const spy = jest.spyOn(console, 'log'); + mockOne(); + mockTwo(); + mockThree(); + expect(spy).not.toHaveBeenCalled(); }); test('unmockedFunction should log into console', () => { - // Write your test here + const spy = jest.spyOn(console, 'log'); + unmockedFunction(); + expect(spy).toHaveBeenCalledWith('I am not mocked'); }); }); From 1583ed5cb75cb59116a6d94f7d6ab51261670c2f Mon Sep 17 00:00:00 2001 From: "@a.schepkivsky" Date: Mon, 12 Feb 2024 23:16:27 +0500 Subject: [PATCH 4/5] feat: 06 --- src/06-mocking-node-api/index.test.ts | 35 ++++++++++++++++++++------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/06-mocking-node-api/index.test.ts b/src/06-mocking-node-api/index.test.ts index 8dc3afd79..833572a00 100644 --- a/src/06-mocking-node-api/index.test.ts +++ b/src/06-mocking-node-api/index.test.ts @@ -1,5 +1,5 @@ -// Uncomment the code below and write your tests -// import { readFileAsynchronously, doStuffByTimeout, doStuffByInterval } from '.'; +import path from 'path'; +import { readFileAsynchronously, doStuffByTimeout, doStuffByInterval } from '.'; describe('doStuffByTimeout', () => { beforeAll(() => { @@ -11,11 +11,18 @@ describe('doStuffByTimeout', () => { }); test('should set timeout with provided callback and timeout', () => { - // Write your test here + const callback = jest.fn(); + const spy = jest.spyOn(global, 'setTimeout'); + doStuffByTimeout(callback, 100); + expect(spy).toHaveBeenCalledWith(callback, 100); }); test('should call callback only after timeout', () => { - // Write your test here + const callback = jest.fn(); + doStuffByTimeout(callback, 500); + expect(callback).not.toHaveBeenCalled(); + jest.advanceTimersByTime(500); + expect(callback).toHaveBeenCalled(); }); }); @@ -29,24 +36,34 @@ describe('doStuffByInterval', () => { }); test('should set interval with provided callback and timeout', () => { - // Write your test here + const callback = jest.fn(); + const spy = jest.spyOn(global, 'setInterval'); + doStuffByInterval(callback, 100); + expect(spy).toHaveBeenCalledWith(callback, 100); }); test('should call callback multiple times after multiple intervals', () => { - // Write your test here + const callback = jest.fn(); + doStuffByInterval(callback, 500); + jest.advanceTimersByTime(1000); + expect(callback).toHaveBeenCalledTimes(2); }); }); describe('readFileAsynchronously', () => { test('should call join with pathToFile', async () => { - // Write your test here + const spy = jest.spyOn(path, 'join'); + await readFileAsynchronously('index.ts'); + expect(spy).toHaveBeenCalledWith(__dirname, 'index.ts'); }); test('should return null if file does not exist', async () => { - // Write your test here + const result = await readFileAsynchronously('not-exist.txt'); + expect(result).toBeNull(); }); test('should return file content if file exists', async () => { - // Write your test here + const result = await readFileAsynchronously('index.ts'); + expect(result).toBeDefined(); }); }); From 1d0fa13e0b84b953bfc3f6f0d9b1cc13f904d0db Mon Sep 17 00:00:00 2001 From: "@a.schepkivsky" Date: Mon, 12 Feb 2024 23:16:39 +0500 Subject: [PATCH 5/5] feat: 08 --- .../__snapshots__/index.test.ts.snap | 17 +++++++++++++++ src/08-snapshot-testing/index.test.ts | 21 +++++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 src/08-snapshot-testing/__snapshots__/index.test.ts.snap diff --git a/src/08-snapshot-testing/__snapshots__/index.test.ts.snap b/src/08-snapshot-testing/__snapshots__/index.test.ts.snap new file mode 100644 index 000000000..b06ad6e10 --- /dev/null +++ b/src/08-snapshot-testing/__snapshots__/index.test.ts.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`generateLinkedList should generate linked list from values 2 1`] = ` +{ + "next": { + "next": { + "next": { + "next": null, + "value": null, + }, + "value": 3, + }, + "value": 2, + }, + "value": 1, +} +`; diff --git a/src/08-snapshot-testing/index.test.ts b/src/08-snapshot-testing/index.test.ts index 67c345706..05eb8e8b7 100644 --- a/src/08-snapshot-testing/index.test.ts +++ b/src/08-snapshot-testing/index.test.ts @@ -1,14 +1,27 @@ -// Uncomment the code below and write your tests -// import { generateLinkedList } from './index'; +import { generateLinkedList } from './index'; describe('generateLinkedList', () => { // Check match by expect(...).toStrictEqual(...) test('should generate linked list from values 1', () => { - // Write your test here + const list = generateLinkedList([1, 2, 3]); + expect(list).toStrictEqual({ + value: 1, + next: { + value: 2, + next: { + value: 3, + next: { + value: null, + next: null, + }, + }, + }, + }); }); // Check match by comparison with snapshot test('should generate linked list from values 2', () => { - // Write your test here + const list = generateLinkedList([1, 2, 3]); + expect(list).toMatchSnapshot(); }); });