diff --git a/lib/models/category.js b/lib/models/category.js index b7df7ceaf4..a58cd42054 100644 --- a/lib/models/category.js +++ b/lib/models/category.js @@ -67,7 +67,7 @@ module.exports = function(ctx){ parent: parent || {$exists: false} }); - if (cat && cat._id === data._id){ + if (cat){ throw new Error('Category `' + name + '` has already existed!'); } }); diff --git a/lib/models/tag.js b/lib/models/tag.js index 8f1dc9d45e..efe5e28496 100644 --- a/lib/models/tag.js +++ b/lib/models/tag.js @@ -53,7 +53,7 @@ module.exports = function(ctx){ var Tag = ctx.model('Tag'); var tag = Tag.findOne({name: name}); - if (tag && tag._id === data._id){ + if (tag){ throw new Error('Tag `' + name + '` has already existed!'); } }); diff --git a/test/scripts/box/box.js b/test/scripts/box/box.js index 7dd481e5a9..44e8b06986 100644 --- a/test/scripts/box/box.js +++ b/test/scripts/box/box.js @@ -6,6 +6,7 @@ var fs = require('hexo-fs'); var Promise = require('bluebird'); var crypto = require('crypto'); var util = require('hexo-util'); +var sinon = require('sinon'); var Pattern = util.Pattern; var testUtil = require('../../util'); @@ -82,12 +83,17 @@ describe('Box', function(){ it('addProcessor() - no fn', function(){ var box = newBox(); + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'fn must be a function'); + }); try { box.addProcessor('test'); } catch (err){ - err.should.have.property('message', 'fn must be a function'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it('_loadFiles() - create', function(){ @@ -430,11 +436,16 @@ describe('Box', function(){ it.skip('watch() - watcher has started', function(callback){ var box = newBox(); + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'Watcher has already started.'); + }); box.watch().then(function(){ box.watch().catch(function(err){ - err.should.have.property('message', 'Watcher has already started.'); + errorCallback(err); box.unwatch(); + }).finally(function() { + errorCallback.calledOnce.should.be.false; callback(); }); }); @@ -482,12 +493,17 @@ describe('Box', function(){ it('unwatch() - watcher not started', function(){ var box = newBox(); + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'Watcher hasn\'t started yet.'); + }); try { box.unwatch(); } catch (err){ - err.should.have.property('message', 'Watcher hasn\'t started yet.'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it.skip('isWatching()', function(){ diff --git a/test/scripts/extend/filter.js b/test/scripts/extend/filter.js index c939bcc443..9c601c5c0e 100644 --- a/test/scripts/extend/filter.js +++ b/test/scripts/extend/filter.js @@ -75,22 +75,32 @@ describe('Filter', function(){ it('unregister() - type is required', function(){ var f = new Filter(); + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'type is required'); + }); try { f.unregister(); } catch (err){ - err.should.have.property('message', 'type is required'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it('unregister() - fn must be a function', function(){ var f = new Filter(); + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'fn must be a function'); + }); try { f.unregister('test'); } catch (err){ - err.should.have.property('message', 'fn must be a function'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it('list()', function(){ diff --git a/test/scripts/extend/tag.js b/test/scripts/extend/tag.js index 7d6523c937..34a660b168 100644 --- a/test/scripts/extend/tag.js +++ b/test/scripts/extend/tag.js @@ -1,6 +1,7 @@ 'use strict'; var should = require('chai').should(); +var sinon = require('sinon'); var Promise = require('bluebird'); describe('Tag', function(){ @@ -123,19 +124,31 @@ describe('Tag', function(){ }); it('register() - name is required', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'name is required'); + }); + try { tag.register(); } catch (err){ - err.should.have.property('message', 'name is required'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it('register() - fn must be a function', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'fn must be a function'); + }); + try { tag.register('test'); } catch (err){ - err.should.have.property('message', 'fn must be a function'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it('render() - context', function(){ diff --git a/test/scripts/filters/new_post_path.js b/test/scripts/filters/new_post_path.js index 7d5707e886..3073bbd40e 100644 --- a/test/scripts/filters/new_post_path.js +++ b/test/scripts/filters/new_post_path.js @@ -1,6 +1,7 @@ 'use strict'; var should = require('chai').should(); +var sinon = require('sinon'); var pathFn = require('path'); var moment = require('moment'); var Promise = require('bluebird'); @@ -170,8 +171,12 @@ describe('new_post_path', function(){ }); it('data is required', function(){ - return newPostPath().catch(function(err){ + var errorCallback = sinon.spy(function(err){ err.should.have.property('message', 'Either data.path or data.slug is required!'); }); + + return newPostPath().catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; + }); }); }); \ No newline at end of file diff --git a/test/scripts/helpers/partial.js b/test/scripts/helpers/partial.js index ee96f2601c..69396c667b 100644 --- a/test/scripts/helpers/partial.js +++ b/test/scripts/helpers/partial.js @@ -1,6 +1,7 @@ 'use strict'; var should = require('chai').should(); +var sinon = require('sinon'); var pathFn = require('path'); var fs = require('hexo-fs'); var Promise = require('bluebird'); @@ -80,10 +81,16 @@ describe('partial', function(){ }); it('name must be a string', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'name must be a string!'); + }); + try { partial(); } catch (err){ - err.should.have.property('message', 'name must be a string!'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); }); \ No newline at end of file diff --git a/test/scripts/hexo/hexo.js b/test/scripts/hexo/hexo.js index e2524af8d9..2f98ea0718 100644 --- a/test/scripts/hexo/hexo.js +++ b/test/scripts/hexo/hexo.js @@ -89,9 +89,13 @@ describe('Hexo', function(){ }); it('call() - console not registered', function(){ - return hexo.call('nothing').catch(function(err){ + var errorCallback = sinon.spy(function(err){ err.should.have.property('message', 'Console `nothing` has not been registered yet!'); }); + + return hexo.call('nothing').catch(errorCallback).finally(function(){ + errorCallback.calledOnce.should.be.true; + }); }); it('init()', function(){ diff --git a/test/scripts/hexo/locals.js b/test/scripts/hexo/locals.js index 23b1fd3260..9b51b19877 100644 --- a/test/scripts/hexo/locals.js +++ b/test/scripts/hexo/locals.js @@ -1,17 +1,24 @@ 'use strict'; var should = require('chai').should(); +var sinon = require('sinon'); describe('Locals', function(){ var Locals = require('../../../lib/hexo/locals'); var locals = new Locals(); it('get() - name must be a string', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'name must be a string!'); + }); + try { locals.get(); } catch (err){ - err.should.have.property('message', 'name must be a string!'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it('set() - function', function(){ @@ -32,19 +39,31 @@ describe('Locals', function(){ }); it('set() - name must be a string', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'name must be a string!'); + }); + try { locals.set(); } catch (err){ - err.should.have.property('message', 'name must be a string!'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it('set() - value is required', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'value is required!'); + }); + try { locals.set('test'); } catch (err){ - err.should.have.property('message', 'value is required!'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it('remove()', function(){ @@ -57,11 +76,17 @@ describe('Locals', function(){ }); it('remove() - name must be a string', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'name must be a string!'); + }); + try { locals.remove(); } catch (err){ - err.should.have.property('message', 'name must be a string!'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it('toObject()', function(){ diff --git a/test/scripts/hexo/render.js b/test/scripts/hexo/render.js index 7ea99f3bbb..b9e37fea7f 100644 --- a/test/scripts/hexo/render.js +++ b/test/scripts/hexo/render.js @@ -99,8 +99,12 @@ describe('Render', function(){ }); it('render() - no path and text', function(){ - return hexo.render.render().catch(function(err){ + var errorCallback = sinon.spy(function(err){ err.should.have.property('message', 'No input file or string!'); + }) + + return hexo.render.render().catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; }); }); @@ -220,11 +224,17 @@ describe('Render', function(){ }); it('renderSync() - no path and text', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'No input file or string!'); + }); + try { hexo.render.renderSync(); } catch (err){ - err.should.have.property('message', 'No input file or string!'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it('renderSync() - options', function(){ diff --git a/test/scripts/hexo/router.js b/test/scripts/hexo/router.js index 1d9f3fbdcd..ea1d6bbc47 100644 --- a/test/scripts/hexo/router.js +++ b/test/scripts/hexo/router.js @@ -58,11 +58,17 @@ describe('Router', function(){ }); it('format() - path must be a string', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'path must be a string!'); + }) + try { - router.format(); + router.format(function(){}); } catch (err){ - err.should.have.property('message', 'path must be a string!'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }) it('set() - string', function(){ @@ -119,19 +125,31 @@ describe('Router', function(){ }); it('set() - path must be a string', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'path must be a string!'); + }); + try { router.set(); } catch (err){ - err.should.have.property('message', 'path must be a string!'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it('set() - data is required', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'data is required!'); + }); + try { router.set('test'); } catch (err){ - err.should.have.property('message', 'data is required!'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it('get() - error handling', function(){ @@ -139,9 +157,13 @@ describe('Router', function(){ throw new Error('error test'); }); - return testUtil.stream.read(router.get('test')).catch(function(err){ + var errorCallback = sinon.spy(function(err){ err.should.have.property('message', 'error test'); }); + + return testUtil.stream.read(router.get('test')).catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; + }); }); it('get() - no data', function(){ @@ -179,11 +201,17 @@ describe('Router', function(){ }); it('get() - path must be a string', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'path must be a string!'); + }); + try { router.get(); } catch (err){ - err.should.have.property('message', 'path must be a string!'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it('get() - export stringified JSON object', function(){ @@ -213,11 +241,17 @@ describe('Router', function(){ }); it('isModified() - path must be a string', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'path must be a string!'); + }); + try { router.isModified(); } catch (err){ - err.should.have.property('message', 'path must be a string!'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); it('remove()', function(){ @@ -234,10 +268,16 @@ describe('Router', function(){ }); it('remove() - path must be a string', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'path must be a string!'); + }); + try { router.remove(); } catch (err){ - err.should.have.property('message', 'path must be a string!'); + errorCallback(err); } + + errorCallback.calledOnce.should.be.true; }); }); \ No newline at end of file diff --git a/test/scripts/models/asset.js b/test/scripts/models/asset.js index fb8b446212..edbca65b75 100644 --- a/test/scripts/models/asset.js +++ b/test/scripts/models/asset.js @@ -1,6 +1,7 @@ 'use strict'; var should = require('chai').should(); +var sinon = require('sinon'); var pathFn = require('path'); describe('Asset', function(){ @@ -19,16 +20,24 @@ describe('Asset', function(){ }); it('_id - required', function(){ - return Asset.insert({}).catch(function(err){ + var errorCallback = sinon.spy(function(err) { err.should.have.property('message', 'ID is not defined'); }); + + return Asset.insert({}).catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; + }); }); it('path - required', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', '`path` is required!'); + }); + return Asset.insert({ _id: 'foo' - }).catch(function(err){ - err.should.have.property('message', '`path` is required!'); + }).catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; }); }); diff --git a/test/scripts/models/cache.js b/test/scripts/models/cache.js index da8d37942c..1bff141236 100644 --- a/test/scripts/models/cache.js +++ b/test/scripts/models/cache.js @@ -1,6 +1,7 @@ 'use strict'; var should = require('chai').should(); +var sinon = require('sinon'); describe('Cache', function(){ var Hexo = require('../../../lib/hexo'); @@ -8,8 +9,12 @@ describe('Cache', function(){ var Cache = hexo.model('Cache'); it('_id - required', function(){ - return Cache.insert({}).catch(function(err){ + var errorCallback = sinon.spy(function(err) { err.should.have.property('message', 'ID is not defined'); }); + + return Cache.insert({}).catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; + }); }); }); \ No newline at end of file diff --git a/test/scripts/models/category.js b/test/scripts/models/category.js index b4459a24b4..c468b47ef5 100644 --- a/test/scripts/models/category.js +++ b/test/scripts/models/category.js @@ -1,6 +1,7 @@ 'use strict'; var should = require('chai').should(); +var sinon = require('sinon'); var Promise = require('bluebird'); describe('Category', function(){ @@ -15,9 +16,13 @@ describe('Category', function(){ }); it('name - required', function(){ - return Category.insert({}).catch(function(err){ + var errorCallback = sinon.spy(function(err) { err.should.have.property('message', '`name` is required!'); }); + + return Category.insert({}).catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; + }); }); it.skip('parent - reference'); @@ -209,16 +214,22 @@ describe('Category', function(){ }); it('check whether a category exists', function(){ + var errorCallback = sinon.spy(function(err){ + err.should.have.property('message', 'Category `foo` has already existed!'); + }); + return Category.insert({ name: 'foo' }).then(function(data){ + var errorCall + Category.insert({ name: 'foo' - }).catch(function(err){ - err.should.have.property('message', 'Category `foo` has already existed!'); - }); + }).catch(errorCallback); return Category.removeById(data._id); + }).finally(function() { + errorCallback.calledOnce.should.be.true; }); }); diff --git a/test/scripts/models/page.js b/test/scripts/models/page.js index a78f53ffdb..1675c8642d 100644 --- a/test/scripts/models/page.js +++ b/test/scripts/models/page.js @@ -1,6 +1,7 @@ 'use strict'; var should = require('chai').should(); +var sinon = require('sinon'); var pathFn = require('path'); describe('Page', function(){ @@ -31,16 +32,24 @@ describe('Page', function(){ }); it('source - required', function(){ - return Page.insert({}).catch(function(err){ + var errorCallback = sinon.spy(function(err) { err.should.have.property('message', '`source` is required!'); }); + + return Page.insert({}).catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; + }); }); it('path - required', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', '`path` is required!'); + }); + return Page.insert({ source: 'foo' - }).catch(function(err){ - err.should.have.property('message', '`path` is required!'); + }).catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; }); }); diff --git a/test/scripts/models/post.js b/test/scripts/models/post.js index a57e686018..525af4d6c4 100644 --- a/test/scripts/models/post.js +++ b/test/scripts/models/post.js @@ -1,6 +1,7 @@ 'use strict'; var should = require('chai').should(); +var sinon = require('sinon'); var pathFn = require('path'); var Promise = require('bluebird'); @@ -44,16 +45,24 @@ describe('Post', function(){ }); it('source - required', function(){ - return Post.insert({}).catch(function(err){ + var errorCallback = sinon.spy(function(err){ err.should.have.property('message', '`source` is required!'); }); + + return Post.insert({}).catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; + }); }); it('slug - required', function(){ + var errorCallback = sinon.spy(function(err){ + err.should.have.property('message', '`slug` is required!'); + }); + return Post.insert({ source: 'foo.md' - }).catch(function(err){ - err.should.have.property('message', '`slug` is required!'); + }).catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; }); }); diff --git a/test/scripts/models/post_asset.js b/test/scripts/models/post_asset.js index 351fe866ec..1e2603eabe 100644 --- a/test/scripts/models/post_asset.js +++ b/test/scripts/models/post_asset.js @@ -1,6 +1,7 @@ 'use strict'; var should = require('chai').should(); +var sinon = require('sinon'); var url = require('url'); var pathFn = require('path'); @@ -34,17 +35,25 @@ describe('PostAsset', function(){ }); it('_id - required', function(){ - return PostAsset.insert({}).catch(function(err){ + var errorCallback = sinon.spy(function(err) { err.should.have.property('message', 'ID is not defined'); }); + + return PostAsset.insert({}).catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; + });; }); it('slug - required', function(){ - return PostAsset.insert({ - _id: 'foo' - }).catch(function(err){ + var errorCallback = sinon.spy(function(err) { err.should.have.property('message', '`slug` is required!'); }); + + return PostAsset.insert({ + _id: 'foo' + }).catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; + });; }); it('path - virtual', function(){ diff --git a/test/scripts/models/tag.js b/test/scripts/models/tag.js index d51bc03799..1a3a0de06e 100644 --- a/test/scripts/models/tag.js +++ b/test/scripts/models/tag.js @@ -1,6 +1,7 @@ 'use strict'; var should = require('chai').should(); +var sinon = require('sinon'); var Promise = require('bluebird'); var _ = require('lodash'); @@ -16,9 +17,13 @@ describe('Tag', function(){ }); it('name - required', function(){ - return Tag.insert({}).catch(function(err){ + var errorCallback = sinon.spy(function(err) { err.should.have.property('message', '`name` is required!'); }); + + return Tag.insert({}).catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; + }); }); it('slug - virtual', function(){ @@ -191,16 +196,20 @@ describe('Tag', function(){ }); it('check whether a tag exists', function(){ + var errorCallback = sinon.spy(function(err) { + err.should.have.property('message', 'Tag `foo` has already existed!'); + }); + return Tag.insert({ name: 'foo' }).then(function(data){ Tag.insert({ name: 'foo' - }).catch(function(err){ - err.should.have.property('message', 'Tag `foo` has already existed!'); - }); + }).catch(errorCallback); return Tag.removeById(data._id); + }).finally(function() { + errorCallback.calledOnce.should.be.true; }); }); diff --git a/test/scripts/theme_processors/config.js b/test/scripts/theme_processors/config.js index 94fc5b2915..bcf5e3094b 100644 --- a/test/scripts/theme_processors/config.js +++ b/test/scripts/theme_processors/config.js @@ -1,6 +1,7 @@ 'use strict'; var should = require('chai').should(); +var sinon = require('sinon'); var pathFn = require('path'); var fs = require('hexo-fs'); var Promise = require('bluebird'); @@ -82,8 +83,12 @@ describe('config', function(){ type: 'create' }); - return process(file).catch(function(err){ + var errorCallback = sinon.spy(function(err) { err.should.have.property('message', 'Theme config load failed.'); + }); + + return process(file).catch(errorCallback).finally(function() { + errorCallback.calledOnce.should.be.true; }).catch(function(){}); // Catch again because it throws error }); }); \ No newline at end of file