Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tests: implement basic jest tests #1

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 43 additions & 8 deletions src/01-simple-tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,67 @@
// 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: 2, b: 3, action: Action.Add })).toBe(5);
expect(simpleCalculator({ a: -2, b: -3, action: Action.Add })).toBe(-5);
expect(simpleCalculator({ a: -5, b: 3, action: Action.Add })).toBe(-2);
});

test('should subtract two numbers', () => {
// Write your test here
expect(simpleCalculator({ a: 2, b: 3, action: Action.Subtract })).toBe(-1);
expect(simpleCalculator({ a: -2, b: -3, action: Action.Subtract })).toBe(1);
expect(simpleCalculator({ a: 5, b: 3, action: Action.Subtract })).toBe(2);
});

test('should multiply two numbers', () => {
// Write your test here
expect(simpleCalculator({ a: 2, b: 3, action: Action.Multiply })).toBe(6);
expect(simpleCalculator({ a: -2, b: -3, action: Action.Multiply })).toBe(6);
expect(simpleCalculator({ a: -2, b: 3, action: Action.Multiply })).toBe(-6);
expect(simpleCalculator({ a: -2, b: 0, action: Action.Multiply })).toBe(-0);
});

test('should divide two numbers', () => {
// Write your test here
expect(simpleCalculator({ a: 6, b: 2, action: Action.Divide })).toBe(3);
expect(simpleCalculator({ a: -6, b: 2, action: Action.Divide })).toBe(-3);
expect(simpleCalculator({ a: -6, b: -2, action: Action.Divide })).toBe(3);
expect(simpleCalculator({ a: -6, b: 0, action: Action.Divide })).toBe(
Number.NEGATIVE_INFINITY,
);
expect(simpleCalculator({ a: 6, b: 4, action: Action.Divide })).toBe(1.5);
});

test('should exponentiate two numbers', () => {
// Write your test here
expect(simpleCalculator({ a: 2, b: 2, action: Action.Exponentiate })).toBe(
4,
);
expect(simpleCalculator({ a: -2, b: 2, action: Action.Exponentiate })).toBe(
4,
);
expect(simpleCalculator({ a: -2, b: 3, action: Action.Exponentiate })).toBe(
-8,
);
expect(simpleCalculator({ a: 6, b: 0, action: Action.Exponentiate })).toBe(
1,
);
expect(simpleCalculator({ a: -6, b: 0, action: Action.Exponentiate })).toBe(
1,
);
expect(
simpleCalculator({ a: 9, b: 0.5, action: Action.Exponentiate }),
).toBe(3);
expect(simpleCalculator({ a: 2, b: -1, action: Action.Exponentiate })).toBe(
0.5,
);
});

test('should return null for invalid action', () => {
// Write your test here
expect(simpleCalculator({ a: 6, b: 0, action: 'lg' })).toBe(null);
expect(simpleCalculator({ a: 6, b: 0, action: 5 })).toBe(null);
});

test('should return null for invalid arguments', () => {
// Write your test here
expect(simpleCalculator({ a: '6', b: 2, action: Action.Add })).toBe(null);
expect(simpleCalculator({ a: 6, b: '2', action: Action.Add })).toBe(null);
});
});
28 changes: 16 additions & 12 deletions src/02-table-tests/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
// 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: 3, b: 2, action: Action.Subtract, expected: 1 },
{ a: -3, b: -2, action: Action.Subtract, expected: -1 },
{ a: 3, b: 2, action: Action.Multiply, expected: 6 },
{ a: 3, b: 2, action: Action.Divide, expected: 1.5 },
{ a: 3, b: 2, action: Action.Exponentiate, expected: 9 },
];

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)(
'test $action with $a, $b arguments',
({ a, b, expected, action }) => {
expect(simpleCalculator({ a, b, action })).toBe(expected);
},
);
});
21 changes: 14 additions & 7 deletions src/03-error-handling-async/index.test.ts
Original file line number Diff line number Diff line change
@@ -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
await expect(resolveValue('resolved value')).resolves.toBe(
'resolved value',
);
});
});

describe('throwError', () => {
test('should throw error with provided message', () => {
// Write your test here
expect(() => throwError('test message')).toThrowError('test message');
});

test('should throw error with default message if message is not provided', () => {
// Write your test here
expect(throwError).toThrowError('Oops!');
});
});

describe('throwCustomError', () => {
test('should throw custom error', () => {
// Write your test here
expect(throwCustomError).toThrowError(MyAwesomeError);
});
});

describe('rejectCustomError', () => {
test('should reject custom error', async () => {
// Write your test here
expect(rejectCustomError).rejects.toThrowError(MyAwesomeError);
});
});
71 changes: 59 additions & 12 deletions src/04-test-class/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,91 @@
// Uncomment the code below and write your tests
// import { getBankAccount } from '.';
import {
getBankAccount,
InsufficientFundsError,
SynchronizationFailedError,
TransferFailedError,
} from '.';
import lodash from 'lodash';

