backbone.test.js | |
---|---|
(function($) {
/**
* # Test the DrupalBackbone library.
*/
Drupal.tests.backbone = {
getInfo: function() {
return {
name: 'Backbone',
description: 'Tests the DrupalBackbone library for node loading, etc.',
group: 'Backbone'
};
},
test: function() { | |
Expect assertions contained in async calls. | expect(26);
var self = this; |
Stop the test runner, we will restart when all of our async tests have completed. TODO: Look into adding an asyncTest interface for Drupal QUnit. | stop(); |
Test Infrastructure SetupCreate QueueCreate a jQuery queue to make nested asyn easier. (Otherwise these would need to be nested within eachother). TODO: Look into $.deffered for handling this more robustly. | var asyncQueue = $({}); |
dequeueFuncs functionA factory function that uses closures to produce success and error callbacks for our Ajaj tests. | var dequeueFuncs = function(msg) {
return {
success: function() {
ok(true, Drupal.t(msg));
asyncQueue.dequeue('asyncQueue');
},
error: function() {
ok(false, Drupal.t(msg)); |
After erroring out, don't continue with tests. TODO: determine how to clean up if we've created but not destroyed our test node. | asyncQueue.clearQueue('asyncQueue'); |
Restart QUnit tests, continue on to next test. | start();
}
};
}; |
Drupal.Backbone.NodeModel TestsNodeModel Test SetupCreate a node object to use in our testing. | self.testNode = new Drupal.Backbone.NodeModel({
'title': 'Backbone Test Node',
'type': 'page'
}); |
Test Node CreateWe use a queue to manage asynchronous processes, so each stage in the CRUD runs after the prior callback has completed.
| asyncQueue.queue('asyncQueue', function() {
self.testNode.save( {}, dequeueFuncs('Drupal CRUD REST call: Create Node'));
}); |
Test Node Update
| asyncQueue.queue('asyncQueue', function() {
self.testNode.set('title', 'Updated Title');
self.testNode.save( {}, dequeueFuncs('Drupal CRUD REST call: Update Node'));
}); |
Test Drupal.Backbone.Collection and children.Test Node IndexSince we have a node created. | self.testNodeIndexCollection = new Drupal.Backbone.NodeIndexCollection();
asyncQueue.queue('asyncQueue', function() {
self.testNodeIndexCollection.setParam('pagesize', 1);
self.testNodeIndexCollection.fetch(dequeueFuncs('Fetch Node Index collection'));
}); |
Verify returned Node Index collection
| asyncQueue.queue('asyncQueue', function() {
equals(self.testNodeIndexCollection.length, 1, Drupal.t('Node Index fetch returned one node.'));
equals(self.testNodeIndexCollection.at(0).get('title'), 'Updated Title', Drupal.t('Top node in Node Index is correct one.'));
asyncQueue.dequeue('asyncQueue');
}); |
Test pagesize=0, should always be empty. | asyncQueue.queue('asyncQueue', function() {
self.testNodeIndexCollection.setParam('pagesize', 0);
self.testNodeIndexCollection.fetch(dequeueFuncs('Fetch empty Node Index collection'));
});
asyncQueue.queue('asyncQueue', function() {
equals(self.testNodeIndexCollection.length, 0, Drupal.t('Node Index page size setting worked correctly, no nodes returned.'));
asyncQueue.dequeue('asyncQueue');
}); |
Test Views collectionThis is different from Backbone.View! We test collections holding node views since we have a node created. | var viewCollection = new Drupal.Backbone.NodeViewCollection();
viewCollection.viewName = 'backbone_test';
asyncQueue.queue('asyncQueue', function() {
viewCollection.setParam('limit', 1);
viewCollection.fetch(dequeueFuncs('Fetch View collection'));
}); |
Test returned collection.TODO test offset/page number. | asyncQueue.queue('asyncQueue', function() {
equals(viewCollection.length, 1, Drupal.t('View fetch returned one node.'));
equals(viewCollection.at(0).get('title'), 'Updated Title',
Drupal.t('Top node in View is correct one.'));
asyncQueue.dequeue('asyncQueue');
}); |
Drupal.Backbone.View testsTest View RenderTest rendering a simple node view (Backbone.View, not Drupal views view). | asyncQueue.queue('asyncQueue', function() {
var TestView = Drupal.Backbone.View.extend({
model: self.testNode,
templateSelector: '#qunit-test-template',
id: 'qunit-test-view-content'
});
$('body').append('<script id="qunit-test-template" type="text/underscore-template"><h2><%= node.title %></h2></script>');
var view = new TestView();
$('body').append(view.render().el);
equals($('#qunit-test-view-content > h2').text(), self.testNode.get('title'),
Drupal.t('Drupal.Backbone.View test template rendered successfully.'));
view.unrender();
$('#qunit-test-template').remove();
asyncQueue.dequeue('asyncQueue');
}); |
CommentModel TestSet up CommentModel Test Objects | self.testComment = new Drupal.Backbone.CommentModel({
"subject": "Backbone QUnit Test Comment",
"comment_body": {
"und": [
{
value: "This is a test comment created by the Backbone module's QUnit tests."
}
]
},
uid: 1
});
self.testCommentB = new Drupal.Backbone.CommentModel();
asyncQueue.queue('asyncQueue', function() {
self.testComment.set('nid', self.testNode.get('nid'));
self.testComment.save({}, dequeueFuncs('Drupal CRUD REST call: Comment CREATE'));
});
asyncQueue.queue('asyncQueue', function() {
self.testCommentB.set('cid', self.testComment.get('cid'));
self.testCommentB.fetch(dequeueFuncs('Drupal CRUD REST call: Comment READ'));
});
asyncQueue.queue('asyncQueue', function() {
equals(self.testComment.get('subject'), self.testCommentB.get('subject'),
Drupal.t('Confirmed that comment title saved and fetched correctly.'));
self.testComment.set('subject', "UPDATED Backbone QUnit Test Comment");
self.testComment.save({}, dequeueFuncs('Drupal CRUD REST call: Comment UPDATE'));
});
asyncQueue.queue('asyncQueue', function() {
self.testCommentB.fetch().success(function() {
asyncQueue.dequeue('asyncQueue');
}).error(function() {
ok(false, Drupal.t('Error loading updated comment, unexpected. Something is wrong.'));
});
});
asyncQueue.queue('asyncQueue', function() {
equals(self.testComment.get('subject'), self.testCommentB.get('subject'),
Drupal.t('Confirmed that comment title updated and fetched correctly.'));
self.testComment.destroy(dequeueFuncs('Drupal CRUD REST call: Comment DELETE'));
});
asyncQueue.queue('asynceQueue', function() {
self.testCommentB.fetch().success(function() {
ok(false, Drupal.t('Comment DELETE did not actually delete comment, able to load post-destroy.'));
asyncQueue.dequeue('asyncQueue');
}).error(function() {
ok(true, Drupal.t('Confirmed that DELETE did in fact destroy object on server. Unable to load after destroy.'));
asyncQueue.dequeue('asyncQueue');
});
}); |
Node (cont).Test Node delete.
| asyncQueue.queue('asyncQueue', function() {
self.testNode.destroy(dequeueFuncs('Drupal CRUD REST call: Destroy Node'));
}); |
Test the User resource | |
Set up test objects. Generate a uniq string so we don't have to worry about dups. | var uniq = new Date().getTime().toString(36);
var testUserValues = {
"name": "backbone_test_user_" + uniq ,
"pass": "backbone",
"mail": "drupal-backbone-test@fakedomain-" + uniq + ".com"
};
self.testUser = new Drupal.Backbone.Models.User(testUserValues);
var testLoadUser = new Drupal.Backbone.Models.User();
var testUserIndexCollection = new Drupal.Backbone.UserIndexCollection(); |
Test User creation.Create a new user. | asyncQueue.queue('asyncQueue', function() {
self.testUser.save({}, dequeueFuncs('Drupal CRUD REST call: Create User'));
}); |
Test User retrieval.Fetch our new user using another user object. | asyncQueue.queue('asyncQueue', function() {
testLoadUser.set('uid', self.testUser.get('uid'));
testLoadUser.fetch(dequeueFuncs('Drupal CRUD REST call: Retrieve User'));
}); |
Confirm User READ. | asyncQueue.queue('asyncQueue', function() {
equals(testLoadUser.get('name'), testUserValues.name, 'User name saved and retrieved correctly.');
asyncQueue.dequeue('asyncQueue');
}); |
User Collections TestsTest UserIndexCollection | asyncQueue.queue('asyncQueue', function() {
testUserIndexCollection.setParam('pagesize', 1);
testUserIndexCollection.fetch(dequeueFuncs('Fetch User Index collection'));
}); |
Verify returned User Index collection
| asyncQueue.queue('asyncQueue', function() {
equals(testUserIndexCollection.length, 1, Drupal.t('User Index fetch returned one user.'));
equals(testUserIndexCollection.at(0).get('name'), testUserValues.name, Drupal.t('Top user in User Index is correct one.'));
asyncQueue.dequeue('asyncQueue');
}); |
UserModel (cont.)Test User DELETE | asyncQueue.queue('asyncQueue', function() {
self.testUser.destroy(dequeueFuncs('Drupal CRUD REST call: Delete User'));
}); |
Check User DELETEVerify that our user was deleted in the server. Note that we're using the new jQuery deferreds approach to this, because it's easier to write. This introduces a dependency on the jqueryupdate module, but if you're developing a Backbone app, you should probably be using jqueryupdate anyhow. | asyncQueue.queue('asyncQueue', function() {
self.testUser.fetch().success(function(model, res) {
ok(false, Drupal.t('User not deleted properly. Post-delete fetch was successful when should not be.'));
asyncQueue.dequeue('asyncQueue');
}).error(function() {
ok(true, Drupal.t('User deleted in database. Could not retrieve after destroy.'));
asyncQueue.dequeue('asyncQueue');
});
}); |
End test.Last queue item: wrap up this test by restarting QUnit's asynchronous testing. | asyncQueue.queue('asyncQueue', function() {
start();
}); |
Run the queued operaitons: Go! | asyncQueue.dequeue('asyncQueue');
}, |
Teardown functionDelete all objects created on the server again, just in case we have some left over fixtures do to failed tests short circuiting the tests. | teardown: function() {
if (this.testNode) { this.testNode.destroy(); }
if (this.testUser) { this.testUser.destroy(); }
if (this.testComment) { this.testComment.destroy(); }
}
};
})(jQuery);
|