diff --git a/.gitignore b/.gitignore
index 4d29575..8822593 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,5 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
+
+todos.ts
\ No newline at end of file
diff --git a/package.json b/package.json
index d906efe..0c6663b 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
+ "test": "env CI=true react-scripts test",
"test:ci": "env CI=true react-scripts test --passWithNoTests",
"test:cov": "env CI=true react-scripts test --coverage",
"eject": "react-scripts eject",
diff --git a/src/App.test.tsx b/src/App.test.tsx
deleted file mode 100644
index 2a68616..0000000
--- a/src/App.test.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import React from 'react';
-import { render, screen } from '@testing-library/react';
-import App from './App';
-
-test('renders learn react link', () => {
- render();
- const linkElement = screen.getByText(/learn react/i);
- expect(linkElement).toBeInTheDocument();
-});
diff --git a/src/utils/index.ts b/src/utils/index.ts
new file mode 100644
index 0000000..f6fe0ee
--- /dev/null
+++ b/src/utils/index.ts
@@ -0,0 +1,72 @@
+/**
+ *
+ * @function isEmptyString - Checks if passed value is an empty string or not
+ * @param {string} value
+ * @returns `boolean` indicating whether `value` is an empty string
+ *
+ */
+export const isEmptyString = (value: string | T): boolean =>
+ typeof value !== 'string' || !value?.trim()?.length;
+
+/**
+ *
+ * @function isValidNumber - Checks if passed value is a valid number or not
+ * @param {number | string} value
+ * @returns `boolean` indicating whether `value` is a valid number
+ *
+ */
+export const isValidNumber = (value: number | string | T): boolean =>
+ ['number', 'string'].includes(typeof value) &&
+ value !== '' &&
+ !isNaN(Number(value));
+
+/**
+ *
+ * @function isEmptyList - Checks if passed object is an empty list or not
+ * @param {Array} obj
+ * @returns `boolean` indicating whether `obj` is an empty list
+ *
+ */
+export const isEmptyList = (obj: Array | T): boolean =>
+ !Array.isArray(obj) || (Array.isArray(obj) && obj.length === 0);
+
+/**
+ *
+ * @function isEmptyObject - Checks if passed object is an empty object or not
+ * @param {Object} obj
+ * @returns `boolean` indicating whether `obj` is an empty object
+ *
+ */
+export const isEmptyObject = (obj: Object | T): boolean =>
+ !obj ||
+ typeof obj !== 'object' ||
+ Array.isArray(obj) ||
+ Object.keys(obj).length === 0;
+
+/**
+ *
+ * @function truncateStringToLength - Truncates passed value to specified length
+ * @param {string} value
+ * @param {number} length
+ * @returns truncated `value` if its length is greater than or equal to `length`
+ *
+ */
+export const truncateStringToLength = (
+ value: string,
+ length: number
+): string => {
+ if (isEmptyString(value) || !isValidNumber(length) || length <= 0)
+ return value;
+ return value?.length <= length ? value : `${value?.substring(0, length)}...`;
+};
+
+/**
+ *
+ * @function createListOfSize - Creates a list of length `size` containing integers from `start`
+ * @param {number} size - specifies size of list
+ * @param {number} start - specifies first value of list
+ * @returns list containing integers from start to start + size - 1
+ *
+ */
+export const createListOfSize = (size: number, start: number = 1): number[] =>
+ size > 0 ? Array.from(Array(size)).map(() => start++) : [];
diff --git a/src/utils/tests/createListOfSize.test.ts b/src/utils/tests/createListOfSize.test.ts
new file mode 100644
index 0000000..65f9aef
--- /dev/null
+++ b/src/utils/tests/createListOfSize.test.ts
@@ -0,0 +1,32 @@
+import { createListOfSize } from '..';
+
+test('createListOfSize with no start argument and positive size', () => {
+ const size = 5;
+ const list = createListOfSize(size);
+ expect(list).toBeInstanceOf(Array);
+ expect(list.length).toBe(size);
+ list.forEach((val, index) => expect(val).toBe(index + 1));
+});
+
+test('createListOfSize with no start argument and 0 size', () => {
+ const size = 0;
+ const list = createListOfSize(size);
+ expect(list).toBeInstanceOf(Array);
+ expect(list.length).toBe(size);
+});
+
+test('createListOfSize with no start argument and negative size', () => {
+ const size = -2;
+ const list = createListOfSize(size);
+ expect(list).toBeInstanceOf(Array);
+ expect(list.length).toBe(0);
+});
+
+test('createListOfSize with start argument', () => {
+ const size = 5;
+ const start = size * 2;
+ const list = createListOfSize(size, start);
+ expect(list).toBeInstanceOf(Array);
+ expect(list.length).toBe(size);
+ list.forEach((val, index) => expect(val).toBe(start + index));
+});
diff --git a/src/utils/tests/isEmptyList.test.ts b/src/utils/tests/isEmptyList.test.ts
new file mode 100644
index 0000000..df0d3cb
--- /dev/null
+++ b/src/utils/tests/isEmptyList.test.ts
@@ -0,0 +1,37 @@
+import { isEmptyList } from '..';
+
+test('isEmptyList on empty list', () => {
+ expect(isEmptyList([])).toBeTruthy();
+});
+
+test('isEmptyList on non-empty lists', () => {
+ expect(isEmptyList([[]])).toBeFalsy();
+ expect(isEmptyList([1, 2, 3])).toBeFalsy();
+ expect(isEmptyList([1, 'true', {}])).toBeFalsy();
+});
+
+test('isEmptyList on null and undefined values', () => {
+ expect(isEmptyList(null)).toBeTruthy();
+ expect(isEmptyList(undefined)).toBeTruthy();
+});
+
+test('isEmptyList on string values', () => {
+ expect(isEmptyList('')).toBeTruthy();
+ expect(isEmptyList('hello world')).toBeTruthy();
+});
+
+test('isEmptyList on numeric values', () => {
+ expect(isEmptyList(1)).toBeTruthy();
+ expect(isEmptyList(0)).toBeTruthy();
+ expect(isEmptyList(-1)).toBeTruthy();
+});
+
+test('isEmptyList on boolean values', () => {
+ expect(isEmptyList(true)).toBeTruthy();
+ expect(isEmptyList(false)).toBeTruthy();
+});
+
+test('isEmptyList on object values', () => {
+ expect(isEmptyList({})).toBeTruthy();
+ expect(isEmptyList({ key: [] })).toBeTruthy();
+});
diff --git a/src/utils/tests/isEmptyObject.test.ts b/src/utils/tests/isEmptyObject.test.ts
new file mode 100644
index 0000000..edcc1ad
--- /dev/null
+++ b/src/utils/tests/isEmptyObject.test.ts
@@ -0,0 +1,36 @@
+import { isEmptyObject } from '..';
+
+test('isEmptyObject on empty object', () => {
+ expect(isEmptyObject({})).toBeTruthy();
+});
+
+test('isEmptyObject on non-empty objects', () => {
+ expect(isEmptyObject({ key: {} })).toBeFalsy();
+ expect(isEmptyObject({ 1: 1, 2: 2 })).toBeFalsy();
+});
+
+test('isEmptyObject on null and undefined values', () => {
+ expect(isEmptyObject(null)).toBeTruthy();
+ expect(isEmptyObject(undefined)).toBeTruthy();
+});
+
+test('isEmptyObject on string values', () => {
+ expect(isEmptyObject('')).toBeTruthy();
+ expect(isEmptyObject('hello world')).toBeTruthy();
+});
+
+test('isEmptyObject on numeric values', () => {
+ expect(isEmptyObject(1)).toBeTruthy();
+ expect(isEmptyObject(0)).toBeTruthy();
+ expect(isEmptyObject(-1)).toBeTruthy();
+});
+
+test('isEmptyObject on boolean values', () => {
+ expect(isEmptyObject(true)).toBeTruthy();
+ expect(isEmptyObject(false)).toBeTruthy();
+});
+
+test('isEmptyObject on array values', () => {
+ expect(isEmptyObject([])).toBeTruthy();
+ expect(isEmptyObject([{}])).toBeTruthy();
+});
diff --git a/src/utils/tests/isEmptyString.test.ts b/src/utils/tests/isEmptyString.test.ts
new file mode 100644
index 0000000..2feb543
--- /dev/null
+++ b/src/utils/tests/isEmptyString.test.ts
@@ -0,0 +1,32 @@
+import { isEmptyString } from '..';
+
+test('isEmptyString on empty string', () => {
+ expect(isEmptyString('')).toBeTruthy();
+});
+
+test('isEmptyString on non-empty strings', () => {
+ expect(isEmptyString('hello')).toBeFalsy();
+ expect(isEmptyString('hello world')).toBeFalsy();
+ expect(isEmptyString('123')).toBeFalsy();
+});
+
+test('isEmptyString on null and undefined values', () => {
+ expect(isEmptyString(null)).toBeTruthy();
+ expect(isEmptyString(undefined)).toBeTruthy();
+});
+
+test('isEmptyString on numeric values', () => {
+ expect(isEmptyString(1)).toBeTruthy();
+ expect(isEmptyString(0)).toBeTruthy();
+ expect(isEmptyString(-1)).toBeTruthy();
+});
+
+test('isEmptyString on boolean values', () => {
+ expect(isEmptyString(true)).toBeTruthy();
+ expect(isEmptyString(false)).toBeTruthy();
+});
+
+test('isEmptyString on object values', () => {
+ expect(isEmptyString({})).toBeTruthy();
+ expect(isEmptyString([])).toBeTruthy();
+});
diff --git a/src/utils/tests/isValidNumber.test.ts b/src/utils/tests/isValidNumber.test.ts
new file mode 100644
index 0000000..da51c57
--- /dev/null
+++ b/src/utils/tests/isValidNumber.test.ts
@@ -0,0 +1,34 @@
+import { isValidNumber } from '..';
+
+test('isValidNumber on numeric values', () => {
+ expect(isValidNumber(1)).toBeTruthy();
+ expect(isValidNumber(0)).toBeTruthy();
+ expect(isValidNumber(-1)).toBeTruthy();
+});
+
+test('isValidNumber on numeric strings', () => {
+ expect(isValidNumber('1')).toBeTruthy();
+ expect(isValidNumber('0')).toBeTruthy();
+ expect(isValidNumber('-1')).toBeTruthy();
+});
+
+test('isValidNumber on non-numeric strings', () => {
+ expect(isValidNumber('')).toBeFalsy();
+ expect(isValidNumber('hello world')).toBeFalsy();
+});
+
+test('isValidNumber on null, undefined and NaN values', () => {
+ expect(isValidNumber(null)).toBeFalsy();
+ expect(isValidNumber(undefined)).toBeFalsy();
+ expect(isValidNumber(NaN)).toBeFalsy();
+});
+
+test('isValidNumber on boolean values', () => {
+ expect(isValidNumber(true)).toBeFalsy();
+ expect(isValidNumber(false)).toBeFalsy();
+});
+
+test('isValidNumber on object values', () => {
+ expect(isValidNumber({})).toBeFalsy();
+ expect(isValidNumber([])).toBeFalsy();
+});
diff --git a/src/utils/tests/truncateStringToLength.test.ts b/src/utils/tests/truncateStringToLength.test.ts
new file mode 100644
index 0000000..8891c03
--- /dev/null
+++ b/src/utils/tests/truncateStringToLength.test.ts
@@ -0,0 +1,37 @@
+import { truncateStringToLength } from '..';
+
+test('truncateStringToLength with empty value', () => {
+ const value = '';
+ const truncatedString = truncateStringToLength(value, 2);
+ expect(truncatedString).toBe(value);
+});
+
+test('truncateStringToLength with length as 0', () => {
+ const value = 'hello world';
+ const truncatedString = truncateStringToLength(value, 0);
+ expect(truncatedString).toBe(value);
+});
+
+test('truncateStringToLength with negative length', () => {
+ const value = 'hello world';
+ const truncatedString = truncateStringToLength(value, -2);
+ expect(truncatedString).toBe(value);
+});
+
+test('truncateStringToLength with length greater than the length of value', () => {
+ const value = 'hello world';
+ const truncatedString = truncateStringToLength(value, value.length * 2);
+ expect(truncatedString).toBe(value);
+});
+
+test('truncateStringToLength with length same as the length of value', () => {
+ const value = 'hello world';
+ const truncatedString = truncateStringToLength(value, value.length);
+ expect(truncatedString).toBe(value);
+});
+
+test('truncateStringToLength with length less than the length of value', () => {
+ const value = 'hello world';
+ const truncatedString = truncateStringToLength(value, value.length / 2);
+ expect(truncatedString).toBe(`${value.slice(0, value.length / 2)}...`);
+});