blob: 93ed8f177cfd2e30601a0e551028d4f1d30b62fc [file]
defmodule ValidateDocUpdateTest do
use CouchTestCase
@moduledoc """
Test validate_doc_update behaviour
"""
@js_type_check %{
language: "javascript",
validate_doc_update: ~s"""
function (newDoc) {
if (!newDoc.type) {
throw {forbidden: 'Documents must have a type field'};
}
}
"""
}
@tag :with_db
test "JavaScript VDU accepts a valid document", context do
db = context[:db_name]
Couch.put("/#{db}/_design/js-test", body: @js_type_check)
resp = Couch.put("/#{db}/doc", body: %{"type" => "movie"})
assert resp.status_code == 201
assert resp.body["ok"] == true
end
@tag :with_db
test "JavaScript VDU rejects an invalid document", context do
db = context[:db_name]
Couch.put("/#{db}/_design/js-test", body: @js_type_check)
resp = Couch.put("/#{db}/doc", body: %{"not" => "valid"})
assert resp.status_code == 403
assert resp.body["error"] == "forbidden"
end
@js_change_check %{
language: "javascript",
validate_doc_update: ~s"""
function (newDoc, oldDoc) {
if (oldDoc && newDoc.type !== oldDoc.type) {
throw {forbidden: 'Documents cannot change their type field'};
}
}
"""
}
@tag :with_db
test "JavaScript VDU accepts a valid change", context do
db = context[:db_name]
Couch.put("/#{db}/_design/js-test", body: @js_change_check)
Couch.put("/#{db}/doc", body: %{"type" => "movie"})
doc = Couch.get("/#{db}/doc").body
updated = doc |> Map.merge(%{"type" => "movie", "title" => "Duck Soup"})
resp = Couch.put("/#{db}/doc", body: updated)
assert resp.status_code == 201
end
@tag :with_db
test "JavaScript VDU rejects an invalid change", context do
db = context[:db_name]
Couch.put("/#{db}/_design/js-test", body: @js_change_check)
Couch.put("/#{db}/doc", body: %{"type" => "movie"})
doc = Couch.get("/#{db}/doc").body
updated = doc |> Map.put("type", "director")
resp = Couch.put("/#{db}/doc", body: updated)
assert resp.status_code == 403
end
@mango_type_check %{
language: "query",
validate_doc_update: %{
"newDoc" => %{"type" => %{"$exists" => true}}
}
}
@tag :with_db
test "Mango VDU accepts a valid document", context do
db = context[:db_name]
resp = Couch.put("/#{db}/_design/mango-test", body: @mango_type_check)
assert resp.status_code == 201
resp = Couch.put("/#{db}/doc", body: %{"type" => "movie"})
assert resp.status_code == 201
assert resp.body["ok"] == true
end
@tag :with_db
test "Mango VDU rejects an invalid document", context do
db = context[:db_name]
resp = Couch.put("/#{db}/_design/mango-test", body: @mango_type_check)
assert resp.status_code == 201
resp = Couch.put("/#{db}/doc", body: %{"no" => "type"})
assert resp.status_code == 403
assert resp.body["error"] == "forbidden"
end
@tag :with_db
test "updating a Mango VDU updates its effects", context do
db = context[:db_name]
resp = Couch.put("/#{db}/_design/mango-test", body: @mango_type_check)
assert resp.status_code == 201
ddoc = %{
language: "query",
validate_doc_update: %{
"newDoc" => %{
"type" => %{"$type" => "string"},
"year" => %{"$lt" => 2026}
}
}
}
resp = Couch.put("/#{db}/_design/mango-test", body: ddoc, query: %{rev: resp.body["rev"]})
assert resp.status_code == 201
resp = Couch.put("/#{db}/doc1", body: %{"type" => "movie", "year" => 1994})
assert resp.status_code == 201
resp = Couch.put("/#{db}/doc2", body: %{"type" => 42, "year" => 1994})
assert resp.status_code == 403
assert resp.body["error"] == "forbidden"
resp = Couch.put("/#{db}/doc3", body: %{"type" => "movie", "year" => 2094})
assert resp.status_code == 403
assert resp.body["error"] == "forbidden"
end
@tag :with_db
test "converting a Mango VDU to JavaScript updates its effects", context do
db = context[:db_name]
resp = Couch.put("/#{db}/_design/mango-test", body: @mango_type_check)
assert resp.status_code == 201
ddoc = %{
language: "javascript",
validate_doc_update: ~s"""
function (newDoc) {
if (typeof newDoc.year !== 'number') {
throw {forbidden: 'Documents must have a valid year field'};
}
}
"""
}
resp = Couch.put("/#{db}/_design/mango-test", body: ddoc, query: %{rev: resp.body["rev"]})
assert resp.status_code == 201
resp = Couch.put("/#{db}/doc1", body: %{"year" => 1994})
assert resp.status_code == 201
resp = Couch.put("/#{db}/doc2", body: %{"year" => "1994"})
assert resp.status_code == 403
assert resp.body["error"] == "forbidden"
end
@tag :with_db
test "deleting a Mango VDU removes its effects", context do
db = context[:db_name]
resp = Couch.put("/#{db}/_design/mango-test", body: @mango_type_check)
assert resp.status_code == 201
resp = Couch.delete("/#{db}/_design/mango-test", query: %{rev: resp.body["rev"]})
assert resp.status_code == 200
resp = Couch.put("/#{db}/doc", body: %{"no" => "type"})
assert resp.status_code == 201
end
@tag :with_db
test "Mango VDU rejects a doc if any existing ddoc fails to match", context do
db = context[:db_name]
resp = Couch.put("/#{db}/_design/mango-test", body: @mango_type_check)
assert resp.status_code == 201
ddoc = %{
language: "query",
validate_doc_update: %{
"newDoc" => %{"year" => %{"$lt" => 2026}}
}
}
resp = Couch.put("/#{db}/_design/mango-test-2", body: ddoc)
assert resp.status_code == 201
resp = Couch.put("/#{db}/doc1", body: %{"type" => "movie", "year" => 1994})
assert resp.status_code == 201
resp = Couch.put("/#{db}/doc2", body: %{"year" => 1994})
assert resp.status_code == 403
assert resp.body["error"] == "forbidden"
resp = Couch.put("/#{db}/doc3", body: %{"type" => "movie", "year" => 2094})
assert resp.status_code == 403
assert resp.body["error"] == "forbidden"
end
end