Skip to content
Merged
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
116 changes: 116 additions & 0 deletions src/05-queue-deque/__test__/deque-js.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { describe, expect, test, beforeEach } from '@jest/globals';

// eslint-disable-next-line @typescript-eslint/no-require-imports
const Deque = require('../deque.js') as new () => {
addFront(item: any): void;
addRear(item: any): void;
removeFront(): any;
removeRear(): any;
peekFront(): any;
peekRear(): any;
isEmpty(): boolean;
size: number;
clear(): void;
toString(): string;
};

describe('Deque (deque.js)', () => {
let deque: InstanceType<typeof Deque>;

beforeEach(() => {
deque = new Deque();
});

test('should add an element to the front of the deque', () => {
deque.addFront(1);
deque.addFront(2);
expect(deque.toString()).toBe('2, 1');
});

test('should add an element to the rear of the deque', () => {
deque.addRear(1);
deque.addRear(2);
expect(deque.toString()).toBe('1, 2');
});

test('should remove an element from the front of the deque', () => {
deque.addFront(1);
deque.addFront(2);
expect(deque.removeFront()).toBe(2);
expect(deque.toString()).toBe('1');
});

test('should return undefined when removing from the front of an empty deque', () => {
expect(deque.removeFront()).toBeUndefined();
});

test('should remove an element from the rear of the deque', () => {
deque.addRear(1);
deque.addRear(2);
expect(deque.removeRear()).toBe(2);
expect(deque.toString()).toBe('1');
});

test('should return undefined when removing from the rear of an empty deque', () => {
expect(deque.removeRear()).toBeUndefined();
});

test('should return the front element of the deque', () => {
deque.addFront(1);
deque.addFront(2);
expect(deque.peekFront()).toBe(2);
});

test('should return undefined when peeking the front of an empty deque', () => {
expect(deque.peekFront()).toBeUndefined();
});

test('should return the rear element of the deque', () => {
deque.addRear(1);
deque.addRear(2);
expect(deque.peekRear()).toBe(2);
});

test('should return undefined when peeking the rear of an empty deque', () => {
expect(deque.peekRear()).toBeUndefined();
});

test('should return true if the deque is empty', () => {
expect(deque.isEmpty()).toBe(true);
});

test('should return false if the deque is not empty', () => {
deque.addFront(1);
expect(deque.isEmpty()).toBe(false);
});

test('should return the size of the deque', () => {
deque.addFront(1);
deque.addFront(2);
expect(deque.size).toBe(2);
});

test('should clear the deque', () => {
deque.addFront(1);
deque.addFront(2);
deque.clear();
expect(deque.isEmpty()).toBe(true);
expect(deque.size).toBe(0);
});

test('should convert an empty deque to string', () => {
expect(deque.toString()).toBe('Empty Deque');
});

test('should convert the deque to a string with primitive values', () => {
deque.addRear(1);
deque.addRear('two');
expect(deque.toString()).toBe('1, two');
});

test('should convert the deque to a string with objects', () => {
deque.addFront({ key: 'a', value: 1 });
deque.addFront({ key: 'b', value: 2 });
expect(deque.toString()).toBe('{"key":"b","value":2}, {"key":"a","value":1}');
});
});
185 changes: 185 additions & 0 deletions src/06-linked-list/__test__/linked-list_.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import { describe, expect, test, beforeEach } from '@jest/globals';

// eslint-disable-next-line @typescript-eslint/no-require-imports
const LinkedList = require('../linked-list_') as new () => {
append(data: any): void;
prepend(data: any): void;
insert(data: any, position: number): boolean;
removeAt(position: number): any;
remove(data: any, compareFunction?: (a: any, b: any) => boolean): any;
indexOf(data: any, compareFunction?: (a: any, b: any) => boolean): number;
isEmpty(): boolean;
clear(): void;
size: number;
forEach(callback: (data: any, index: number) => void): void;
toString(): string;
reverse(): void;
};

