couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From robertkowal...@apache.org
Subject fauxton commit: updated refs/heads/master to 455f0a5
Date Tue, 26 May 2015 10:16:13 GMT
Repository: couchdb-fauxton
Updated Branches:
  refs/heads/master 17e4d040a -> 455f0a53b


tests: don't delete _replicator every time

 - we just need the replicator db for one test, so do the cleanup
   just there. saves one request for all other tests

 - try to fix flaky tests

 - cleanup mocha tests
    - make react 13 compatible
    - do not patch jquery
    - fix async race conditions
    - do not couple tightly to implementation (event handlers)

 - a dedicated db for create databases

 - tests: createBadView - harden test

 - viewEdit.js fix

 - paginateAllDocs.js tweak

 - viewCreateBadView: work on selectors

 - delete meaningless test
     the div #globalnotifications exists always

 - .click -> clickWhenVisible

 - verifyInstallTest

 - add helpers, do not rely on notifications

 - add spy.restore()

 - make sure changes are there opening the page & before asserting

PR: #423
PR-URL: https://github.com/apache/couchdb-fauxton/pull/423
Reviewed-By: Benjamin Keen <ben.keen@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/455f0a53
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/455f0a53
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/455f0a53

Branch: refs/heads/master
Commit: 455f0a53b068b6e6fdbd17c6f050852cc60bad3b
Parents: 17e4d04
Author: Robert Kowalski <robertkowalski@apache.org>
Authored: Tue May 19 19:57:38 2015 +0200
Committer: Robert Kowalski <robertkowalski@apache.org>
Committed: Tue May 26 12:19:43 2015 +0200

----------------------------------------------------------------------
 .../tests/nightwatch/createsDatabase.js         |  24 +++-
 .../tests/nightwatch/deletesDatabase.js         |  10 +-
 .../nightwatch/deletesDatabaseSpecialChars.js   |  10 +-
 .../tests/changes.componentsSpec.react.jsx      |   1 +
 .../documents/tests/nightwatch/bulkDelete.js    |   2 -
 .../documents/tests/nightwatch/bulkSelect.js    |   6 +-
 .../documents/tests/nightwatch/changes.js       |   3 +-
 .../documents/tests/nightwatch/changesFilter.js |   5 +
 .../tests/nightwatch/createsDocument.js         |  11 +-
 .../tests/nightwatch/deleteDatabaseModal.js     |  20 ++-
 .../tests/nightwatch/editDocumentsFromView.js   |   3 +-
 .../documents/tests/nightwatch/lookaheadTray.js |   3 +-
 .../documents/tests/nightwatch/mangoIndex.js    |  11 +-
 .../documents/tests/nightwatch/mangoQuery.js    |   3 +-
 ...AfterEditingDocShouldShowAConfirmationBox.js |   8 +-
 .../tests/nightwatch/navigateFromNewDoc.js      |   8 +-
 .../tests/nightwatch/navigateToNewView.js       |   8 +-
 .../tests/nightwatch/paginateAllDocs.js         |   1 +
 .../switchDatabaseViaLookaheadTray.js           |   3 +-
 .../documents/tests/nightwatch/viewCreate.js    |  14 +-
 .../tests/nightwatch/viewCreateBadView.js       |  18 +--
 .../documents/tests/nightwatch/viewEdit.js      |  26 +++-
 .../tests/nightwatch/viewQueryOptions.js        |   2 +-
 .../tests/nightwatch/viewSaveManyTimes.js       |  52 --------
 .../fauxton/tests/componentsSpec.react.jsx      | 128 ++++++++-----------
 .../tests/nightwatch/testVerification.js        |   9 +-
 .../custom-commands/checkForDatabaseCreated.js  |  52 ++++++++
 .../custom-commands/checkForDatabaseDeleted.js  |  52 ++++++++
 .../custom-commands/checkForDocumentCreated.js  |  53 ++++++++
 .../custom-commands/checkForStringNotPresent.js |  55 ++++++++
 .../custom-commands/checkForStringPresent.js    |  55 ++++++++
 test/nightwatch_tests/helpers/helpers.js        |  13 +-
 32 files changed, 437 insertions(+), 232 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/databases/tests/nightwatch/createsDatabase.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/tests/nightwatch/createsDatabase.js b/app/addons/databases/tests/nightwatch/createsDatabase.js
