Files
asciidisco.com/build/node_modules/dbly-linked-list/test/list.spec.js
2023-08-01 13:49:46 +02:00

401 lines
14 KiB
JavaScript

/* globals describe it beforeEach afterEach */
var should = require('should');
var LinkedList = require('../');
describe('Linked List', function() {
var list = null;
// Utility function to populate the list with dummy data.
// The number of nodes added will be specified by the 'numNodes'
// parameter.
var populateList = function (aList, numNodes) {
for (var i = 0; i < numNodes; i++) {
aList.insert('test item ' + (i + 1));
}
};
beforeEach(function() {
list = new LinkedList();
});
afterEach(function() {
list = null;
});
it('should have a working test environment', function() {
true.should.equal(true);
});
it('should initially contain zero items', function() {
list.isEmpty().should.equal(true);
list.getSize().should.equal(0);
});
it('should clear the list and set head and tail to null', function () {
populateList(list, 10);
list.getSize().should.equal(10);
list.clear();
list.getSize().should.equal(0);
should.not.exist(list.getHeadNode());
should.not.exist(list.getTailNode());
});
it('should return an array of all the data in the list', function() {
list.insert({
id: 1,
name: 'test item 1'
});
list.insert({
id: 2,
name: 'test item 2'
});
list.insert({
id: 3,
name: 'test item 3'
});
var listArray = list.toArray();
listArray.should.be.an.Array;
listArray.should.have.length(3);
});
describe('iterator functionality', function() {
it('should exist when a list is instantiated', function() {
list.iterator.should.be.ok;
});
it('should have iterator currentNode be null when first instantiated',
function() {
should.not.exist(list.iterator.next());
});
it('should return the tail node when iterator.last() is called', function() {
populateList(list, 10);
var last = list.iterator.last();
last.should.equal(list.getTailNode());
})
it('should return the head node when iterator.first() is called',
function() {
populateList(list, 10);
var first = list.iterator.first();
first.should.equal(list.getHeadNode());
});
it('should return correct boolean value for hasNext()', function() {
populateList(list, 3);
list.iterator.reset();
list.iterator.hasNext().should.equal(true);
// get first element
list.iterator.next();
list.iterator.hasNext().should.equal(true);
// get second element
list.iterator.next();
list.iterator.hasNext().should.equal(true);
// get third element
list.iterator.next();
// should be no more element in list
list.iterator.hasNext().should.equal(false);
});
it('should return correct boolean value for hasNext() in reverse order', function() {
populateList(list, 3);
list.iterator.reset_reverse();
list.iterator.hasNext().should.equal(true);
list.iterator.next_reverse();
list.iterator.hasNext().should.equal(true);
list.iterator.next_reverse();
list.iterator.hasNext().should.equal(true);
list.iterator.next_reverse();
list.iterator.hasNext().should.equal(false);
});
it('should go through elements from head to tail when calling iterator.each()', function() {
populateList(list, 3);
var array = [];
//expected result
var expectedArray = ["test item 1", "test item 2", "test item 3"];
var dummyCallback = function(node) {
array.push(node.getData());
}
list.iterator.reset()
list.iterator.each(dummyCallback);
array.should.be.eql(expectedArray);
});
it('should go through elements from tail to head when calling iterator.each_reverse()', function() {
populateList(list, 3);
var array = [];
var expectedArray = ["test item 3", "test item 2", "test item 1"];
var dummyCallback = function(node) {
array.push(node.getData());
};
list.iterator.reset_reverse();
list.iterator.each_reverse(dummyCallback);
array.should.be.eql(expectedArray);
});
it('should stop in the middle of iteration if iterator.interrupt() is called', function() {
populateList(list, 5);
var count = 0;
var dummyCallback = function() {
count += 1;
if (count === 3) {
list.iterator.interrupt();
}
};
// head to tail
list.iterator.reset();
list.iterator.each(dummyCallback);
count.should.be.equal(3);
// tail to head
count = 0;
list.iterator.reset_reverse();
list.iterator.each_reverse(dummyCallback);
count.should.be.equal(3);
})
});
describe('insert functionality', function() {
it('should set the head node equal to the tail node when first item ' +
'is inserted', function() {
list.insert('test item 1');
list.getHeadNode().should.equal(list.getTailNode());
list.getSize().should.equal(1);
});
it('should insert items to the back of the list', function() {
populateList(list, 5);
list.isEmpty().should.equal(false);
list.getSize().should.equal(5);
var tail = list.getTailNode();
tail.getData().should.equal('test item 5');
});
it('should insert items to the front of the list', function() {
list.insert('test item 1');
list.insert('test item 2');
list.insertFirst('new item 0');
list.getHeadNode().data.should.equal('new item 0');
list.getHeadNode().hasPrev().should.equal(false);
list.getSize().should.equal(3);
});
it('should insert item at a particular index', function() {
populateList(list, 3);
list.insert('test item 5');
list.getSize().should.equal(4);
var success = list.insertAt(3, 'test item 4');
success.should.equal(true);
list.getSize().should.equal(5);
var node = list.findAt(3);
node.getData().should.equal('test item 4');
});
it('should insert new head node when inserting at index 0', function() {
populateList(list, 3);
list.getSize().should.equal(3);
var success = list.insertAt(0, 'test item 0');
success.should.equal(true);
list.getSize().should.equal(4);
var node = list.getHeadNode();
node.getData().should.equal('test item 0');
});
it('should return false when trying to insert at index out of bounds', function() {
populateList(list, 3);
var success = list.insertAt(5, 'test item 4');
success.should.equal(false);
});
it('should insert item before a particular node', function () {
populateList(list, 3);
list.insert('test item 5');
list.getSize().should.equal(4);
list.insertBefore('test item 5', 'test item 4');
list.getSize().should.equal(5);
var node = list.findAt(3);
node.getData().should.equal('test item 4');
// test for inserting before the head node
list.insertBefore('test item 1', 'test item 0');
list.getSize().should.equal(6);
node = list.getHeadNode();
node.getData().should.equal('test item 0');
});
it('should insert item after a particular node', function () {
populateList(list, 3);
list.insert('test item 5');
list.getSize().should.equal(4);
list.insertAfter('test item 3', 'test item 4');
list.getSize().should.equal(5);
var node = list.findAt(3);
node.getData().should.equal('test item 4');
// test for inserting after the tail node
list.insertAfter('test item 5', 'test item 6');
list.getSize().should.equal(6);
node = list.getTailNode();
node.getData().should.equal('test item 6');
});
});
describe('remove functionality', function() {
it('should return null if remove is called on an empty list',
function() {
var node = list.remove();
should.not.exist(node);
});
it('should remove items from the back of the list', function() {
populateList(list, 3);
list.isEmpty().should.equal(false);
list.getSize().should.equal(3);
var node = list.remove();
node.getData().should.equal('test item 3');
list.getSize().should.equal(2);
var last = list.getTailNode();
last.getData().should.equal('test item 2');
last.hasNext().should.equal(false);
});
it('should return null if removeFirst is called on an empty list',
function() {
var node = list.removeFirst();
should.not.exist(node);
});
it('should remove items from the front of the list', function() {
populateList(list, 3);
list.isEmpty().should.equal(false);
list.getSize().should.equal(3);
var node = list.removeFirst();
node.getData().should.equal('test item 1');
list.getSize().should.equal(2);
var first = list.getHeadNode();
first.getData().should.equal('test item 2');
first.hasPrev().should.equal(false);
});
it('should remove item from the front of a list with only one node', function () {
list.insert('test item 1');
var node = list.removeFirst();
node.getData().should.equal('test item 1');
list.getSize().should.equal(0);
});
it('should remove item at a particulary index', function() {
populateList(list, 4);
list.getSize().should.equal(4);
var node = list.removeAt(1);
node.getData().should.equal('test item 2');
list.getSize().should.equal(3);
});
it('should remove a node with given data', function() {
populateList(list, 4);
list.getSize().should.equal(4);
var node = list.removeNode('test item 3');
node.getData().should.equal('test item 3');
list.getSize().should.equal(3);
});
});
describe('find functionality', function() {
it('should find a node with the data provided', function() {
populateList(list, 3);
var node = list.find('test item 2');
node.should.be.an.Object;
node.getData().should.equal('test item 2');
});
it('should find a node with a complex obj', function () {
list.insert({key: 'key', value: 'value123'});
var node = list.find({key: 'key', value: 'value123'});
node.getData().should.be.an.Object;
node.getData().should.have.properties(['key', 'value']);
});
it('should return -1 if a node does not exist with the given data',
function() {
populateList(list, 3);
var node = list.find('not found...');
node.should.not.be.an.Object;
node.should.equal(-1);
});
it('should return -1 if find() is called on an empty list',
function() {
var node = list.find('not found...');
node.should.not.be.an.Object;
node.should.equal(-1);
});
it('should return the index of node containing the provided data',
function() {
populateList(list, 3);
var index = list.indexOf('test item 1');
index.should.equal(0);
index = list.indexOf('test item 2');
index.should.equal(1);
index = list.indexOf('test item 3');
index.should.equal(2);
});
it('should return -1 for the index of node with the given data if the' +
'node does not exist',
function() {
populateList(list, 3);
var index = list.indexOf('not found');
index.should.equal(-1);
});
it('should return node at given index', function() {
list.insert('test item 1');
list.insert('test item 2');
var node = list.findAt(0);
node.should.be.an.Object;
node.getData().should.equal('test item 1');
node = list.findAt(1);
node.should.be.an.Object;
node.getData().should.equal('test item 2');
});
it('should return -1 when findAt() is called w/ index > than list size',
function() {
var node = list.findAt(0);
node.should.not.be.an.Object;
node.should.equal(-1);
});
it('should return true if list contains specified data,' +
'false otherwise',
function () {
populateList(list, 3);
var result = list.contains('test item 2');
result.should.equal(true);
result = list.contains('not found');
result.should.equal(false);
});
});
});