describe('LinkedList (linked-list_.js)', () => {
let linkedList: InstanceType<typeof LinkedList>;

beforeEach(() => {
linkedList = new LinkedList();
});

test('should create an empty linked list', () => {
expect(linkedList.toString()).toBe('');
expect(linkedList.isEmpty()).toBe(true);
expect(linkedList.size).toBe(0);
});

test('should append nodes to the linked list', () => {
linkedList.append(1);
linkedList.append(2);
linkedList.append(3);
expect(linkedList.toString()).toBe('1, 2, 3');
expect(linkedList.size).toBe(3);
});

test('should prepend nodes to the linked list', () => {
linkedList.prepend(2);
expect(linkedList.toString()).toBe('2');
linkedList.append(1);
linkedList.prepend(3);
expect(linkedList.toString()).toBe('3, 2, 1');
});

test('should insert a node at position 0', () => {
linkedList.append(1);
expect(linkedList.insert(2, 0)).toBe(true);
expect(linkedList.toString()).toBe('2, 1');
});

test('should insert a node at a given middle position', () => {
linkedList.append(1);
linkedList.append(3);
expect(linkedList.insert(2, 1)).toBe(true);
expect(linkedList.toString()).toBe('1, 2, 3');
});

test('should return false when inserting at an invalid position', () => {
linkedList.append(1);
linkedList.append(3);
expect(linkedList.insert(2, 5)).toBe(false);
expect(linkedList.insert(2, -1)).toBe(false);
expect(linkedList.toString()).toBe('1, 3');
});

test('should remove a node from the head', () => {
linkedList.append(1);
linkedList.append(2);
expect(linkedList.removeAt(0)).toBe(1);
expect(linkedList.toString()).toBe('2');
});

test('should remove a node from the middle', () => {
linkedList.append(1);
linkedList.append(2);
linkedList.append(3);
expect(linkedList.removeAt(1)).toBe(2);
expect(linkedList.toString()).toBe('1, 3');
});

test('should remove a node from the end', () => {
linkedList.append(1);
linkedList.append(2);
linkedList.append(3);
expect(linkedList.removeAt(2)).toBe(3);
expect(linkedList.toString()).toBe('1, 2');
});

test('should throw when removing from an empty list', () => {
expect(() => linkedList.removeAt(0)).toThrow('Cannot remove from an empty list.');
});

test('should throw when removing at an invalid position', () => {
linkedList.append(1);
expect(() => linkedList.removeAt(5)).toThrow('Invalid position');
expect(() => linkedList.removeAt(-1)).toThrow('Invalid position');
});

test('should remove an element by value', () => {
linkedList.append(1);
linkedList.append(2);
linkedList.append(3);
expect(linkedList.remove(2)).toBe(2);
expect(linkedList.toString()).toBe('1, 3');
});

test('should return null when removing a value that is not found', () => {
linkedList.append(1);
linkedList.append(2);
expect(linkedList.remove(3)).toBeNull();
});

test('should remove using a custom compare function', () => {
linkedList.append({ id: 1 });
linkedList.append({ id: 2 });
const removed = linkedList.remove({ id: 2 }, (a: any, b: any) => a.id === b.id);
expect(removed).toEqual({ id: 2 });
expect(linkedList.size).toBe(1);
});

test('should find the index of an element', () => {
linkedList.append(1);
linkedList.append(2);
linkedList.append(3);
expect(linkedList.indexOf(1)).toBe(0);
expect(linkedList.indexOf(2)).toBe(1);
expect(linkedList.indexOf(3)).toBe(2);
});

test('should return -1 when the element is not found', () => {
linkedList.append(1);
expect(linkedList.indexOf(2)).toBe(-1);
});

test('should report whether the list is empty', () => {
expect(linkedList.isEmpty()).toBe(true);
linkedList.append(1);
expect(linkedList.isEmpty()).toBe(false);
});

test('should clear the list', () => {
linkedList.append(1);
linkedList.append(2);
linkedList.clear();
expect(linkedList.isEmpty()).toBe(true);
expect(linkedList.size).toBe(0);
expect(linkedList.toString()).toBe('');
});

test('should iterate all elements with forEach', () => {
linkedList.append(1);
linkedList.append(2);
linkedList.append(3);
const seen: Array<[any, number]> = [];
linkedList.forEach((data: any, index: number) => seen.push([data, index]));
expect(seen).toEqual([[1, 0], [2, 1], [3, 2]]);
});

test('should convert objects to string using JSON.stringify', () => {
linkedList.append({ key: 'key1', value: 1 });
expect(linkedList.toString()).toBe('{"key":"key1","value":1}');
});

test('should reverse the linked list', () => {
linkedList.append(1);
linkedList.append(2);
linkedList.append(3);
linkedList.reverse();
expect(linkedList.toString()).toBe('3, 2, 1');
});

test('should reverse a single-element list without error', () => {
linkedList.append(1);
linkedList.reverse();
expect(linkedList.toString()).toBe('1');
});

test('should reverse an empty list without error', () => {
linkedList.reverse();
expect(linkedList.toString()).toBe('');
});
});
Loading
Loading