From 9ada31bb3c86cc22d2ffd93772016f011c2aaab7 Mon Sep 17 00:00:00 2001 From: adevksh Date: Sun, 9 Nov 2025 15:44:54 +0100 Subject: [PATCH 1/8] feat: add simple tests --- src/01-simple-tests/index.test.ts | 49 +++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/src/01-simple-tests/index.test.ts b/src/01-simple-tests/index.test.ts index fbbea85de..4415e0d26 100644 --- a/src/01-simple-tests/index.test.ts +++ b/src/01-simple-tests/index.test.ts @@ -1,32 +1,63 @@ -// 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: 7, b: 6, action: Action.Add })).toBe(13); + expect(simpleCalculator({ a: -7, b: 6, action: Action.Add })).toBe(-1); + expect(simpleCalculator({ a: 2, b: 2, action: Action.Add })).toBe(4); }); test('should subtract two numbers', () => { - // Write your test here + expect(simpleCalculator({ a: 7, b: 6, action: Action.Subtract })).toBe(1); + expect(simpleCalculator({ a: -7, b: 6, action: Action.Subtract })).toBe( + -13, + ); + expect(simpleCalculator({ a: 2, b: 2, action: Action.Subtract })).toBe(0); }); test('should multiply two numbers', () => { - // Write your test here + expect(simpleCalculator({ a: 7, b: 6, action: Action.Multiply })).toBe(42); + expect(simpleCalculator({ a: -7, b: 6, action: Action.Multiply })).toBe( + -42, + ); + expect(simpleCalculator({ a: 0, b: 2, action: Action.Multiply })).toBe(0); }); test('should divide two numbers', () => { - // Write your test here + expect(simpleCalculator({ a: 15, b: 3, action: Action.Divide })).toBe(5); + expect(simpleCalculator({ a: -15, b: 3, action: Action.Divide })).toBe(-5); + expect(simpleCalculator({ a: 0, b: 2, action: Action.Divide })).toBe(0); + expect(simpleCalculator({ a: 2, b: 0, action: Action.Divide })).toBe( + Infinity, + ); }); test('should exponentiate two numbers', () => { - // Write your test here + expect(simpleCalculator({ a: 2, b: 3, action: Action.Exponentiate })).toBe( + 8, + ); + expect(simpleCalculator({ a: -2, b: 3, action: Action.Exponentiate })).toBe( + -8, + ); + expect(simpleCalculator({ a: 2, b: -3, action: Action.Exponentiate })).toBe( + 0.125, + ); + expect(simpleCalculator({ a: 0, b: 3, action: Action.Exponentiate })).toBe( + 0, + ); }); test('should return null for invalid action', () => { - // Write your test here + expect(simpleCalculator({ a: 7, b: 6, action: '%' })).toBeNull(); }); test('should return null for invalid arguments', () => { - // Write your test here + expect(simpleCalculator({ a: '7', b: 6, action: Action.Add })).toBeNull(); + expect( + simpleCalculator({ a: 7, b: '6', action: Action.Subtract }), + ).toBeNull(); + expect( + simpleCalculator({ a: null, b: 6, action: Action.Multiply }), + ).toBeNull(); }); }); From a1ed0571f60300f6f1cd4d0470a5e1472dfcba00 Mon Sep 17 00:00:00 2001 From: adevksh Date: Sun, 9 Nov 2025 15:45:09 +0100 Subject: [PATCH 2/8] feat: add table tests --- src/02-table-tests/index.test.ts | 43 +++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/02-table-tests/index.test.ts b/src/02-table-tests/index.test.ts index 4f36e892e..8c6b79a0f 100644 --- a/src/02-table-tests/index.test.ts +++ b/src/02-table-tests/index.test.ts @@ -1,17 +1,36 @@ -// 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: 7, b: 6, action: Action.Add, expected: 13 }, + { a: -7, b: 6, action: Action.Add, expected: -1 }, + { a: 7, b: 6, action: Action.Subtract, expected: 1 }, + { a: -7, b: 6, action: Action.Subtract, expected: -13 }, + { a: 2, b: 2, action: Action.Subtract, expected: 0 }, + { a: 7, b: 6, action: Action.Multiply, expected: 42 }, + { a: -7, b: 6, action: Action.Multiply, expected: -42 }, + { a: 0, b: 2, action: Action.Multiply, expected: 0 }, + { a: 15, b: 3, action: Action.Divide, expected: 5 }, + { a: -15, b: 3, action: Action.Divide, expected: -5 }, + { a: 0, b: 2, action: Action.Divide, expected: 0 }, + { a: 2, b: 0, action: Action.Divide, expected: Infinity }, + { a: 2, b: 3, action: Action.Exponentiate, expected: 8 }, + { a: -2, b: 3, action: Action.Exponentiate, expected: -8 }, + { a: 2, b: -3, action: Action.Exponentiate, expected: 0.125 }, + { a: 0, b: 3, action: Action.Exponentiate, expected: 0 }, + { a: 7, b: 6, action: '%', expected: null }, + { a: '7', b: 6, action: Action.Add, expected: null }, + { a: 7, b: '6', action: Action.Add, expected: null }, + { a: null, b: 6, action: Action.Add, 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 return $expected for a=$a, b=$b, action=$action', + ({ a, b, action, expected }) => { + expect(simpleCalculator({ a, b, action })).toBe(expected); + }, + ); }); From c039e0179662935fcf7182ce7a82f0d701b2b92a Mon Sep 17 00:00:00 2001 From: adevksh Date: Sun, 9 Nov 2025 15:45:16 +0100 Subject: [PATCH 3/8] feat: add error handling & async tests --- src/03-error-handling-async/index.test.ts | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/03-error-handling-async/index.test.ts b/src/03-error-handling-async/index.test.ts index 6e106a6d6..e3521663a 100644 --- a/src/03-error-handling-async/index.test.ts +++ b/src/03-error-handling-async/index.test.ts @@ -1,30 +1,37 @@ -// 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 = 'Hello, world!'; + await expect(resolveValue(value)).resolves.toBe(value); }); }); describe('throwError', () => { test('should throw error with provided message', () => { - // Write your test here + const message = 'Error message'; + expect(() => throwError(message)).toThrow(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); }); }); From fe0abfd1aa52baea26f885572477748e6bc69b96 Mon Sep 17 00:00:00 2001 From: adevksh Date: Sun, 9 Nov 2025 15:45:25 +0100 Subject: [PATCH 4/8] feat: add testing class --- src/04-test-class/index.test.ts | 84 ++++++++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 12 deletions(-) diff --git a/src/04-test-class/index.test.ts b/src/04-test-class/index.test.ts index 937490d82..a350ec0ef 100644 --- a/src/04-test-class/index.test.ts +++ b/src/04-test-class/index.test.ts @@ -1,44 +1,104 @@ -// Uncomment the code below and write your tests -// import { getBankAccount } from '.'; +import { + getBankAccount, + InsufficientFundsError, + TransferFailedError, + SynchronizationFailedError, +} from '.'; +import { random } from 'lodash'; + +jest.mock('lodash', () => ({ + random: jest.fn(), +})); + +const initialBalance = 1000; +const balance = 100; describe('BankAccount', () => { test('should create account with initial balance', () => { - // Write your test here + const account = getBankAccount(initialBalance); + + expect(account.getBalance()).toBe(initialBalance); }); test('should throw InsufficientFundsError error when withdrawing more than balance', () => { - // Write your test here + const account = getBankAccount(initialBalance); + + expect(() => account.withdraw(10000)).toThrow(InsufficientFundsError); }); test('should throw error when transferring more than balance', () => { - // Write your test here + const account1 = getBankAccount(initialBalance); + const account2 = getBankAccount(initialBalance); + + expect(() => account1.transfer(10000, account2)).toThrow( + InsufficientFundsError, + ); }); test('should throw error when transferring to the same account', () => { - // Write your test here + const account = getBankAccount(initialBalance); + + expect(() => account.transfer(100, account)).toThrow(TransferFailedError); }); test('should deposit money', () => { - // Write your test here + const account = getBankAccount(initialBalance); + const depositAmount = 100; + + account.deposit(depositAmount); + expect(account.getBalance()).toBe(initialBalance + depositAmount); }); test('should withdraw money', () => { - // Write your test here + const account = getBankAccount(initialBalance); + const withdrawAmount = 100; + + account.withdraw(withdrawAmount); + expect(account.getBalance()).toBe(initialBalance - withdrawAmount); }); test('should transfer money', () => { - // Write your test here + const account1 = getBankAccount(initialBalance); + const account2 = getBankAccount(initialBalance); + const transferAmount = 100; + + account1.transfer(transferAmount, account2); + expect(account1.getBalance()).toBe(initialBalance - transferAmount); + expect(account2.getBalance()).toBe(initialBalance + transferAmount); }); test('fetchBalance should return number in case if request did not failed', async () => { - // Write your tests here + const account = getBankAccount(initialBalance); + const balance = 100; + const requestSucceeded = 1; + + (random as jest.Mock) + .mockReturnValueOnce(balance) + .mockReturnValueOnce(requestSucceeded); + await expect(account.fetchBalance()).resolves.toBe(balance); }); test('should set new balance if fetchBalance returned number', async () => { - // Write your tests here + const account = getBankAccount(initialBalance); + const requestSucceeded = 1; + + (random as jest.Mock) + .mockReturnValueOnce(balance) + .mockReturnValueOnce(requestSucceeded); + await account.synchronizeBalance(); + expect(account.getBalance()).toBe(balance); }); test('should throw SynchronizationFailedError if fetchBalance returned null', async () => { - // Write your tests here + const account = getBankAccount(initialBalance); + const requestFailed = 0; + + (random as jest.Mock) + .mockReturnValueOnce(balance) + .mockReturnValueOnce(requestFailed); + await expect(account.synchronizeBalance()).rejects.toThrow( + SynchronizationFailedError, + ); + expect(account.getBalance()).toBe(initialBalance); }); }); From 7fece188d59b2ee3655d5f015e704eeedfd5eaa3 Mon Sep 17 00:00:00 2001 From: adevksh Date: Sun, 9 Nov 2025 15:45:32 +0100 Subject: [PATCH 5/8] feat: add partial mocking --- src/05-partial-mocking/index.test.ts | 32 ++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/05-partial-mocking/index.test.ts b/src/05-partial-mocking/index.test.ts index 9d8a66cbd..a500136b1 100644 --- a/src/05-partial-mocking/index.test.ts +++ b/src/05-partial-mocking/index.test.ts @@ -1,20 +1,34 @@ -// 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', () => { - afterAll(() => { - jest.unmock('./index'); - }); - test('mockOne, mockTwo, mockThree should not log into console', () => { - // Write your test here + const consoleSpy = jest.spyOn(console, 'log'); + mockOne(); + mockTwo(); + mockThree(); + expect(mockOne).toHaveBeenCalled(); + expect(mockTwo).toHaveBeenCalled(); + expect(mockThree).toHaveBeenCalled(); + expect(consoleSpy).not.toHaveBeenCalled(); + consoleSpy.mockRestore(); }); test('unmockedFunction should log into console', () => { - // Write your test here + const consoleSpy = jest.spyOn(console, 'log'); + unmockedFunction(); + expect(consoleSpy).toHaveBeenCalledWith('I am not mocked'); + consoleSpy.mockRestore(); }); }); From 56c113cbd4652783fbd8239ad5cb46c3ad15a4c2 Mon Sep 17 00:00:00 2001 From: adevksh Date: Sun, 9 Nov 2025 15:45:39 +0100 Subject: [PATCH 6/8] feat: add tests to mocking Node.js API --- src/06-mocking-node-api/index.test.ts | 97 ++++++++++++++++++++------- 1 file changed, 74 insertions(+), 23 deletions(-) diff --git a/src/06-mocking-node-api/index.test.ts b/src/06-mocking-node-api/index.test.ts index 8dc3afd79..0dfb4052a 100644 --- a/src/06-mocking-node-api/index.test.ts +++ b/src/06-mocking-node-api/index.test.ts @@ -1,52 +1,103 @@ -// Uncomment the code below and write your tests -// import { readFileAsynchronously, doStuffByTimeout, doStuffByInterval } from '.'; +import fs from 'fs'; +import fsPromises from 'fs/promises'; +import path from 'path'; -describe('doStuffByTimeout', () => { - beforeAll(() => { - jest.useFakeTimers(); - }); +import { readFileAsynchronously, doStuffByTimeout, doStuffByInterval } from '.'; - afterAll(() => { - jest.useRealTimers(); - }); +jest.mock('fs'); +jest.mock('fs/promises'); +jest.mock('path'); + +const time = 1000; + +beforeAll(() => { + jest.useFakeTimers(); +}); + +afterAll(() => { + jest.useRealTimers(); +}); +describe('doStuffByTimeout', () => { test('should set timeout with provided callback and timeout', () => { - // Write your test here + const spy = jest.spyOn(globalThis, 'setTimeout'); + const cb = jest.fn(); + + doStuffByTimeout(cb, time); + + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith(cb, time); + spy.mockRestore(); }); test('should call callback only after timeout', () => { - // Write your test here + const cb = jest.fn(); + + doStuffByTimeout(cb, time); + + expect(cb).not.toHaveBeenCalled(); + jest.advanceTimersByTime(time); + expect(cb).toHaveBeenCalledTimes(1); }); }); describe('doStuffByInterval', () => { - beforeAll(() => { - jest.useFakeTimers(); - }); + test('should set interval with provided callback and timeout', () => { + const spy = jest.spyOn(globalThis, 'setInterval'); + const cb = jest.fn(); - afterAll(() => { - jest.useRealTimers(); - }); + doStuffByInterval(cb, time); - test('should set interval with provided callback and timeout', () => { - // Write your test here + expect(spy).toHaveBeenCalledWith(cb, time); + spy.mockRestore(); }); test('should call callback multiple times after multiple intervals', () => { - // Write your test here + const spy = jest.spyOn(globalThis, 'setInterval'); + const cb = jest.fn(); + + doStuffByInterval(cb, time); + + expect(spy).toHaveBeenCalledWith(cb, time); + spy.mockRestore(); + expect(cb).not.toHaveBeenCalled(); + + jest.advanceTimersByTime(time); + expect(cb).toHaveBeenCalledTimes(1); + + jest.advanceTimersByTime(time); + expect(cb).toHaveBeenCalledTimes(2); }); }); describe('readFileAsynchronously', () => { + const fileName = 'file.txt'; + test('should call join with pathToFile', async () => { - // Write your test here + const spy = jest.spyOn(path, 'join'); + jest.spyOn(fs, 'existsSync').mockReturnValue(false); + + await readFileAsynchronously(fileName); + + expect(spy).toHaveBeenCalledWith(__dirname, fileName); }); test('should return null if file does not exist', async () => { - // Write your test here + jest.spyOn(fs, 'existsSync').mockReturnValue(false); + + const result = await readFileAsynchronously('notfound.txt'); + + expect(result).toBeNull(); }); test('should return file content if file exists', async () => { - // Write your test here + const content = 'content'; + + jest.spyOn(fs, 'existsSync').mockReturnValue(true); + jest.spyOn(fsPromises, 'readFile').mockResolvedValue(content); + + const result = await readFileAsynchronously(fileName); + + expect(result).toBe(content); }); }); From 782c9d9a49f508db22ec9f898dc8d38e2271fe37 Mon Sep 17 00:00:00 2001 From: adevksh Date: Sun, 9 Nov 2025 15:45:45 +0100 Subject: [PATCH 7/8] feat: add tests to mocking library API --- src/07-mocking-lib-api/index.test.ts | 46 ++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/src/07-mocking-lib-api/index.test.ts b/src/07-mocking-lib-api/index.test.ts index e1dd001ef..ae87fa3ec 100644 --- a/src/07-mocking-lib-api/index.test.ts +++ b/src/07-mocking-lib-api/index.test.ts @@ -1,17 +1,51 @@ -// Uncomment the code below and write your tests -/* import axios from 'axios'; -import { throttledGetDataFromApi } from './index'; */ +import axios from 'axios'; +import { throttledGetDataFromApi } from './index'; + +jest.mock('lodash', () => ({ + throttle: jest.fn((fn) => fn), +})); + +jest.mock('axios'); describe('throttledGetDataFromApi', () => { + const baseUrl = 'https://jsonplaceholder.typicode.com'; + const newUrl = '/test'; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + const setupMockGet = (responseData: unknown) => { + const mockGet = jest.fn().mockResolvedValue({ data: responseData }); + (axios.create as jest.Mock).mockReturnValue({ + get: mockGet, + }); + return mockGet; + }; + test('should create instance with provided base url', async () => { - // Write your test here + setupMockGet('response'); + const spy = jest.spyOn(axios, 'create'); + + await throttledGetDataFromApi(newUrl); + + expect(spy).toHaveBeenCalledWith({ baseURL: baseUrl }); }); test('should perform request to correct provided url', async () => { - // Write your test here + const mockGet = setupMockGet({}); + + await throttledGetDataFromApi(newUrl); + + expect(mockGet).toHaveBeenCalledWith(newUrl); }); test('should return response data', async () => { - // Write your test here + const mockData = { title: 'test' }; + setupMockGet(mockData); + + const result = await throttledGetDataFromApi(newUrl); + + expect(result).toEqual(mockData); }); }); From 5bf9fda3b3dd278d3e11da2c4d42bdbc929b7b5b Mon Sep 17 00:00:00 2001 From: adevksh Date: Sun, 9 Nov 2025 15:45:53 +0100 Subject: [PATCH 8/8] feat: add snapshot testing --- .../__snapshots__/index.test.ts.snap | 14 ++++++++++ src/08-snapshot-testing/index.test.ts | 26 ++++++++++++++----- 2 files changed, 34 insertions(+), 6 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..b00c929a9 --- /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": 1, +} +`; diff --git a/src/08-snapshot-testing/index.test.ts b/src/08-snapshot-testing/index.test.ts index 67c345706..b1f6c9659 100644 --- a/src/08-snapshot-testing/index.test.ts +++ b/src/08-snapshot-testing/index.test.ts @@ -1,14 +1,28 @@ -// 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 values = [1, 2]; + const result = generateLinkedList(values); + + const expected = { + value: 1, + next: { + value: 2, + next: { + value: null, + next: null, + }, + }, + }; + + expect(result).toStrictEqual(expected); }); - // Check match by comparison with snapshot test('should generate linked list from values 2', () => { - // Write your test here + const values = [1, 2]; + const result = generateLinkedList(values); + + expect(result).toMatchSnapshot(); }); });