diff --git a/src/01-simple-tests/index.test.ts b/src/01-simple-tests/index.test.ts index fbbea85de..a5da5c9c0 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: 5, b: 3, action: Action.Subtract })).toBe(2); }); test('should multiply two numbers', () => { - // Write your test here + expect(simpleCalculator({ a: 4, b: 6, action: Action.Multiply })).toBe(24); }); test('should divide two numbers', () => { - // Write your test here + expect(simpleCalculator({ a: 72, b: 8, action: Action.Divide })).toBe(9); }); test('should exponentiate two numbers', () => { - // Write your test here + expect(simpleCalculator({ a: 2, b: 5, action: Action.Exponentiate })).toBe( + 32, + ); }); test('should return null for invalid action', () => { - // Write your test here + expect(simpleCalculator({ a: 2, b: 5, action: 'string' })).toBe(null); }); test('should return null for invalid arguments', () => { - // Write your test here + expect(simpleCalculator({ a: 'string', b: {}, action: Action.Add })).toBe( + null, + ); }); }); diff --git a/src/02-table-tests/index.test.ts b/src/02-table-tests/index.test.ts index 4f36e892e..67ea6493d 100644 --- a/src/02-table-tests/index.test.ts +++ b/src/02-table-tests/index.test.ts @@ -1,17 +1,33 @@ // 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: 9, b: 2, action: Action.Subtract, expected: 7 }, + { a: 8, b: 2, action: Action.Subtract, expected: 6 }, + { a: 7, b: 2, action: Action.Subtract, expected: 5 }, + + { a: 42, b: 7, action: Action.Divide, expected: 6 }, + { a: 81, b: 9, action: Action.Divide, expected: 9 }, + { a: 15, b: 3, action: Action.Divide, expected: 5 }, + + { a: 4, b: 7, action: Action.Multiply, expected: 28 }, + { a: 2, b: 5, action: Action.Multiply, expected: 10 }, + { a: 12, b: 12, action: Action.Multiply, expected: 144 }, + + { a: 2, b: 3, action: Action.Exponentiate, expected: 8 }, + { a: 3, b: 4, action: Action.Exponentiate, expected: 81 }, + { a: 4, b: 5, action: Action.Exponentiate, expected: 1024 }, +]; 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 return $expected when $a $action $b', + ({ a, b, action, expected }) => { + expect(simpleCalculator({ a, b, action })).toBe(expected); + }, + ); }); diff --git a/src/03-error-handling-async/index.test.ts b/src/03-error-handling-async/index.test.ts index 6e106a6d6..27109621e 100644 --- a/src/03-error-handling-async/index.test.ts +++ b/src/03-error-handling-async/index.test.ts @@ -1,30 +1,36 @@ // 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 + await expect(resolveValue(5)).resolves.toBe(5); }); }); describe('throwError', () => { test('should throw error with provided message', () => { - // Write your test here + expect(() => throwError('Error message')).toThrow('Error message'); }); 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 + expect(throwCustomError).toThrow(MyAwesomeError); }); }); describe('rejectCustomError', () => { test('should reject custom error', async () => { - // Write your test here + await expect(rejectCustomError).rejects.toThrow(MyAwesomeError); }); }); diff --git a/src/04-test-class/index.test.ts b/src/04-test-class/index.test.ts index 937490d82..c064fdb46 100644 --- a/src/04-test-class/index.test.ts +++ b/src/04-test-class/index.test.ts @@ -1,44 +1,62 @@ // Uncomment the code below and write your tests -// import { getBankAccount } from '.'; +import { getBankAccount } from '.'; describe('BankAccount', () => { test('should create account with initial balance', () => { - // Write your test here + expect(getBankAccount(100).getBalance()).toBe(100); }); test('should throw InsufficientFundsError error when withdrawing more than balance', () => { - // Write your test here + expect(getBankAccount(100).getBalance()).toBe(100); }); test('should throw error when transferring more than balance', () => { - // Write your test here + expect(() => getBankAccount(100).withdraw(200)).toThrow(); }); test('should throw error when transferring to the same account', () => { - // Write your test here + const account = getBankAccount(100); + expect(() => account.transfer(200, account)).toThrow(); }); test('should deposit money', () => { - // Write your test here + expect(getBankAccount(100).deposit(200).getBalance()).toBe(300); }); test('should withdraw money', () => { - // Write your test here + expect(getBankAccount(300).withdraw(170).getBalance()).toBe(130); }); test('should transfer money', () => { - // Write your test here + const firstAccount = getBankAccount(300); + const secondAccount = getBankAccount(100); + + expect(firstAccount.transfer(150, secondAccount).getBalance()).toBe(150); + expect(secondAccount.getBalance()).toBe(250); }); test('fetchBalance should return number in case if request did not failed', async () => { - // Write your tests here + const balance = await getBankAccount(100).fetchBalance(); + + if (balance === null) { + expect(balance).toBeNull(); + } else { + expect(typeof balance).toBe('number'); + expect(balance).toBeGreaterThanOrEqual(0); + expect(balance).toBeLessThanOrEqual(100); + } }); test('should set new balance if fetchBalance returned number', async () => { - // Write your tests here + const account = getBankAccount(100); + jest.spyOn(account, 'fetchBalance').mockResolvedValue(200); + await account.synchronizeBalance(); + expect(account.getBalance()).toBe(200); }); test('should throw SynchronizationFailedError if fetchBalance returned null', async () => { - // Write your tests here + const account = getBankAccount(100); + jest.spyOn(account, 'fetchBalance').mockResolvedValue(null); + expect(account.synchronizeBalance).rejects.toThrow(); }); }); diff --git a/src/05-partial-mocking/index.test.ts b/src/05-partial-mocking/index.test.ts index 9d8a66cbd..8675b4e19 100644 --- a/src/05-partial-mocking/index.test.ts +++ b/src/05-partial-mocking/index.test.ts @@ -1,8 +1,16 @@ // 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 originalModule = + jest.requireActual('./index'); + + return { + ...originalModule, + mockOne: jest.fn(), + mockTwo: jest.fn(), + mockThree: jest.fn(), + }; }); describe('partial mocking', () => { @@ -11,10 +19,20 @@ describe('partial mocking', () => { }); test('mockOne, mockTwo, mockThree should not log into console', () => { - // Write your test here + const spyLog = jest.spyOn(console, 'log'); + + mockOne(); + mockTwo(); + mockThree(); + + expect(spyLog).not.toHaveBeenCalled(); }); test('unmockedFunction should log into console', () => { - // Write your test here + const spyLog = jest.spyOn(console, 'log'); + + unmockedFunction(); + + expect(spyLog).toHaveBeenCalledWith('I am not mocked'); }); }); diff --git a/src/06-mocking-node-api/index.test.ts b/src/06-mocking-node-api/index.test.ts index 8dc3afd79..48d8e9095 100644 --- a/src/06-mocking-node-api/index.test.ts +++ b/src/06-mocking-node-api/index.test.ts @@ -1,5 +1,8 @@ // Uncomment the code below and write your tests -// import { readFileAsynchronously, doStuffByTimeout, doStuffByInterval } from '.'; +import { readFileAsynchronously, doStuffByTimeout, doStuffByInterval } from '.'; +import path from 'path'; +import fs from 'fs'; +import fsPromises from 'fs/promises'; describe('doStuffByTimeout', () => { beforeAll(() => { @@ -11,11 +14,22 @@ describe('doStuffByTimeout', () => { }); test('should set timeout with provided callback and timeout', () => { - // Write your test here + const spyTimeout = jest.spyOn(global, 'setTimeout'); + const cb = jest.fn(); + const timeout = 1000; + + doStuffByTimeout(cb, timeout); + expect(spyTimeout).toHaveBeenCalledWith(cb, timeout); }); test('should call callback only after timeout', () => { - // Write your test here + const cb = jest.fn(); + const timeout = 1000; + + doStuffByTimeout(cb, timeout); + expect(cb).not.toHaveBeenCalled(); + jest.advanceTimersByTime(timeout); + expect(cb).toHaveBeenCalled(); }); }); @@ -29,24 +43,50 @@ describe('doStuffByInterval', () => { }); test('should set interval with provided callback and timeout', () => { - // Write your test here + const spyInterval = jest.spyOn(global, 'setInterval'); + const cb = jest.fn(); + const interval = 1000; + + doStuffByInterval(cb, interval); + expect(spyInterval).toHaveBeenCalledWith(cb, interval); }); test('should call callback multiple times after multiple intervals', () => { - // Write your test here + const cb = jest.fn(); + const interval = 1000; + + doStuffByInterval(cb, interval); + expect(cb).not.toHaveBeenCalled(); + jest.advanceTimersByTime(interval * 3); + expect(cb).toHaveBeenCalledTimes(3); }); }); describe('readFileAsynchronously', () => { test('should call join with pathToFile', async () => { - // Write your test here + const spyJoin = jest.spyOn(path, 'join'); + const filePath = 'test'; + + await readFileAsynchronously(filePath); + expect(spyJoin).toHaveBeenCalledWith(__dirname, filePath); }); test('should return null if file does not exist', async () => { - // Write your test here + jest.spyOn(fs, 'existsSync').mockReturnValue(false); + const filePath = 'test'; + const result = await readFileAsynchronously(filePath); + + expect(result).toBeNull(); }); test('should return file content if file exists', async () => { - // Write your test here + jest.spyOn(fs, 'existsSync').mockReturnValue(true); + const filePath = 'test'; + const content = 'test'; + const bufferContent = Buffer.from(content); + + jest.spyOn(fsPromises, 'readFile').mockResolvedValue(bufferContent); + const result = await readFileAsynchronously(filePath); + expect(result).toBe(content); }); }); diff --git a/src/07-mocking-lib-api/index.test.ts b/src/07-mocking-lib-api/index.test.ts index e1dd001ef..cb160ccbc 100644 --- a/src/07-mocking-lib-api/index.test.ts +++ b/src/07-mocking-lib-api/index.test.ts @@ -1,17 +1,68 @@ // Uncomment the code below and write your tests -/* import axios from 'axios'; -import { throttledGetDataFromApi } from './index'; */ +import axios from 'axios'; +import { throttledGetDataFromApi, THROTTLE_TIME } from './index'; describe('throttledGetDataFromApi', () => { + jest.mock('axios'); + test('should create instance with provided base url', async () => { - // Write your test here + jest.useFakeTimers(); + + const data = { test: 'test' }; + const relativePath = '/test'; + + const mockCreate = jest + .fn() + .mockReturnValue({ get: jest.fn().mockResolvedValue(data) }); + (axios.create as jest.Mock) = mockCreate; + + await throttledGetDataFromApi(relativePath); + + expect(mockCreate).toHaveBeenCalledWith({ + baseURL: 'https://jsonplaceholder.typicode.com', + }); + + jest.useRealTimers(); + jest.clearAllMocks(); }); test('should perform request to correct provided url', async () => { - // Write your test here + jest.useFakeTimers(); + + const data = { test: 'test' }; + const relativePath = '/test'; + + const mockGet = jest.fn().mockResolvedValue({ data }); + const mockCreate = jest.fn().mockReturnValue({ get: mockGet }); + (axios.create as jest.Mock) = mockCreate; + + jest.advanceTimersByTime(THROTTLE_TIME); + + await throttledGetDataFromApi(relativePath); + + expect(mockGet).toHaveBeenCalledWith(relativePath); + + jest.useFakeTimers(); + jest.clearAllMocks(); }); test('should return response data', async () => { - // Write your test here + jest.useFakeTimers(); + + const data = { test: 'test' }; + const relativePath = '/test'; + + const mockGet = jest.fn().mockResolvedValue({ data }); + const mockCreate = jest.fn().mockReturnValue({ get: mockGet }); + (axios.create as jest.Mock) = mockCreate; + + jest.advanceTimersByTime(THROTTLE_TIME); + + const result = await throttledGetDataFromApi(relativePath); + + expect(result).toEqual(data); + + jest.useFakeTimers(); + jest.clearAllMocks(); }); }); 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..44cc7e1f7 --- /dev/null +++ b/src/08-snapshot-testing/__snapshots__/index.test.ts.snap @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`generateLinkedList should generate linked list from values 2 1`] = ` +{ + "next": { + "next": { + "next": null, + "value": null, + }, + "value": 2, + }, + "value": 2, +} +`; diff --git a/src/08-snapshot-testing/index.test.ts b/src/08-snapshot-testing/index.test.ts index 67c345706..b3a0e21b0 100644 --- a/src/08-snapshot-testing/index.test.ts +++ b/src/08-snapshot-testing/index.test.ts @@ -1,14 +1,23 @@ // 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 + expect(generateLinkedList([1, 1])).toStrictEqual({ + value: 1, + next: { + value: 1, + next: { + value: null, + next: null, + }, + }, + }); }); // Check match by comparison with snapshot test('should generate linked list from values 2', () => { - // Write your test here + expect(generateLinkedList([2, 2])).toMatchSnapshot(); }); });