UNPKG

base-test-suite

Version:
665 lines (574 loc) 24.3 kB
'use strict'; var path = require('path'); var assert = require('assert'); module.exports = function(App, options, runner) { var app; var get = require('get-value'); var each = require('async-each'); var typeOf = require('kind-of'); var support = require('./support/'); var isBuffer = require('is-buffer'); assert.containEql = support.containEql; var List = App.List; var Views = App.Views; var list, views; describe('list', function() { describe('constructor', function() { it('should create an instance of List', function() { var list = new List(); assert(list instanceof List); }); }); describe('static methods', function() { it('should expose `extend`', function() { assert.equal(typeof List.extend, 'function'); }); }); describe('prototype methods', function() { beforeEach(function() { list = new List(); }); var methods = [ 'use', 'setItem', 'addItem', 'addItems', 'addList', 'getItem', 'constructor', 'set', 'get', 'del', 'define', 'visit', 'on', 'once', 'off', 'emit', 'listeners', 'hasListeners' ]; methods.forEach(function(method) { it('should expose the ' + method + ' method', function() { assert.equal(typeof list[method], 'function'); }); }); it('should expose the isList property', function() { assert.equal(typeof list.isList, 'boolean'); }); it('should expose the keys property', function() { assert(Array.isArray(list.keys)); }); it('should expose the items property', function() { assert(Array.isArray(list.items)); }); it('should expose the options property', function() { assert.equal(typeOf(list.options), 'object'); }); }); describe('instance', function() { beforeEach(function() { list = new List(); }); it('should set a value on the instance', function() { list.set('a', 'b'); assert.equal(list.a, 'b'); }); it('should get a value from the instance', function() { list.set('a', 'b'); assert.equal(list.get('a'), 'b'); }); }); describe('use', function() { beforeEach(function() { list = new List(); }); it('should expose the instance to plugins', function() { list .use(function(inst) { inst.foo = 'bar'; }); assert.equal(list.foo, 'bar'); }); it('should expose `item` when the plugin returns a function', function() { list .use(function() { return function(item) { item.foo = 'bar'; }; }); list.addItem('aaa'); list.addItem('bbb'); list.addItem('ccc'); assert.equal(list.items[0].foo, 'bar'); assert.equal(list.items[1].foo, 'bar'); assert.equal(list.items[2].foo, 'bar'); }); }); describe('addItem', function() { beforeEach(function() { list = new List(); }); it('should add items to a list', function() { list.addItem('a', {content: '...'}); list.addItem('b', {content: '...'}); list.addItem('c', {content: '...'}); assert.equal(list.items.length, 3); }); }); describe('deleteItem', function() { beforeEach(function() { list = new List(); }); it('should remove an item from `items`', function() { list.addItem('a', {content: '...'}); list.addItem('b', {content: '...'}); list.addItem('c', {content: '...'}); assert.equal(list.items.length, 3); var a = list.getItem('a'); list.deleteItem(a); assert.equal(list.items.length, 2); var c = list.getItem('c'); list.deleteItem(c); assert.equal(list.items[0].key, 'b'); }); it('should remove an item from `items` by key', function() { list.addItem('a', {content: '...'}); list.addItem('b', {content: '...'}); list.addItem('c', {content: '...'}); assert.equal(list.items.length, 3); list.deleteItem('c'); assert.equal(list.items.length, 2); list.deleteItem('b'); assert.equal(list.items[0].key, 'a'); }); }); describe('addItems', function() { beforeEach(function() { list = new List(); }); it('should add an object with multiple items', function() { list.addItems({ one: {content: 'foo'}, two: {content: 'bar'} }); assert(isBuffer(list.items[0].contents)); assert(isBuffer(list.items[1].contents)); }); it('should signal `loaded` when finished (addItems)', function() { list.on('addItems', function(items) { for (var key in items) { if (key === 'c') { list.loaded = true; break; } list.addItem('foo/' + key, items[key]); } }); list.addItems({ a: {path: 'a.txt'}, b: {path: 'b.txt'}, c: {path: 'c.txt'} }); assert.equal(list.items.length, 2); assert.equal(list.items[0].key, 'foo/a'); assert.equal(list.items[0].path, 'a.txt'); }); }); describe('addList', function() { beforeEach(function() { list = new List(); }); it('should add an array with multiple items', function() { list.addList([ {path: 'one', content: 'foo'}, {path: 'two', content: 'bar'} ]); assert(isBuffer(list.items[0].contents)); assert(isBuffer(list.items[1].contents)); }); it('should take a callback on `addList`', function() { function addContents(item) { item.contents = new Buffer(item.path.charAt(0)); } list.addList([ { path: 'a.md', locals: { date: '2014-01-01', foo: 'zzz', bar: 1 } }, { path: 'f.md', locals: { date: '2014-01-01', foo: 'mmm', bar: 2 } }, { path: 'd.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 3 } } ], addContents); assert(isBuffer(list.items[0].contents)); assert(isBuffer(list.items[1].contents)); assert(isBuffer(list.items[2].contents)); }); it('should throw an error when the list is not an array', function(cb) { function addContents(item) { item.contents = new Buffer(item.path.charAt(0)); } try { list.addList({ 'a.md': {locals: { date: '2014-01-01', foo: 'zzz', bar: 1 }}, 'f.md': {locals: { date: '2014-01-01', foo: 'mmm', bar: 2 }}, 'd.md': {locals: { date: '2014-01-01', foo: 'xxx', bar: 3 }} }, addContents); assert(isBuffer(list.items[0].contents)); assert(isBuffer(list.items[1].contents)); assert(isBuffer(list.items[2].contents)); cb(new Error('expected an error')); } catch (err) { assert.equal(err.message, 'expected list to be an array.'); cb(); } }); it('should signal `loaded` when finished (addList)', function() { list.on('addList', function(items) { var len = items.length; var i = -1; while (++i < len) { if (items[i].path === 'd.md') { list.loaded = true; break; } list.addItem('foo/' + items[i].path, items[i]); } }); list.addList([ { path: 'a.md', locals: { date: '2014-01-01', foo: 'zzz', bar: 1 } }, { path: 'f.md', locals: { date: '2014-01-01', foo: 'mmm', bar: 2 } }, { path: 'd.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 3 } } ]); assert.equal(list.items.length, 2); assert.equal(list.keys.indexOf('d.md'), -1); }); }); describe('sortBy', function() { var items = [ { path: 'a.md', locals: { date: '2014-01-01', foo: 'zzz', bar: 1 } }, { path: 'f.md', locals: { date: '2014-01-01', foo: 'mmm', bar: 2 } }, { path: 'd.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 3 } }, { path: 'i.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 5 } }, { path: 'k.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 1 } }, { path: 'j.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 4 } }, { path: 'h.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 6 } }, { path: 'l.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 7 } }, { path: 'e.md', locals: { date: '2015-01-02', foo: 'aaa', bar: 8 } }, { path: 'b.md', locals: { date: '2012-01-02', foo: 'ccc', bar: 9 } }, { path: 'f.md', locals: { date: '2014-06-01', foo: 'rrr', bar: 10 } }, { path: 'c.md', locals: { date: '2015-04-12', foo: 'ttt', bar: 11 } }, { path: 'g.md', locals: { date: '2014-02-02', foo: 'yyy', bar: 12 } } ]; it('should sort a list', function() { list = new List(); list.addList(items); var compare = function(prop) { return function(a, b, fn) { var valA = get(a, prop); var valB = get(b, prop); return fn(valA, valB); }; }; var res = list.sortBy('locals.date', 'doesnt.exist', [ compare('locals.foo'), compare('locals.bar') ]); assert.containEql(res.items, [ { key: 'b.md', locals: { date: '2012-01-02', foo: 'ccc', bar: 9 } }, { key: 'f.md', locals: { date: '2014-01-01', foo: 'mmm', bar: 2 } }, { key: 'k.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 1 } }, { key: 'd.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 3 } }, { key: 'j.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 4 } }, { key: 'i.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 5 } }, { key: 'h.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 6 } }, { key: 'l.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 7 } }, { key: 'a.md', locals: { date: '2014-01-01', foo: 'zzz', bar: 1 } }, { key: 'g.md', locals: { date: '2014-02-02', foo: 'yyy', bar: 12 } }, { key: 'f.md', locals: { date: '2014-06-01', foo: 'rrr', bar: 10 } }, { key: 'e.md', locals: { date: '2015-01-02', foo: 'aaa', bar: 8 } }, { key: 'c.md', locals: { date: '2015-04-12', foo: 'ttt', bar: 11 } } ]); }); it('should not sort the (original) instance list `items`', function() { list = new List(); list.addList(items); var compare = function(prop) { return function(a, b, fn) { var valA = get(a, prop); var valB = get(b, prop); return fn(valA, valB); }; }; var res = list.sortBy('locals.date', 'doesnt.exist', [ compare('locals.foo'), compare('locals.bar') ]); // should not be sorted assert.containEql(list.items, items); // should be sorted assert.containEql(res.items, [ { key: 'b.md', locals: { date: '2012-01-02', foo: 'ccc', bar: 9 } }, { key: 'f.md', locals: { date: '2014-01-01', foo: 'mmm', bar: 2 } }, { key: 'k.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 1 } }, { key: 'd.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 3 } }, { key: 'j.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 4 } }, { key: 'i.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 5 } }, { key: 'h.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 6 } }, { key: 'l.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 7 } }, { key: 'a.md', locals: { date: '2014-01-01', foo: 'zzz', bar: 1 } }, { key: 'g.md', locals: { date: '2014-02-02', foo: 'yyy', bar: 12 } }, { key: 'f.md', locals: { date: '2014-06-01', foo: 'rrr', bar: 10 } }, { key: 'e.md', locals: { date: '2015-01-02', foo: 'aaa', bar: 8 } }, { key: 'c.md', locals: { date: '2015-04-12', foo: 'ttt', bar: 11 } } ]); }); it('should pass options to array-sort from the constructor', function() { list = new List({sort: {reverse: true}}); list.addList(items); var compare = function(prop) { return function(a, b, fn) { var valA = get(a, prop); var valB = get(b, prop); return fn(valA, valB); }; }; var res = list.sortBy('locals.date', 'doesnt.exist', [ compare('locals.foo'), compare('locals.bar') ]); assert.containEql(res.items, [ { key: 'c.md', locals: { date: '2015-04-12', foo: 'ttt', bar: 11 } }, { key: 'e.md', locals: { date: '2015-01-02', foo: 'aaa', bar: 8 } }, { key: 'f.md', locals: { date: '2014-06-01', foo: 'rrr', bar: 10 } }, { key: 'g.md', locals: { date: '2014-02-02', foo: 'yyy', bar: 12 } }, { key: 'a.md', locals: { date: '2014-01-01', foo: 'zzz', bar: 1 } }, { key: 'l.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 7 } }, { key: 'h.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 6 } }, { key: 'i.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 5 } }, { key: 'j.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 4 } }, { key: 'd.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 3 } }, { key: 'k.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 1 } }, { key: 'f.md', locals: { date: '2014-01-01', foo: 'mmm', bar: 2 } }, { key: 'b.md', locals: { date: '2012-01-02', foo: 'ccc', bar: 9 } } ]); }); it('should pass options to array-sort from the sortBy method', function() { list = new List(); list.addList(items); var compare = function(prop) { return function(a, b, fn) { var valA = get(a, prop); var valB = get(b, prop); return fn(valA, valB); }; }; var res = list.sortBy('locals.date', 'doesnt.exist', [ compare('locals.foo'), compare('locals.bar') ], {reverse: true}); assert.containEql(res.items, [ { key: 'c.md', locals: { date: '2015-04-12', foo: 'ttt', bar: 11 } }, { key: 'e.md', locals: { date: '2015-01-02', foo: 'aaa', bar: 8 } }, { key: 'f.md', locals: { date: '2014-06-01', foo: 'rrr', bar: 10 } }, { key: 'g.md', locals: { date: '2014-02-02', foo: 'yyy', bar: 12 } }, { key: 'a.md', locals: { date: '2014-01-01', foo: 'zzz', bar: 1 } }, { key: 'l.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 7 } }, { key: 'h.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 6 } }, { key: 'i.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 5 } }, { key: 'j.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 4 } }, { key: 'd.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 3 } }, { key: 'k.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 1 } }, { key: 'f.md', locals: { date: '2014-01-01', foo: 'mmm', bar: 2 } }, { key: 'b.md', locals: { date: '2012-01-02', foo: 'ccc', bar: 9 } } ]); }); }); describe('groupBy', function() { var items = [ { path: 'a.md', locals: { date: '2014-01-01', foo: 'zzz', bar: 1 } }, { path: 'f.md', locals: { date: '2014-01-01', foo: 'mmm', bar: 2 } }, { path: 'd.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 3 } }, { path: 'i.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 5 } }, { path: 'k.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 1 } }, { path: 'j.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 4 } }, { path: 'h.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 6 } }, { path: 'l.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 7 } }, { path: 'e.md', locals: { date: '2015-01-02', foo: 'aaa', bar: 8 } }, { path: 'm.md', locals: { date: '2012-01-02', foo: 'ccc', bar: 9 } }, { path: 'b.md', locals: { date: '2014-06-01', foo: 'rrr', bar: 10 } }, { path: 'c.md', locals: { date: '2015-04-12', foo: 'ttt', bar: 11 } }, { path: 'g.md', locals: { date: '2014-02-02', foo: 'yyy', bar: 12 } } ]; it('should group a list by a property', function() { list = new List(); list.addList(items); var res = list.groupBy('locals.foo'); var keys = ['zzz', 'mmm', 'xxx', 'aaa', 'ccc', 'rrr', 'ttt', 'yyy']; assert.deepEqual(Object.keys(res), keys); }); it('should group a collection by a property', function() { list = new List(); list.addList(items); var views = new Views(list); var res = views.groupBy('locals.foo'); var keys = ['zzz', 'mmm', 'xxx', 'aaa', 'ccc', 'rrr', 'ttt', 'yyy']; assert.deepEqual(Object.keys(res), keys); }); }); describe('sort and group', function() { var items = [ { path: 'a.md', locals: { date: '2014-01-01', foo: 'zzz', bar: 1 } }, { path: 'f.md', locals: { date: '2014-01-01', foo: 'mmm', bar: 2 } }, { path: 'd.md', locals: { date: '2013-01-01', foo: 'xxx', bar: 3 } }, { path: 'i.md', locals: { date: '2013-02-01', foo: 'xxx', bar: 5 } }, { path: 'i.md', locals: { date: '2013-02-01', foo: 'lll', bar: 5 } }, { path: 'k.md', locals: { date: '2013-03-01', foo: 'xxx', bar: 1 } }, { path: 'j.md', locals: { date: '2013-02-01', foo: 'xxx', bar: 4 } }, { path: 'h.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 6 } }, { path: 'm.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 7 } }, { path: 'n.md', locals: { date: '2013-01-01', foo: 'xxx', bar: 7 } }, { path: 'o.md', locals: { date: '2013-01-01', foo: 'xxx', bar: 7 } }, { path: 'p.md', locals: { date: '2013-01-01', foo: 'xxx', bar: 7 } }, { path: 'e.md', locals: { date: '2015-01-02', foo: 'aaa', bar: 8 } }, { path: 'b.md', locals: { date: '2012-01-02', foo: 'ccc', bar: 9 } }, { path: 'f.md', locals: { date: '2014-06-01', foo: 'rrr', bar: 10 } }, { path: 'c.md', locals: { date: '2015-04-12', foo: 'ttt', bar: 11 } }, { path: 'g.md', locals: { date: '2014-02-02', foo: 'yyy', bar: 12 } } ]; it('should group a list by a property', function() { list = new List(items); var context = list .sortBy('locals.date') .groupBy(function(view) { var date = view.locals.date; view.locals.year = date.slice(0, 4); view.locals.month = date.slice(5, 7); view.locals.day = date.slice(8, 10); return view.locals.year; }, 'locals.month'); var keys = Object.keys(context); assert.equal(keys[0], '2012'); assert.equal(keys[1], '2013'); assert.equal(keys[2], '2014'); assert.equal(keys[3], '2015'); }); }); describe('paginate', function() { var items = [ { path: 'a.md', locals: { date: '2014-01-01', foo: 'zzz', bar: 1 } }, { path: 'f.md', locals: { date: '2014-01-01', foo: 'mmm', bar: 2 } }, { path: 'd.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 3 } }, { path: 'i.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 5 } }, { path: 'k.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 1 } }, { path: 'j.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 4 } }, { path: 'h.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 6 } }, { path: 'l.md', locals: { date: '2014-01-01', foo: 'xxx', bar: 7 } }, { path: 'e.md', locals: { date: '2015-01-02', foo: 'aaa', bar: 8 } }, { path: 'b.md', locals: { date: '2012-01-02', foo: 'ccc', bar: 9 } }, { path: 'f.md', locals: { date: '2014-06-01', foo: 'rrr', bar: 10 } }, { path: 'c.md', locals: { date: '2015-04-12', foo: 'ttt', bar: 11 } }, { path: 'g.md', locals: { date: '2014-02-02', foo: 'yyy', bar: 12 } } ]; it('should paginate a list', function() { list = new List(items); var res = list.paginate(); assert.equal(res.length, 2); assert.containEql(res[0].items, items.slice(0, 10)); assert.containEql(res[1].items, items.slice(10)); }); it('should add pager properties', function() { list = new List({pager: true}); list.addList(items); list.items.forEach(function(item, i) { assert.equal(item.data.pager.index, i); }); }); it('should render items when pager is `true`', function(cb) { list = new List({pager: true}); list.engine('.md', require('engine-base')); list.addList(items); each(list.items, function(item, next) { item.render(next); }, cb); }); it('should paginate a list with given options', function() { list = new List(items); var res = list.paginate({limit: 5}); assert.equal(res.length, 3); assert.containEql(res[0].items, items.slice(0, 5)); assert.containEql(res[1].items, items.slice(5, 10)); assert.containEql(res[2].items, items.slice(10)); }); }); describe('Views instance', function() { beforeEach(function() { views = new Views(); }); it('should add views from an instance of Views', function() { views.addViews({ one: {content: 'foo'}, two: {content: 'bar'} }); list = new List(views); assert(isBuffer(list.items[0].contents)); assert(isBuffer(list.items[1].contents)); }); }); describe('getIndex', function() { beforeEach(function() { list = new List(); }); it('should get the index of a key when key is not renamed', function() { list.addItem('a/b/c/ddd.hbs', {content: 'ddd'}); list.addItem('a/b/c/eee.hbs', {content: 'eee'}); assert.equal(list.getIndex('a/b/c/ddd.hbs'), 0); assert.equal(list.getIndex('a/b/c/eee.hbs'), 1); }); it('should get the index of a key when key is renamed', function() { list = new List({ renameKey: function(key) { return path.basename(key); } }); list.addItem('a/b/c/ddd.hbs', {content: 'ddd'}); list.addItem('a/b/c/eee.hbs', {content: 'eee'}); assert.equal(list.getIndex('a/b/c/ddd.hbs'), 0); assert.equal(list.getIndex('ddd.hbs'), 0); assert.equal(list.getIndex('a/b/c/eee.hbs'), 1); assert.equal(list.getIndex('eee.hbs'), 1); }); }); describe('getItem', function() { beforeEach(function() { list = new List(); }); it('should get an item from `items`', function() { list.addItem('one', {content: 'aaa'}); list.addItem('two', {content: 'zzz'}); assert.equal(list.items.length, 2); assert(isBuffer(list.items[0].contents)); assert(isBuffer(list.getItem('one').contents)); assert.equal(list.getItem('one').contents.toString(), 'aaa'); assert.equal(list.getItem('two').contents.toString(), 'zzz'); }); it('should return `undefined` when the item is not found', function() { assert.equal(typeof list.getItem('flflflfl'), 'undefined'); }); }); describe('use', function() { beforeEach(function() { list = new List(); }); it('should use middleware on a list', function() { list.addItem('one', {content: 'aaa'}); list.addItem('two', {content: 'zzz'}); list .use(function() { this.set('foo', 'bar'); }) .use(function() { this.set('one', 'two'); }); assert.equal(list.one, 'two'); assert.equal(list.foo, 'bar'); }); }); }); };