blob: c29b31a4d7951c970c717373c015f361a2bed395 [file] [log] [blame]
defmodule UpdateDocumentsTest do
use CouchTestCase
@ddoc %{
_id: "_design/update",
language: "javascript",
updates: %{
hello: """
function(doc, 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": """
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];
}
""",
"form-update": """
function(doc, req) {
for (var field in req.form) {
doc[field] = req.form[field];
}
var message = "updated doc from form";
return [doc, message];
}
""",
"bump-counter": """
function(doc, req) {
if (!doc.counter) doc.counter = 0;
doc.counter += 1;
var message = "<h1>bumped it!</h1>";
return [doc, message];
}
""",
error: """
function(doc, req) {
superFail.badCrash;
}
""",
"get-uuid": """
function(doc, req) {
return [null, req.uuid];
}
""",
"code-n-bump": """
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": """
function(doc,req) {
resp = {"code": 302}
return [null, resp];
}
""",
"resp-code-and-json": """
function(doc,req) {
resp = {"code": 302, "json": {"ok": true}}
return [{"_id": req["uuid"]}, resp];
}
""",
binary: """
function(doc, req) {
var resp = {
"headers" : {
"Content-Type" : "application/octet-stream"
},
"base64" : "aGVsbG8gd29ybGQh" // "hello world!" encoded
};
return [doc, resp];
}
""",
empty: """
function(doc, req) {
return [{}, 'oops'];
}
"""
}
}
@document %{word: "plankton", name: "Rusty"}
@tag :with_db
test "update error invalid path", context do
db_name = context[:db_name]
create_doc(db_name, @ddoc)
resp = Couch.post("/#{db_name}/_design/update/_update/")
assert resp.status_code == 404
assert resp.body["reason"] == "Invalid path."
end
@tag :with_db
test "update document", context do
db_name = context[:db_name]
create_doc(db_name, @ddoc)
{:ok, resp} = create_doc(db_name, @document)
docid = resp.body["id"]
resp = Couch.put("/#{db_name}/_design/update/_update/hello/#{docid}")
assert resp.status_code == 201
assert resp.body == "<p>hello doc</p>"
assert String.contains?(resp.headers["Content-Type"], "charset=utf-8")
assert resp.headers["X-Couch-Id"] == docid
resp = Couch.get("/#{db_name}/#{docid}")
assert resp.status_code == 200
assert resp.body["world"] == "hello"
# Fix for COUCHDB-379
assert String.starts_with?(resp.headers["Server"], "CouchDB")
resp = Couch.put("/#{db_name}/_design/update/_update/hello")
assert resp.status_code == 200
assert resp.body == "<p>Empty World</p>"
end
@tag :with_db
test "GET is not allowed", context do
db_name = context[:db_name]
create_doc(db_name, @ddoc)
resp = Couch.get("/#{db_name}/_design/update/_update/hello")
assert resp.body["error"] == "method_not_allowed"
end
@tag :with_db
test "doc can be created", context do
db_name = context[:db_name]
create_doc(db_name, @ddoc)
resp = Couch.get("/#{db_name}/nonExistingDoc")
assert resp.status_code == 404
resp = Couch.put("/#{db_name}/_design/update/_update/hello/nonExistingDoc")
assert resp.status_code == 201
assert resp.body == "<p>New World</p>"
resp = Couch.get("/#{db_name}/nonExistingDoc")
assert resp.status_code == 200
end
@tag :with_db
test "in place update", context do
db_name = context[:db_name]
create_doc(db_name, @ddoc)
{:ok, resp} = create_doc(db_name, @document)
docid = resp.body["id"]
resp =
Couch.put(
"/#{db_name}/_design/update/_update/in-place/#{docid}?field=title&value=test"
)
assert resp.status_code == 201
assert resp.body == "set title to test"
resp = Couch.get("/#{db_name}/#{docid}")
assert resp.status_code == 200
assert resp.body["title"] == "test"
end
@tag :with_db
test "form update via application/x-www-form-urlencoded", context do
db_name = context[:db_name]
create_doc(db_name, @ddoc)
{:ok, resp} = create_doc(db_name, @document)
docid = resp.body["id"]
resp =
Couch.put(
"/#{db_name}/_design/update/_update/form-update/#{docid}",
headers: ["Content-Type": "application/x-www-form-urlencoded"],
body: "formfoo=bar&formbar=foo"
)
assert resp.status_code == 201
assert resp.body == "updated doc from form"
resp = Couch.get("/#{db_name}/#{docid}")
assert resp.status_code == 200
assert resp.body["formfoo"] == "bar"
assert resp.body["formbar"] == "foo"
end
@tag :with_db
test "bump counter", context do
db_name = context[:db_name]
create_doc(db_name, @ddoc)
{:ok, resp} = create_doc(db_name, @document)
docid = resp.body["id"]
resp =
Couch.put("/#{db_name}/_design/update/_update/bump-counter/#{docid}",
headers: ["X-Couch-Full-Commit": "true"]
)
assert resp.status_code == 201
assert resp.body == "<h1>bumped it!</h1>"
resp = Couch.get("/#{db_name}/#{docid}")
assert resp.status_code == 200
assert resp.body["counter"] == 1
resp =
Couch.put("/#{db_name}/_design/update/_update/bump-counter/#{docid}",
headers: ["X-Couch-Full-Commit": "true"]
)
newrev = resp.headers["X-Couch-Update-NewRev"]
resp = Couch.get("/#{db_name}/#{docid}")
assert resp.status_code == 200
assert resp.body["counter"] == 2
assert resp.body["_rev"] == newrev
end
@tag :with_db
test "Server provides UUID when POSTing without an ID in the URL", context do
db_name = context[:db_name]
create_doc(db_name, @ddoc)
resp = Couch.put("/#{db_name}/_design/update/_update/get-uuid/")
assert resp.status_code == 200
assert String.length(resp.body) == 32
end
@tag :with_db
test "COUCHDB-1229 - allow slashes in doc ids for update handlers", context do
db_name = context[:db_name]
create_doc(db_name, @ddoc)
create_doc(db_name, %{_id: "with/slash", counter: 1})
resp = Couch.put("/#{db_name}/_design/update/_update/bump-counter/with/slash")
assert resp.status_code == 201
assert resp.body == "<h1>bumped it!</h1>"
resp = Couch.get("/#{db_name}/with%2Fslash")
assert resp.status_code == 200
assert resp.body["counter"] == 2
end
@tag :with_db
test "COUCHDB-648 - the code in the JSON response should be honored", context do
db_name = context[:db_name]
create_doc(db_name, @ddoc)
{:ok, resp} = create_doc(db_name, @document)
docid = resp.body["id"]
Couch.put("/#{db_name}/_design/update/_update/bump-counter/#{docid}")
Couch.put("/#{db_name}/_design/update/_update/bump-counter/#{docid}")
resp = Couch.put("/#{db_name}/_design/update/_update/code-n-bump/#{docid}")
assert resp.status_code == 302
assert resp.body == "<h1>bumped it!</h1>"
resp = Couch.get("/#{db_name}/#{docid}")
assert resp.status_code == 200
assert resp.body["counter"] == 3
resp = Couch.put("/#{db_name}/_design/update/_update/resp-code/")
assert resp.status_code == 302
resp = Couch.put("/#{db_name}/_design/update/_update/resp-code-and-json/")
assert resp.status_code == 302
assert resp.body["ok"] == true
end
@tag :with_db
test "base64 response", context do
db_name = context[:db_name]
create_doc(db_name, @ddoc)
{:ok, resp} = create_doc(db_name, @document)
docid = resp.body["id"]
resp =
Couch.put("/#{db_name}/_design/update/_update/binary/#{docid}",
body: "rubbish"
)
assert resp.status_code == 201
assert resp.body == "hello world!"
assert String.contains?(resp.headers["Content-Type"], "application/octet-stream")
end
@tag :with_db
test "Insert doc with empty id", context do
db_name = context[:db_name]
create_doc(db_name, @ddoc)
resp = Couch.put("/#{db_name}/_design/update/_update/empty/foo")
assert resp.status_code == 400
assert resp.body["reason"] == "Document id must not be empty"
end
end