describe('BankAccount', () => {
const initialBalance = 1000;
let bankAccount = getBankAccount(initialBalance);
let destinationAccount = getBankAccount(initialBalance);

beforeAll(() => {
bankAccount = getBankAccount(initialBalance);
destinationAccount = getBankAccount(initialBalance);
});

test('should create account with initial balance', () => {
// Write your test here
expect(bankAccount.getBalance()).toBe(initialBalance);
});

test('should throw InsufficientFundsError error when withdrawing more than balance', () => {
// Write your test here
expect(() => bankAccount.withdraw(initialBalance + 1000)).toThrowError(
InsufficientFundsError,
);
});

test('should throw error when transferring more than balance', () => {
// Write your test here
expect(() =>
bankAccount.transfer(initialBalance + 1000, destinationAccount),
).toThrowError(InsufficientFundsError);
});

test('should throw error when transferring to the same account', () => {
// Write your test here
expect(() =>
bankAccount.transfer(initialBalance - 500, bankAccount),
).toThrowError(TransferFailedError);
});

test('should deposit money', () => {
// Write your test here
const deposit = 500;
const currentBalance = bankAccount.getBalance();
expect(bankAccount.deposit(deposit).getBalance()).toBe(
currentBalance + deposit,
);
});

test('should withdraw money', () => {
// Write your test here
const withdraw = 200;
const currentBalance = bankAccount.getBalance();
expect(bankAccount.withdraw(withdraw).getBalance()).toBe(
currentBalance - withdraw,
);
});

test('should transfer money', () => {
// Write your test here
const transfer = 200;
const currentBalance = bankAccount.getBalance();
expect(
bankAccount.transfer(transfer, destinationAccount).getBalance(),
).toBe(currentBalance - transfer);

expect(destinationAccount.getBalance()).toBe(initialBalance + transfer);
});

test('fetchBalance should return number in case if request did not failed', async () => {
// Write your tests here
const mockedValue = 400;
jest.spyOn(lodash, 'random').mockReturnValue(mockedValue);

const result = await bankAccount.fetchBalance();
expect(result).toBe(mockedValue);
});

test('should set new balance if fetchBalance returned number', async () => {
// Write your tests here
const mockedValue = 400;
jest.spyOn(lodash, 'random').mockReturnValue(mockedValue);

await bankAccount.synchronizeBalance();
expect(bankAccount.getBalance()).toBe(mockedValue);
});

test('should throw SynchronizationFailedError if fetchBalance returned null', async () => {
// Write your tests here
const mockedValue = 0;
jest.spyOn(lodash, 'random').mockReturnValue(mockedValue);

expect(bankAccount.synchronizeBalance()).rejects.toThrowError(
SynchronizationFailedError,
);
});
});
24 changes: 19 additions & 5 deletions src/05-partial-mocking/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
// 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<typeof import('./index')>('./index');
const originalModule =
jest.requireActual<typeof import('./index')>('./index');
return {
__esModule: true,
...originalModule,
mockOne: jest.fn(),
mockTwo: jest.fn(),
mockThree: jest.fn(),
};
});

describe('partial mocking', () => {
Expand All @@ -11,10 +18,17 @@ describe('partial mocking', () => {
});

test('mockOne, mockTwo, mockThree should not log into console', () => {
// Write your test here
const log = jest.spyOn(console, 'log');
mockOne();
mockTwo();
mockThree();

expect(log).not.toBeCalled();
});

test('unmockedFunction should log into console', () => {
// Write your test here
const log = jest.spyOn(console, 'log');
unmockedFunction();
expect(log).toHaveBeenCalled();
});
});
49 changes: 41 additions & 8 deletions src/06-mocking-node-api/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
// Uncomment the code below and write your tests
// import { readFileAsynchronously, doStuffByTimeout, doStuffByInterval } from '.';
import { doStuffByInterval, doStuffByTimeout, readFileAsynchronously } from '.';
import path from 'path';
import fs from 'fs';
import fsPromises from 'fs/promises';

jest.mock('fs');
jest.mock('fs/promises');

describe('doStuffByTimeout', () => {
beforeAll(() => {
Expand All @@ -11,11 +17,18 @@ describe('doStuffByTimeout', () => {
});

test('should set timeout with provided callback and timeout', () => {
// Write your test here
jest.spyOn(global, 'setTimeout');
const cb = jest.fn();
doStuffByTimeout(cb, 1000);
expect(setTimeout).toBeCalledWith(cb, 1000);
});

test('should call callback only after timeout', () => {
// Write your test here
const cb = jest.fn();
doStuffByTimeout(cb, 1000);
expect(cb).not.toBeCalled();
jest.advanceTimersByTime(1000);
expect(cb).toBeCalled();
});
});

Expand All @@ -29,24 +42,44 @@ describe('doStuffByInterval', () => {
});

test('should set interval with provided callback and timeout', () => {
// Write your test here
jest.spyOn(global, 'setInterval');
const cb = jest.fn();
doStuffByInterval(cb, 1000);
expect(setInterval).toBeCalledWith(cb, 1000);
});

test('should call callback multiple times after multiple intervals', () => {
// Write your test here
const cb = jest.fn();
doStuffByInterval(cb, 1000);
expect(cb).not.toBeCalled();
jest.advanceTimersByTime(1000);
expect(cb).toBeCalledTimes(1);
jest.advanceTimersByTime(2000);
expect(cb).toBeCalledTimes(3);
});
});

describe('readFileAsynchronously', () => {
test('should call join with pathToFile', async () => {
// Write your test here
const join = jest.spyOn(path, 'join');
const pathToFile = 'test.txt';
readFileAsynchronously(pathToFile);
expect(join).toHaveBeenCalledWith(expect.anything(), pathToFile);
});

test('should return null if file does not exist', async () => {
// Write your test here
jest.spyOn(fs, 'existsSync').mockReturnValue(false);
const pathToFile = 'fake-path.txt';

await expect(readFileAsynchronously(pathToFile)).resolves.toBeNull();
});

test('should return file content if file exists', async () => {
// Write your test here
const fileContent = 'File content';
jest.spyOn(fs, 'existsSync').mockReturnValue(true);
jest.spyOn(fsPromises, 'readFile').mockResolvedValue(fileContent);
const pathToFile = 'fake-path.txt';

await expect(readFileAsynchronously(pathToFile)).resolves.toBe(fileContent);
});
});
Loading