From b0017aa7a9a235c4309f9fec74e5d826968d6b5a Mon Sep 17 00:00:00 2001 From: Jonathan Pool Date: Thu, 18 May 2017 16:21:34 -0700 Subject: [PATCH] Developed, tested, and debugged Node2 and Queue2 (Pool versions of Node and Queue). --- spec/double_node.js | 75 ++++++++++++++++++++++- spec/linkedListTest.js | 2 +- spec/node2.js | 133 +++++++++++++++++++++++++++++++++++++++++ spec/queue2.js | 66 ++++++++++++++++++++ src/node2.js | 7 ++- src/priority_node.js | 2 +- src/priority_queue.js | 4 +- src/queue2.js | 42 +++++++++++++ 8 files changed, 323 insertions(+), 8 deletions(-) create mode 100644 spec/node2.js create mode 100644 spec/queue2.js create mode 100644 src/queue2.js diff --git a/spec/double_node.js b/spec/double_node.js index 26eabe3..e8576dc 100644 --- a/spec/double_node.js +++ b/spec/double_node.js @@ -71,7 +71,6 @@ describe('DoubleNode', function() { const nbNode = new DoubleNode({data: 1, next: 0}) const dxnbNode = new DoubleNode({next: ngNode}) const ngbNode = new DoubleNode({data: 0, next: dxnbNode}) - const emptyNode = new DoubleNode() const pgNode = new DoubleNode({data: 2, next: nnNode, previous: nnNode}) const pgbNode = new DoubleNode({data: 3, next: ngNode, previous: nbNode}) const pbNode = new DoubleNode({data: 4, next: ngNode, previous: "node"}) @@ -135,4 +134,78 @@ describe('DoubleNode', function() { ) }) + context('getPrevious()', function() { + const nnNode = new DoubleNode({data: 'astring'}) + const ngNode = new DoubleNode({data: 0, next: nnNode}) + const nbNode = new DoubleNode({data: 1, next: 0}) + const dxpbNode = new DoubleNode({previous: ngNode}) + const pgNode = new DoubleNode({data: 2, next: nnNode, previous: nnNode}) + const pgbNode = new DoubleNode({data: 3, next: ngNode, previous: nbNode}) + const pbNode = new DoubleNode({data: 4, next: ngNode, previous: "node"}) + it('returns the correct type, if specified', function() { + expect(pgNode.getPrevious() instanceof DoubleNode).to.be.true + }) + it('returns a DoubleNode, if an invalid one is specified', function() { + expect(pgbNode.getPrevious() instanceof DoubleNode).to.be.true + }) + it('returns the correct value, if specified', function() { + expect(pgNode.getPrevious()).to.be.deep.equal(nnNode) + }) + it( + 'returns a DoubleNode with a retrievable property, if specified', + function() { + expect(pgNode.getPrevious().getData()).to.be.equal('astring') + } + ) + it('returns null, if unspecified', function() { + expect(nnNode.getPrevious()).to.be.null + }) + it('returns null, if specified but not a DoubleNode', function() { + expect(pbNode.getPrevious()).to.be.null + }) + it('returns null, if specified but data is unspecified', function() { + expect(dxpbNode.getPrevious()).to.be.null + }) + }) + + context('setPrevious()', function() { + const nnNode = new DoubleNode({data: 0}) + const ngNode = new DoubleNode({data: 'astring', next: nnNode}) + const nbNode = new DoubleNode({data: 1, next: "nonode"}) + const pbNode = new DoubleNode({data: 2, next: ngNode, previous: "bad"}) + it('returns a DoubleNode', function() { + expect(nnNode.setPrevious(ngNode) instanceof DoubleNode).to.be.true + }) + it('returns the correct DoubleNode', function() { + expect(nnNode.setPrevious(ngNode)).to.be.deep.equal(nnNode) + }) + it( + 'returns a DoubleNode with a retrievable data property', + function() { + expect(ngNode.setPrevious(nnNode).getData()).to.be.equal('astring') + } + ) + it( + 'returns a DoubleNode with a retrievable good new previous property', + function() { + expect(nnNode.setPrevious(nnNode).getPrevious()) + .to.be.deep.equal(nnNode) + } + ) + it( + 'returns a DoubleNode with a retrievable bad new next property', + function() { + expect(nnNode.setPrevious(nbNode).getPrevious()) + .to.be.deep.equal(nbNode) + } + ) + it( + 'fails to change previous (from last value), if newPrevious is invalid', + function() { + expect(nnNode.setPrevious("badNode").getPrevious()) + .to.be.deep.equal(nbNode) + } + ) + }) + }) diff --git a/spec/linkedListTest.js b/spec/linkedListTest.js index 994efa2..f80eff5 100644 --- a/spec/linkedListTest.js +++ b/spec/linkedListTest.js @@ -5,7 +5,7 @@ import LinkedList from '../src/linkedList' chai.use(chaiChange) -describe.only('LinkedList', () => { +describe('LinkedList', () => { 'use strict' const list = new LinkedList() list.insert( {data: 'apple'} ) diff --git a/spec/node2.js b/spec/node2.js new file mode 100644 index 0000000..3497d57 --- /dev/null +++ b/spec/node2.js @@ -0,0 +1,133 @@ +import chai, { expect } from 'chai' +import chaiChange from 'chai-change' +import Node from '../src/node2' + +chai.use(chaiChange) + +describe('Node2', function() { + 'use strict' + + it('is a function', function() { + expect(Node).to.be.a('function') + }) + + context('getData()', function() { + const dsNode = new Node({data: 'string'}) + const dnNode = new Node({data: 0}) + const daNode = new Node({data: [1, 2]}) + const doNode = new Node({data: {'a': 1, 'b': 2}}) + const emptyNode = new Node() + const ngNode = new Node({data: 1, next: dsNode}) + const nbNode = new Node({data: 2, next: "dnNode"}) + const ngbNode = new Node({data: 3, next: nbNode}) + it('returns the correct type, if a string', function() { + expect(dsNode.getData()).to.be.a('string') + }) + it('returns the correct value, if a string', function() { + expect(dsNode.getData()).to.be.equal('string') + }) + it('returns the correct type, if a number', function() { + expect(dnNode.getData()).to.be.a('number') + }) + it('returns the correct value, if a number', function() { + expect(dnNode.getData()).to.be.equal(0) + }) + it('returns the correct type, if an array', function() { + expect(Array.isArray(daNode.getData())).to.be.true + }) + it('returns the correct value, if an array', function() { + expect(daNode.getData()).to.be.deep.equal([1, 2]) + }) + it('returns the correct type, if an object', function() { + expect(doNode.getData()).to.be.an('object') + }) + it('returns the correct value, if an object', function() { + expect(doNode.getData()).to.be.deep.equal({'a': 1, 'b': 2}) + }) + it('returns an object with a retrievable property, if an object', function() { + expect(doNode.getData().a).to.be.equal(1) + }) + it('returns the correct value, if next is specified', function() { + expect(ngNode.getData()).to.be.equal(1) + }) + it('returns the correct value, if next is a bad Node', function() { + expect(ngbNode.getData()).to.be.equal(3) + }) + it('returns undefined, if unspecified', function() { + expect(emptyNode.getData()).to.be.undefined + }) + it('returns undefined, if next is not a Node', function() { + expect(nbNode.getData()).to.be.undefined + }) + }) + + context('getNext()', function() { + const nnNode = new Node({data: 'string'}) + const ngNode = new Node({data: 0, next: nnNode}) + const nbNode = new Node({data: 1, next: 0}) + const dxnbNode = new Node({next: ngNode}) + const ngbNode = new Node({data: 0, next: dxnbNode}) + const emptyNode = new Node() + it('returns the correct type, if specified', function() { + expect(ngNode.getNext() instanceof Node).to.be.true + }) + it('returns the correct value, if specified', function() { + expect(ngNode.getNext()).to.be.deep.equal(nnNode) + }) + it( + 'returns a Node with a retrievable property, if specified', + function() { + expect(ngNode.getNext().getData()).to.be.equal('string') + } + ) + it('returns null, if unspecified', function() { + expect(nnNode.getNext()).to.be.null + }) + it('returns null, if specified but not a Node', function() { + expect(nbNode.getNext()).to.be.null + }) + it('returns null, if specified but data is unspecified', function() { + expect(dxnbNode.getNext()).to.be.null + }) + it('returns null, if data unspecified', function() { + expect(emptyNode.getNext()).to.be.null + }) + }) + + context('setNext()', function() { + const nnNode = new Node({data: 0}) + const ngNode = new Node({data: 'astring', next: nnNode}) + const nbNode = new Node({data: 1, next: "nonode"}) + it('returns a Node', function() { + expect(nnNode.setNext(ngNode) instanceof Node).to.be.true + }) + it('returns the correct Node', function() { + expect(nnNode.setNext(ngNode)).to.be.deep.equal(nnNode) + }) + it( + 'returns a Node with a retrievable data property', + function() { + expect(ngNode.setNext(nnNode).getData()).to.be.equal('astring') + } + ) + it( + 'returns a Node with a retrievable good new next property', + function() { + expect(nnNode.setNext(ngNode).getNext()).to.be.deep.equal(ngNode) + } + ) + it( + 'returns a Node with a retrievable bad new next property', + function() { + expect(nnNode.setNext(nbNode).getNext()).to.be.deep.equal(nbNode) + } + ) + it( + 'fails to change next (from last value), if newNext is invalid', + function() { + expect(nnNode.setNext("badNode").getNext()).to.be.deep.equal(nbNode) + } + ) + }) + +}) diff --git a/spec/queue2.js b/spec/queue2.js new file mode 100644 index 0000000..9046f2f --- /dev/null +++ b/spec/queue2.js @@ -0,0 +1,66 @@ +import chai, { expect } from 'chai' +import chaiChange from 'chai-change' +import Queue from '../src/queue2' + +chai.use(chaiChange) + +describe('Queue2', function() { + 'use strict' + + it('is a function', function() { + expect(Queue).to.be.a('function') + }) + + context('empty queue', function() { + const emptyQueue = new Queue() + it('front() returns null', function() { + expect(emptyQueue.front()).to.be.null + }) + it('back() returns null', function() { + expect(emptyQueue.back()).to.be.null + }) + it('isEmpty() returns true', function() { + expect(emptyQueue.isEmpty()).to.be.true + }) + it('length() returns 0', function() { + expect(emptyQueue.length()).to.be.equal(0) + }) + it('dequeue() returns null', function() { + expect(emptyQueue.dequeue()).to.be.null + }) + }) + + context('non-empty queue', function() { + const sQueue = new Queue() + sQueue.enqueue('bad') + sQueue.enqueue('ok') + sQueue.enqueue('good') + it('the element back() returns is “good”', function() { + expect(sQueue.back().getData()).to.be.equal('good') + }) + it('the element front() returns is “bad”', function() { + expect(sQueue.front().getData()).to.be.equal('bad') + }) + it('isEmpty() returns false', function() { + expect(sQueue.isEmpty()).to.be.false + }) + it('length() returns 3', function() { + expect(sQueue.length()).to.be.equal(3) + }) + it('the element dequeue() returns is “bad”', function() { + expect(sQueue.dequeue().getData()).to.be.equal('bad') + }) + it('the length is 2 after 1 dequeuing', function() { + expect(sQueue.length()).to.be.equal(2) + }) + it('the length is 3 after a valid enqueuing', function() { + sQueue.enqueue('excellent') + expect(sQueue.length()).to.be.equal(3) + }) + it('the length stays 3 after an invalid enqueuing', function() { + sQueue.enqueue() + expect(sQueue.length()).to.be.equal(3) + }) + }) + +}) diff --git a/src/node2.js b/src/node2.js index e5d4f2c..5855eae 100644 --- a/src/node2.js +++ b/src/node2.js @@ -8,14 +8,15 @@ export default class Node { constructor(nodeProps) { // If the argument is valid: if ( - nodeProps.data !== undefined + nodeProps !== undefined + && nodeProps.data !== undefined && ( nodeProps.next === undefined || nodeProps.next instanceof Node ) ) { this.data = nodeProps.data; - this.next = nodeProps.next; + this.next = nodeProps.next || null; } } // Returns the node’s data. @@ -28,7 +29,7 @@ export default class Node { } // Changes the next node, if specified, and returns this node. setNext(newNext) { - if (newNext instanceof PriorityNode) { + if (newNext instanceof Node) { this.next = newNext; } return this; diff --git a/src/priority_node.js b/src/priority_node.js index a7fc004..c22a6e0 100644 --- a/src/priority_node.js +++ b/src/priority_node.js @@ -20,7 +20,7 @@ export default class PriorityNode { ) { this.data = nodeProps.data; this.priority = nodeProps.priority || 0; - this.next = nodeProps.next; + this.next = nodeProps.next || null; } } // Returns the node’s data. diff --git a/src/priority_queue.js b/src/priority_queue.js index 21fe40b..37c97fe 100644 --- a/src/priority_queue.js +++ b/src/priority_queue.js @@ -39,11 +39,11 @@ export default class PriorityQueue { isEmpty() { return this.queue.length === 0; } - // Changes the next node, if specified, and returns this node. + // Returns the count of elements. length() { return this.queue.length; } - // Adds a specified element to the queue. + // Removes and returns a specified element from the queue. dequeue() { return this.queue.pop() || null; } diff --git a/src/queue2.js b/src/queue2.js new file mode 100644 index 0000000..95d451e --- /dev/null +++ b/src/queue2.js @@ -0,0 +1,42 @@ +'use strict'; +import Node from './node2'; + +/* + Class declaration for Queue and export statement making that object the + default export from this module. +*/ +export default class Queue { + constructor() { + this.queue = []; + } + // Adds a specified element to the back of the queue. + enqueue(d) { + const newNode = new Node({data: d}); + if (newNode.data !== undefined) { + this.queue.push(newNode); + } + } + /* + Removes and returns the front element from the queue. Returns null if + the queue is empty. + */ + dequeue() { + return this.queue.shift() || null; + } + // Returns the front node. + front() { + return this.queue[0] || null; + } + // Returns the back node. + back() { + return this.queue[this.queue.length - 1] || null; + } + // Returns whether the queue is empty. + isEmpty() { + return this.queue.length === 0; + } + // Returns the count of elements. + length() { + return this.queue.length; + } +}