| // 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. |
| |
| |
| couchTests.update_documents = function(debug) { |
| var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"}); |
| db.deleteDb(); |
| db.createDb(); |
| if (debug) debugger; |
| |
| var designDoc = { |
| _id:"_design/update", |
| language: "javascript", |
| updates: { |
| "hello" : stringFun(function(doc, req) { |
| log(doc); |
| log(req); |
| if (!doc) { |
| if (req.id) { |
| return [ |
| // Creates a new document with the PUT docid, |
| { _id : req.id, |
| reqs : [req] }, |
| // and returns an HTML response to the client. |
| "<p>New World</p>"]; |
| }; |
| // |
| return [null, "<p>Empty World</p>"]; |
| }; |
| // we can update the document inline |
| doc.world = "hello"; |
| // we can record aspects of the request or use them in application logic. |
| doc.reqs && doc.reqs.push(req); |
| doc.edited_by = req.userCtx; |
| return [doc, "<p>hello doc</p>"]; |
| }), |
| "in-place" : stringFun(function(doc, req) { |
| var field = req.query.field; |
| var value = req.query.value; |
| var message = "set "+field+" to "+value; |
| doc[field] = value; |
| return [doc, message]; |
| }), |
| "bump-counter" : stringFun(function(doc, req) { |
| if (!doc.counter) doc.counter = 0; |
| doc.counter += 1; |
| var message = "<h1>bumped it!</h1>"; |
| return [doc, message]; |
| }), |
| "error" : stringFun(function(doc, req) { |
| superFail.badCrash; |
| }), |
| "xml" : stringFun(function(doc, req) { |
| var xml = new XML('<xml></xml>'); |
| xml.title = doc.title; |
| var posted_xml = new XML(req.body); |
| doc.via_xml = posted_xml.foo.toString(); |
| var resp = { |
| "headers" : { |
| "Content-Type" : "application/xml" |
| }, |
| "body" : xml.toXMLString() |
| }; |
| |
| return [doc, resp]; |
| }), |
| "get-uuid" : stringFun(function(doc, req) { |
| return [null, req.uuid]; |
| }), |
| "code-n-bump" : stringFun(function(doc,req) { |
| if (!doc.counter) doc.counter = 0; |
| doc.counter += 1; |
| var message = "<h1>bumped it!</h1>"; |
| resp = {"code": 302, "body": message} |
| return [doc, resp]; |
| }), |
| "resp-code" : stringFun(function(doc,req) { |
| resp = {"code": 302} |
| return [null, resp]; |
| }), |
| "resp-code-and-json" : stringFun(function(doc,req) { |
| resp = {"code": 302, "json": {"ok": true}} |
| return [{"_id": req["uuid"]}, resp]; |
| }), |
| "binary" : stringFun(function(doc, req) { |
| var resp = { |
| "headers" : { |
| "Content-Type" : "application/octet-stream" |
| }, |
| "base64" : "aGVsbG8gd29ybGQh" // "hello world!" encoded |
| }; |
| return [doc, resp]; |
| }), |
| "empty" : stringFun(function(doc, req) { |
| return [{}, 'oops']; |
| }) |
| } |
| }; |
| T(db.save(designDoc).ok); |
| |
| var doc = {"word":"plankton", "name":"Rusty"} |
| var resp = db.save(doc); |
| T(resp.ok); |
| var docid = resp.id; |
| |
| // update error |
| var xhr = CouchDB.request("POST", "/test_suite_db/_design/update/_update/"); |
| T(xhr.status == 404, 'Should be missing'); |
| T(JSON.parse(xhr.responseText).reason == "Invalid path."); |
| |
| // hello update world |
| xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/hello/"+docid); |
| T(xhr.status == 201); |
| T(xhr.responseText == "<p>hello doc</p>"); |
| T(/charset=utf-8/.test(xhr.getResponseHeader("Content-Type"))); |
| T(equals(docid, xhr.getResponseHeader("X-Couch-Id"))); |
| |
| doc = db.open(docid); |
| T(doc.world == "hello"); |
| |
| // Fix for COUCHDB-379 |
| T(equals(xhr.getResponseHeader("Server").substr(0,7), "CouchDB")); |
| |
| // hello update world (no docid) |
| xhr = CouchDB.request("POST", "/test_suite_db/_design/update/_update/hello"); |
| T(xhr.status == 200); |
| T(xhr.responseText == "<p>Empty World</p>"); |
| |
| // no GET allowed |
| xhr = CouchDB.request("GET", "/test_suite_db/_design/update/_update/hello"); |
| // T(xhr.status == 405); // TODO allow qs to throw error code as well as error message |
| T(JSON.parse(xhr.responseText).error == "method_not_allowed"); |
| |
| // // hello update world (non-existing docid) |
| xhr = CouchDB.request("GET", "/test_suite_db/nonExistingDoc"); |
| T(xhr.status == 404); |
| xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/hello/nonExistingDoc"); |
| T(xhr.status == 201); |
| T(xhr.responseText == "<p>New World</p>"); |
| xhr = CouchDB.request("GET", "/test_suite_db/nonExistingDoc"); |
| T(xhr.status == 200); |
| |
| // in place update |
| xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/in-place/"+docid+'?field=title&value=test'); |
| T(xhr.status == 201); |
| T(xhr.responseText == "set title to test"); |
| doc = db.open(docid); |
| T(doc.title == "test"); |
| |
| // bump counter |
| xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/bump-counter/"+docid, { |
| headers : {"X-Couch-Full-Commit":"true"} |
| }); |
| T(xhr.status == 201); |
| T(xhr.responseText == "<h1>bumped it!</h1>"); |
| doc = db.open(docid); |
| T(doc.counter == 1); |
| |
| // _update honors full commit if you need it to |
| xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/bump-counter/"+docid, { |
| headers : {"X-Couch-Full-Commit":"true"} |
| }); |
| |
| var NewRev = xhr.getResponseHeader("X-Couch-Update-NewRev"); |
| doc = db.open(docid); |
| T(doc['_rev'] == NewRev); |
| |
| |
| T(doc.counter == 2); |
| |
| // parse xml |
| xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/xml/"+docid, { |
| headers : {"X-Couch-Full-Commit":"true"}, |
| "body" : '<xml><foo>bar</foo></xml>' |
| }); |
| T(xhr.status == 201); |
| T(xhr.responseText == "<xml>\n <title>test</title>\n</xml>"); |
| |
| doc = db.open(docid); |
| T(doc.via_xml == "bar"); |
| |
| // Server provides UUID when POSTing without an ID in the URL |
| xhr = CouchDB.request("POST", "/test_suite_db/_design/update/_update/get-uuid/"); |
| T(xhr.status == 200); |
| T(xhr.responseText.length == 32); |
| |
| // COUCHDB-1229 - allow slashes in doc ids for update handlers |
| // /db/_design/doc/_update/handler/doc/id |
| |
| var doc = { |
| _id:"with/slash", |
| counter:1 |
| }; |
| db.save(doc); |
| xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/bump-counter/with/slash"); |
| TEquals(201, xhr.status, "should return a 200 status"); |
| TEquals("<h1>bumped it!</h1>", xhr.responseText, "should report bumping"); |
| |
| var doc = db.open("with/slash"); |
| TEquals(2, doc.counter, "counter should be 2"); |
| |
| // COUCHDB-648 - the code in the JSON response should be honored |
| |
| xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/code-n-bump/"+docid, { |
| headers : {"X-Couch-Full-Commit":"true"} |
| }); |
| T(xhr.status == 302); |
| T(xhr.responseText == "<h1>bumped it!</h1>"); |
| doc = db.open(docid); |
| T(doc.counter == 3); |
| |
| xhr = CouchDB.request("POST", "/test_suite_db/_design/update/_update/resp-code/"); |
| T(xhr.status == 302); |
| |
| xhr = CouchDB.request("POST", "/test_suite_db/_design/update/_update/resp-code-and-json/"); |
| TEquals(302, xhr.status); |
| T(JSON.parse(xhr.responseText).ok); |
| |
| // base64 response |
| xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/binary/"+docid, { |
| headers : {"X-Couch-Full-Commit":"false"}, |
| body : 'rubbish' |
| }); |
| T(xhr.status == 201); |
| T(xhr.responseText == "hello world!"); |
| T(/application\/octet-stream/.test(xhr.getResponseHeader("Content-Type"))); |
| |
| // Insert doc with empty id |
| xhr = CouchDB.request("PUT", "/test_suite_db/_design/update/_update/empty/foo"); |
| TEquals(400, xhr.status); |
| TEquals("Document id must not be empty", JSON.parse(xhr.responseText).reason); |
| |
| }; |