index 9233aeb..4f6b1ee 100644
--- a/app/addons/databases/tests/nightwatch/createsDatabase.js
+++ b/app/addons/databases/tests/nightwatch/createsDatabase.js
@@ -10,15 +10,31 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
+var newDatabaseName = 'fauxton-selenium-tests-db-create';
+var helpers = require('../../../../../test/nightwatch_tests/helpers/helpers.js');
 module.exports = {
+
+  before: function (client, done) {
+    var nano = helpers.getNanoInstance();
+    nano.db.destroy(newDatabaseName, function (err, body, header) {
+      done();
+    });
+  },
+
+  after: function (client, done) {
+    var nano = helpers.getNanoInstance();
+    nano.db.destroy(newDatabaseName, function (err, body, header) {
+      done();
+    });
+  },
+
   'Creates a Database' : function (client) {
     var waitTime = client.globals.maxWaitTime,
-        newDatabaseName = client.globals.testDatabaseName,
         baseUrl = client.globals.test_settings.launch_url;
 
     client
       .loginToGUI()
-      .deleteDatabase(newDatabaseName) //need to delete the automatic database 'fauxton-selenium-tests' that has been set up before each test
+      .checkForDatabaseDeleted(newDatabaseName, waitTime)
       .url(baseUrl)
 
       // ensure the page has fully loaded
@@ -28,9 +44,7 @@ module.exports = {
       .waitForElementVisible('#js-new-database-name', waitTime, false)
       .setValue('#js-new-database-name', [newDatabaseName])
       .clickWhenVisible('#js-create-database', waitTime, false)
-      .waitForAttribute('#global-notifications', 'textContent', function (successAlertText) {
-        return (/Database created successfully/).test(successAlertText);
-      })
+      .checkForDatabaseCreated(newDatabaseName, waitTime)
       .url(baseUrl + '/_all_dbs')
       .waitForElementVisible('html', waitTime, false)
       .getText('html', function (result) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/databases/tests/nightwatch/deletesDatabase.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/tests/nightwatch/deletesDatabase.js b/app/addons/databases/tests/nightwatch/deletesDatabase.js
index 75ea8ee..a5249c0 100644
--- a/app/addons/databases/tests/nightwatch/deletesDatabase.js
+++ b/app/addons/databases/tests/nightwatch/deletesDatabase.js
@@ -27,16 +27,8 @@ module.exports = {
       .waitForElementVisible('#db-name', waitTime, false)
       .clickWhenVisible('#db-name', waitTime, false)
       .setValue('#db-name', [newDatabaseName, client.Keys.ENTER])
-      .waitForElementVisible('#global-notifications .alert.alert-info', waitTime, false)
-      .url(baseUrl + '/_all_dbs')
-      .waitForElementPresent('pre', waitTime, false)
-      .getText('body', function (result) {
-        var data = result.value,
-            createdDatabaseIsNotPresent = data.indexOf('"' + newDatabaseName + '"');
+      .checkForDatabaseDeleted(newDatabaseName, waitTime)
 
-        this.verify.ok(createdDatabaseIsNotPresent === -1,
-          'Checking if new database no longer shows up in _all_dbs.');
-      })
     .end();
   }
 };

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/databases/tests/nightwatch/deletesDatabaseSpecialChars.js
----------------------------------------------------------------------
diff --git a/app/addons/databases/tests/nightwatch/deletesDatabaseSpecialChars.js b/app/addons/databases/tests/nightwatch/deletesDatabaseSpecialChars.js
index 61b7c37..d43c330 100644
--- a/app/addons/databases/tests/nightwatch/deletesDatabaseSpecialChars.js
+++ b/app/addons/databases/tests/nightwatch/deletesDatabaseSpecialChars.js
@@ -27,16 +27,8 @@ module.exports = {
       .waitForElementPresent('#db-name', waitTime, false)
       .clickWhenVisible('#db-name', waitTime, false)
       .setValue('#db-name', [newDatabaseName, client.Keys.ENTER])
-      .waitForElementVisible('#global-notifications .alert.alert-info', waitTime, false)
-      .url(baseUrl + '/_all_dbs')
-      .waitForElementPresent('pre', waitTime, false)
-      .getText('body', function (result) {
-        var data = result.value,
-            createdDatabaseIsNotPresent = data.indexOf('"' + newDatabaseName + '"');
+      .checkForDatabaseDeleted(newDatabaseName, waitTime)
 
-        this.verify.ok(createdDatabaseIsNotPresent === -1,
-          'Checking if new database no longer shows up in _all_dbs.');
-      })
     .end();
   }
 };

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/changes/tests/changes.componentsSpec.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/documents/changes/tests/changes.componentsSpec.react.jsx b/app/addons/documents/changes/tests/changes.componentsSpec.react.jsx
index ecf3f35..155206c 100644
--- a/app/addons/documents/changes/tests/changes.componentsSpec.react.jsx
+++ b/app/addons/documents/changes/tests/changes.componentsSpec.react.jsx
@@ -45,6 +45,7 @@ define([
       });
 
       afterEach(function () {
+        spy.restore();
         Stores.changesStore.reset();
         React.unmountComponentAtNode(container);
       });

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/bulkDelete.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/bulkDelete.js b/app/addons/documents/tests/nightwatch/bulkDelete.js
index a729aad..205f3b4 100644
--- a/app/addons/documents/tests/nightwatch/bulkDelete.js
+++ b/app/addons/documents/tests/nightwatch/bulkDelete.js
@@ -30,7 +30,6 @@ module.exports = {
       .waitForElementVisible('.prettyprint', waitTime, false)
 
       .clickWhenVisible('.control-toggle-alternative-header')
-      .waitForElementPresent('.control-select-all', waitTime, false)
       .clickWhenVisible('.control-select-all', waitTime, false)
       .clickWhenVisible('.control-delete', waitTime, false)
       .acceptAlert()
@@ -57,7 +56,6 @@ module.exports = {
       .loginToGUI()
       .createManyDocuments(25, newDatabaseName)
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs')
-      .waitForElementPresent('.control-toggle-alternative-header', waitTime, false)
 
       // ensures page content has loaded before proceeding
       .waitForElementVisible('.prettyprint', waitTime, false)

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/bulkSelect.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/bulkSelect.js b/app/addons/documents/tests/nightwatch/bulkSelect.js
index be6dad1..f0189f1 100644
--- a/app/addons/documents/tests/nightwatch/bulkSelect.js
+++ b/app/addons/documents/tests/nightwatch/bulkSelect.js
@@ -26,10 +26,8 @@ module.exports = {
       .createDocument(newDocumentName1, newDatabaseName)
       .createDocument(newDocumentName2, newDatabaseName)
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs')
-      .waitForElementPresent('.control-toggle-alternative-header', waitTime, false)
-      .click('.control-toggle-alternative-header')
-      .waitForElementPresent('.control-select-all', waitTime, false)
-      .click('.control-select-all')
+      .clickWhenVisible('.control-toggle-alternative-header')
+      .clickWhenVisible('.control-select-all')
       .assert.attributeEquals('.control-select-all', 'disabled', 'true')
       .end();
   }

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/changes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/changes.js b/app/addons/documents/tests/nightwatch/changes.js
index 41000d4..e2de61b 100644
--- a/app/addons/documents/tests/nightwatch/changes.js
+++ b/app/addons/documents/tests/nightwatch/changes.js
@@ -39,8 +39,7 @@ module.exports = {
       .waitForElementPresent('.change-box[data-id="doc_1"]', waitTime, false)
 
       // confirm only the single result is now listed in the page
-      .waitForElementVisible('.js-doc-link', waitTime, false)
-      .click('.js-doc-link')
+      .clickWhenVisible('.js-doc-link')
       .waitForElementPresent('#doc-editor-actions-panel', waitTime, false)
       .end();
   },

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/changesFilter.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/changesFilter.js b/app/addons/documents/tests/nightwatch/changesFilter.js
index 73846d8..050df1c 100644
--- a/app/addons/documents/tests/nightwatch/changesFilter.js
+++ b/app/addons/documents/tests/nightwatch/changesFilter.js
@@ -25,6 +25,11 @@ module.exports = {
       .createDocument('doc_1', newDatabaseName)
       .createDocument('doc_2', newDatabaseName)
       .createDocument('doc_3', newDatabaseName)
+
+      .checkForStringPresent(newDatabaseName + '/_changes', 'doc_1')
+      .checkForStringPresent(newDatabaseName + '/_changes', 'doc_2')
+      .checkForStringPresent(newDatabaseName + '/_changes', 'doc_3')
+
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_changes')
 
       // confirm all 3 changes are there

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/createsDocument.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/createsDocument.js b/app/addons/documents/tests/nightwatch/createsDocument.js
index 19ec1a8..ec0e33b 100644
--- a/app/addons/documents/tests/nightwatch/createsDocument.js
+++ b/app/addons/documents/tests/nightwatch/createsDocument.js
@@ -21,10 +21,8 @@ module.exports = {
     client
       .loginToGUI()
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs')
-      .waitForElementPresent('#new-all-docs-button', waitTime, false)
-      .click('#new-all-docs-button a')
-      .waitForElementPresent('#new-all-docs-button a[href="#/database/' + newDatabaseName + '/new"]', waitTime, false)
-      .click('#new-all-docs-button a[href="#/database/' + newDatabaseName + '/new"]')
+      .clickWhenVisible('#new-all-docs-button a')
+      .clickWhenVisible('#new-all-docs-button a[href="#/database/' + newDatabaseName + '/new"]')
       .waitForElementPresent('#editor-container', waitTime, false)
       .verify.urlEquals(baseUrl + '/#/database/' + newDatabaseName + '/new')
       .execute('\
@@ -33,9 +31,8 @@ module.exports = {
         editor.removeWordRight();\
         editor.insert("' + newDocumentName + '");\
       ')
-      .waitForElementPresent('#doc-editor-actions-panel .save-doc', waitTime, false)
-      .click('#doc-editor-actions-panel .save-doc')
-      .pause(1000)
+      .clickWhenVisible('#doc-editor-actions-panel .save-doc')
+      .checkForDocumentCreated(newDocumentName)
       .url(baseUrl + '/' + newDatabaseName + '/_all_docs')
       .waitForElementPresent('body', waitTime, false)
       .getText('body', function (result) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/deleteDatabaseModal.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/deleteDatabaseModal.js b/app/addons/documents/tests/nightwatch/deleteDatabaseModal.js
index 2995d39..30fb60e 100644
--- a/app/addons/documents/tests/nightwatch/deleteDatabaseModal.js
+++ b/app/addons/documents/tests/nightwatch/deleteDatabaseModal.js
@@ -10,7 +10,23 @@
 // License for the specific language governing permissions and limitations under
 // the License.
 
+var helpers = require('../../../../../test/nightwatch_tests/helpers/helpers.js');
 module.exports = {
+
+  before: function (client, done) {
+    var nano = helpers.getNanoInstance();
+    nano.db.create('_replicator', function (err, body, header) {
+      done();
+    });
+  },
+
+  after: function (client, done) {
+    var nano = helpers.getNanoInstance();
+    nano.db.destroy('_replicator', function (err, body, header) {
+      done();
+    });
+  },
+
   'Shows a warning for system databases (prefixed with _)': function (client) {
     var waitTime = client.globals.maxWaitTime,
         baseUrl = client.globals.test_settings.launch_url;
@@ -18,7 +34,6 @@ module.exports = {
     client
       .loginToGUI()
       .url(baseUrl + '/#/database/_replicator/_all_docs')
-      .waitForElementPresent("#header-dropdown-menu a.dropdown-toggle.icon.fonticon-cog", waitTime, false)
       .clickWhenVisible("#header-dropdown-menu a.dropdown-toggle.icon.fonticon-cog", waitTime, false)
       .waitForElementPresent("#header-dropdown-menu .fonticon-trash", waitTime, false)
       .clickWhenVisible('#header-dropdown-menu .fonticon-trash', waitTime, false)
@@ -36,11 +51,10 @@ module.exports = {
     client
       .loginToGUI()
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs')
-      .waitForElementPresent("#header-dropdown-menu a.dropdown-toggle.icon.fonticon-cog", waitTime, false)
       .clickWhenVisible('#header-dropdown-menu a.dropdown-toggle.icon.fonticon-cog', waitTime, false)
       .waitForElementPresent("#header-dropdown-menu .fonticon-trash", waitTime, false)
-      .waitForElementPresent('#delete-db-modal', waitTime, false)
       .clickWhenVisible('#header-dropdown-menu .fonticon-trash', waitTime, false)
+      .waitForElementPresent('#delete-db-modal', waitTime, false)
       .waitForElementVisible('input#db-name', waitTime, false)
       .assert.elementNotPresent('.warning')
     .end();

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/editDocumentsFromView.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/editDocumentsFromView.js b/app/addons/documents/tests/nightwatch/editDocumentsFromView.js
index 8237399..b435e9e 100644
--- a/app/addons/documents/tests/nightwatch/editDocumentsFromView.js
+++ b/app/addons/documents/tests/nightwatch/editDocumentsFromView.js
@@ -36,8 +36,7 @@ module.exports = {
       .clickWhenVisible('#nav-header-abc')
       .clickWhenVisible('#nav-design-function-abcviews')
       .clickWhenVisible('#abc_evens')
-      .waitForElementVisible('a[href="#/database/fauxton-selenium-tests/document_10"]', waitTime, false)
-      .click('a[href="#/database/fauxton-selenium-tests/document_10"]')
+      .clickWhenVisible('a[href="#/database/fauxton-selenium-tests/document_10"]')
 
       //navigated to editor
       .waitForElementVisible('#editor-container', waitTime, false)

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/lookaheadTray.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/lookaheadTray.js b/app/addons/documents/tests/nightwatch/lookaheadTray.js
index 4eef03b..88a5737 100644
--- a/app/addons/documents/tests/nightwatch/lookaheadTray.js
+++ b/app/addons/documents/tests/nightwatch/lookaheadTray.js
@@ -19,8 +19,7 @@ module.exports = {
     client
       .loginToGUI()
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs')
-      .waitForElementVisible('.lookahead-tray-link', waitTime, false)
-      .click('.lookahead-tray-link')
+      .clickWhenVisible('.lookahead-tray-link')
       .waitForElementVisible('.lookahead-tray', waitTime, false)
       .end();
   }

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/mangoIndex.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/mangoIndex.js b/app/addons/documents/tests/nightwatch/mangoIndex.js
index f6a6b0d..a47e319 100644
--- a/app/addons/documents/tests/nightwatch/mangoIndex.js
+++ b/app/addons/documents/tests/nightwatch/mangoIndex.js
@@ -25,7 +25,6 @@ module.exports = {
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_index')
       .waitForElementPresent('.prettyprint', waitTime, false)
       .waitForElementNotPresent('.loading-lines', waitTime, false)
-      .assert.containsText('.editor-description', 'is an easy way to find documents on predefined indexes')
       .execute('\
         var json = \'{\
           "index": {\
@@ -39,9 +38,9 @@ module.exports = {
       ')
       .execute('$(".save")[0].scrollIntoView();')
       .clickWhenVisible('button.btn-success.save')
-
-      .waitForElementVisible('#global-notifications .alert.alert-success', waitTime, false)
-      .waitForElementNotVisible('#global-notifications .alert.alert-success', waitTime, false)
+      .checkForStringPresent(newDatabaseName + '/_index', 'rocko-artischocko')
+      .checkForStringPresent(newDatabaseName + '/_index', 'gans_gans_mango')
+      .waitForElementPresent('.prettyprint', waitTime, false)
       .assert.containsText('#dashboard-lower-content', 'gans_gans_mango')
     .end();
   },
@@ -63,8 +62,8 @@ module.exports = {
       .clickWhenVisible('.control-delete')
       .acceptAlert()
 
-      .waitForElementVisible('#global-notifications .alert.alert-info', waitTime, false)
-      .waitForElementNotVisible('#global-notifications .alert.alert-info', waitTime, false)
+      .checkForStringNotPresent(newDatabaseName + '/_index', '"name":"rocko-artischocko"')
+      .checkForStringNotPresent(newDatabaseName + '/_index', 'gans_gans_mango')
       .getText('body', function (result) {
         var data = result.value;
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/mangoQuery.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/mangoQuery.js b/app/addons/documents/tests/nightwatch/mangoQuery.js
index 2e5c8a5..f173824 100644
--- a/app/addons/documents/tests/nightwatch/mangoQuery.js
+++ b/app/addons/documents/tests/nightwatch/mangoQuery.js
@@ -23,7 +23,6 @@ module.exports = {
       .loginToGUI()
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_find')
       .waitForElementPresent('.watermark-logo', waitTime, false)
-      .assert.containsText('.editor-description', 'is an easy way to find documents on predefined indexes')
       .execute('\
         var json = \'{\
           "selector": {\
@@ -34,7 +33,7 @@ module.exports = {
         editor.getSession().setValue(json);\
       ')
       .execute('$(".save")[0].scrollIntoView();')
-      .click('button.btn-success.save')
+      .clickWhenVisible('button.btn-success.save')
 
       .waitForElementPresent('.prettyprint', waitTime, false)
       .assert.containsText('#dashboard-lower-content', 'number')

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/navigateAfterEditingDocShouldShowAConfirmationBox.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/navigateAfterEditingDocShouldShowAConfirmationBox.js b/app/addons/documents/tests/nightwatch/navigateAfterEditingDocShouldShowAConfirmationBox.js
index 38bdc48..95e1282 100644
--- a/app/addons/documents/tests/nightwatch/navigateAfterEditingDocShouldShowAConfirmationBox.js
+++ b/app/addons/documents/tests/nightwatch/navigateAfterEditingDocShouldShowAConfirmationBox.js
@@ -22,15 +22,13 @@ module.exports = {
     client
       .loginToGUI()
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs')
-      .waitForElementPresent('#new-all-docs-button', waitTime, false)
-      .click('#new-all-docs-button a')
-      .waitForElementPresent('#new-all-docs-button a[href="' + newLink + '"]', waitTime, false)
-      .click('#new-all-docs-button a[href="' + newLink + '"]')
+      .clickWhenVisible('#new-all-docs-button a')
+      .clickWhenVisible('#new-all-docs-button a[href="' + newLink + '"]')
       .waitForElementPresent('.code-region', waitTime, false)
       .verify.urlEquals(baseUrl + '/' + newLink)
 
       .keys(['.ace_variable', 'v'])
-      .click('a[href="#/activetasks"]')
+      .clickWhenVisible('a[href="#/activetasks"]')
       .accept_alert()
       .verify.urlEquals(baseUrl + '/#/activetasks');
   }

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/navigateFromNewDoc.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/navigateFromNewDoc.js b/app/addons/documents/tests/nightwatch/navigateFromNewDoc.js
index c5167dd..6807a3d 100644
--- a/app/addons/documents/tests/nightwatch/navigateFromNewDoc.js
+++ b/app/addons/documents/tests/nightwatch/navigateFromNewDoc.js
@@ -24,15 +24,13 @@ module.exports = {
     client
       .loginToGUI()
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs')
-      .waitForElementPresent('#new-all-docs-button', waitTime, false)
-      .click('#new-all-docs-button a')
-      .waitForElementPresent('#new-all-docs-button a[href="' + newLink + '"]', waitTime, false)
-      .click('#new-all-docs-button a[href="' + newLink + '"]')
+      .clickWhenVisible('#new-all-docs-button a')
+      .clickWhenVisible('#new-all-docs-button a[href="' + newLink + '"]')
       .waitForElementPresent('.code-region', waitTime, false)
       .verify.urlEquals(baseUrl + '/' + newLink)
 
       // now redirect back to the all docs page and check it's loaded properly
-      .click('.fonticon-left-open')
+      .clickWhenVisible('.fonticon-left-open')
       .verify.urlEquals(baseUrl + '/#database/' + newDatabaseName + '/_all_docs');
   }
 };

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/navigateToNewView.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/navigateToNewView.js b/app/addons/documents/tests/nightwatch/navigateToNewView.js
index ed8d8c3..232ef7c 100644
--- a/app/addons/documents/tests/nightwatch/navigateToNewView.js
+++ b/app/addons/documents/tests/nightwatch/navigateToNewView.js
@@ -22,15 +22,13 @@ module.exports = {
     client
       .loginToGUI()
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs')
-      .waitForElementPresent('#new-all-docs-button', waitTime, false)
-      .click('#new-all-docs-button a')
-      .waitForElementPresent('#new-all-docs-button a[href="#/database/' + newDatabaseName + '/new_view"]', waitTime, false)
-      .click('#new-all-docs-button a[href="#/database/' + newDatabaseName + '/new_view"]')
+      .clickWhenVisible('#new-all-docs-button a')
+      .clickWhenVisible('#new-all-docs-button a[href="#/database/' + newDatabaseName + '/new_view"]')
       .waitForElementPresent('.define-view', waitTime, false)
       .verify.urlEquals(baseUrl + '/#/database/' + newDatabaseName + '/new_view')
 
       // now redirect back to the database page and check it's loaded properly
-      .click('#nav-links a[href="#/_all_dbs"]')
+      .clickWhenVisible('#nav-links a[href="#/_all_dbs"]')
       .waitForElementPresent('#dashboard-content .databases', waitTime, false);
   }
 };

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/paginateAllDocs.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/paginateAllDocs.js b/app/addons/documents/tests/nightwatch/paginateAllDocs.js
index b9a4b6b..d23ab30 100644
--- a/app/addons/documents/tests/nightwatch/paginateAllDocs.js
+++ b/app/addons/documents/tests/nightwatch/paginateAllDocs.js
@@ -37,6 +37,7 @@ module.exports = {
       .keys(['\uE013', '\uE006'])
       .waitForElementPresent('.prettyprint', waitTime, false)
       .waitForElementNotPresent('div[data-id="document_16"]', waitTime)
+      .waitForElementPresent('.doc-row', waitTime, false)
       .execute(function () {
         return $('.doc-row').length;
       }, function (result) {

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/switchDatabaseViaLookaheadTray.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/switchDatabaseViaLookaheadTray.js b/app/addons/documents/tests/nightwatch/switchDatabaseViaLookaheadTray.js
index 4cd739c..da297cf 100644
--- a/app/addons/documents/tests/nightwatch/switchDatabaseViaLookaheadTray.js
+++ b/app/addons/documents/tests/nightwatch/switchDatabaseViaLookaheadTray.js
@@ -25,8 +25,7 @@ module.exports = {
 
       // now select the first database, and select the second db from the lookahead tray
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs')
-      .waitForElementPresent('#breadcrumbs .lookahead-tray-link', waitTime, false)
-      .click('#breadcrumbs .lookahead-tray-link')
+      .clickWhenVisible('#breadcrumbs .lookahead-tray-link')
       .setValue('#breadcrumbs .search-autocomplete', [secondDatabaseName, client.Keys.ENTER])
       .getText('body', function (result) {
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/viewCreate.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/viewCreate.js b/app/addons/documents/tests/nightwatch/viewCreate.js
index 45960d5..cbcb6ab 100644
--- a/app/addons/documents/tests/nightwatch/viewCreate.js
+++ b/app/addons/documents/tests/nightwatch/viewCreate.js
@@ -29,6 +29,7 @@ module.exports = {
       .execute('$(".save")[0].scrollIntoView();')
       .waitForElementPresent('button.btn.btn-success.save', waitTime, false)
       .clickWhenVisible('button.btn.btn-success.save', waitTime, false)
+      .checkForDocumentCreated('_design/test_design_doc-selenium-1')
       .waitForElementPresent('.prettyprint', waitTime, false)
       .waitForElementNotPresent('.loading-lines', waitTime, false)
       .assert.containsText('.prettyprint', 'hasehase')
@@ -53,7 +54,8 @@ module.exports = {
         editor.getSession().setValue("function (doc) { emit(\'gansgans\'); }");\
       ')
       .execute('$(".save")[0].scrollIntoView();')
-      .click('button.btn-success.save')
+      .clickWhenVisible('button.btn-success.save')
+      .checkForDocumentCreated('_design/test_design_doc-selenium-2')
       .waitForElementPresent('.prettyprint', waitTime, false)
       .waitForElementNotPresent('.loading-lines', waitTime, false)
       .assert.containsText('.prettyprint', 'gansgans')
@@ -67,7 +69,6 @@ module.exports = {
     /*jshint multistr: true */
 
     openDifferentDropdownsAndClick(client, '#nav-header-testdesigndoc')
-      .waitForElementPresent('#index-name', waitTime, false)
       .waitForElementVisible('#index-name', waitTime, false)
       .clearValue('#index-name')
       .setValue('#index-name', 'test-new-view')
@@ -77,10 +78,11 @@ module.exports = {
         editor.getSession().setValue("function (doc) { emit(\'enteente\', 1); }");\
       ')
       .execute('$(".save")[0].scrollIntoView();')
-      .click('button.btn-success.save')
-      .waitForAttribute('#global-notifications', 'textContent', function (notification) {
-        return (/View Saved./).test(notification.trim());
-      })
+      .clickWhenVisible('button.btn-success.save')
+      .checkForDocumentCreated('_design/testdesigndoc/_view/test-new-view')
+
+      .waitForElementPresent('.prettyprint', waitTime, false)
+      .waitForElementNotPresent('.loading-lines', waitTime, false)
       //go back to all docs
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs')
       .clickWhenVisible('#nav-header-testdesigndoc', waitTime, false)

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/viewCreateBadView.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/viewCreateBadView.js b/app/addons/documents/tests/nightwatch/viewCreateBadView.js
index f82f7af..f4a693d 100644
--- a/app/addons/documents/tests/nightwatch/viewCreateBadView.js
+++ b/app/addons/documents/tests/nightwatch/viewCreateBadView.js
@@ -24,22 +24,23 @@ module.exports = {
       .populateDatabase(newDatabaseName)
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs')
       .waitForElementPresent(dropDownElement, waitTime, false)
-      .click(dropDownElement + ' a')
-      .click(dropDownElement + ' a[href*="new_view"]')
+      .clickWhenVisible(dropDownElement + ' a')
+      .clickWhenVisible(dropDownElement + ' a[href*="new_view"]')
       .waitForElementVisible('#new-ddoc', waitTime, false)
       .setValue('#new-ddoc', 'test_design_doc-selenium-bad-reduce')
       .clearValue('#index-name')
       .setValue('#index-name', 'hasenindex')
-      .click('#reduce-function-selector')
+      .clickWhenVisible('#reduce-function-selector')
       .keys(['\uE013', '\uE013', '\uE013', '\uE013', '\uE006'])
       .execute('\
         var editor = ace.edit("map-function");\
         editor.getSession().setValue("function (doc) { emit(\'boom\', doc._id); }");\
       ')
       .execute('$(".save")[0].scrollIntoView();')
-      .click('button.btn-success.save')
-      .waitForElementVisible('.alert-error', waitTime, false)
-      .assert.containsText('.alert-error', '_sum function requires')
+      .clickWhenVisible('button.btn-success.save')
+      .waitForAttribute('#global-notifications', 'textContent', function (docContents) {
+        return (/_sum function requires/).test(docContents);
+      })
       .end();
   },
 
@@ -52,8 +53,9 @@ module.exports = {
       .loginToGUI()
       .populateDatabase(newDatabaseName)
       .url(baseUrl + '/#/database/' + newDatabaseName + '/_design/brokenview/_view/brokenview')
-      .waitForElementVisible('.alert-error', waitTime, false)
-      .assert.containsText('.alert-error', '_sum function requires')
+      .waitForAttribute('#global-notifications', 'textContent', function (docContents) {
+        return (/_sum function requires/).test(docContents);
+      })
       .end();
   }
 

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/viewEdit.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/viewEdit.js b/app/addons/documents/tests/nightwatch/viewEdit.js
index cb04c99..1437fce 100644
--- a/app/addons/documents/tests/nightwatch/viewEdit.js
+++ b/app/addons/documents/tests/nightwatch/viewEdit.js
@@ -18,6 +18,7 @@ module.exports = {
         newDatabaseName = client.globals.testDatabaseName,
         baseUrl = client.globals.test_settings.launch_url;
 
+    var viewUrl = newDatabaseName + '/_design/testdesigndoc/_view/hasenindex5000?limit=6&reduce=false';
     client
       .populateDatabase(newDatabaseName)
       .loginToGUI()
@@ -31,10 +32,10 @@ module.exports = {
         editor.getSession().setValue("function (doc) { emit(\'hasehase5000\', 1); }");\
       ')
       .execute('$(".save")[0].scrollIntoView();')
-      .click('button.btn-success.save')
-
-      .waitForElementNotVisible('.global-notification', waitTime, false)
+      .clickWhenVisible('button.btn-success.save')
+      .checkForStringPresent(viewUrl, 'hasehase5000')
       .waitForElementNotPresent('.loading-lines', waitTime, false)
+      .waitForElementVisible('.prettyprint', waitTime, false)
       .assert.containsText('.prettyprint', 'hasehase5000')
     .end();
   },
@@ -45,6 +46,8 @@ module.exports = {
         newDatabaseName = client.globals.testDatabaseName,
         baseUrl = client.globals.test_settings.launch_url;
 
+    var viewUrl = newDatabaseName + '/_design/testdesigndoc/_view/stubview?limit=6&reduce=false';
+
     client
       .populateDatabase(newDatabaseName)
       .loginToGUI()
@@ -54,14 +57,19 @@ module.exports = {
 
       .execute('\
         var editor = ace.edit("map-function");\
-        editor.getSession().setValue("function (doc) { emit(\'hasehase5000\', 1); }");\
+        editor.getSession().setValue("function (doc) { emit(\'hasehase6000\', 1); }");\
         editor._emit(\'blur\');\
       ')
       .execute('$(".save")[0].scrollIntoView();')
+
       .clickWhenVisible('button.btn-success.save')
-      .waitForElementNotVisible('.global-notification', waitTime, false)
+
+      .checkForStringPresent(viewUrl, 'hasehase6000')
       .waitForElementNotPresent('.loading-lines', waitTime, false)
-      .assert.containsText('.prettyprint', 'hasehase5000')
+      .waitForElementVisible('.prettyprint', waitTime, false)
+      .waitForAttribute('#doc-list', 'textContent', function (docContents) {
+        return (/hasehase6000/).test(docContents);
+      })
     .end();
   },
 
@@ -71,10 +79,12 @@ module.exports = {
         newDatabaseName = client.globals.testDatabaseName,
         baseUrl = client.globals.test_settings.launch_url;
 
+    var viewUrl = newDatabaseName + '/_design/testdesigndoc/_view/stubview?reduce=true&group_level=0';
+
     client
       .populateDatabase(newDatabaseName)
       .loginToGUI()
-      .url(baseUrl + '/#/database/' + newDatabaseName + '/_design/testdesigndoc/_view/stubview?reduce=true&group_level=0')
+      .url(baseUrl + '/#/database/' + viewUrl)
       .waitForElementPresent('.prettyprint', waitTime, false)
       .assert.containsText('.prettyprint', '20')
       .clickWhenVisible('#reduce-function-selector option[value="_sum"]')
@@ -84,7 +94,9 @@ module.exports = {
       ')
       .execute('$("button.save")[0].scrollIntoView();')
       .clickWhenVisible('button.save', waitTime, false)
+      .checkForStringPresent(viewUrl, '40')
       .waitForElementNotPresent('.loading-lines', waitTime, false)
+      .waitForElementVisible('.prettyprint', waitTime, false)
       .waitForAttribute('.prettyprint', 'textContent', function (docContents) {
         return (/40/).test(docContents);
       })

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/viewQueryOptions.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/viewQueryOptions.js b/app/addons/documents/tests/nightwatch/viewQueryOptions.js
index b637570..8839dd5 100644
--- a/app/addons/documents/tests/nightwatch/viewQueryOptions.js
+++ b/app/addons/documents/tests/nightwatch/viewQueryOptions.js
@@ -24,7 +24,7 @@ module.exports = {
       .clickWhenVisible('#toggle-query', waitTime, false)
       .clickWhenVisible('[data-action="showByKeys"]', waitTime, false)
       .setValue('#keys-input', '["document_1"]')
-      .click('#query-options .btn-success')
+      .clickWhenVisible('#query-options .btn-success')
       .waitForElementNotPresent('#right-content [data-id="document_2"]', waitTime, false)
       .assert.elementNotPresent('#right-content [data-id="document_2"]')
       .assert.elementNotPresent('#right-content [data-id="document_0"]')

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/documents/tests/nightwatch/viewSaveManyTimes.js
----------------------------------------------------------------------
diff --git a/app/addons/documents/tests/nightwatch/viewSaveManyTimes.js b/app/addons/documents/tests/nightwatch/viewSaveManyTimes.js
deleted file mode 100644
index c6c86da..0000000
--- a/app/addons/documents/tests/nightwatch/viewSaveManyTimes.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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.
-
-module.exports = {
-
-  'View can be saved multiple times': function (client) {
-    /*jshint multistr: true */
-    var waitTime = client.globals.maxWaitTime,
-    newDatabaseName = client.globals.testDatabaseName,
-    dropDownElement = '#header-dropdown-menu',
-    baseUrl = client.globals.test_settings.launch_url;
-
-    client
-    .loginToGUI()
-    .populateDatabase(newDatabaseName)
-    .url(baseUrl + '/#/database/' + newDatabaseName + '/_all_docs')
-    .waitForElementPresent(dropDownElement, waitTime, false)
-    .click(dropDownElement + ' a')
-    .click(dropDownElement + ' a[href*="new_view"]')
-    .waitForElementPresent('.editor-wrapper', waitTime, false)
-    .waitForElementPresent('#new-ddoc', waitTime, false)
-    .setValue('#new-ddoc', 'test_design_doc-save-many-times')
-    .clearValue('#index-name')
-    .setValue('#index-name', 'multiple-saves')
-    .sendKeys("textarea.ace_text-input", client.Keys.Enter)
-    .execute('\
-      var editor = ace.edit("map-function");\
-      editor.getSession().setValue("function (doc) { emit(\'boom\', doc._id); }");\
-      editor._emit(\'blur\');\
-    ')
-    .clickWhenVisible('button#save-view')
-    .waitForElementVisible('#global-notifications', waitTime, false)
-    .waitForElementNotVisible('#global-notifications', waitTime, false)
-
-    .clickWhenVisible('button#save-view')
-    .waitForElementVisible('#global-notifications', waitTime, false)
-    .waitForElementNotVisible('#global-notifications', waitTime, false)
-
-    .clickWhenVisible('button#save-view')
-    .waitForElementVisible('#global-notifications', waitTime, false)
-    .end();
-  },
-};

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/fauxton/tests/componentsSpec.react.jsx
----------------------------------------------------------------------
diff --git a/app/addons/fauxton/tests/componentsSpec.react.jsx b/app/addons/fauxton/tests/componentsSpec.react.jsx
index 52a00d0..f03d065 100644
--- a/app/addons/fauxton/tests/componentsSpec.react.jsx
+++ b/app/addons/fauxton/tests/componentsSpec.react.jsx
@@ -13,7 +13,7 @@ define([
   'api',
   'addons/fauxton/components.react',
   'testUtils',
-  "react"
+  'react'
 ], function (FauxtonAPI, Views, utils, React) {
 
   var assert = utils.assert;
@@ -21,106 +21,59 @@ define([
 
   describe('Tray', function () {
 
-    var container, anotherContainer, trayEl, done, old$;
-    // trace registrations
-    var handlersOn, handlersOff, velocities;
+    var container, trayEl, done;
 
     beforeEach(function () {
-      handlersOn = [];
-      handlersOff = [];
-      velocities = [];
-      done = sinon.spy();
-      // simulate $ to test registration
-      old$ = $;
-      $ = function (what) {
-        this.on = function (id, handler) {
-          handlersOn.push([what, id]);
-        };
-        this.off = function (id) {
-          handlersOff.push([what, id]);
-        };
-        this.velocity = function (trans, speed, callback) {
-          velocities.push([what, trans]);
-          callback();
-        };
-        return this;
-      };
       container = document.createElement('div');
       // when we want to control the diff, we have to render directly
-      trayEl = React.renderComponent(React.createElement(Views.Tray, {className: "traytest"}), container);
+      trayEl = React.render(<Views.Tray className="traytest" />, container);
+      done = sinon.spy();
     });
 
     afterEach(function () {
-      $ = old$;
       React.unmountComponentAtNode(container);
-      if (anotherContainer) {
-        React.unmountComponentAtNode(anotherContainer);
-      }
     });
 
     it('renders trayid and custom classes', function () {
-      assert(trayEl.getDOMNode().getAttribute("class").indexOf("traytest") >= 0);
-    });
-
-    it('registers handler with body', function () {
-      assert.equal(1, handlersOn.length);
-      assert.equal("body", handlersOn[0][0]);
-      assert.equal("click.Tray-", handlersOn[0][1].substring(0, "click.Tray-".length));
-      assert.equal(0, handlersOff.length);
-      // also a 2nd time
-      anotherContainer = document.createElement('div');
-      React.renderComponent(React.createElement(Views.Tray, {className: "traytest"}), anotherContainer);
-      assert.equal(2, handlersOn.length);
-      assert.equal("body", handlersOn[1][0]);
-      assert.equal("click.Tray-", handlersOn[1][1].substring(0, "click.Tray-".length));
-      assert.equal(0, handlersOff.length);
-      // (we have different IDs)
-      assert(handlersOn[0][1] != handlersOn[1][1]);
-      // and we also unregister properly
-      var unmountSuccess = React.unmountComponentAtNode(anotherContainer);
-      assert(unmountSuccess);
-      assert.equal(1, handlersOff.length);
-      assert.equal("body", handlersOff[0][0]);
-      assert.equal("click.Tray-", handlersOff[0][1].substring(0, "click.Tray-".length));
-      // (the ID of the 2nd element)
-      assert(handlersOn[1][1] == handlersOff[0][1]);
+      assert(trayEl.getDOMNode().getAttribute('class').indexOf('traytest') >= 0);
     });
 
     it('is initially closed', function () {
-      assert.equal("none", trayEl.getDOMNode().style.display);
+      assert.equal('none', trayEl.getDOMNode().style.display);
     });
 
     it('shows when requested', function () {
-      trayEl.setVisible(true);
-      assert.equal(1, velocities.length);
-      assert.equal("block", trayEl.getDOMNode().style.display);
+      trayEl.setVisible(true, function () {
+        assert.equal('block', trayEl.getDOMNode().style.display);
+      });
     });
 
     it('hides when requested', function () {
-      trayEl.show();
-      trayEl.setVisible(false);
-      assert.equal(2, velocities.length);
-      assert.equal("none", trayEl.getDOMNode().style.display);
+      trayEl.show(function () {
+        trayEl.setVisible(false, function () {
+          assert.equal('none', trayEl.getDOMNode().style.display);
+        });
+      });
     });
 
     it('does nothing when already hidden', function () {
-      trayEl.setVisible(false);
-      assert.equal(0, velocities.length);
+      trayEl.setVisible(false, function () {
+        throw new Error('should do nothing');
+      });
     });
 
     it('toggles open with callback', function () {
-      trayEl.toggle(done);
-      assert.ok(done.calledOnce);
-      assert.equal(1, velocities.length);
-      assert.equal("block", trayEl.getDOMNode().style.display);
+      trayEl.toggle(function () {
+        assert.equal('block', trayEl.getDOMNode().style.display);
+      });
     });
 
     it('toggles close again with callback', function () {
-      trayEl.show();
-      trayEl.toggle(done);
-      assert.ok(done.calledOnce);
-      assert.equal(2, velocities.length);
-      assert.equal("none", trayEl.getDOMNode().style.display);
+      trayEl.show(function () {
+        trayEl.toggle(function () {
+          assert.equal('none', trayEl.getDOMNode().style.display);
+        });
+      });
     });
 
   });
@@ -142,8 +95,12 @@ define([
       React.unmountComponentAtNode(container);
     });
 
-    it("renders 20-wise pages per default", function () {
-      var pageEl = React.renderComponent(React.createElement(Views.Pagination, {page: 3, total: 55, urlPrefix: "?prefix=", urlSuffix: "&suffix=88"}), container);
+    it('renders 20-wise pages per default', function () {
+      var pageEl = React.render(
+        <Views.Pagination page={3} total={55} urlPrefix="?prefix=" urlSuffix="&suffix=88" />,
+        container
+      );
+
       var lis = pageEl.getDOMNode().getElementsByTagName("li");
       assert.equal(1 + 3 + 1, lis.length);
       assert(nvl(lis[0].getAttribute("class")).indexOf("disabled") < 0);
@@ -156,13 +113,20 @@ define([
     });
 
     it("can overwrite collection size", function () {
-      var pageEl = React.renderComponent(React.createElement(Views.Pagination, {perPage: 10, page: 3, total: 55}), container);
+      var pageEl = React.render(
+        <Views.Pagination perPage={10} page={3} total={55} urlPrefix="?prefix=" urlSuffix="&suffix=88" />,
+        container
+      );
+
       var lis = pageEl.getDOMNode().getElementsByTagName("li");
       assert.equal(1 + 6 + 1, lis.length);
     });
 
     it("handles large collections properly - beginning", function () {
-      var pageEl = React.renderComponent(React.createElement(Views.Pagination, {page: 3, total: 600}), container);
+      var pageEl = React.render(
+        <Views.Pagination page={3} total={600} />,
+        container
+      );
       var lis = pageEl.getDOMNode().getElementsByTagName("li");
       assert.equal(1 + 10 + 1, lis.length);
       assert(nvl(lis[3].getAttribute("class")).indexOf("active") >= 0);
@@ -172,7 +136,11 @@ define([
     });
 
     it("handles large collections properly - middle", function () {
-      var pageEl = React.renderComponent(React.createElement(Views.Pagination, {page: 10, total: 600}), container);
+      var pageEl = React.render(
+        <Views.Pagination page={10} total={600} />,
+        container
+      );
+
       var lis = pageEl.getDOMNode().getElementsByTagName("li");
       assert.equal(1 + 10 + 1, lis.length);
       assert(nvl(lis[6].getAttribute("class")).indexOf("active") >= 0);
@@ -182,7 +150,11 @@ define([
     });
 
     it("handles large collections properly - end", function () {
-      var pageEl = React.renderComponent(React.createElement(Views.Pagination, {page: 29, total: 600}), container);
+      var pageEl = React.render(
+        <Views.Pagination page={29} total={600} />,
+        container
+      );
+
       var lis = pageEl.getDOMNode().getElementsByTagName("li");
       assert.equal(1 + 10 + 1, lis.length);
       assert(nvl(lis[9].getAttribute("class")).indexOf("active") >= 0);

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/app/addons/verifyinstall/tests/nightwatch/testVerification.js
----------------------------------------------------------------------
diff --git a/app/addons/verifyinstall/tests/nightwatch/testVerification.js b/app/addons/verifyinstall/tests/nightwatch/testVerification.js
index 1fbb717..3772b8c 100644
--- a/app/addons/verifyinstall/tests/nightwatch/testVerification.js
+++ b/app/addons/verifyinstall/tests/nightwatch/testVerification.js
@@ -13,16 +13,19 @@
 module.exports = {
   'Run the Verification test' : function (client) {
     var waitTime = client.globals.maxWaitTime,
-      baseUrl = client.globals.test_settings.launch_url;
+        baseUrl = client.globals.test_settings.launch_url;
 
     client
       .loginToGUI()
       .url(baseUrl + '#verifyinstall')
-      .waitForElementPresent('#start', waitTime, false)
-      .click('#start')
+      .clickWhenVisible('#start')
       .waitForElementVisible('.alert-success', waitTime, false)
       .getText('html', function (result) {
         var testPassed = result.value.indexOf('Success! Your CouchDB installation is working. Time to Relax.') !== -1;
+        if (!testPassed) {
+          console.error(result.value);
+        }
+
         this.verify.ok(testPassed, 'Checking the verification set passed.');
       })
       .end();

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/test/nightwatch_tests/custom-commands/checkForDatabaseCreated.js
----------------------------------------------------------------------
diff --git a/test/nightwatch_tests/custom-commands/checkForDatabaseCreated.js b/test/nightwatch_tests/custom-commands/checkForDatabaseCreated.js
new file mode 100644
index 0000000..91c0941
--- /dev/null
+++ b/test/nightwatch_tests/custom-commands/checkForDatabaseCreated.js
@@ -0,0 +1,52 @@
+// 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.
+
+var util = require('util'),
+    events = require('events'),
+    helpers = require('../helpers/helpers.js'),
+    request = require('request');
+
+function CheckForDatabaseCreated () {
+  events.EventEmitter.call(this);
+}
+
+// inherit from node's event emitter
+util.inherits(CheckForDatabaseCreated, events.EventEmitter);
+
+CheckForDatabaseCreated.prototype.command = function (databaseName, timeout) {
+  var couchUrl = helpers.test_settings.db_url;
+
+  if (!timeout) {
+    timeout = 10000;
+  }
+
+  var timeOutId = setTimeout(function () {
+    throw new Error('timeout waiting for db to appear');
+  }, timeout);
+
+  var intervalId = setInterval(function () {
+    request(couchUrl + '/_all_dbs', function (er, res, body) {
+      if (body) {
+        if (body.indexOf(databaseName) !== -1) {
+          clearTimeout(timeOutId);
+          console.log('database created: ' + databaseName);
+          clearInterval(intervalId);
+          this.emit('complete');
+        }
+      }
+    }.bind(this));
+  }.bind(this), 1000);
+
+  return this;
+};
+
+module.exports = CheckForDatabaseCreated;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/test/nightwatch_tests/custom-commands/checkForDatabaseDeleted.js
----------------------------------------------------------------------
diff --git a/test/nightwatch_tests/custom-commands/checkForDatabaseDeleted.js b/test/nightwatch_tests/custom-commands/checkForDatabaseDeleted.js
new file mode 100644
index 0000000..c5c42ce
--- /dev/null
+++ b/test/nightwatch_tests/custom-commands/checkForDatabaseDeleted.js
@@ -0,0 +1,52 @@
+// 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.
+
+var util = require('util'),
+    events = require('events'),
+    helpers = require('../helpers/helpers.js'),
+    request = require('request');
+
+function CheckForDatabaseDeleted () {
+  events.EventEmitter.call(this);
+}
+
+// inherit from node's event emitter
+util.inherits(CheckForDatabaseDeleted, events.EventEmitter);
+
+CheckForDatabaseDeleted.prototype.command = function (databaseName, timeout) {
+  var couchUrl = helpers.test_settings.db_url;
+
+  if (!timeout) {
+    timeout = 10000;
+  }
+
+  var timeOutId = setTimeout(function () {
+    throw new Error('timeout waiting for db to disappear');
+  }, timeout);
+
+  var intervalId = setInterval(function () {
+    request(couchUrl + '/_all_dbs', function (er, res, body) {
+      if (body) {
+        if (body.indexOf(databaseName) === -1) {
+          clearTimeout(timeOutId);
+          console.log('database not there: ' + databaseName);
+          clearInterval(intervalId);
+          this.emit('complete');
+        }
+      }
+    }.bind(this));
+  }.bind(this), 1000);
+
+  return this;
+};
+
+module.exports = CheckForDatabaseDeleted;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/test/nightwatch_tests/custom-commands/checkForDocumentCreated.js
----------------------------------------------------------------------
diff --git a/test/nightwatch_tests/custom-commands/checkForDocumentCreated.js b/test/nightwatch_tests/custom-commands/checkForDocumentCreated.js
new file mode 100644
index 0000000..2468883
--- /dev/null
+++ b/test/nightwatch_tests/custom-commands/checkForDocumentCreated.js
@@ -0,0 +1,53 @@
+// 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.
+
+var util = require('util'),
+    events = require('events'),
+    helpers = require('../helpers/helpers.js'),
+    request = require('request');
+
+function CheckForDocumentCreated () {
+  events.EventEmitter.call(this);
+}
+
+// inherit from node's event emitter
+util.inherits(CheckForDocumentCreated, events.EventEmitter);
+
+CheckForDocumentCreated.prototype.command = function (doc, timeout) {
+  var couchUrl = helpers.test_settings.db_url,
+      db = helpers.testDatabaseName;
+
+  if (!timeout) {
+    timeout = 10000;
+  }
+
+  var timeOutId = setTimeout(function () {
+    throw new Error('timeout waiting for doc to appear');
+  }, timeout);
+
+  var intervalId = setInterval(function () {
+    var url = [couchUrl, db, doc].join('/');
+
+    request(url, function (er, res, body) {
+      if (res && /^2..$/.test(res.statusCode)) {
+        clearTimeout(timeOutId);
+        console.log('doc created: ' + doc);
+        clearInterval(intervalId);
+        this.emit('complete');
+      }
+    }.bind(this));
+  }.bind(this), 1000);
+
+  return this;
+};
+
+module.exports = CheckForDocumentCreated;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/test/nightwatch_tests/custom-commands/checkForStringNotPresent.js
----------------------------------------------------------------------
diff --git a/test/nightwatch_tests/custom-commands/checkForStringNotPresent.js b/test/nightwatch_tests/custom-commands/checkForStringNotPresent.js
new file mode 100644
index 0000000..5712173
--- /dev/null
+++ b/test/nightwatch_tests/custom-commands/checkForStringNotPresent.js
@@ -0,0 +1,55 @@
+// 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.
+
+var util = require('util'),
+    events = require('events'),
+    helpers = require('../helpers/helpers.js'),
+    request = require('request');
+
+function CheckForStringNotPresent () {
+  events.EventEmitter.call(this);
+}
+
+// inherit from node's event emitter
+util.inherits(CheckForStringNotPresent, events.EventEmitter);
+
+CheckForStringNotPresent.prototype.command = function (path, string, timeout) {
+  var couchUrl = helpers.test_settings.db_url,
+      db = helpers.testDatabaseName;
+
+  if (!timeout) {
+    timeout = 10000;
+  }
+
+  var timeOutId = setTimeout(function () {
+    throw new Error('timeout waiting for string to disappear');
+  }, timeout);
+
+  var intervalId = setInterval(function () {
+    var url = [couchUrl, path].join('/');
+
+    request(url, function (er, res, body) {
+      if (body) {
+        if (body.indexOf(string) === -1) {
+          clearTimeout(timeOutId);
+          console.log('string disappeared: ' + string);
+          clearInterval(intervalId);
+          this.emit('complete');
+        }
+      }
+    }.bind(this));
+  }.bind(this), 1000);
+
+  return this;
+};
+
+module.exports = CheckForStringNotPresent;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/test/nightwatch_tests/custom-commands/checkForStringPresent.js
----------------------------------------------------------------------
diff --git a/test/nightwatch_tests/custom-commands/checkForStringPresent.js b/test/nightwatch_tests/custom-commands/checkForStringPresent.js
new file mode 100644
index 0000000..f367f8b
--- /dev/null
+++ b/test/nightwatch_tests/custom-commands/checkForStringPresent.js
@@ -0,0 +1,55 @@
+// 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.
+
+var util = require('util'),
+    events = require('events'),
+    helpers = require('../helpers/helpers.js'),
+    request = require('request');
+
+function CheckForStringPresent () {
+  events.EventEmitter.call(this);
+}
+
+// inherit from node's event emitter
+util.inherits(CheckForStringPresent, events.EventEmitter);
+
+CheckForStringPresent.prototype.command = function (path, string, timeout) {
+  var couchUrl = helpers.test_settings.db_url,
+      db = helpers.testDatabaseName;
+
+  if (!timeout) {
+    timeout = 10000;
+  }
+
+  var timeOutId = setTimeout(function () {
+    throw new Error('timeout waiting for string to appear');
+  }, timeout);
+
+  var intervalId = setInterval(function () {
+    var url = [couchUrl, path].join('/');
+
+    request(url, function (er, res, body) {
+      if (body) {
+        if (body.indexOf(string) !== -1) {
+          clearTimeout(timeOutId);
+          console.log('string found: ' + string);
+          clearInterval(intervalId);
+          this.emit('complete');
+        }
+      }
+    }.bind(this));
+  }.bind(this), 1000);
+
+  return this;
+};
+
+module.exports = CheckForStringPresent;

http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/455f0a53/test/nightwatch_tests/helpers/helpers.js
----------------------------------------------------------------------
diff --git a/test/nightwatch_tests/helpers/helpers.js b/test/nightwatch_tests/helpers/helpers.js
index ed034ed..5d36d20 100644
--- a/test/nightwatch_tests/helpers/helpers.js
+++ b/test/nightwatch_tests/helpers/helpers.js
@@ -11,6 +11,7 @@
 // the License.
 
 var nano = require('nano');
+var async = require('async');
 
 module.exports = {
   maxWaitTime: 30000,
@@ -25,23 +26,21 @@ module.exports = {
 
     console.log("nano setting up database");
     // clean up the database we created previously
+
     nano.db.destroy(database, function (err, body, header) {
-      if (err) {
-        if (err.message != 'Database does not exist.' && err.message != 'missing') {
-          console.log('Error in setting up ' + database, err.message);
-        }
+      if (err && err.message !== 'Database does not exist.' && err.message !== 'missing') {
+        console.log('Error in setting up ' + database, err.message);
       }
       // create a new database
       nano.db.create(database, function (err, body, header) {
         if (err) {
           console.log('Error in setting up ' + database, err.message);
         }
-        nano.db.create('_replicator', function (err, body, header) {
-          done();
-        });
+        done();
       });
     });
   },
+
   afterEach: function (done) {
     var nano = module.exports.getNanoInstance(),
         database = module.exports.testDatabaseName;


Mime
View raw message