summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGarren Smith <garren.smith@gmail.com>2014-02-19 15:23:52 +0200
committerGarren Smith <garren.smith@gmail.com>2014-03-03 11:18:42 +0200
commitf796b38ef2474bdfed5303a627136ee3ad8ea8d2 (patch)
tree54ecfbbd47c3bd4260295d6af83e844fa4014747
parent4e10385a13e335d00f5b342e32ac6964fbb6634f (diff)
downloadcouchdb-f796b38ef2474bdfed5303a627136ee3ad8ea8d2.tar.gz
Add new pagination algorithmn
-rw-r--r--src/fauxton/app/addons/documents/resources.js54
-rw-r--r--src/fauxton/app/addons/documents/routes.js105
-rw-r--r--src/fauxton/app/addons/documents/tests/resourcesSpec.js27
-rw-r--r--src/fauxton/app/addons/documents/views.js133
-rw-r--r--src/fauxton/app/addons/fauxton/base.js14
-rw-r--r--src/fauxton/app/addons/fauxton/components.js38
-rw-r--r--src/fauxton/app/addons/fauxton/tests/paginateSpec.js18
-rw-r--r--src/fauxton/test/mocha/chai.js804
-rw-r--r--src/fauxton/test/test.config.underscore4
9 files changed, 765 insertions, 432 deletions
diff --git a/src/fauxton/app/addons/documents/resources.js b/src/fauxton/app/addons/documents/resources.js
index c2f9a706c..6112bab28 100644
--- a/src/fauxton/app/addons/documents/resources.js
+++ b/src/fauxton/app/addons/documents/resources.js
@@ -18,6 +18,51 @@ define([
function(app, FauxtonAPI) {
var Documents = FauxtonAPI.addon();
+ Documents.paginate = {
+ next: function (docs, currentParams, perPage, _isAllDocs) {
+ var params = {limit: perPage, skip: 1},
+ doc = _.last(docs),
+ docId = '',
+ lastId = '',
+ isView = !!!_isAllDocs,
+ key;
+
+ if (currentParams.keys) {
+ throw "Cannot paginate _all_docs with keys";
+ }
+
+ if (_.isUndefined(doc)) {
+ throw "Require docs to paginate";
+ }
+
+ params = _.reduce(['reduce', 'keys', 'endkey', 'descending', 'inclusive_end'], function (params, p) {
+ if (_.has(currentParams, p)) {
+ params[p] = currentParams[p];
+ }
+ return params;
+ }, params);
+
+ lastId = doc.id || doc._id;
+
+ if (isView) {
+ key = doc.key;
+ docId = lastId;
+ } else {
+ docId = key = lastId;
+ }
+
+ if (isView && !currentParams.keys) {
+ params.startkey_docid = docId;
+ params.startkey = key;
+ } else if (currentParams.startkey) {
+ params.startkey = key;
+ } else {
+ params.startkey_docid = docId;
+ }
+ return params;
+ }
+ };
+
Documents.Doc = FauxtonAPI.Model.extend({
idAttribute: "_id",
documentation: function(){
@@ -274,6 +319,7 @@ function(app, FauxtonAPI) {
Documents.AllDocs = FauxtonAPI.Collection.extend({
model: Documents.Doc,
+ isAllDocs: true,
documentation: function(){
return "docs";
},
@@ -330,6 +376,10 @@ function(app, FauxtonAPI) {
this.params.limit = limit;
},
+ updateParams: function (params) {
+ this.params = params;
+ },
+
nextPage: function (num, lastId) {
if (!lastId) {
var doc = this.last();
@@ -478,6 +528,10 @@ function(app, FauxtonAPI) {
return this.url('app');
},
+ updateParams: function (params) {
+ this.params = params;
+ },
+
updateLimit: function (limit) {
if (this.params.startkey_docid && this.params.startkey) {
//we are paginating so set limit + 1
diff --git a/src/fauxton/app/addons/documents/routes.js b/src/fauxton/app/addons/documents/routes.js
index 0d143dedc..5ce66b18d 100644
--- a/src/fauxton/app/addons/documents/routes.js
+++ b/src/fauxton/app/addons/documents/routes.js
@@ -160,8 +160,8 @@ function(app, FauxtonAPI, Documents, Databases) {
},
initialize: function (route, masterLayout, options) {
- var docOptions = app.getParams();
- docOptions.include_docs = true;
+ var docParams = app.getParams();
+ docParams.include_docs = true;
this.databaseName = options[0];
@@ -186,23 +186,32 @@ function(app, FauxtonAPI, Documents, Databases) {
return this.data.designDocs.fetch();
},
+ createParams: function (options) {
+ var urlParams = app.getParams(options);
+ return {
+ urlParams: urlParams,
+ docParams: _.extend(_.clone(urlParams), {limit: 20})
+ };
+ },
+
+ /*
+ * docParams are the options collection uses to fetch from the server
+ * urlParams are what are shown in the url and to the user
+ * They are not the same when paginating
+ */
allDocs: function(databaseName, options) {
- var docOptions = app.getParams(options),
- docLimit;
+ var params = this.createParams(options),
+ urlParams = params.urlParams,
+ docParams = params.docParams;
if (this.eventAllDocs) {
this.eventAllDocs = false;
return;
}
- if (docOptions.limit) {
- docLimit = docOptions.limit;
- }
-
- docOptions.limit = 20; //default per page
- this.data.database.buildAllDocs(docOptions);
+ this.data.database.buildAllDocs(docParams);
- if (docOptions.startkey && docOptions.startkey.indexOf('_design') > -1) {
+ if (docParams.startkey && docParams.startkey.indexOf('_design') > -1) {
this.sidebar.setSelectedTab('design-docs');
} else {
this.sidebar.setSelectedTab('all-docs');
@@ -218,12 +227,14 @@ function(app, FauxtonAPI, Documents, Databases) {
this.setView("#dashboard-upper-content", new Documents.Views.AllDocsLayout({
database: this.data.database,
collection: this.data.database.allDocs,
- params: docOptions
+ params: urlParams,
+ docParams: docParams
}));
this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
collection: this.data.database.allDocs,
- docLimit: parseInt(docLimit, 10)
+ docParams: docParams,
+ params: urlParams
}));
this.crumbs = [
@@ -313,43 +324,34 @@ function(app, FauxtonAPI, Documents, Databases) {
updateAllDocsFromView: function (event) {
var view = event.view,
- docOptions = app.getParams(),
+ params = this.createParams(),
+ urlParams = params.urlParams,
+ docParams = params.docParams,
ddoc = event.ddoc,
- docLimit;
+ collection;
- if (docOptions.limit) {
- docLimit = docOptions.limit;
- }
+ docParams.limit = this.documentsView.perPage();
- docOptions.limit = this.documentsView.perPage();
- this.documentsView && this.documentsView.remove();
+ this.documentsView.forceRender();
if (event.allDocs) {
this.eventAllDocs = true; // this is horrible. But I cannot get the trigger not to fire the route!
- this.data.database.buildAllDocs(docOptions);
- this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
- collection: this.data.database.allDocs,
- docLimit: parseInt(docLimit, 10)
- }));
- return;
- }
+ this.data.database.buildAllDocs(docParams);
+ collection = this.data.database.allDocs;
- this.data.indexedDocs = new Documents.IndexCollection(null, {
- database: this.data.database,
- design: ddoc,
- view: view,
- params: app.getParams()
- });
+ } else {
+ collection = this.data.indexedDocs = new Documents.IndexCollection(null, {
+ database: this.data.database,
+ design: ddoc,
+ view: view,
+ params: docParams
+ });
- this.documentsView = this.setView("#dashboard-lower-content", new Documents.Views.AllDocsList({
- database: this.data.database,
- collection: this.data.indexedDocs,
- nestedView: Documents.Views.Row,
- viewList: true,
- docLimit: parseInt(docLimit, 10)
- }));
+ this.apiUrl = [this.data.indexedDocs.url("apiurl"), "docs"];
+ }
- this.apiUrl = [this.data.indexedDocs.url("apiurl"), "docs"];
+ this.documentsView.setCollection(collection);
+ this.documentsView.setParams(docParams, urlParams);
},
updateAllDocsFromPreview: function (event) {
@@ -373,24 +375,23 @@ function(app, FauxtonAPI, Documents, Databases) {
},
perPageChange: function (perPage) {
+ this.perPage = perPage;
this.documentsView.collection.updateLimit(perPage);
this.documentsView.forceRender();
},
paginate: function (options) {
+ var params = options.params,
+ urlParams = app.getParams(),
+ collection = this.documentsView.collection;
+
this.documentsView.forceRender();
if (options.direction === 'next') {
- this.documentsView.collection.skipFirstItem = true;
- this.documentsView.collection.nextPage(options.perPage);
- } else {
- if (options.params && options.params.startkey) {
- this.documentsView.collection.skipFirstItem = true;
- } else {
- this.documentsView.collection.skipFirstItem = false;
- }
- this.documentsView.collection.previousPage(options.perPage, options.params);
+ params = Documents.paginate.next(collection.map(function (item) { return item.toJSON(); }), collection.params, options.perPage, !!collection.isAllDocs);
}
+
+ collection.updateParams(params);
},
reloadDesignDocs: function (event) {
@@ -421,9 +422,9 @@ function(app, FauxtonAPI, Documents, Databases) {
this.databaseName = options[0];
this.database = new Databases.Model({id: this.databaseName});
- var docOptions = app.getParams();
+ var docParams = app.getParams();
- this.database.buildChanges(docOptions);
+ this.database.buildChanges(docParams);
this.setView("#tabs", new Documents.Views.Tabs({
collection: this.designDocs,
diff --git a/src/fauxton/app/addons/documents/tests/resourcesSpec.js b/src/fauxton/app/addons/documents/tests/resourcesSpec.js
index 380a4e4fc..62506e6e4 100644
--- a/src/fauxton/app/addons/documents/tests/resourcesSpec.js
+++ b/src/fauxton/app/addons/documents/tests/resourcesSpec.js
@@ -32,20 +32,6 @@ define([
});
- it('Should return urlNext', function () {
- var url = collection.urlNextPage(20);
-
- assert.equal(url, 'database/databaseId/_design/myDoc/_view/?limit=21&reduce=false&startkey_docid=myId2&startkey=');
-
- });
-
- it('Should return urlPrevious', function () {
- var url = collection.urlPreviousPage(20, {limit: 21, reduce: false, startkey_docid: "myId1",startkey:"myId1"} );
-
- assert.equal(url, 'database/databaseId/_design/myDoc/_view/?limit=20&reduce=false&startkey_docid=myId1&startkey=myId1');
-
- });
-
});
describe('AllDocs', function () {
@@ -65,19 +51,6 @@ define([
});
- it('Should return urlNext', function () {
- var url = collection.urlNextPage(20);
-
- assert.equal(url, 'database/databaseId/_all_docs?limit=21&startkey_docid=%22myId2%22&startkey=%22myId2%22');
-
- });
-
- it('Should return urlPrevious', function () {
- var url = collection.urlPreviousPage(20, {limit: 21, startkey_docid: "myId1",startkey:"myId1"} );
- assert.equal(url, 'database/databaseId/_all_docs?limit=20&startkey_docid=myId1&startkey=myId1');
- });
-
-
});
});
diff --git a/src/fauxton/app/addons/documents/views.js b/src/fauxton/app/addons/documents/views.js
index c5ad1bb10..dea0bc7cc 100644
--- a/src/fauxton/app/addons/documents/views.js
+++ b/src/fauxton/app/addons/documents/views.js
@@ -415,8 +415,9 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
initialize: function (options) {
this.newView = options.newView || false;
this.pagination = options.pagination;
+ _.bindAll(this);
- this._perPage = 20;
+ this._perPage = options.perPageDefault || 20;
this.listenTo(this.collection, 'totalRows:decrement', this.render);
},
@@ -466,6 +467,10 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
perPage: function () {
return this._perPage;
+ },
+
+ setCollection: function (collection) {
+ this.collection = collection;
}
});
@@ -484,20 +489,16 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
toggleQuery: function (event) {
$('#dashboard-content').scrollTop(0);
- console.log('hi');
this.$('#query').toggle('slow');
},
beforeRender: function () {
- this.eventer = _.extend({}, Backbone.Events);
-
this.advancedOptions = this.insertView('#query', new Views.AdvancedOptions({
updateViewFn: this.updateAllDocs,
previewFn: this.previewView,
hasReduce: false,
showPreview: false,
database: this.database,
- eventer: this.eventer
}));
},
@@ -505,7 +506,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
if (this.params) {
this.advancedOptions.updateFromParams(this.params);
}
-
},
updateAllDocs: function (event, paramInfo) {
@@ -574,13 +574,16 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
this.rows = {};
this.viewList = !! options.viewList;
this.database = options.database;
+
if (options.ddocInfo) {
this.designDocs = options.ddocInfo.designDocs;
this.ddocID = options.ddocInfo.id;
}
this.newView = options.newView || false;
- this.docLimit = options.docLimit;
+ this.docParams = options.docParams;
+ this.params = options.params || {};
this.expandDocs = true;
+ this.perPageDefault = options.perPageDefault || 20;
},
establish: function() {
@@ -666,13 +669,13 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
this.pagination = new Components.IndexPagination({
collection: this.collection,
scrollToSelector: '#dashboard-content',
- docLimit: this.docLimit
+ docLimit: this.params.limit
});
},
cleanup: function () {
- this.pagination.remove();
- this.allDocsNumber.remove();
+ this.pagination && this.pagination.remove();
+ this.allDocsNumber && this.allDocsNumber.remove();
_.each(this.rows, function (row) {row.remove();});
},
@@ -682,13 +685,16 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
this.addPagination();
}
- this.insertView('#documents-pagination', this.pagination);
+ if (!this.params.keys) { //cannot paginate with keys
+ this.insertView('#documents-pagination', this.pagination);
+ }
if (!this.allDocsNumber) {
this.allDocsNumber = new Views.AllDocsNumber({
collection: this.collection,
newView: this.newView,
- pagination: this.pagination
+ pagination: this.pagination,
+ perPageDefault: this.perPageDefault
});
}
@@ -703,6 +709,21 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
}, this);
},
+ setCollection: function (collection) {
+ this.collection = collection;
+ this.pagination.setCollection(collection);
+ this.allDocsNumber.setCollection(collection);
+ },
+
+ setParams: function (docParams, urlParams) {
+ this.docParams = docParams;
+ this.params = urlParams;
+
+ if (this.params.limit) {
+ this.pagination.docLimit = this.params.limit;
+ }
+ },
+
afterRender: function(){
prettyPrint();
},
@@ -1007,73 +1028,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
}
});
- Views.AdvancedOptionsMenu = FauxtonAPI.View.extend({
- template: 'addons/documents/templates/advanced_options_menu',
- tagName: "div",
- className: "controls-group advanced-options-menu",
- events: {
- "click input": "updateRows",
- 'change #group-level': 'updateRows',
- 'click #query-nav': 'toggleMenu'
- },
-
- initialize: function (options) {
- this.hasReduce = options.hasReduce;
- this.eventer = options.eventer;
- },
-
- toggleMenu: function (event) {
- this.$('.checkbox').toggle();
- },
-
- updateRows: function (event) {
- var $groupLevel = this.$('#group-level-label'),
- params = {
- include_docs: false,
- reduce: false,
- group_level: 0
- };
-
- if (this.$('#include-docs-views').prop('checked')) {
- params.include_docs = true;
- }
-
- if (this.hasReduce && this.$('#reduce').prop('checked')) {
- params.reduce = true;
- params.group_level = this.$('#group-level option:selected').val();
- $groupLevel.show();
- } else {
- $groupLevel.hide();
- }
- this.eventer.trigger('options:param_update', params);
- },
-
- updateFromParams: function (params) {
- if (params.reduce) {
- var $reduce = this.$('#reduce');
- $reduce.prop("checked", true);
- this.$('#group-level-label').show();
- this.$('option[value="' + params.group_level + '"]').prop('selected', true);
-
- } else if (params.include_docs) {
- var $include_docs = this.$('#include-docs-views');
- $include_docs.prop("checked", true);
- }
- },
-
- serialize: function () {
- return {
- hasReduce: this.hasReduce
- };
- },
-
- setHasReduce: function (hasReduce) {
- this.hasReduce = hasReduce;
- }
-
- });
-
-
Views.AdvancedOptions = FauxtonAPI.View.extend({
template: "addons/documents/templates/advanced_options",
className: "advanced-options well",
@@ -1084,7 +1038,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
this.viewName = options.viewName;
this.updateViewFn = options.updateViewFn;
this.previewFn = options.previewFn;
- this.eventer = options.eventer;
if (typeof(options.hasReduce) === 'undefined') {
this.hasReduce = true;
@@ -1097,8 +1050,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
} else {
this.showPreview = options.showPreview;
}
-
- this.eventer && this.listenTo(this.eventer, 'options:param_update', this.optionsParamsUpdate);
},
events: {
@@ -1108,24 +1059,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, resizeColum
"click button.preview": "previewView"
},
- optionsParamsUpdate: function (params) {
- var $form = this.$el.find("form.view-query-update");
-
- if (!params.group_level) {
- this.$("select[name='group_level']").attr('disabled', 'disabled');
- }
-
- if (params.reduce && params.group_level) {
- $form.find("select[name='group_level']").val(params.group_level).removeAttr('disabled');
- delete params.group_level;
- }
-
- _.each(params, function(val, key) {
- $form.find("input[name='"+key+"']").prop('checked', val);
- });
- this.$('form.view-query-update').submit();
- },
-
beforeRender: function () {
if (this.viewName && this.ddocName) {
var buttonViews = FauxtonAPI.getExtensions('advancedOptions:ViewButton');
diff --git a/src/fauxton/app/addons/fauxton/base.js b/src/fauxton/app/addons/fauxton/base.js
index 35babb5f6..a6e462a28 100644
--- a/src/fauxton/app/addons/fauxton/base.js
+++ b/src/fauxton/app/addons/fauxton/base.js
@@ -45,7 +45,6 @@ function(app, FauxtonAPI, resizeColumns) {
}
});
-
Fauxton.initialize = function () {
app.footer = new Fauxton.Footer({el: "#footer-content"}),
app.navBar = new Fauxton.NavBar();
@@ -93,7 +92,7 @@ function(app, FauxtonAPI, resizeColumns) {
});
};
- Fauxton.Breadcrumbs = Backbone.View.extend({
+ Fauxton.Breadcrumbs = FauxtonAPI.View.extend({
template: "templates/fauxton/breadcrumbs",
serialize: function() {
@@ -114,10 +113,7 @@ function(app, FauxtonAPI, resizeColumns) {
}
});
- // TODO: this View should extend from FauxtonApi.View.
- // Chicken and egg problem, api.js extends fauxton/base.js.
- // Need to sort the loading order.
- Fauxton.Footer = Backbone.View.extend({
+ Fauxton.Footer = FauxtonAPI.View.extend({
template: "templates/fauxton/footer",
initialize: function() {
@@ -135,7 +131,7 @@ function(app, FauxtonAPI, resizeColumns) {
}
});
- Fauxton.NavBar = Backbone.View.extend({
+ Fauxton.NavBar = FauxtonAPI.View.extend({
className:"navbar",
template: "templates/fauxton/nav_bar",
// TODO: can we generate this list from the router?
@@ -260,7 +256,7 @@ function(app, FauxtonAPI, resizeColumns) {
// TODO: ADD ACTIVE CLASS
});
- Fauxton.ApiBar = Backbone.View.extend({
+ Fauxton.ApiBar = FauxtonAPI.View.extend({
template: "templates/fauxton/api_bar",
endpoint: '_all_docs',
@@ -304,7 +300,7 @@ function(app, FauxtonAPI, resizeColumns) {
});
- Fauxton.Notification = Backbone.View.extend({
+ Fauxton.Notification = FauxtonAPI.View.extend({
fadeTimer: 5000,
initialize: function(options) {
diff --git a/src/fauxton/app/addons/fauxton/components.js b/src/fauxton/app/addons/fauxton/components.js
index f8032fee6..a9f4ef4b5 100644
--- a/src/fauxton/app/addons/fauxton/components.js
+++ b/src/fauxton/app/addons/fauxton/components.js
@@ -71,14 +71,21 @@ function(app, FauxtonAPI, ace, spin) {
this.nextUrlfn = options.nextUrlfn;
this.scrollToSelector = options.scrollToSelector;
_.bindAll(this);
+ this.docLimit = options.docLimit || 1000000;
+ this.perPage = 20;
+ this.setDefaults();
+ },
+
+ setDefaults: function () {
this._pageNumber = [];
this._pageStart = 1;
- this.perPage = 20;
- this.docLimit = options.docLimit || 1000000;
this.paramsHistory = [];
+ this.enabled = true;
},
canShowPreviousfn: function () {
+ if (!this.enabled) { return this.enabled; }
+
if (this._pageStart === 1) {
return false;
}
@@ -86,6 +93,8 @@ function(app, FauxtonAPI, ace, spin) {
},
canShowNextfn: function () {
+ if (!this.enabled) { return this.enabled; }
+
if (this.collection.length < (this.perPage -1)) {
return false;
}
@@ -94,6 +103,10 @@ function(app, FauxtonAPI, ace, spin) {
return false;
}
+ if (this.collection.viewMeta && this.collection.viewMeta.total_rows <= this.pageStart() + this.perPage) {
+ return false;
+ }
+
return true;
},
@@ -103,11 +116,12 @@ function(app, FauxtonAPI, ace, spin) {
if (!this.canShowPreviousfn()) { return; }
this.decPageNumber();
+ var params = this.paramsHistory.pop();
FauxtonAPI.triggerRouteEvent('paginate', {
direction: 'previous',
perPage: this.perPage,
- params: this.paramsHistory.pop()
+ params: params
});
},
@@ -179,12 +193,22 @@ function(app, FauxtonAPI, ace, spin) {
},
pageEnd: function () {
- if (this.collection.length < this.perPage) {
- return this.page() + this.collection.length;
- }
+ return this.page() + this.collection.length;
+ },
- return this.page() + this.perPage;
+ disable: function () {
+ this.enabled = false;
+ },
+
+ enable: function () {
+ this.enabled = true;
+ },
+
+ setCollection: function (collection) {
+ this.collection = collection;
+ this.setDefaults();
}
+
});
//TODO allow more of the typeahead options.
diff --git a/src/fauxton/app/addons/fauxton/tests/paginateSpec.js b/src/fauxton/app/addons/fauxton/tests/paginateSpec.js
index 535e26f4a..8fc409a5d 100644
--- a/src/fauxton/app/addons/fauxton/tests/paginateSpec.js
+++ b/src/fauxton/app/addons/fauxton/tests/paginateSpec.js
@@ -58,15 +58,6 @@ define([
//FauxtonAPI.navigate.restore && FauxtonAPI.navigate.restore();
});
- it('Should navigate', function () {
- var navigateMock = sinon.spy(FauxtonAPI, 'navigate');
-
- paginate.$('a#next').click();
-
- assert.ok(navigateMock.calledOnce);
- FauxtonAPI.navigate.restore();
- });
-
it('Should trigger routeEvent', function () {
var navigateMock = sinon.spy(FauxtonAPI, 'triggerRouteEvent');
@@ -81,15 +72,6 @@ define([
describe('#previous', function () {
- it('Should navigate', function () {
- var navigateMock = sinon.spy(FauxtonAPI, 'navigate');
-
- paginate.$('a#previous').click();
-
- assert.ok(navigateMock.calledOnce);
- FauxtonAPI.navigate.restore();
- });
-
it('Should trigger routeEvent', function () {
var navigateMock = sinon.spy(FauxtonAPI, 'triggerRouteEvent');
diff --git a/src/fauxton/test/mocha/chai.js b/src/fauxton/test/mocha/chai.js
index 2a67f982b..9dd7b0a78 100644
--- a/src/fauxton/test/mocha/chai.js
+++ b/src/fauxton/test/mocha/chai.js
@@ -27,10 +27,14 @@ function require(path, parent, orig) {
// perform real require()
// by invoking the module's
// registered function
- if (!module.exports) {
- module.exports = {};
- module.client = module.component = true;
- module.call(this, module.exports, require.relative(resolved), module);
+ if (!module._resolving && !module.exports) {
+ var mod = {};
+ mod.exports = {};
+ mod.client = mod.component = true;
+ module._resolving = true;
+ module.call(this, mod.exports, require.relative(resolved), mod);
+ delete module._resolving;
+ module.exports = mod.exports;
}
return module.exports;
@@ -309,6 +313,411 @@ AssertionError.prototype.toJSON = function (stack) {
};
});
+require.register("chaijs-type-detect/lib/type.js", function(exports, require, module){
+/*!
+ * type-detect
+ * Copyright(c) 2013 jake luer <jake@alogicalparadox.com>
+ * MIT Licensed
+ */
+
+/*!
+ * Primary Exports
+ */
+
+var exports = module.exports = getType;
+
+/*!
+ * Detectable javascript natives
+ */
+
+var natives = {
+ '[object Array]': 'array'
+ , '[object RegExp]': 'regexp'
+ , '[object Function]': 'function'
+ , '[object Arguments]': 'arguments'
+ , '[object Date]': 'date'
+};
+
+/**
+ * ### typeOf (obj)
+ *
+ * Use several different techniques to determine
+ * the type of object being tested.
+ *
+ *
+ * @param {Mixed} object
+ * @return {String} object type
+ * @api public
+ */
+
+function getType (obj) {
+ var str = Object.prototype.toString.call(obj);
+ if (natives[str]) return natives[str];
+ if (obj === null) return 'null';
+ if (obj === undefined) return 'undefined';
+ if (obj === Object(obj)) return 'object';
+ return typeof obj;
+}
+
+exports.Library = Library;
+
+/**
+ * ### Library
+ *
+ * Create a repository for custom type detection.
+ *
+ * ```js
+ * var lib = new type.Library;
+ * ```
+ *
+ */
+
+function Library () {
+ this.tests = {};
+}
+
+/**
+ * #### .of (obj)
+ *
+ * Expose replacement `typeof` detection to the library.
+ *
+ * ```js
+ * if ('string' === lib.of('hello world')) {
+ * // ...
+ * }
+ * ```
+ *
+ * @param {Mixed} object to test
+ * @return {String} type
+ */
+
+Library.prototype.of = getType;
+
+/**
+ * #### .define (type, test)
+ *
+ * Add a test to for the `.test()` assertion.
+ *
+ * Can be defined as a regular expression:
+ *
+ * ```js
+ * lib.define('int', /^[0-9]+$/);
+ * ```
+ *
+ * ... or as a function:
+ *
+ * ```js
+ * lib.define('bln', function (obj) {
+ * if ('boolean' === lib.of(obj)) return true;
+ * var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ];
+ * if ('string' === lib.of(obj)) obj = obj.toLowerCase();
+ * return !! ~blns.indexOf(obj);
+ * });
+ * ```
+ *
+ * @param {String} type
+ * @param {RegExp|Function} test
+ * @api public
+ */
+
+Library.prototype.define = function (type, test) {
+ if (arguments.length === 1) return this.tests[type];
+ this.tests[type] = test;
+ return this;
+};
+
+/**
+ * #### .test (obj, test)
+ *
+ * Assert that an object is of type. Will first
+ * check natives, and if that does not pass it will
+ * use the user defined custom tests.
+ *
+ * ```js
+ * assert(lib.test('1', 'int'));
+ * assert(lib.test('yes', 'bln'));
+ * ```
+ *
+ * @param {Mixed} object
+ * @param {String} type
+ * @return {Boolean} result
+ * @api public
+ */
+
+Library.prototype.test = function (obj, type) {
+ if (type === getType(obj)) return true;
+ var test = this.tests[type];
+
+ if (test && 'regexp' === getType(test)) {
+ return test.test(obj);
+ } else if (test && 'function' === getType(test)) {
+ return test(obj);
+ } else {
+ throw new ReferenceError('Type test "' + type + '" not defined or invalid.');
+ }
+};
+
+});
+require.register("chaijs-deep-eql/lib/eql.js", function(exports, require, module){
+/*!
+ * deep-eql
+ * Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com>
+ * MIT Licensed
+ */
+
+/*!
+ * Module dependencies
+ */
+
+var type = require('type-detect');
+
+/*!
+ * Buffer.isBuffer browser shim
+ */
+
+var Buffer;
+try { Buffer = require('buffer').Buffer; }
+catch(ex) {
+ Buffer = {};
+ Buffer.isBuffer = function() { return false; }
+}
+
+/*!
+ * Primary Export
+ */
+
+module.exports = deepEqual;
+
+/**
+ * Assert super-strict (egal) equality between
+ * two objects of any type.
+ *
+ * @param {Mixed} a
+ * @param {Mixed} b
+ * @param {Array} memoised (optional)
+ * @return {Boolean} equal match
+ */
+
+function deepEqual(a, b, m) {
+ if (sameValue(a, b)) {
+ return true;
+ } else if ('date' === type(a)) {
+ return dateEqual(a, b);
+ } else if ('regexp' === type(a)) {
+ return regexpEqual(a, b);
+ } else if (Buffer.isBuffer(a)) {
+ return bufferEqual(a, b);
+ } else if ('arguments' === type(a)) {
+ return argumentsEqual(a, b, m);
+ } else if (!typeEqual(a, b)) {
+ return false;
+ } else if (('object' !== type(a) && 'object' !== type(b))
+ && ('array' !== type(a) && 'array' !== type(b))) {
+ return sameValue(a, b);
+ } else {
+ return objectEqual(a, b, m);
+ }
+}
+
+/*!
+ * Strict (egal) equality test. Ensures that NaN always
+ * equals NaN and `-0` does not equal `+0`.
+ *
+ * @param {Mixed} a
+ * @param {Mixed} b
+ * @return {Boolean} equal match
+ */
+
+function sameValue(a, b) {
+ if (a === b) return a !== 0 || 1 / a === 1 / b;
+ return a !== a && b !== b;
+}
+
+/*!
+ * Compare the types of two given objects and
+ * return if they are equal. Note that an Array
+ * has a type of `array` (not `object`) and arguments
+ * have a type of `arguments` (not `array`/`object`).
+ *
+ * @param {Mixed} a
+ * @param {Mixed} b
+ * @return {Boolean} result
+ */
+
+function typeEqual(a, b) {
+ return type(a) === type(b);
+}
+
+/*!
+ * Compare two Date objects by asserting that
+ * the time values are equal using `saveValue`.
+ *
+ * @param {Date} a
+ * @param {Date} b
+ * @return {Boolean} result
+ */
+
+function dateEqual(a, b) {
+ if ('date' !== type(b)) return false;
+ return sameValue(a.getTime(), b.getTime());
+}
+
+/*!
+ * Compare two regular expressions by converting them
+ * to string and checking for `sameValue`.
+ *
+ * @param {RegExp} a
+ * @param {RegExp} b
+ * @return {Boolean} result
+ */
+
+function regexpEqual(a, b) {
+ if ('regexp' !== type(b)) return false;
+ return sameValue(a.toString(), b.toString());
+}
+
+/*!
+ * Assert deep equality of two `arguments` objects.
+ * Unfortunately, these must be sliced to arrays
+ * prior to test to ensure no bad behavior.
+ *
+ * @param {Arguments} a
+ * @param {Arguments} b
+ * @param {Array} memoize (optional)
+ * @return {Boolean} result
+ */
+
+function argumentsEqual(a, b, m) {
+ if ('arguments' !== type(b)) return false;
+ a = [].slice.call(a);
+ b = [].slice.call(b);
+ return deepEqual(a, b, m);
+}
+
+/*!
+ * Get enumerable properties of a given object.
+ *
+ * @param {Object} a
+ * @return {Array} property names
+ */
+
+function enumerable(a) {
+ var res = [];
+ for (var key in a) res.push(key);
+ return res;
+}
+
+/*!
+ * Simple equality for flat iterable objects
+ * such as Arrays or Node.js buffers.
+ *
+ * @param {Iterable} a
+ * @param {Iterable} b
+ * @return {Boolean} result
+ */
+
+function iterableEqual(a, b) {
+ if (a.length !== b.length) return false;
+
+ var i = 0;
+ var match = true;
+
+ for (; i < a.length; i++) {
+ if (a[i] !== b[i]) {
+ match = false;
+ break;
+ }
+ }
+
+ return match;
+}
+
+/*!
+ * Extension to `iterableEqual` specifically
+ * for Node.js Buffers.
+ *
+ * @param {Buffer} a
+ * @param {Mixed} b
+ * @return {Boolean} result
+ */
+
+function bufferEqual(a, b) {
+ if (!Buffer.isBuffer(b)) return false;
+ return iterableEqual(a, b);
+}
+
+/*!
+ * Block for `objectEqual` ensuring non-existing
+ * values don't get in.
+ *
+ * @param {Mixed} object
+ * @return {Boolean} result
+ */
+
+function isValue(a) {
+ return a !== null && a !== undefined;
+}
+
+/*!
+ * Recursively check the equality of two objects.
+ * Once basic sameness has been established it will
+ * defer to `deepEqual` for each enumerable key
+ * in the object.
+ *
+ * @param {Mixed} a
+ * @param {Mixed} b
+ * @return {Boolean} result
+ */
+
+function objectEqual(a, b, m) {
+ if (!isValue(a) || !isValue(b)) {
+ return false;
+ }
+
+ if (a.prototype !== b.prototype) {
+ return false;
+ }
+
+ var i;
+ if (m) {
+ for (i = 0; i < m.length; i++) {
+ if ((m[i][0] === a && m[i][1] === b)
+ || (m[i][0] === b && m[i][1] === a)) {
+ return true;
+ }
+ }
+ } else {
+ m = [];
+ }
+
+ try {
+ var ka = enumerable(a);
+ var kb = enumerable(b);
+ } catch (ex) {
+ return false;
+ }
+
+ ka.sort();
+ kb.sort();
+
+ if (!iterableEqual(ka, kb)) {
+ return false;
+ }
+
+ m.push([ a, b ]);
+
+ var key;
+ for (i = ka.length - 1; i >= 0; i--) {
+ key = ka[i];
+ if (!deepEqual(a[key], b[key], m)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+});
require.register("chai/index.js", function(exports, require, module){
module.exports = require('./lib/chai');
@@ -316,7 +725,7 @@ module.exports = require('./lib/chai');
require.register("chai/lib/chai.js", function(exports, require, module){
/*!
* chai
- * Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -327,7 +736,7 @@ var used = []
* Chai version
*/
-exports.version = '1.7.2';
+exports.version = '1.8.1';
/*!
* Assertion Error
@@ -400,7 +809,7 @@ require.register("chai/lib/chai/assertion.js", function(exports, require, module
/*!
* chai
* http://chaijs.com
- * Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -480,6 +889,10 @@ module.exports = function (_chai, util) {
util.overwriteMethod(this.prototype, name, fn);
};
+ Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) {
+ util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior);
+ };
+
/*!
* ### .assert(expression, message, negateMessage, expected, actual)
*
@@ -533,7 +946,7 @@ require.register("chai/lib/chai/core/assertions.js", function(exports, require,
/*!
* chai
* http://chaijs.com
- * Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -545,7 +958,7 @@ module.exports = function (chai, _) {
/**
* ### Language Chains
*
- * The following are provide as chainable getters to
+ * The following are provided as chainable getters to
* improve the readability of your assertions. They
* do not provide an testing capability unless they
* have been overwritten by a plugin.
@@ -558,6 +971,7 @@ module.exports = function (chai, _) {
* - is
* - that
* - and
+ * - has
* - have
* - with
* - at
@@ -569,7 +983,7 @@ module.exports = function (chai, _) {
*/
[ 'to', 'be', 'been'
- , 'is', 'and', 'have'
+ , 'is', 'and', 'has', 'have'
, 'with', 'that', 'at'
, 'of', 'same' ].forEach(function (chain) {
Assertion.addProperty(chain, function () {
@@ -677,9 +1091,21 @@ module.exports = function (chai, _) {
function include (val, msg) {
if (msg) flag(this, 'message', msg);
- var obj = flag(this, 'object')
+ var obj = flag(this, 'object');
+
+ if (_.type(val) === 'object') {
+ if (!flag(this, 'negate')) {
+ for (var k in val) new Assertion(obj).property(k, val[k]);
+ return;
+ }
+ var subset = {}
+ for (var k in val) subset[k] = obj[k]
+ var expected = _.eql(subset, val);
+ } else {
+ var expected = obj && ~obj.indexOf(val)
+ }
this.assert(
- ~obj.indexOf(val)
+ expected
, 'expected #{this} to include ' + _.inspect(val)
, 'expected #{this} to not include ' + _.inspect(val));
}
@@ -776,8 +1202,8 @@ module.exports = function (chai, _) {
*
* Asserts that the target is `undefined`.
*
- * expect(undefined).to.be.undefined;
- * expect(null).to.not.be.undefined;
+ * expect(undefined).to.be.undefined;
+ * expect(null).to.not.be.undefined;
*
* @name undefined
* @api public
@@ -1534,6 +1960,7 @@ module.exports = function (chai, _) {
* @param {String|RegExp} expected error message
* @param {String} message _optional_
* @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
+ * @returns error for chaining (null if no error)
* @api public
*/
@@ -1558,7 +1985,10 @@ module.exports = function (chai, _) {
constructor = null;
errMsg = null;
} else if (typeof constructor === 'function') {
- name = (new constructor()).name;
+ name = constructor.prototype.name || constructor.name;
+ if (name === 'Error' && constructor !== Error) {
+ name = (new constructor()).name;
+ }
} else {
constructor = null;
}
@@ -1572,12 +2002,14 @@ module.exports = function (chai, _) {
err === desiredError
, 'expected #{this} to throw #{exp} but #{act} was thrown'
, 'expected #{this} to not throw #{exp}'
- , desiredError
- , err
+ , (desiredError instanceof Error ? desiredError.toString() : desiredError)
+ , (err instanceof Error ? err.toString() : err)
);
+ flag(this, 'object', err);
return this;
}
+
// next, check constructor
if (constructor) {
this.assert(
@@ -1585,11 +2017,15 @@ module.exports = function (chai, _) {
, 'expected #{this} to throw #{exp} but #{act} was thrown'
, 'expected #{this} to not throw #{exp} but #{act} was thrown'
, name
- , err
+ , (err instanceof Error ? err.toString() : err)
);
- if (!errMsg) return this;
+ if (!errMsg) {
+ flag(this, 'object', err);
+ return this;
+ }
}
+
// next, check message
var message = 'object' === _.type(err) && "message" in err
? err.message
@@ -1604,6 +2040,7 @@ module.exports = function (chai, _) {
, message
);
+ flag(this, 'object', err);
return this;
} else if ((message != null) && errMsg && 'string' === typeof errMsg) {
this.assert(
@@ -1614,6 +2051,7 @@ module.exports = function (chai, _) {
, message
);
+ flag(this, 'object', err);
return this;
} else {
thrown = true;
@@ -1636,9 +2074,11 @@ module.exports = function (chai, _) {
thrown === true
, 'expected #{this} to throw ' + expectedThrown + actuallyGot
, 'expected #{this} to not throw ' + expectedThrown + actuallyGot
- , desiredError
- , thrownError
+ , (desiredError instanceof Error ? desiredError.toString() : desiredError)
+ , (thrownError instanceof Error ? thrownError.toString() : thrownError)
);
+
+ flag(this, 'object', thrownError);
};
Assertion.addMethod('throw', assertThrows);
@@ -1657,8 +2097,8 @@ module.exports = function (chai, _) {
* To check if a constructor will respond to a static function,
* set the `itself` flag.
*
- * Klass.baz = function(){};
- * expect(Klass).itself.to.respondTo('baz');
+ * Klass.baz = function(){};
+ * expect(Klass).itself.to.respondTo('baz');
*
* @name respondTo
* @param {String} method
@@ -1686,12 +2126,12 @@ module.exports = function (chai, _) {
*
* Sets the `itself` flag, later used by the `respondTo` assertion.
*
- * function Foo() {}
- * Foo.bar = function() {}
- * Foo.prototype.baz = function() {}
+ * function Foo() {}
+ * Foo.bar = function() {}
+ * Foo.prototype.baz = function() {}
*
- * expect(Foo).itself.to.respondTo('bar');
- * expect(Foo).itself.not.to.respondTo('baz');
+ * expect(Foo).itself.to.respondTo('bar');
+ * expect(Foo).itself.not.to.respondTo('baz');
*
* @name itself
* @api public
@@ -1805,7 +2245,7 @@ module.exports = function (chai, _) {
require.register("chai/lib/chai/interface/assert.js", function(exports, require, module){
/*!
* chai
- * Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -1860,13 +2300,12 @@ module.exports = function (chai, util) {
*/
assert.fail = function (actual, expected, message, operator) {
- throw new chai.AssertionError({
+ message = message || 'assert.fail()';
+ throw new chai.AssertionError(message, {
actual: actual
, expected: expected
- , message: message
, operator: operator
- , stackStartFunction: assert.fail
- });
+ }, assert.fail);
};
/**
@@ -2462,19 +2901,7 @@ module.exports = function (chai, util) {
*/
assert.include = function (exp, inc, msg) {
- var obj = new Assertion(exp, msg);
-
- if (Array.isArray(exp)) {
- obj.to.include(inc);
- } else if ('string' === typeof exp) {
- obj.to.contain.string(inc);
- } else {
- throw new chai.AssertionError(
- 'expected an array or string'
- , null
- , assert.include
- );
- }
+ new Assertion(exp, msg).include(inc);
};
/**
@@ -2494,19 +2921,7 @@ module.exports = function (chai, util) {
*/
assert.notInclude = function (exp, inc, msg) {
- var obj = new Assertion(exp, msg);
-
- if (Array.isArray(exp)) {
- obj.to.not.include(inc);
- } else if ('string' === typeof exp) {
- obj.to.not.contain.string(inc);
- } else {
- throw new chai.AssertionError(
- 'expected an array or string'
- , null
- , assert.notInclude
- );
- }
+ new Assertion(exp, msg).not.include(inc);
};
/**
@@ -2750,7 +3165,8 @@ module.exports = function (chai, util) {
errt = null;
}
- new Assertion(fn, msg).to.Throw(errt, errs);
+ var assertErr = new Assertion(fn, msg).to.Throw(errt, errs);
+ return flag(assertErr, 'object');
};
/**
@@ -2888,7 +3304,7 @@ module.exports = function (chai, util) {
require.register("chai/lib/chai/interface/expect.js", function(exports, require, module){
/*!
* chai
- * Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -2903,7 +3319,7 @@ module.exports = function (chai, util) {
require.register("chai/lib/chai/interface/should.js", function(exports, require, module){
/*!
* chai
- * Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -2982,7 +3398,7 @@ module.exports = function (chai, util) {
require.register("chai/lib/chai/utils/addChainableMethod.js", function(exports, require, module){
/*!
* Chai - addChainingMethod utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -3037,15 +3453,27 @@ var call = Function.prototype.call,
*/
module.exports = function (ctx, name, method, chainingBehavior) {
- if (typeof chainingBehavior !== 'function')
+ if (typeof chainingBehavior !== 'function') {
chainingBehavior = function () { };
+ }
+
+ var chainableBehavior = {
+ method: method
+ , chainingBehavior: chainingBehavior
+ };
+
+ // save the methods so we can overwrite them later, if we need to.
+ if (!ctx.__methods) {
+ ctx.__methods = {};
+ }
+ ctx.__methods[name] = chainableBehavior;
Object.defineProperty(ctx, name,
{ get: function () {
- chainingBehavior.call(this);
+ chainableBehavior.chainingBehavior.call(this);
var assert = function () {
- var result = method.apply(this, arguments);
+ var result = chainableBehavior.method.apply(this, arguments);
return result === undefined ? this : result;
};
@@ -3079,7 +3507,7 @@ module.exports = function (ctx, name, method, chainingBehavior) {
require.register("chai/lib/chai/utils/addMethod.js", function(exports, require, module){
/*!
* Chai - addMethod utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -3119,7 +3547,7 @@ module.exports = function (ctx, name, method) {
require.register("chai/lib/chai/utils/addProperty.js", function(exports, require, module){
/*!
* Chai - addProperty utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -3159,142 +3587,10 @@ module.exports = function (ctx, name, getter) {
};
});
-require.register("chai/lib/chai/utils/eql.js", function(exports, require, module){
-// This is (almost) directly from Node.js assert
-// https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/assert.js
-
-module.exports = _deepEqual;
-
-var getEnumerableProperties = require('./getEnumerableProperties');
-
-// for the browser
-var Buffer;
-try {
- Buffer = require('buffer').Buffer;
-} catch (ex) {
- Buffer = {
- isBuffer: function () { return false; }
- };
-}
-
-function _deepEqual(actual, expected, memos) {
-
- // 7.1. All identical values are equivalent, as determined by ===.
- if (actual === expected) {
- return true;
-
- } else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
- if (actual.length != expected.length) return false;
-
- for (var i = 0; i < actual.length; i++) {
- if (actual[i] !== expected[i]) return false;
- }
-
- return true;
-
- // 7.2. If the expected value is a Date object, the actual value is
- // equivalent if it is also a Date object that refers to the same time.
- } else if (expected instanceof Date) {
- if (!(actual instanceof Date)) return false;
- return actual.getTime() === expected.getTime();
-
- // 7.3. Other pairs that do not both pass typeof value == 'object',
- // equivalence is determined by ==.
- } else if (typeof actual != 'object' && typeof expected != 'object') {
- return actual === expected;
-
- } else if (expected instanceof RegExp) {
- if (!(actual instanceof RegExp)) return false;
- return actual.toString() === expected.toString();
-
- // 7.4. For all other Object pairs, including Array objects, equivalence is
- // determined by having the same number of owned properties (as verified
- // with Object.prototype.hasOwnProperty.call), the same set of keys
- // (although not necessarily the same order), equivalent values for every
- // corresponding key, and an identical 'prototype' property. Note: this
- // accounts for both named and indexed properties on Arrays.
- } else {
- return objEquiv(actual, expected, memos);
- }
-}
-
-function isUndefinedOrNull(value) {
- return value === null || value === undefined;
-}
-
-function isArguments(object) {
- return Object.prototype.toString.call(object) == '[object Arguments]';
-}
-
-function objEquiv(a, b, memos) {
- if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
- return false;
-
- // an identical 'prototype' property.
- if (a.prototype !== b.prototype) return false;
-
- // check if we have already compared a and b
- var i;
- if (memos) {
- for(i = 0; i < memos.length; i++) {
- if ((memos[i][0] === a && memos[i][1] === b) ||
- (memos[i][0] === b && memos[i][1] === a))
- return true;
- }
- } else {
- memos = [];
- }
-
- //~~~I've managed to break Object.keys through screwy arguments passing.
- // Converting to array solves the problem.
- if (isArguments(a)) {
- if (!isArguments(b)) {
- return false;
- }
- a = pSlice.call(a);
- b = pSlice.call(b);
- return _deepEqual(a, b, memos);
- }
- try {
- var ka = getEnumerableProperties(a),
- kb = getEnumerableProperties(b),
- key;
- } catch (e) {//happens when one is a string literal and the other isn't
- return false;
- }
-
- // having the same number of owned properties (keys incorporates
- // hasOwnProperty)
- if (ka.length != kb.length)
- return false;
-
- //the same set of keys (although not necessarily the same order),
- ka.sort();
- kb.sort();
- //~~~cheap key test
- for (i = ka.length - 1; i >= 0; i--) {
- if (ka[i] != kb[i])
- return false;
- }
-
- // remember objects we have compared to guard against circular references
- memos.push([ a, b ]);
-
- //equivalent values for every corresponding key, and
- //~~~possibly expensive deep test
- for (i = ka.length - 1; i >= 0; i--) {
- key = ka[i];
- if (!_deepEqual(a[key], b[key], memos)) return false;
- }
-
- return true;
-}
-
-});
require.register("chai/lib/chai/utils/flag.js", function(exports, require, module){
/*!
* Chai - flag utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -3329,7 +3625,7 @@ module.exports = function (obj, key, value) {
require.register("chai/lib/chai/utils/getActual.js", function(exports, require, module){
/*!
* Chai - getActual utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -3351,7 +3647,7 @@ module.exports = function (obj, args) {
require.register("chai/lib/chai/utils/getEnumerableProperties.js", function(exports, require, module){
/*!
* Chai - getEnumerableProperties utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -3379,7 +3675,7 @@ module.exports = function getEnumerableProperties(object) {
require.register("chai/lib/chai/utils/getMessage.js", function(exports, require, module){
/*!
* Chai - message composition utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -3431,7 +3727,7 @@ module.exports = function (obj, args) {
require.register("chai/lib/chai/utils/getName.js", function(exports, require, module){
/*!
* Chai - getName utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -3454,7 +3750,7 @@ module.exports = function (func) {
require.register("chai/lib/chai/utils/getPathValue.js", function(exports, require, module){
/*!
* Chai - getPathValue utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* @see https://github.com/logicalparadox/filtr
* MIT Licensed
*/
@@ -3559,7 +3855,7 @@ function _getPathValue (parsed, obj) {
require.register("chai/lib/chai/utils/getProperties.js", function(exports, require, module){
/*!
* Chai - getProperties utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -3659,7 +3955,7 @@ exports.transferFlags = require('./transferFlags');
* Deep equal utility
*/
-exports.eql = require('./eql');
+exports.eql = require('deep-eql');
/*!
* Deep path value
@@ -3703,6 +3999,12 @@ exports.overwriteMethod = require('./overwriteMethod');
exports.addChainableMethod = require('./addChainableMethod');
+/*!
+ * Overwrite chainable method
+ */
+
+exports.overwriteChainableMethod = require('./overwriteChainableMethod');
+
});
require.register("chai/lib/chai/utils/inspect.js", function(exports, require, module){
@@ -4031,7 +4333,7 @@ function objectToString(o) {
require.register("chai/lib/chai/utils/objDisplay.js", function(exports, require, module){
/*!
* Chai - flag utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -4082,7 +4384,7 @@ module.exports = function (obj) {
require.register("chai/lib/chai/utils/overwriteMethod.js", function(exports, require, module){
/*!
* Chai - overwriteMethod utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -4136,7 +4438,7 @@ module.exports = function (ctx, name, method) {
require.register("chai/lib/chai/utils/overwriteProperty.js", function(exports, require, module){
/*!
* Chai - overwriteProperty utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -4190,10 +4492,66 @@ module.exports = function (ctx, name, getter) {
};
});
+require.register("chai/lib/chai/utils/overwriteChainableMethod.js", function(exports, require, module){
+/*!
+ * Chai - overwriteChainableMethod utility
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
+ * MIT Licensed
+ */
+
+/**
+ * ### overwriteChainableMethod (ctx, name, fn)
+ *
+ * Overwites an already existing chainable method
+ * and provides access to the previous function or
+ * property. Must return functions to be used for
+ * name.
+ *
+ * utils.overwriteChainableMethod(chai.Assertion.prototype, 'length',
+ * function (_super) {
+ * }
+ * , function (_super) {
+ * }
+ * );
+ *
+ * Can also be accessed directly from `chai.Assertion`.
+ *
+ * chai.Assertion.overwriteChainableMethod('foo', fn, fn);
+ *
+ * Then can be used as any other assertion.
+ *
+ * expect(myFoo).to.have.length(3);
+ * expect(myFoo).to.have.length.above(3);
+ *
+ * @param {Object} ctx object whose method / property is to be overwritten
+ * @param {String} name of method / property to overwrite
+ * @param {Function} method function that returns a function to be used for name
+ * @param {Function} chainingBehavior function that returns a function to be used for property
+ * @name overwriteChainableMethod
+ * @api public
+ */
+
+module.exports = function (ctx, name, method, chainingBehavior) {
+ var chainableBehavior = ctx.__methods[name];
+
+ var _chainingBehavior = chainableBehavior.chainingBehavior;
+ chainableBehavior.chainingBehavior = function () {
+ var result = chainingBehavior(_chainingBehavior).call(this);
+ return result === undefined ? this : result;
+ };
+
+ var _method = chainableBehavior.method;
+ chainableBehavior.method = function () {
+ var result = method(_method).apply(this, arguments);
+ return result === undefined ? this : result;
+ };
+};
+
+});
require.register("chai/lib/chai/utils/test.js", function(exports, require, module){
/*!
* Chai - test utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -4222,7 +4580,7 @@ module.exports = function (obj, args) {
require.register("chai/lib/chai/utils/transferFlags.js", function(exports, require, module){
/*!
* Chai - transferFlags utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -4269,7 +4627,7 @@ module.exports = function (assertion, object, includeAll) {
require.register("chai/lib/chai/utils/type.js", function(exports, require, module){
/*!
* Chai - type utility
- * Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
+ * Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
@@ -4314,17 +4672,25 @@ module.exports = function (obj) {
};
});
+
+
+
+
require.alias("chaijs-assertion-error/index.js", "chai/deps/assertion-error/index.js");
require.alias("chaijs-assertion-error/index.js", "chai/deps/assertion-error/index.js");
require.alias("chaijs-assertion-error/index.js", "assertion-error/index.js");
require.alias("chaijs-assertion-error/index.js", "chaijs-assertion-error/index.js");
-
-require.alias("chai/index.js", "chai/index.js");
-
-if (typeof exports == "object") {
+require.alias("chaijs-deep-eql/lib/eql.js", "chai/deps/deep-eql/lib/eql.js");
+require.alias("chaijs-deep-eql/lib/eql.js", "chai/deps/deep-eql/index.js");
+require.alias("chaijs-deep-eql/lib/eql.js", "deep-eql/index.js");
+require.alias("chaijs-type-detect/lib/type.js", "chaijs-deep-eql/deps/type-detect/lib/type.js");
+require.alias("chaijs-type-detect/lib/type.js", "chaijs-deep-eql/deps/type-detect/index.js");
+require.alias("chaijs-type-detect/lib/type.js", "chaijs-type-detect/index.js");
+require.alias("chaijs-deep-eql/lib/eql.js", "chaijs-deep-eql/index.js");
+require.alias("chai/index.js", "chai/index.js");if (typeof exports == "object") {
module.exports = require("chai");
} else if (typeof define == "function" && define.amd) {
- define(function(){ return require("chai"); });
+ define([], function(){ return require("chai"); });
} else {
this["chai"] = require("chai");
}})();
diff --git a/src/fauxton/test/test.config.underscore b/src/fauxton/test/test.config.underscore
index 5cebe7837..95494a4ed 100644
--- a/src/fauxton/test/test.config.underscore
+++ b/src/fauxton/test/test.config.underscore
@@ -7,7 +7,11 @@ require.config(
require([
"app",
<% _.each(testFiles, function (test) {%>
+ <% if (test[0] === '.') { %>
'../<%= test %>',
+ <% } else { %>
+ '<%= test %>',
+ <% } %>
<% }) %>
], function() {
if (window.mochaPhantomJS) { mochaPhantomJS.run(); }