Repository: couchdb-fauxton Updated Branches: refs/heads/master bf1b42833 -> c7fa6fad7
Allow editing documents from a view -included: Allow entire document card to be clickable for editing clickWhenVisible custom function for Nightwatch Closes COUCH-2494 Project: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/commit/c7fa6fad Tree: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/tree/c7fa6fad Diff: http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/diff/c7fa6fad Branch: refs/heads/master Commit: c7fa6fad7c4113e4f776830846ac0274cb7af422 Parents: bf1b428 Author: Michelle Phung <[email protected]> Authored: Sun Dec 7 12:57:25 2014 -0500 Committer: Robert Kowalski <[email protected]> Committed: Mon Dec 15 22:31:21 2014 +0100 ---------------------------------------------------------------------- app/addons/documents/resources.js | 46 +++++----------- app/addons/documents/routes-doc-editor.js | 8 ++- app/addons/documents/routes-documents.js | 35 +++++++----- .../documents/templates/all_docs_item.html | 21 ++++---- .../documents/templates/index_row_docular.html | 29 ---------- .../tests/nightwatch/editDocumentsFromView.js | 57 ++++++++++++++++++++ app/addons/documents/views-index.js | 21 -------- app/addons/documents/views.js | 8 +-- .../custom-commands/clickWhenVisible.js | 12 +++++ .../custom-commands/createDocument.js | 8 ++- .../custom-commands/populateDatabase.js | 2 +- test/nightwatch_tests/nightwatch_README.md | 4 +- 12 files changed, 138 insertions(+), 113 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/resources.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/resources.js b/app/addons/documents/resources.js index 1eaa6bb..7a80ab2 100644 --- a/app/addons/documents/resources.js +++ b/app/addons/documents/resources.js @@ -89,6 +89,18 @@ function(app, FauxtonAPI, PagingCollection) { return this.docType() != "reduction"; }, + isFromView: function(){ + return !this.id; + }, + + isReducedShown : function () { + if (this.collection) { + return this.collection.params.reduce; + } else { + return false; + } + }, + isDdoc: function() { return this.docType() === "design doc"; }, @@ -251,38 +263,6 @@ function(app, FauxtonAPI, PagingCollection) { } }); - Documents.ViewRow = FauxtonAPI.Model.extend({ - // this is a hack so that backbone.collections doesn't group - // these by id and reduce the number of items returned. - idAttribute: "_id", - - docType: function() { - if (!this.id) return "reduction"; - - return this.id.match(/^_design/) ? "design doc" : "doc"; - }, - documentation: function(){ - return FauxtonAPI.constants.DOC_URLS.GENERAL; - }, - url: function(context) { - return this.collection.database.url(context) + "/" + this.safeID(); - }, - - isEditable: function() { - return this.docType() != "reduction"; - }, - safeID: function() { - var id = this.id || this.get("id"); - - return app.utils.safeURLName(id); - }, - - prettyJSON: function() { - //var data = this.get("doc") ? this.get("doc") : this; - return JSON.stringify(this, null, " "); - } - }); - Documents.NewDoc = Documents.Doc.extend({ fetch: function() { var uuid = new FauxtonAPI.UUID(); @@ -492,7 +472,7 @@ function(app, FauxtonAPI, PagingCollection) { }); Documents.IndexCollection = PagingCollection.extend({ - model: Documents.ViewRow, + model: Documents.Doc, documentation: function(){ return FauxtonAPI.constants.DOC_URLS.GENERAL; }, http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/routes-doc-editor.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/routes-doc-editor.js b/app/addons/documents/routes-doc-editor.js index 83cca0b..4efed7c 100644 --- a/app/addons/documents/routes-doc-editor.js +++ b/app/addons/documents/routes-doc-editor.js @@ -39,7 +39,8 @@ function(app, FauxtonAPI, Documents, DocEditor, Databases) { routes: { "database/:database/:doc/code_editor": "code_editor", - "database/:database/:doc": "code_editor" + "database/:database/:doc": "code_editor", + "database/:database/_design/:ddoc" :"showDesignDoc" }, events: { @@ -70,6 +71,11 @@ function(app, FauxtonAPI, Documents, DocEditor, Databases) { model: this.doc, database: this.database })); + + }, + + showDesignDoc: function (database, ddoc) { + this.code_editor(database, '_design/' + ddoc); }, reRenderDoc: function () { http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/routes-documents.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/routes-documents.js b/app/addons/documents/routes-documents.js index cbec036..59e2044 100644 --- a/app/addons/documents/routes-documents.js +++ b/app/addons/documents/routes-documents.js @@ -86,8 +86,7 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou "route:perPageChange": "perPageChange", "route:changesFilterAdd": "addFilter", "route:changesFilterRemove": "removeFilter", - "route:updateQueryOptions": "updateQueryOptions", - "route:resetQueryOptions": "resetQueryOptions" + "route:updateQueryOptions": "updateQueryOptions" }, overrideBreadcrumbs: true, @@ -356,13 +355,26 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou return [this.indexedDocs.urlRef("apiurl", urlParams), FauxtonAPI.constants.DOC_URLS.GENERAL]; }; - this.rightHeader.showQueryOptions(); - this.rightHeader.resetQueryOptions({ - queryParams: urlParams, - showStale: true, - hasReduce: true, - viewName: viewName, - ddocName: ddoc + this.showQueryOptions(urlParams, ddoc, viewName); + }, + + showQueryOptions: function (urlParams, ddoc, viewName) { + var promise = this.designDocs.fetch({reset: true}), + that = this, + hasReduceFunction; + + promise.then(function(resp) { + var design = _.findWhere(that.designDocs.models, {id: '_design/'+ddoc}); + !_.isUndefined(hasReduceFunction = design.attributes.doc.views[viewName].reduce); + + that.rightHeader.showQueryOptions(); + that.rightHeader.resetQueryOptions({ + queryParams: urlParams, + showStale: true, + hasReduce: hasReduceFunction, + viewName: viewName, + ddocName: ddoc + }); }); }, @@ -492,6 +504,7 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou paginate: function (options) { var collection = this.documentsView.collection; + this.documentsView.collection.reset(collection); this.documentsView.forceRender(); collection.paging.pageSize = options.perPage; @@ -570,10 +583,6 @@ function(app, FauxtonAPI, Documents, Changes, Index, DocEditor, Databases, Resou this.changesView.render(); }, - resetQueryOptions: function(options) { - this.rightHeader.resetQueryOptions(options); - }, - updateQueryOptions: function(options) { this.rightHeader.updateQueryOptions(options); }, http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/templates/all_docs_item.html ---------------------------------------------------------------------- diff --git a/app/addons/documents/templates/all_docs_item.html b/app/addons/documents/templates/all_docs_item.html index e0c62fc..74e944a 100644 --- a/app/addons/documents/templates/all_docs_item.html +++ b/app/addons/documents/templates/all_docs_item.html @@ -20,15 +20,18 @@ the License. </div> <div class="doc-item"> <header> - <span class="header-keylabel"><%- doc.isEditable() ? 'id' : 'key' %></span> <span class="header-doc-id">"<%- docIdentifier %>"</span> - - <% if (doc.isEditable()) { %> - <div class="doc-edit-symbol pull-right"> - <a href="#<%- doc.url('web-index') %>"> - <i class="fonticon-pencil"></i> - </a> - </div> - <% } %> + <span class="header-keylabel"><%- doc.isFromView() ? 'key' : 'id' %></span> <span class="header-doc-id">"<%- docIdentifier %>"</span> + <% if (!doc.isReducedShown()) { %> + <div class="doc-edit-symbol pull-right"> + <% if (doc.isFromView()) { %> + <a href="#<%- doc.url('app') %>"> + <% } else { %> + <a href="#<%- doc.url('web-index')%>"> + <% } %> + <i class="fonticon-pencil"></i> + </a> + </div> + <% } %> </header> <div class="doc-data"> <pre class="prettyprint"><%- doc.prettyJSON() %></pre> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/templates/index_row_docular.html ---------------------------------------------------------------------- diff --git a/app/addons/documents/templates/index_row_docular.html b/app/addons/documents/templates/index_row_docular.html deleted file mode 100644 index e8973ad..0000000 --- a/app/addons/documents/templates/index_row_docular.html +++ /dev/null @@ -1,29 +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. ---> -<% if (doc.isEditable()) { %> - <td class="select"><input type="checkbox"></td> -<% } %> -<td> - <div> - <pre class="prettyprint"><%- doc.prettyJSON() %></pre> - - <div class="btn-group"> - <a href="#<%= url %>" class="btn btn-small edits">Edit <%= doc.docType() %></a> - <% if (doc.isEditable()) { %> - <button href="#" class="btn btn-small btn-danger delete" title="Delete this document."><i class="icon icon-trash"></i></button> - <% } %> - </div> - - </div> -</td> http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/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 new file mode 100644 index 0000000..48c08f6 --- /dev/null +++ b/app/addons/documents/tests/nightwatch/editDocumentsFromView.js @@ -0,0 +1,57 @@ +// 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 = { + 'Edit is allowed from default Map Views' : function (client) { + var waitTime = 10000, + newDatabaseName = client.globals.testDatabaseName, + newDocumentName = '_design/abc', + baseUrl = client.globals.test_settings.launch_url, + ddocContents = { + "views": { + "evens": { + "map": "function (doc) { if (doc.number%2 === 0){ emit(doc._id, doc.number); } }", + "reduce" : "_count" + } + }, + "language": "javascript" + }; + + client + .loginToGUI() + .createDocument(newDocumentName, newDatabaseName, ddocContents ) + .populateDatabase(newDatabaseName) + + //navigate to 'evens' view (declared above), then click on first document's pencil icon + .clickWhenVisible('#dashboard-content a[href="#/database/' + newDatabaseName + '/_all_docs"]') + .clickWhenVisible('#nav-header-abc') + .clickWhenVisible('#nav-design-function-abcviews') + .clickWhenVisible('#abc_evens') + .clickWhenVisible('a[href="#/database/fauxton-selenium-tests/document_10"]') + + //navigated to editor + .waitForElementVisible('#editor-container', waitTime, false) + .verify.urlContains('#/database/' + newDatabaseName +'/document_10'); + }, + + 'Edit is not allowed for Map Views where reduce is checked' : function (client) { + var waitTime = 10000; + + client + .clickWhenVisible('#doc-actions .cancel-button') + .clickWhenVisible('#toggle-query') + .clickWhenVisible('#query-options-tray label[for="qoReduce"]') + .clickWhenVisible('#button-options button[type="submit"]') + .waitForElementNotPresent('i.fonticon-pencil', waitTime) + .end(); + } +}; http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/views-index.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/views-index.js b/app/addons/documents/views-index.js index 6fda62c..e0445fc 100644 --- a/app/addons/documents/views-index.js +++ b/app/addons/documents/views-index.js @@ -33,16 +33,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, QueryOption var Views = {}; - - // this is a temporary workaround until I hear of a better on. The problem is that on initial page load (i.e. a refresh - // of the View page) the afterRender() functions calls a FauxtonAPI.triggerRouteEvent(). That causes this View to be - // rendered twice (at least, the afterRender() function then gets called twice) - and that causes the header content to - // disappear. This var tracks whether the View has been rendered and if not, doesn't call the triggerRouteEvent. btw, - // the reason the triggerRouteEvent('resetQueryOptions') code is there is that it ensures the Query Options tray shows - // the appropriate content for the current View (i.e. hasReduce or not) - var hasRenderedOnce = false; - - Views.ViewEditor = FauxtonAPI.View.extend({ template: "addons/documents/templates/view_editor", builtinReduces: ['_sum', '_count', '_stats'], @@ -454,15 +444,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, QueryOption }, afterRender: function() { - if (this.params && !this.newView && hasRenderedOnce) { - FauxtonAPI.triggerRouteEvent('resetQueryOptions', { - queryParams: this.params, - hasReduce: this.hasReduce(), - showStale: true, - viewName: this.viewName, - ddocName: this.ddocInfo.get('name') - }); - } this.designDocSelector.updateDesignDoc(); if (this.newView || this.showIndex) { @@ -473,8 +454,6 @@ function(app, FauxtonAPI, Components, Documents, Databases, pouchdb, QueryOption this.$('#index-nav').parent().removeClass('active'); } - // note that this View has been rendered - hasRenderedOnce = true; }, showEditors: function () { http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/app/addons/documents/views.js ---------------------------------------------------------------------- diff --git a/app/addons/documents/views.js b/app/addons/documents/views.js index 06d092c..dc47feb 100644 --- a/app/addons/documents/views.js +++ b/app/addons/documents/views.js @@ -196,7 +196,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions) }, events: { - "dblclick pre.prettyprint": "edit" + "dblclick .doc-item": "edit" }, attributes: function() { @@ -207,7 +207,7 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions) serialize: function() { return { - docIdentifier: this.model.isEditable() ? this.model.get('_id') : this.model.get('key'), + docIdentifier: this.model.isReducedShown() ? this.model.get('key') : this.model.get('_id'), doc: this.model, checked: this.checked }; @@ -219,7 +219,9 @@ function(app, FauxtonAPI, Components, Documents, Databases, Views, QueryOptions) edit: function(event) { event.preventDefault(); - FauxtonAPI.navigate("#" + this.model.url('web-index')); + if (!this.model.isReducedShown()) { + FauxtonAPI.navigate(this.model.url('app')); + } } }); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/test/nightwatch_tests/custom-commands/clickWhenVisible.js ---------------------------------------------------------------------- diff --git a/test/nightwatch_tests/custom-commands/clickWhenVisible.js b/test/nightwatch_tests/custom-commands/clickWhenVisible.js new file mode 100644 index 0000000..e1b4071 --- /dev/null +++ b/test/nightwatch_tests/custom-commands/clickWhenVisible.js @@ -0,0 +1,12 @@ +exports.command = function (element, waitTime) { + + if(waitTime === undefined){ + waitTime = 10000; + } + + this + .waitForElementVisible(element, waitTime, false) + .click(element); + + return this; +}; http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/test/nightwatch_tests/custom-commands/createDocument.js ---------------------------------------------------------------------- diff --git a/test/nightwatch_tests/custom-commands/createDocument.js b/test/nightwatch_tests/custom-commands/createDocument.js index 388dc5a..4d08505 100644 --- a/test/nightwatch_tests/custom-commands/createDocument.js +++ b/test/nightwatch_tests/custom-commands/createDocument.js @@ -9,12 +9,16 @@ function CreateDocument () { // inherit from node's event emitter util.inherits(CreateDocument, events.EventEmitter); -CreateDocument.prototype.command = function (documentName, databaseName) { +CreateDocument.prototype.command = function (documentName, databaseName, docContents) { var that = this, nano = helpers.getNanoInstance(), database = nano.use(databaseName); - database.insert({ dummyKey: "testingValue" }, documentName, function (err, body, header) { + if (docContents === undefined) { + docContents = { dummyKey: "testingValue" }; + } + + database.insert(docContents, documentName, function (err, body, header) { if (err) { console.log('Error in nano CreateDocument Function: '+documentName+', in database: '+databaseName, err.message); http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/test/nightwatch_tests/custom-commands/populateDatabase.js ---------------------------------------------------------------------- diff --git a/test/nightwatch_tests/custom-commands/populateDatabase.js b/test/nightwatch_tests/custom-commands/populateDatabase.js index ea1cbf8..bf01c97 100644 --- a/test/nightwatch_tests/custom-commands/populateDatabase.js +++ b/test/nightwatch_tests/custom-commands/populateDatabase.js @@ -19,7 +19,7 @@ PopulateDatabase.prototype.command = function (databaseName) { function () { return i < 20; }, function (cb) { i++; - var document_id = 'document_ '+ i; + var document_id = 'document_'+ i; database.insert({ number: i }, document_id, cb); }, function (err) { http://git-wip-us.apache.org/repos/asf/couchdb-fauxton/blob/c7fa6fad/test/nightwatch_tests/nightwatch_README.md ---------------------------------------------------------------------- diff --git a/test/nightwatch_tests/nightwatch_README.md b/test/nightwatch_tests/nightwatch_README.md index a18d6a7..761d6f8 100644 --- a/test/nightwatch_tests/nightwatch_README.md +++ b/test/nightwatch_tests/nightwatch_README.md @@ -51,8 +51,10 @@ has failed, and will not exit or skip subsequent tests. 3. `.waitForElementNotPresent()`, `.waitForElementNotVisible()`, `.waitForElementPresent()`, `.waitForElementVisible()`, will exit testing by default if the Element is not found. There is a third argument, 'abortOnFailure', if you set this to 'false', the rest of the tests will continue even if this assertion fails. +> there is a custom function called clickWhenReady which will wait for an element to visible, then click on it + 4. Sometimes `.click()` doesn't work reliably (most likely if the element you are clicking on doesn't have an -individual ID selector). You can use jquery to simulate a click by using `.execute($("#CSS Selector.HERE").click();)` +individual ID selector). You can use jquery to simulate a click by using `.execute('$("#CSS Selector.HERE").click();')`. 5. The function `.pause(time)` is sometimes necessary, although we have tried to avoid excessive use of a hard coded pausing. Instead try and make use of the `.waitForElement` functions instead of `.pause(time)`.
