summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarren Smith <garren.smith@gmail.com>2013-08-21 16:50:35 +0200
committerGarren Smith <garren.smith@gmail.com>2013-08-22 17:39:25 +0200
commitdd2272cef08aac6865bccbc36a786b92ed85ede5 (patch)
tree0dd86f1f4cf1f79add8c01c2cf443bd12810c716
parentb65f11ff93223571175d6a9b39e9d55cc9d1bdec (diff)
downloadcouchdb-dd2272cef08aac6865bccbc36a786b92ed85ede5.tar.gz
Fauxton: Add active task tests
Also improve testing framework
-rw-r--r--src/fauxton/Gruntfile.js12
-rw-r--r--src/fauxton/app/addons/activetasks/tests/viewsSpec.js139
-rw-r--r--src/fauxton/app/addons/activetasks/views.js41
-rw-r--r--src/fauxton/test/core/layoutSpec.js94
-rw-r--r--src/fauxton/test/mocha/testUtils.js27
-rw-r--r--src/fauxton/test/runner.html1
6 files changed, 290 insertions, 24 deletions
diff --git a/src/fauxton/Gruntfile.js b/src/fauxton/Gruntfile.js
index 1c58bb649..a548a9d98 100644
--- a/src/fauxton/Gruntfile.js
+++ b/src/fauxton/Gruntfile.js
@@ -180,8 +180,12 @@ module.exports = function(grunt) {
index_css: {
src: ["dist/debug/css/*.css", 'assets/css/*.css'],
dest: 'dist/debug/css/index.css'
- }
+ },
+ test_config_js: {
+ src: ["dist/debug/templates.js", "test/test.config.js"],
+ dest: 'test/test.config.js'
+ }
},
cssmin: {
@@ -330,12 +334,12 @@ module.exports = function(grunt) {
// on watch events configure jshint:all to only run on changed file
grunt.event.on('watch', function(action, filepath) {
- if (!!filepath.match(/.js$/)) {
+ if (!!filepath.match(/.js$/) && filepath.indexOf('test.config.js') === -1) {
grunt.config(['jshint', 'all'], filepath);
}
if (!!filepath.match(/[Ss]pec.js$/)) {
- grunt.task.run(['mochaSetup','mocha_phantomjs']);
+ grunt.task.run(['mochaSetup','jst', 'concat:test_config_js', 'mocha_phantomjs']);
}
});
@@ -381,7 +385,7 @@ module.exports = function(grunt) {
*/
// clean out previous build artefactsa and lint
grunt.registerTask('lint', ['clean', 'jshint']);
- grunt.registerTask('test', ['lint', 'mochaSetup', 'mocha_phantomjs']);
+ grunt.registerTask('test', ['lint', 'mochaSetup','jst', 'concat:test_config_js', 'mocha_phantomjs']);
// Fetch dependencies (from git or local dir), lint them and make load_addons
grunt.registerTask('dependencies', ['get_deps', 'gen_load_addons:default']);
// build templates, js and css
diff --git a/src/fauxton/app/addons/activetasks/tests/viewsSpec.js b/src/fauxton/app/addons/activetasks/tests/viewsSpec.js
new file mode 100644
index 000000000..395b60a79
--- /dev/null
+++ b/src/fauxton/app/addons/activetasks/tests/viewsSpec.js
@@ -0,0 +1,139 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+define([
+ 'api',
+ 'addons/activetasks/views',
+ 'addons/activetasks/resources',
+ 'testUtils'
+], function (FauxtonAPI, Views, Models, testUtils) {
+ var assert = testUtils.assert,
+ ViewSandbox = testUtils.ViewSandbox;
+
+ describe("TabMenu", function () {
+ var tabMenu;
+
+ beforeEach(function () {
+ var newtasks = new Models.Tasks({
+ currentView: "all",
+ id:'activeTasks'
+ });
+
+ tabMenu = new Views.TabMenu({
+ currentView: "all",
+ model: newtasks
+ });
+ });
+
+ describe("on change polling rate", function () {
+ var viewSandbox;
+ beforeEach(function () {
+ viewSandbox = new ViewSandbox();
+ viewSandbox.renderView(tabMenu);
+ });
+
+ afterEach(function () {
+ viewSandbox.remove();
+ });
+
+ it("Should set polling rate", function () {
+ $range = tabMenu.$('#pollingRange');
+ $range.val(15);
+ $range.trigger('change');
+
+ assert.equal(tabMenu.$('span').text(), 15);
+ });
+
+ it("Should clearInterval", function () {
+ $range = tabMenu.$('#pollingRange');
+ clearIntervalMock = sinon.spy(window,'clearInterval');
+ $range.trigger('change');
+
+ assert.ok(clearIntervalMock.calledOnce);
+
+ });
+
+ it("Should trigger update:poll event", function () {
+ var spy = sinon.spy();
+ Views.Events.on('update:poll', spy);
+ $range = tabMenu.$('#pollingRange');
+ $range.trigger('change');
+
+ assert.ok(spy.calledOnce);
+ });
+
+ });
+
+ describe('on request by type', function () {
+ var viewSandbox;
+ beforeEach(function () {
+ viewSandbox = new ViewSandbox();
+ viewSandbox.renderView(tabMenu);
+ });
+
+ afterEach(function () {
+ viewSandbox.remove();
+ });
+
+ it("should change model view", function () {
+ var spy = sinon.spy(tabMenu.model, 'changeView');
+ var $rep = tabMenu.$('li[data-type="replication"]');
+ $rep.click();
+ assert.ok(spy.calledOnce);
+ });
+
+ it("should set correct active tab", function () {
+ var spy = sinon.spy(tabMenu.model, 'changeView');
+ var $rep = tabMenu.$('li[data-type="replication"]');
+ $rep.click();
+ assert.ok($rep.hasClass('active'));
+ });
+
+ });
+
+ });
+
+ describe('DataSection', function () {
+ var viewSandbox, dataSection;
+ beforeEach(function () {
+ var newtasks = new Models.Tasks({
+ currentView: "all",
+ id:'activeTasks'
+ });
+ newtasks.parse([]);
+
+ dataSection = new Views.DataSection({
+ currentView: "all",
+ model: newtasks
+ });
+
+ viewSandbox = new ViewSandbox();
+ viewSandbox.renderView(dataSection);
+ });
+
+ afterEach(function () {
+ viewSandbox.remove();
+ });
+
+ describe('#setPolling', function () {
+
+ it('Should set polling interval', function () {
+ var spy = sinon.spy(window, 'setInterval');
+ dataSection.setPolling();
+ assert.ok(spy.calledOnce);
+ });
+
+ });
+
+
+
+ });
+});
diff --git a/src/fauxton/app/addons/activetasks/views.js b/src/fauxton/app/addons/activetasks/views.js
index 89feff26e..005d48717 100644
--- a/src/fauxton/app/addons/activetasks/views.js
+++ b/src/fauxton/app/addons/activetasks/views.js
@@ -26,7 +26,7 @@ function (app, FauxtonAPI, activetasks) {
};
- _.extend(Events, Backbone.Events);
+ Views.Events = _.extend(Events, Backbone.Events);
Views.TabMenu = FauxtonAPI.View.extend({
template: "addons/activetasks/templates/tabs",
@@ -43,11 +43,11 @@ function (app, FauxtonAPI, activetasks) {
};
},
afterRender: function(){
- $('.task-tabs').find('li').eq(0).addClass('active');
+ this.$('.task-tabs').find('li').eq(0).addClass('active');
},
changePollInterval: function(e){
- var range = $(e.currentTarget).val();
- $('label[for="pollingRange"] span').text(range);
+ var range = this.$(e.currentTarget).val();
+ this.$('label[for="pollingRange"] span').text(range);
pollingInfo.rate = range;
clearInterval(pollingInfo.intervalId);
Events.trigger('update:poll');
@@ -59,33 +59,30 @@ function (app, FauxtonAPI, activetasks) {
requestByType: function(e){
var currentTarget = e.currentTarget;
- datatype = $(currentTarget).attr("data-type");
+ datatype = this.$(currentTarget).attr("data-type");
- $('.task-tabs').find('li').removeClass('active');
- $(currentTarget).addClass('active');
+ this.$('.task-tabs').find('li').removeClass('active');
+ this.$(currentTarget).addClass('active');
this.model.changeView(datatype);
}
});
Views.DataSection = FauxtonAPI.View.extend({
showData: function(){
- var that = this,
- currentData = this.model.getCurrentViewData();
- //remove the old stuff in a nice clean way
+ var currentData = this.model.getCurrentViewData();
+
if (this.dataView) {
- this.dataView.remove();
+ this.dataView.update(currentData, this.model.get('currentView').replace('_',' '));
+ } else {
+ this.dataView = this.insertView( new Views.TableData({
+ collection: currentData,
+ currentView: this.model.get('currentView').replace('_',' ')
+ }));
}
-
- //add the new stuff
- this.dataView = that.insertView( new Views.TableData({
- collection: currentData,
- currentView: this.model.get('currentView').replace('_',' ')
- }));
-
},
showDataAndRender: function () {
this.showData();
- this.render();
+ this.dataView.render();
},
beforeRender: function () {
@@ -133,6 +130,12 @@ function (app, FauxtonAPI, activetasks) {
collection: this.collection
};
},
+
+ update: function (collection, currentView) {
+ this.collection = collection;
+ this.currentView = currentView;
+ },
+
beforeRender: function(){
//iterate over the collection to add each
this.collection.forEach(function(item) {
diff --git a/src/fauxton/test/core/layoutSpec.js b/src/fauxton/test/core/layoutSpec.js
new file mode 100644
index 000000000..3876b701a
--- /dev/null
+++ b/src/fauxton/test/core/layoutSpec.js
@@ -0,0 +1,94 @@
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+define([
+ 'modules/fauxton/layout',
+ 'testUtils'
+], function (Layout, testUtils) {
+ var assert = testUtils.assert;
+
+ describe("Faxuton Layout", function () {
+ var layout;
+
+ beforeEach(function () {
+ var navBar = new Backbone.View();
+ var apiBar = new Backbone.View();
+ layout = new Layout(navBar, apiBar);
+ });
+
+ describe('#setTemplate', function () {
+
+ it("Should set template without prefix", function () {
+ layout.setTemplate('myTemplate');
+
+ assert.equal(layout.layout.template, 'templates/layouts/myTemplate');
+
+ });
+
+ it("Should set template with prefix", function () {
+ layout.setTemplate({name: 'myTemplate', prefix: 'myPrefix/'});
+
+ assert.equal(layout.layout.template, 'myPrefix/myTemplate');
+ });
+
+ it("Should remove old views", function () {
+ var view = {
+ remove: function () {}
+ };
+
+ layout.layoutViews = {
+ 'selector': view
+ };
+
+ var mockRemove = sinon.spy(view, 'remove');
+ layout.setTemplate('myTemplate');
+ assert.ok(mockRemove.calledOnce);
+
+ });
+
+ it("Should render", function () {
+ var mockRender = sinon.spy(layout, 'render');
+
+ layout.setTemplate('myTemplate');
+
+ assert.ok(mockRender.calledOnce);
+
+ });
+
+ });
+
+ describe('#renderView', function () {
+
+ it('Should render existing view', function () {
+ var view = new Backbone.View();
+ var mockRender = sinon.spy(view, 'render');
+ layout.layoutViews = {
+ '#selector': view
+ };
+
+ var out = layout.renderView('#selector');
+
+ assert.ok(mockRender.calledOnce);
+ });
+
+ it('Should return false for non-existing view', function () {
+ var view = new Backbone.View();
+ layout.layoutViews = {
+ 'selector': view
+ };
+
+ var out = layout.renderView('wrongSelector');
+ assert.notOk(out, 'No view found');
+ });
+ });
+
+ });
+});
diff --git a/src/fauxton/test/mocha/testUtils.js b/src/fauxton/test/mocha/testUtils.js
index 08b46de61..3eb111830 100644
--- a/src/fauxton/test/mocha/testUtils.js
+++ b/src/fauxton/test/mocha/testUtils.js
@@ -13,13 +13,38 @@
define([
"chai",
"sinon-chai",
+ "underscore"
],
function(chai, sinonChai) {
chai.use(sinonChai);
+ var ViewSandbox = function () {
+ this.initialize();
+ };
+
+ _.extend(ViewSandbox.prototype, {
+ initialize: function () {
+ this.$el = $('<div></div>');
+ this.$ = this.$el.find;
+ },
+ views: [],
+ renderView: function (view) {
+ this.views.push(view);
+ this.$el.append(view.el);
+ view.render();
+ },
+
+ remove: function () {
+ _.each(this.views, function (view) {
+ view.remove();
+ }, this);
+ }
+ });
+
return {
chai: chai,
- assert: chai.assert
+ assert: chai.assert,
+ ViewSandbox: ViewSandbox
};
});
diff --git a/src/fauxton/test/runner.html b/src/fauxton/test/runner.html
index b86855ec7..b27fdda66 100644
--- a/src/fauxton/test/runner.html
+++ b/src/fauxton/test/runner.html
@@ -11,6 +11,7 @@
<script type="text/javascript">
// MOCHA SETUP
mocha.setup('bdd');
+ mocha.reporter('html');
</script>
<script data-main="./test.config.js" src="../assets/js/libs/require.js"></script>
</body>