diff --git a/Gruntfile.js b/Gruntfile.js
index 4207422..a252a89 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -66,7 +66,12 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
+ //copies required libraries for testing
grunt.registerTask('vendor', ['copy:jquery', 'copy:underscore', 'copy:backbone', 'copy:mocha', 'copy:chai', 'copy:promise']);
+
+ //applies jshint to project files
grunt.registerTask('test', ['jshint']);
+
+ //minifies library
grunt.registerTask('release', ['jshint', 'uglify:dist']);
};
\ No newline at end of file
diff --git a/README.md b/README.md
index 89fc591..1cb4c29 100644
--- a/README.md
+++ b/README.md
@@ -153,7 +153,7 @@ var Contact = Backbone.Async.Contact.extend({
var contact = new Contact({id: 1});
//setup event listener
-var object = {
+var obj = {
beforeFetch: function(data) {
console.log('Contact is being fetched...');
},
@@ -163,9 +163,9 @@ var object = {
}
};
-_.extend(object, Backbone.Events);
-object.listenTo(contact, 'before:fetch', object.beforeFetch);
-object.listenTo(contact, 'before:save', object.beforeSave);
+_.extend(obj, Backbone.Events);
+obj.listenTo(contact, 'before:fetch', obj.beforeFetch);
+obj.listenTo(contact, 'before:save', obj.beforeSave);
//fetch contact
contact.fetch()
@@ -192,7 +192,7 @@ The *before:fetch* and *before:destroy* event handlers will receive an object co
* model: The model instance.
* options: The options provided.
-The *before:save* event handler also includes an additional property named *attrs* with the attributes being saved. All *after:event* handlers receive the exact same object provided to the fulfilled and rejection callbacks plus a *success* argument.
+The *before:save* event handler argument also includes an additional property named *attrs* with the attributes being saved. All *after:[event]* handlers receive the exact same object provided to the fulfilled and rejection callbacks plus a *success* argument.
###License
diff --git a/bower.json b/bower.json
index cfcf801..55895b0 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
{
"name": "backbone.async",
- "version": "0.3.0",
+ "version": "1.0.0",
"homepage": "https://github.com/emaphp/backbone.async",
"authors": [
"Emmanuel Antico "
diff --git a/dist/backbone.async.js b/dist/backbone.async.js
index 61e885b..3e04311 100644
--- a/dist/backbone.async.js
+++ b/dist/backbone.async.js
@@ -1,5 +1,5 @@
/*
- * Backbone.Async v0.3.0
+ * Backbone.Async v1.0.0
* Copyright 2015 Emmanuel Antico
* This library is distributed under the terms of the MIT license.
*/
@@ -94,7 +94,7 @@
};
var Async = Backbone.Async = Backbone.Async || {};
- Async.VERSION = '0.3.0';
+ Async.VERSION = '1.0.0';
Async.Model = Backbone.Model.extend(
buildPrototype(Backbone.Model, ['fetch', 'save', 'destroy'])
diff --git a/dist/backbone.async.min.js b/dist/backbone.async.min.js
index a8ce790..0f7d7f2 100644
--- a/dist/backbone.async.min.js
+++ b/dist/backbone.async.min.js
@@ -1 +1 @@
-!function(a,b){"function"==typeof define&&define.amd?define(["backbone","underscore"],function(c,d){return b(a,c,d)}):"undefined"!=typeof exports?module.exports=b(a,require("backbone"),require("underscore")):b(a,a.Backbone,a._)}(this,function(a,b,c){var d=function(a,b,c){return function(d,e,f){a&&a.apply(d,arguments);var g={response:e,options:f};g[c.collection?"collection":"model"]=d,b(g),"undefined"!=typeof f.silent&&f.silent||d.trigger("after:"+c.method,g,c.success)}},e=function(a,b,d,e){var f,g;return"save"===a?null===b||"object"==typeof b?(f=b,g=d):b&&((f={})[b]=d,g=e):g=b,g=g?c.extend({},g):{},{attrs:f,options:g}},f=function(a){return function(f,g){return f[g]=function(f,h,i){var j=this,k=e(g,f,h,i),l=k.options,m=k.attrs,n=l.success,o=l.error,p={method:g,collection:a===b.Collection.prototype};return new Promise(function(b,e){l.success=d(n,b,c.extend({success:!0},p)),l.error=d(o,e,c.extend({success:!1},p)),p.collection?("undefined"!=typeof l.silent&&l.silent||j.trigger("before:"+g,{collection:j,options:l}),a[g].call(j,l)):("undefined"!=typeof l.silent&&l.silent||j.trigger("before:"+g,"save"===g?{model:j,options:l,attrs:m}:{model:j,options:l}),a[g].apply(j,"save"===g?[m,l]:[l]))})},f}},g=function(a,b){return b.reduce(f(a.prototype),{})},h=b.Async=b.Async||{};return h.VERSION="0.3.0",h.Model=b.Model.extend(g(b.Model,["fetch","save","destroy"])),h.Collection=b.Collection.extend(g(b.Collection,["fetch"])),h});
\ No newline at end of file
+!function(a,b){"function"==typeof define&&define.amd?define(["backbone","underscore"],function(c,d){return b(a,c,d)}):"undefined"!=typeof exports?module.exports=b(a,require("backbone"),require("underscore")):b(a,a.Backbone,a._)}(this,function(a,b,c){var d=function(a,b,c){return function(d,e,f){a&&a.apply(d,arguments);var g={response:e,options:f};g[c.collection?"collection":"model"]=d,b(g),"undefined"!=typeof f.silent&&f.silent||d.trigger("after:"+c.method,g,c.success)}},e=function(a,b,d,e){var f,g;return"save"===a?null===b||"object"==typeof b?(f=b,g=d):b&&((f={})[b]=d,g=e):g=b,g=g?c.extend({},g):{},{attrs:f,options:g}},f=function(a){return function(f,g){return f[g]=function(f,h,i){var j=this,k=e(g,f,h,i),l=k.options,m=k.attrs,n=l.success,o=l.error,p={method:g,collection:a===b.Collection.prototype};return new Promise(function(b,e){l.success=d(n,b,c.extend({success:!0},p)),l.error=d(o,e,c.extend({success:!1},p)),p.collection?("undefined"!=typeof l.silent&&l.silent||j.trigger("before:"+g,{collection:j,options:l}),a[g].call(j,l)):("undefined"!=typeof l.silent&&l.silent||j.trigger("before:"+g,"save"===g?{model:j,options:l,attrs:m}:{model:j,options:l}),a[g].apply(j,"save"===g?[m,l]:[l]))})},f}},g=function(a,b){return b.reduce(f(a.prototype),{})},h=b.Async=b.Async||{};return h.VERSION="1.0.0",h.Model=b.Model.extend(g(b.Model,["fetch","save","destroy"])),h.Collection=b.Collection.extend(g(b.Collection,["fetch"])),h});
\ No newline at end of file
diff --git a/package.json b/package.json
index dcd953f..e71229f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "backbone.async",
- "version": "0.3.0",
+ "version": "1.0.0",
"description": "Backbone Models meet Promises",
"author": "Emmanuel Antico ",
"license": "MIT",
diff --git a/test/specs/model.js b/test/specs/model.js
index 2e9cc52..c50c765 100644
--- a/test/specs/model.js
+++ b/test/specs/model.js
@@ -379,7 +379,7 @@ describe("ASync.Model tests", function() {
done();
})
- .catch(function(err){done(err)});
+ .catch(function(err){done(err);});
server.respond();
});
@@ -702,10 +702,320 @@ describe("ASync.Model tests", function() {
});
describe('Delete tests', function() {
+ it('must call then', function(done) {
+ server.respondWith(
+ 'DELETE',
+ '/contacts/1',
+ [
+ 204,
+ null,
+ ''
+ ]
+ );
+
+ var contact = new FIXTURES.Contact({id: 1});
+
+ contact.destroy({test: true, silent:false})
+ .then(function(data) {
+ expect(data).to.be.a('object');
+ expect(data).to.have.property('model');
+ expect(data).to.have.property('response');
+ expect(data).to.have.property('options');
+ expect(data.model).to.be.deep.equal(contact);
+
+ var attrs = data.model.attributes;
+ expect(attrs).to.have.property('id');
+
+ var response = data.response;
+ expect(response).to.be.undefined;
+
+ expect(data.options).to.be.a('object');
+ expect(data.options).to.have.property('test');
+ expect(data.options).to.have.property('silent');
+
+ expect(data.options.test).to.be.true;
+ expect(data.options.silent).to.be.false;
+
+ done();
+ })
+ .catch(function(err) { done(err); });
+ server.respond();
+ });
+
+ it('must call callbacks in order', function(done) {
+ server.respondWith(
+ 'DELETE',
+ '/contacts/2',
+ [
+ 204,
+ null,
+ ''
+ ]
+ );
+
+ var contact = new FIXTURES.Contact({id: 2});
+ var callback1 = sinon.spy();
+ var callback2 = sinon.spy();
+
+ contact.destroy()
+ .then(callback1)
+ .then(callback2)
+ .then(function(data) {
+ expect(callback1.called).to.be.true;
+ expect(callback1.calledOnce).to.be.true;
+ expect(callback2.called).to.be.true;
+ expect(callback2.calledOnce).to.be.true;
+ expect(callback1.calledBefore(callback2)).to.be.true;
+ done();
+ })
+ .catch(function(err) { done(err); });
+
+ server.respond();
+ });
+
+ it('must call event handlers', function(done) {
+ server.respondWith(
+ 'DELETE',
+ '/contacts/3',
+ [
+ 204,
+ null,
+ ''
+ ]
+ );
+
+ var obj = _.extend({}, Backbone.Events);
+ var beforeCallback = sinon.spy();
+ var afterCallback = sinon.spy();
+ var contact = new FIXTURES.Contact({id: 3});
+ obj.listenTo(contact, 'before:destroy', beforeCallback);
+ obj.listenTo(contact, 'after:destroy', afterCallback);
+
+ contact.destroy({test: true, silent:false})
+ .then(function(data) {
+ expect(beforeCallback.called).to.be.true;
+ expect(afterCallback.called).to.be.true;
+ expect(beforeCallback.calledBefore(afterCallback)).to.be.true;
+
+ var dataArg = beforeCallback.args[0][0];
+ expect(dataArg).to.be.a('object');
+ expect(dataArg).to.have.property('model');
+ expect(dataArg).to.have.property('options');
+ expect(dataArg.model).to.be.deep.equal(contact);
+ expect(dataArg.options).to.have.property('test');
+ expect(dataArg.options).to.have.property('silent');
+ expect(dataArg.options.test).to.be.true;
+ expect(dataArg.options.silent).to.be.false;
+
+ dataArg = afterCallback.args[0][0];
+ expect(dataArg).to.be.a('object');
+ expect(dataArg).to.have.property('model');
+ expect(dataArg).to.have.property('options');
+ expect(dataArg).to.have.property('response');
+ expect(dataArg.model).to.be.deep.equal(contact);
+ expect(dataArg.response).to.be.undefined;
+ expect(dataArg.options).to.have.property('test');
+ expect(dataArg.options).to.have.property('silent');
+ expect(dataArg.options.test).to.be.true;
+ expect(dataArg.options.silent).to.be.false;
+
+ var success = afterCallback.args[0][1];
+ expect(success).to.be.true;
+
+ done();
+ })
+ .catch(function(err) { done(err); });
+
+ server.respond();
+ });
+
+ it('must not call event handlers', function(done) {
+ server.respondWith(
+ 'DELETE',
+ '/contacts/4',
+ [
+ 204,
+ null,
+ ''
+ ]
+ );
+ var obj = _.extend({}, Backbone.Events);
+ var beforeCallback = sinon.spy();
+ var afterCallback = sinon.spy();
+ var contact = new FIXTURES.Contact({id: 4});
+ obj.listenTo(contact, 'before:destroy', beforeCallback);
+ obj.listenTo(contact, 'after:destroy', afterCallback);
+
+ contact.destroy({test: false, silent: true})
+ .then(function() {
+ expect(beforeCallback.called).to.be.false;
+ expect(afterCallback.called).to.be.false;
+ done();
+ })
+ .catch(function(err) { done(err); });
+
+ server.respond();
+ });
+
+ it('must throw error', function(done) {
+ server.respondWith(
+ 'DELETE',
+ '/contacts/5',
+ [
+ 204,
+ null,
+ ''
+ ]
+ );
+
+ var contact = new FIXTURES.Contact({id: 5});
+
+ contact.destroy()
+ .then(function(data) {
+ throw new Error();
+ })
+ .catch(function(err) {
+ expect(_.isError(err)).to.be.true;
+ done();
+ });
+
+ server.respond();
+ });
});
describe('Delete fail tests', function() {
+ it('must call catch', function(done) {
+ server.respondWith(
+ 'DELETE',
+ '/notes/1',
+ [
+ 500,
+ null,
+ ''
+ ]
+ );
+
+ var note = new FIXTURES.Note({id: 1});
+
+ note.destroy({test: true, silent: false})
+ .then(function() {
+ })
+ .catch(function(data) {
+ expect(data).to.be.a('object');
+
+ expect(data).to.have.property('model');
+ expect(data).to.have.property('response');
+ expect(data).to.have.property('options');
+
+ expect(data.model).to.be.deep.equal(note);
+ expect(data.response).to.be.a('object');
+ expect(data.response).to.have.property('status');
+ expect(data.response).to.have.property('statusText');
+ expect(data.response.status).to.equal(500);
+ expect(data.response.statusText).to.equal('Internal Server Error');
+ var options = data.options;
+ expect(options).to.have.property('test');
+ expect(options).to.have.property('silent');
+ expect(options.test).to.be.true;
+ expect(options.silent).to.be.false;
+ done();
+ });
+
+ server.respond();
+ });
+
+ it('must call event handlers', function(done) {
+ server.respondWith(
+ 'DELETE',
+ '/notes/2',
+ [
+ 500,
+ null,
+ ''
+ ]
+ );
+
+ var obj = _.extend({}, Backbone.Events);
+ var beforeCallback = sinon.spy();
+ var afterCallback = sinon.spy();
+ var note = new FIXTURES.Note({id: 2});
+ obj.listenTo(note, 'before:destroy', beforeCallback);
+ obj.listenTo(note, 'after:destroy', afterCallback);
+
+ note.destroy({test: true, silent:false})
+ .then(function(data) {
+ })
+ .catch(function(data) {
+ expect(beforeCallback.called).to.be.true;
+ expect(afterCallback.called).to.be.true;
+ expect(beforeCallback.calledBefore(afterCallback)).to.be.true;
+
+ var dataArg = beforeCallback.args[0][0];
+ expect(dataArg).to.be.a('object');
+ expect(dataArg).to.have.property('model');
+ expect(dataArg).to.have.property('options');
+ expect(dataArg.model).to.be.deep.equal(note);
+ expect(dataArg.options).to.have.property('test');
+ expect(dataArg.options).to.have.property('silent');
+ expect(dataArg.options.test).to.be.true;
+ expect(dataArg.options.silent).to.be.false;
+
+ dataArg = afterCallback.args[0][0];
+ expect(dataArg).to.be.a('object');
+ expect(dataArg).to.have.property('model');
+ expect(dataArg).to.have.property('options');
+ expect(dataArg).to.have.property('response');
+ expect(dataArg.model).to.be.deep.equal(note);
+ expect(data.response).to.be.a('object');
+ expect(data.response).to.have.property('status');
+ expect(data.response).to.have.property('statusText');
+ expect(data.response.status).to.equal(500);
+ expect(data.response.statusText).to.equal('Internal Server Error');
+
+ expect(dataArg.options).to.have.property('test');
+ expect(dataArg.options).to.have.property('silent');
+ expect(dataArg.options.test).to.be.true;
+ expect(dataArg.options.silent).to.be.false;
+
+ var success = afterCallback.args[0][1];
+ expect(success).to.be.false;
+
+ done();
+ });
+
+ server.respond();
+ });
+
+ it('must not call event handlers', function(done) {
+ server.respondWith(
+ 'DELETE',
+ '/notes/3',
+ [
+ 500,
+ null,
+ ''
+ ]
+ );
+
+ var obj = _.extend({}, Backbone.Events);
+ var beforeCallback = sinon.spy();
+ var afterCallback = sinon.spy();
+ var note = new FIXTURES.Note({id: 3});
+ obj.listenTo(note, 'before:save', beforeCallback);
+ obj.listenTo(note, 'after:save', afterCallback);
+
+ note.destroy({test: false, silent:true})
+ .then(function(data) {
+ })
+ .catch(function(data) {
+ expect(beforeCallback.called).to.be.false;
+ expect(afterCallback.called).to.be.false;
+ done();
+ });
+
+ server.respond();
+ });
});
});
\ No newline at end of file