blob: a3adb3e7d4b6b7ad4858e09ca4a87f1ad80ad86e [file] [log] [blame]
defmodule RewriteJSTest do
use CouchTestCase
@moduletag :js_engine
@moduletag kind: :single_node
@moduledoc """
Test CouchDB rewrites JS
This is a port of the rewrite_js.js suite
"""
@ddoc %{
_id: "_design/test",
language: "javascript",
_attachments: %{
"foo.txt": %{
content_type: "text/plain",
data: "VGhpcyBpcyBhIGJhc2U2NCBlbmNvZGVkIHRleHQ="
}
},
rewrites: """
function(req) {
prefix = req.path[4];
if (prefix === 'foo') {
return 'foo.txt';
}
if (prefix === 'foo2') {
return {path: 'foo.txt', method: 'GET'};
}
if (prefix === 'hello') {
if (req.method != 'PUT') {
return
}
id = req.path[5];
return {path: '_update/hello/' + id};
}
if (prefix === 'welcome') {
if (req.path.length == 6){
name = req.path[5];
return {path: '_show/welcome', query: {'name': name}};
}
return '_show/welcome';
}
if (prefix === 'welcome2') {
return {path: '_show/welcome', query: {'name': 'user'}};
}
if (prefix === 'welcome3') {
name = req.path[5];
if (req.method == 'PUT') {
path = '_update/welcome2/' + name;
} else if (req.method == 'GET') {
path = '_show/welcome2/' + name;
} else {
return;
}
return path;
}
if (prefix === 'welcome4') {
return {path: '_show/welcome3', query: {name: req.path[5]}};
}
if (prefix === 'welcome5') {
rest = req.path.slice(5).join('/');
return {path: '_show/' + rest, query: {name: rest}};
}
if (prefix === 'basicView') {
rest = req.path.slice(5).join('/');
return {path: '_view/basicView'};
}
if (req.path.slice(4).join('/') === 'simpleForm/basicView') {
return {path: '_list/simpleForm/basicView'};
}
if (req.path.slice(4).join('/') === 'simpleForm/basicViewFixed') {
return {path: '_list/simpleForm/basicView',
query: {startkey: '"3"', endkey: '"8"'}};
}
if (req.path.slice(4).join('/') === 'simpleForm/complexView') {
return {path: '_list/simpleForm/complexView',
query: {key: JSON.stringify([1,2])}};
}
if (req.path.slice(4).join('/') === 'simpleForm/complexView2') {
return {path: '_list/simpleForm/complexView',
query: {key: JSON.stringify(['test', {}])}};
}
if (req.path.slice(4).join('/') === 'simpleForm/complexView3') {
return {path: '_list/simpleForm/complexView',
query: {key: JSON.stringify(['test', ['test', 'essai']])}};
}
if (req.path.slice(4).join('/') === 'simpleForm/complexView4') {
return {path: '_list/simpleForm/complexView2',
query: {key: JSON.stringify({"c": 1})}};
}
if (req.path.slice(4).join('/') === 'simpleForm/sendBody1') {
return {path: '_list/simpleForm/complexView2',
method: 'POST',
query: {limit: '1'},
headers:{'Content-type':'application/json'},
body: JSON.stringify( {keys: [{"c": 1}]} )};
}
if (req.path.slice(4).join('/') === '/') {
return {path: '_view/basicView'};
}
if (prefix === 'db') {
return {path: '../../' + req.path.slice(5).join('/')};
}
}
""",
lists: %{
simpleForm: """
function(head, req) {
send('<ul>');
var row, row_number = 0, prevKey, firstKey = null;
while (row = getRow()) {
row_number += 1;
if (!firstKey) firstKey = row.key;
prevKey = row.key;
send('\\n<li>Key: '+row.key
+' Value: '+row.value
+' LineNo: '+row_number+'</li>');
}
return '</ul><p>FirstKey: '+ firstKey + ' LastKey: '+ prevKey+'</p>';
}
"""
},
shows: %{
welcome: """
function(doc,req) {
return "Welcome " + req.query["name"];
}
""",
welcome2: """
function(doc, req) {
return "Welcome " + doc.name;
}
""",
welcome3: """
function(doc,req) {
return "Welcome " + req.query["name"];
}
"""
},
updates: %{
hello: """
function(doc, req) {
if (!doc) {
if (req.id) {
return [{
_id : req.id
}, "New World"]
}
return [null, "Empty World"];
}
doc.world = "hello";
doc.edited_by = req.userCtx;
return [doc, "hello doc"];
}
""",
welcome2: """
function(doc, req) {
if (!doc) {
if (req.id) {
return [{
_id: req.id,
name: req.id
}, "New World"]
}
return [null, "Empty World"];
}
return [doc, "hello doc"];
}
"""
},
views: %{
basicView: %{
map: """
function(doc) {
if (doc.integer) {
emit(doc.integer, doc.string);
}
}
"""
},
complexView: %{
map: """
function(doc) {
if (doc.type == "complex") {
emit([doc.a, doc.b], doc.string);
}
}
"""
},
complexView2: %{
map: """
function(doc) {
if (doc.type == "complex") {
emit(doc.a, doc.string);
}
}
"""
},
complexView3: %{
map: """
function(doc) {
if (doc.type == "complex") {
emit(doc.b, doc.string);
}
}
"""
}
}
}
Enum.each(
["test_rewrite_suite_db", "test_rewrite_suite_db%2Fwith_slashes"],
fn db_name ->
@tag with_random_db: db_name
test "Test basic js rewrites on #{db_name}", context do
db_name = context[:db_name]
create_doc(db_name, @ddoc)
docs1 = make_docs(0..9)
bulk_save(db_name, docs1)
docs2 = [
%{"a" => 1, "b" => 1, "string" => "doc 1", "type" => "complex"},
%{"a" => 1, "b" => 2, "string" => "doc 2", "type" => "complex"},
%{"a" => "test", "b" => %{}, "string" => "doc 3", "type" => "complex"},
%{
"a" => "test",
"b" => ["test", "essai"],
"string" => "doc 4",
"type" => "complex"
},
%{"a" => %{"c" => 1}, "b" => "", "string" => "doc 5", "type" => "complex"}
]
bulk_save(db_name, docs2)
# Test simple rewriting
resp = Couch.get("/#{db_name}/_design/test/_rewrite/foo")
assert resp.body == "This is a base64 encoded text"
assert resp.headers["Content-Type"] == "text/plain"
resp = Couch.get("/#{db_name}/_design/test/_rewrite/foo2")
assert resp.body == "This is a base64 encoded text"
assert resp.headers["Content-Type"] == "text/plain"
# Test POST, hello update world
resp =
Couch.post("/#{db_name}", body: %{"word" => "plankton", "name" => "Rusty"}).body
assert resp["ok"]
doc_id = resp["id"]
assert doc_id
resp = Couch.put("/#{db_name}/_design/test/_rewrite/hello/#{doc_id}")
assert resp.status_code in [201, 202]
assert resp.body == "hello doc"
assert String.match?(resp.headers["Content-Type"], ~r/charset=utf-8/)
assert Couch.get("/#{db_name}/#{doc_id}").body["world"] == "hello"
resp = Couch.get("/#{db_name}/_design/test/_rewrite/welcome?name=user")
assert resp.body == "Welcome user"
resp = Couch.get("/#{db_name}/_design/test/_rewrite/welcome/user")
assert resp.body == "Welcome user"
resp = Couch.get("/#{db_name}/_design/test/_rewrite/welcome2")
assert resp.body == "Welcome user"
resp = Couch.put("/#{db_name}/_design/test/_rewrite/welcome3/test")
assert resp.status_code in [201, 202]
assert resp.body == "New World"
assert String.match?(resp.headers["Content-Type"], ~r/charset=utf-8/)
resp = Couch.get("/#{db_name}/_design/test/_rewrite/welcome3/test")
assert resp.body == "Welcome test"
resp = Couch.get("/#{db_name}/_design/test/_rewrite/welcome4/user")
assert resp.body == "Welcome user"
resp = Couch.get("/#{db_name}/_design/test/_rewrite/welcome5/welcome3")
assert resp.body == "Welcome welcome3"
resp = Couch.get("/#{db_name}/_design/test/_rewrite/basicView")
assert resp.status_code == 200
assert resp.body["total_rows"] == 9
resp = Rawresp.get("/#{db_name}/_design/test/_rewrite/simpleForm/complexView")
assert resp.status_code == 200
assert String.match?(resp.body, ~r/FirstKey: [1, 2]/)
resp = Rawresp.get("/#{db_name}/_design/test/_rewrite/simpleForm/complexView2")
assert resp.status_code == 200
assert String.match?(resp.body, ~r/Value: doc 3/)
resp = Rawresp.get("/#{db_name}/_design/test/_rewrite/simpleForm/complexView3")
assert resp.status_code == 200
assert String.match?(resp.body, ~r/Value: doc 4/)
resp = Rawresp.get("/#{db_name}/_design/test/_rewrite/simpleForm/complexView4")
assert resp.status_code == 200
assert String.match?(resp.body, ~r/Value: doc 5/)
# COUCHDB-1612 - send body rewriting get to post
resp = Rawresp.get("/#{db_name}/_design/test/_rewrite/simpleForm/sendBody1")
assert resp.status_code == 200
assert String.match?(resp.body, ~r/Value: doc 5 LineNo: 1/)
resp = Couch.get("/#{db_name}/_design/test/_rewrite/db/_design/test?meta=true")
assert resp.status_code == 200
assert resp.body["_id"] == "_design/test"
assert Map.has_key?(resp.body, "_revs_info")
end
@tag with_random_db: db_name
test "early response on #{db_name}", context do
db_name = context[:db_name]
ddoc = %{
_id: "_design/response",
rewrites: """
function(req){
status = parseInt(req.query.status);
return {code: status,
body: JSON.stringify({"status": status}),
headers: {'x-foo': 'bar', 'Content-Type': 'application/json'}};
}
"""
}
create_doc(db_name, ddoc)
resp = Couch.get("/#{db_name}/_design/response/_rewrite?status=200")
assert resp.status_code == 200
assert resp.headers["x-foo"] == "bar"
assert resp.body["status"] == 200
resp = Couch.get("/#{db_name}/_design/response/_rewrite?status=451")
assert resp.status_code == 451
assert resp.headers["Content-Type"] == "application/json"
resp = Couch.get("/#{db_name}/_design/response/_rewrite?status=500")
assert resp.status_code == 500
end
@tag with_random_db: db_name
test "path relative to server on #{db_name}", context do
db_name = context[:db_name]
ddoc = %{
_id: "_design/relative",
rewrites: """
function(req){
return '../../../_uuids'
}
"""
}
create_doc(db_name, ddoc)
resp = Couch.get("/#{db_name}/_design/relative/_rewrite/uuids")
assert resp.status_code == 200
assert length(resp.body["uuids"]) == 1
end
@tag with_random_db: db_name
test "loop on #{db_name}", context do
db_name = context[:db_name]
ddoc_loop = %{
_id: "_design/loop",
rewrites: """
function(req) {
return '_rewrite/loop';
}
"""
}
create_doc(db_name, ddoc_loop)
resp = Couch.get("/#{db_name}/_design/loop/_rewrite/loop")
assert resp.status_code == 400
end
@tag with_random_db: db_name
test "requests with body preserve the query string rewrite on #{db_name}",
context do
db_name = context[:db_name]
ddoc_qs = %{
_id: "_design/qs",
rewrites:
"function (r) { return {path: '../../_changes', query: {'filter': '_doc_ids'}};};"
}
create_doc(db_name, ddoc_qs)
create_doc(db_name, %{_id: "qs1"})
create_doc(db_name, %{_id: "qs2"})
resp =
Couch.post("/#{db_name}/_design/qs/_rewrite",
body: %{doc_ids: ["qs2"]}
)
assert resp.status_code == 200
assert length(resp.body["results"]) == 1
assert Enum.at(resp.body["results"], 0)["id"] == "qs2"
end
end
)
end