ds-algo-study
Version:
Just experimenting with publishing a package
751 lines (584 loc) • 17.7 kB
JavaScript
'use strict'
var test = require('tape')
var LinkedList = require('.')
var own = {}.hasOwnProperty
var Item = LinkedList.Item
test('LinkedList [LinkedList]', function(t) {
t.test('@constructor', function(st) {
st.equal(typeof LinkedList.Item, 'function', 'should have an `Item` method')
st.equal(typeof LinkedList.of, 'function', 'should have an `of` method')
st.equal(typeof LinkedList.from, 'function', 'should have a `from` method')
st.end()
})
t.test('of [LinkedList.of]', function(st) {
function C() {}
C.prototype.append = LinkedList.prototype.append
C.of = LinkedList.of
st.ok(
LinkedList.of() instanceof LinkedList,
'should return an instance of self when *no* arguments are given'
)
st.notOk(
own.call(LinkedList.of(null), 'head'),
'should ignore `null` values'
)
st.notOk(
own.call(LinkedList.of(undefined), 'head'),
'should ignore `undefined` values'
)
st.ok(
LinkedList.of(new Item()) instanceof LinkedList,
'should return an instance of self when arguments are given (1)'
)
st.ok(
C.of(new Item()) instanceof C,
'should return an instance of self when arguments are given (2)'
)
st.throws(function() {
LinkedList.of({})
}, 'should throw an error when an invalid item is given')
st.test(
'should add ("append") items in the order they were given',
function(sst) {
var item = new Item()
var item1 = new Item()
var item2 = new Item()
var list = LinkedList.of(item, item1, item2)
sst.equal(list.head, item)
sst.equal(list.head.next, item1)
sst.equal(list.head.next.next, item2)
sst.equal(list.tail, item2)
sst.equal(list.tail.prev, item1)
sst.equal(list.tail.prev.prev, item)
sst.end()
}
)
st.end()
})
t.test('from [LinkedList.from]', function(st) {
function C() {}
C.prototype.append = LinkedList.prototype.append
C.from = LinkedList.from
st.ok(
LinkedList.from() instanceof LinkedList,
'should return an instance of self when *no* arguments are given (1)'
)
st.ok(
C.from() instanceof C,
'should return an instance of self when *no* arguments are given (2)'
)
st.notOk(
own.call(LinkedList.from([null]), 'head'),
'should ignore `null` values'
)
st.notOk(
own.call(LinkedList.from([undefined]), 'head'),
'should ignore `undefined` values'
)
st.ok(
LinkedList.from([new Item()]) instanceof LinkedList,
'should return an instance of self when items are given (1)'
)
st.ok(
C.from([new Item()]) instanceof C,
LinkedList.from([new Item()]) instanceof LinkedList,
'should return an instance of self when items are given (2)'
)
st.throws(function() {
LinkedList.from([{}])
}, 'should throw an error when an invalid item is given')
st.test(
'should add ("append") items in the order they were given',
function(sst) {
var item = new Item()
var item1 = new Item()
var item2 = new Item()
var list = LinkedList.from([item, item1, item2])
sst.equal(list.head, item)
sst.equal(list.head.next, item1)
sst.equal(list.head.next.next, item2)
sst.equal(list.tail, item2)
sst.equal(list.tail.prev, item1)
sst.equal(list.tail.prev.prev, item)
sst.end()
}
)
st.test('should add items from an array with `Symbol.iterator`', function(
sst
) {
var items = [new Item(), new Item(), new Item()]
// Remove iterator to test array branch.
items[Symbol.iterator] = undefined
var list = LinkedList.from(items)
sst.equal(list.head, items[0])
sst.equal(list.head.next, items[1])
sst.equal(list.head.next.next, items[2])
sst.equal(list.tail, items[2])
sst.equal(list.tail.prev, items[1])
sst.equal(list.tail.prev.prev, items[0])
sst.end()
})
st.end()
})
t.test('@instance', function(st) {
st.equal(
new LinkedList().head,
null,
'should have a `head` property set to `null`'
)
st.equal(
new LinkedList().tail,
null,
'should have a `tail` property set to `null`'
)
st.equal(
typeof new LinkedList().prepend,
'function',
'should have a `prepend` method'
)
st.equal(
typeof new LinkedList().append,
'function',
'should have an `append` method'
)
st.equal(
typeof new LinkedList().toArray,
'function',
'should have an `toArray` method'
)
st.test('prepend [LinkedList#prepend]', function(sst) {
var list
var item
var other
sst.equal(
new LinkedList().prepend(),
false,
'should return false when no item is given'
)
item = new Item()
sst.equal(
new LinkedList().prepend(item),
item,
'should return the given item'
)
list = new LinkedList()
sst.throws(function() {
list.prepend({})
}, 'should throw an error when an invalid item is given')
list = new LinkedList()
item = new Item()
list.prepend(item)
sst.equal(list.head, item, 'should set `@head` to the first prependee')
list = new LinkedList()
item = new Item()
list.prepend(item)
sst.equal( list.tail, null, 'shouldn'
t set `@tail`
to the first prependee ')
other = new Item()
list.prepend(other)
sst.equal(
list.head,
other,
'should set `@head` to further prependees (1)'
)
sst.equal(
list.tail,
item,
'should set `@tail` to the first prependee (1)'
)
other = new Item()
list.prepend(other)
sst.equal(
list.head,
other,
'should set `@head` to further prependedees (2)'
)
sst.equal(
list.tail,
item,
'should set `@tail` to the first prependee (2)'
)
list = new LinkedList()
other = new LinkedList()
item = new Item()
list.prepend(item)
other.prepend(item)
sst.equal(
list.head,
null,
'should detach the previous parent list of a prependee'
)
sst.equal(other.head, item, 'should attach a prependee to a new list')
sst.end()
})
st.test('append [LinkedList#append]', function(sst) {
var list
var item
var other
sst.equal(
new LinkedList().append(),
false,
'should return false when no item is given'
)
item = new Item()
sst.equal(
new LinkedList().append(item),
item,
'should return the given item'
)
list = new LinkedList()
sst.throws(function() {
list.append({})
}, 'should throw an error when an invalid item is given')
list = new LinkedList()
item = new Item()
list.append(item)
sst.equal(list.head, item, 'should set `@head` to the first appendee')
list = new LinkedList()
item = new Item()
list.append(item)
sst.equal( list.tail, null, 'shouldn'
t set `@tail`
to the first appendee ')
other = new Item()
list.append(other)
sst.equal(
list.tail,
other,
'should set `@tail` to further appendedees (1)'
)
sst.equal(list.head, item, 'should set `@head` to the first appendee (1)')
other = new Item()
list.append(other)
sst.equal(list.tail, other, 'should set `@tail` to further appendees (2)')
sst.equal(list.head, item, 'should set `@head` to the first appendee (2)')
list = new LinkedList()
other = new LinkedList()
item = new Item()
list.append(item)
other.append(item)
sst.equal(
list.head,
null,
'should detach the previous parent list of an appendee'
)
sst.equal(other.head, item, 'should attach an appendee to a new list')
sst.end()
})
st.test('toArray [LinkedList#toArray]', function(sst) {
var list
var result
sst.ok(
Array.isArray(new LinkedList(new Item()).toArray()),
'should return an array'
)
sst.ok(
Array.isArray(new LinkedList().toArray()),
'should return an array, even when ' +
'the operated on list has no items'
)
list = new LinkedList(new Item(), new Item(), new Item())
result = list.toArray()
sst.equal(result[0], list.head, 'should return a sorted array (1)')
sst.equal(result[1], list.head.next, 'should return a sorted array (2)')
sst.equal(result[2], list.tail, 'should return a sorted array (3)')
sst.end()
})
st.test('@@iterator [LinkedList#@@iterator]', function(sst) {
var list
var result
list = new LinkedList(new Item(), new Item(), new Item())
result = Array.from(list)
sst.equal(result[0], list.head, 'should return a sorted array (1)')
sst.equal(result[1], list.head.next, 'should return a sorted array (2)')
sst.equal(result[2], list.tail, 'should return a sorted array (3)')
sst.end()
})
st.end()
})
t.end()
})
test('Item [LinkedList.Item]', function(t) {
t.equal(new Item().list, null, 'should have a `list` property set to `null`')
t.equal(new Item().prev, null, 'should have a `prev` property set to `null`')
t.equal(new Item().next, null, 'should have a `next` property set to `null`')
t.equal(
typeof new Item().prepend,
'function',
'should have a `prepend` method'
)
t.equal(typeof new Item().append, 'function', 'should have a `append` method')
t.equal(typeof new Item().detach, 'function', 'should have a `detach` method')
t.test('prepend [LinkedList.Item#prepend]', function(st) {
var item = new Item()
var other = new Item()
var list
t.equal(
item.prepend(other),
false,
'should return false when the operated on instance is not attached'
)
t.equal(item.prev, null, 'should do nothing if `item` is detached (1)')
t.equal(other.next, null, 'should do nothing if `item` is detached (2)')
t.throws(function() {
item.prepend(null)
}, 'should throw an error when an invalid item is given (1)')
t.throws(function() {
item.prepend({})
}, 'should throw an error when an invalid item is given (2)')
item = new Item()
other = new Item()
new LinkedList().append(item)
t.equal(
item.prepend(other),
other,
'should return the given item when ' +
'the operated on instance is ' +
'attached'
)
item = new Item()
other = new LinkedList(item)
list = new LinkedList(new Item())
list.head.prepend(item)
t.equal(
other.head,
null,
'should detach the previous parent list of a given item'
)
t.equal(
item.list,
list,
'should attach the given item to the operated on item'
s list '
)
t.equal(
list.head,
item,
'should set the given item as the parent list'
s `head`
when the operated on item is the current `head`
'
)
t.equal(
list.tail,
list.head.next,
'should set the operated on item as the parent list'
s `tail`
when the operated on item is the current `head`
'
)
t.equal(
list.tail.prev,
item,
'should set the operated on item'
s `prev`
property to the given item '
)
t.equal(
list.head.next,
list.tail,
'should set the given item'
s `next`
property to the operated on item '
)
other = list.tail
item = new Item()
other.prepend(item)
t.equal(list.tail, other, 'should not remove the tail')
t.equal(item.next, other, 'should set `next` on the prependee')
t.equal(other.prev, item, 'should set `prev` on the context')
st.end()
})
t.test('append [LinkedList.Item#append]', function(st) {
var item = new Item()
var other = new Item()
var list
t.equal(
item.append(other),
false,
'should return false when the operated on instance is not attached'
)
t.equal(item.prev, null, 'should do nothing if `item` is detached (1)')
t.equal(other.next, null, 'should do nothing if `item` is detached (2)')
t.throws(function() {
item.append(null)
}, 'should throw an error when an invalid item is given (1)')
t.throws(function() {
item.append({})
}, 'should throw an error when an invalid item is given (2)')
item = new Item()
other = new Item()
new LinkedList().append(item)
t.equal(
item.append(other),
other,
'should return the given item when ' +
'the operated on instance is ' +
'attached'
)
item = new Item()
other = new LinkedList(item)
list = new LinkedList(new Item())
list.head.append(item)
t.equal(
other.head,
null,
'should detach the previous parent list of a given item'
)
t.equal(
item.list,
list,
'should attach the given item to the operated on item'
s list '
)
t.equal(
list.tail,
item,
'should set the given item as the parent list'
s `tail`
when the operated on item is the current `tail`
'
)
t.equal(
list.tail.prev,
list.head,
'should keep the operated on item as the parent list'
s `head`
when the operated on item is the current `head`
'
)
other = list.head
item = new Item()
other.append(item)
t.equal(list.head, other, 'should not remove the head')
t.equal(other.next, item, 'should set `next` on the context')
t.equal(item.prev, other, 'should set `prev` on the appendee')
st.end()
})
t.test('detach [LinkedList.Item#detach]', function(st) {
var item = new Item()
var list = new LinkedList()
var other
var other2
list.append(item)
st.equal(item.detach(), item, 'should return self')
st.equal(
item.detach(),
item,
'should return self, even when the item is not attached'
)
item = new Item()
other = new Item()
list = new LinkedList()
list.append(item)
list.append(other)
item.detach()
st.equal(
list.head,
other,
'should set the item'
s `next`
property to the parent list 's `head` when the item is its current `head`'
)
item = new Item()
other = new Item()
other2 = new Item()
list = new LinkedList()
list.append(item)
list.append(other)
list.append(other2)
other2.detach()
st.equal(
list.tail,
other,
'should set the item'
s `prev`
property to the parent list 's `tail` when the item is its current `tail`'
)
item = new Item()
other = new Item()
list = new LinkedList()
list.append(item)
list.append(other)
other.detach()
st.equal(
list.tail,
null,
'should set the parent list'
s `tail`
to `null`
when the item is its current `tail`
and its `prev`
property is the current `tail`
'
)
item = new Item()
other = new Item()
other2 = new Item()
list = new LinkedList()
list.append(item)
list.append(other)
list.append(other2)
other.detach()
st.equal(
item.next,
other2,
'should set the previous item'
s `next`
' +
'property to the current item'
s `next`
' +
'property'
)
item = new Item()
other = new Item()
other2 = new Item()
list = new LinkedList()
list.append(item)
list.append(other)
list.append(other2)
other.detach()
st.equal(
other2.prev,
item,
'should set the next item'
s `prev`
property to ' +
'the current item'
s `prev`
property '
)
item = new Item()
list = new LinkedList()
list.append(item)
item.detach()
st.equal( item.list, null, 'should set the item'
s `list`
property to `null`
')
item = new Item()
other = new Item()
list = new LinkedList()
list.append(other)
list.append(item)
item.detach()
st.equal( item.prev, null, 'should set the item'
s `prev`
property to `null`
')
item = new Item()
other = new Item()
list = new LinkedList()
list.append(item)
list.append(other)
item.detach()
st.equal( item.next, null, 'should set the item'
s `next`
property to `null`
')
st.end()
})
t.end()
})