diff --git a/kong/api/crud_helpers.lua b/kong/api/crud_helpers.lua index 469fe92123c3..6681a347b707 100644 --- a/kong/api/crud_helpers.lua +++ b/kong/api/crud_helpers.lua @@ -39,8 +39,10 @@ function _M.put(self, dao_collection) local new_entity, err if self.params.id then new_entity, err = dao_collection:update(self.params) - if not err then + if not err and new_entity then return responses.send_HTTP_OK(new_entity) + elseif not new_entity then + return responses.send_HTTP_NOT_FOUND() end else new_entity, err = dao_collection:insert(self.params) diff --git a/kong/api/routes/apis.lua b/kong/api/routes/apis.lua index f07afd730fc4..f097630bc97b 100644 --- a/kong/api/routes/apis.lua +++ b/kong/api/routes/apis.lua @@ -1,7 +1,7 @@ local validations = require "kong.dao.schemas" local crud = require "kong.api.crud_helpers" -local function find_by_name_or_id(self, dao_factory, helpers) +local function find_api_by_name_or_id(self, dao_factory, helpers) local fetch_keys = { [validations.is_valid_uuid(self.params.name_or_id) and "id" or "name"] = self.params.name_or_id } @@ -20,6 +20,24 @@ local function find_by_name_or_id(self, dao_factory, helpers) end end +local function find_plugin_by_name_or_id(self, dao_factory, helpers) + local fetch_keys = { + api_id = self.api.id, + [validations.is_valid_uuid(self.params.plugin_name_or_id) and "id" or "name"] = self.params.plugin_name_or_id + } + self.params.plugin_name_or_id = nil + + local data, err = dao_factory.plugins_configurations:find_by_keys(fetch_keys) + if err then + return helpers.yield_error(err) + end + + self.plugin = data[1] + if not self.plugin then + return helpers.responses.send_HTTP_NOT_FOUND() + end +end + return { ["/apis/"] = { GET = function(self, dao_factory) @@ -36,7 +54,7 @@ return { }, ["/apis/:name_or_id"] = { - before = find_by_name_or_id, + before = find_api_by_name_or_id, GET = function(self, dao_factory, helpers) return helpers.responses.send_HTTP_OK(self.api) @@ -54,7 +72,7 @@ return { ["/apis/:name_or_id/plugins/"] = { before = function(self, dao_factory, helpers) - find_by_name_or_id(self, dao_factory, helpers) + find_api_by_name_or_id(self, dao_factory, helpers) self.params.api_id = self.api.id end, @@ -69,5 +87,27 @@ return { PUT = function(self, dao_factory, helpers) crud.put(self, dao_factory.plugins_configurations) end + }, + + ["/apis/:name_or_id/plugins/:plugin_name_or_id"] = { + before = function(self, dao_factory, helpers) + find_api_by_name_or_id(self, dao_factory, helpers) + self.params.api_id = self.api.id + + find_plugin_by_name_or_id(self, dao_factory, helpers) + end, + + GET = function(self, dao_factory, helpers) + return helpers.responses.send_HTTP_OK(self.plugin) + end, + + PATCH = function(self, dao_factory, helpers) + self.params.id = self.plugin.id + crud.patch(self.params, dao_factory.plugins_configurations) + end, + + DELETE = function(self, dao_factory) + crud.delete(self.plugin.id, dao_factory.plugins_configurations) + end } } diff --git a/kong/dao/cassandra/base_dao.lua b/kong/dao/cassandra/base_dao.lua index b9a0ddec7c7b..fb01c8f37b6e 100644 --- a/kong/dao/cassandra/base_dao.lua +++ b/kong/dao/cassandra/base_dao.lua @@ -129,7 +129,7 @@ function BaseDao:_check_all_unique(t, is_updating) elseif not unique and k == "self" then return false, nil, self._entity.." already exists" elseif not unique then - errors = utils.add_error(errors, k, k.." already exists with value "..t[k]) + errors = utils.add_error(errors, k, k.." already exists with value '"..t[k].."'") end end end diff --git a/kong/dao/schemas/consumers.lua b/kong/dao/schemas/consumers.lua index 32dd97bc35b9..6ba7d25d5ec4 100644 --- a/kong/dao/schemas/consumers.lua +++ b/kong/dao/schemas/consumers.lua @@ -2,8 +2,11 @@ local stringy = require "stringy" local constants = require "kong.constants" local function check_custom_id_and_username(value, consumer_t) - if (consumer_t.custom_id == nil or stringy.strip(consumer_t.custom_id) == "") - and (consumer_t.username == nil or stringy.strip(consumer_t.username) == "") then + local custom_id = consumer_t.custom_id + local username = consumer_t.username + + if (custom_id == nil or type(custom_id) == "string" and stringy.strip(custom_id) == "") + and (username == nil or type(username) == "string" and stringy.strip(username) == "") then return false, "At least a 'custom_id' or a 'username' must be specified" end return true diff --git a/spec/integration/admin_api/apis_routes_spec.lua b/spec/integration/admin_api/apis_routes_spec.lua new file mode 100644 index 000000000000..852c398ecd20 --- /dev/null +++ b/spec/integration/admin_api/apis_routes_spec.lua @@ -0,0 +1,375 @@ +local json = require "cjson" +local http_client = require "kong.tools.http_client" +local spec_helper = require "spec.spec_helpers" +local send_content_types = require "spec.integration.admin_api.helpers" + +describe("Admin API", function() + + setup(function() + spec_helper.prepare_db() + spec_helper.start_kong() + end) + + teardown(function() + spec_helper.stop_kong() + end) + + describe("/apis/", function() + + local BASE_URL = spec_helper.API_URL.."/apis/" + + describe("POST", function() + + it("[SUCCESS] should create an API", function() + send_content_types(BASE_URL, "POST", { + name="api POST tests", + public_dns="api.mockbin.com", + target_url="http://mockbin.com" + }, 201, nil, {drop_db=true}) + end) + + it("[FAILURE] should notify of malformed body", function() + local response, status = http_client.post(BASE_URL, '{"hello":"world"', {["content-type"] = "application/json"}) + assert.are.equal(400, status) + assert.are.equal('{"message":"Cannot parse JSON body"}\n', response) + end) + + it("[FAILURE] should return proper errors", function() + send_content_types(BASE_URL, "POST", {}, + 400, + '{"public_dns":"public_dns is required","target_url":"target_url is required"}') + + send_content_types(BASE_URL, "POST", {public_dns="api.mockbin.com"}, + 400, '{"target_url":"target_url is required"}') + + send_content_types(BASE_URL, "POST", { + public_dns="api.mockbin.com", + target_url="http://mockbin.com" + }, 409, '{"public_dns":"public_dns already exists with value \'api.mockbin.com\'"}') + end) + + end) + + describe("PUT", function() + setup(function() + spec_helper.drop_db() + end) + + it("[SUCCESS] should create and update", function() + local api = send_content_types(BASE_URL, "PUT", { + name="api PUT tests", + public_dns="api.mockbin.com", + target_url="http://mockbin.com" + }, 201, nil, {drop_db=true}) + + api = send_content_types(BASE_URL, "PUT", { + id=api.id, + name="api PUT tests updated", + public_dns="updated-api.mockbin.com", + target_url="http://mockbin.com" + }, 200) + assert.equal("api PUT tests updated", api.name) + end) + + it("[FAILURE] should return proper errors", function() + send_content_types(BASE_URL, "PUT", {}, + 400, + '{"public_dns":"public_dns is required","target_url":"target_url is required"}') + + send_content_types(BASE_URL, "PUT", {public_dns="api.mockbin.com"}, + 400, '{"target_url":"target_url is required"}') + + send_content_types(BASE_URL, "PUT", { + public_dns="updated-api.mockbin.com", + target_url="http://mockbin.com" + }, 409, '{"public_dns":"public_dns already exists with value \'updated-api.mockbin.com\'"}') + end) + + end) + + describe("GET", function() + + setup(function() + spec_helper.drop_db() + spec_helper.seed_db(10) + end) + + it("should retrieve all", function() + local response, status = http_client.get(BASE_URL) + assert.equal(200, status) + local body = json.decode(response) + assert.truthy(body.data) + assert.equal(10, table.getn(body.data)) + end) + + it("should retrieve a paginated set", function() + local response, status = http_client.get(BASE_URL, {size=3}) + assert.equal(200, status) + local body_page_1 = json.decode(response) + assert.truthy(body_page_1.data) + assert.equal(3, table.getn(body_page_1.data)) + assert.truthy(body_page_1.next) + + response, status = http_client.get(BASE_URL, {size=3,offset=body_page_1.next}) + assert.equal(200, status) + local body_page_2 = json.decode(response) + assert.truthy(body_page_2.data) + assert.equal(3, table.getn(body_page_2.data)) + assert.truthy(body_page_2.next) + assert.not_same(body_page_1, body_page_2) + + response, status = http_client.get(BASE_URL, {size=4,offset=body_page_2.next}) + assert.equal(200, status) + local body_page_3 = json.decode(response) + assert.truthy(body_page_3.data) + assert.equal(4, table.getn(body_page_3.data)) + -- TODO: fixme + --assert.falsy(body_page_3.next) + assert.not_same(body_page_2, body_page_3) + end) + + end) + end) + + describe("/apis/:api", function() + local BASE_URL = spec_helper.API_URL.."/apis/" + local api + + setup(function() + spec_helper.drop_db() + local fixtures = spec_helper.insert_fixtures { + api = {{ public_dns="mockbin.com", target_url="http://mockbin.com" }} + } + api = fixtures.api[1] + end) + + describe("GET", function() + + it("should retrieve by id", function() + local response, status = http_client.get(BASE_URL..api.id) + assert.equal(200, status) + local body = json.decode(response) + assert.same(api, body) + end) + + it("should retrieve by name", function() + local response, status = http_client.get(BASE_URL..api.name) + assert.equal(200, status) + local body = json.decode(response) + assert.same(api, body) + end) + + end) + + describe("PATCH", function() + + it("[SUCCESS] should update an API", function() + local response, status = http_client.patch(BASE_URL..api.id, {name="patch-updated"}) + assert.equal(200, status) + local body = json.decode(response) + assert.same("patch-updated", body.name) + + api = body + + response, status = http_client.patch(BASE_URL..api.name, {name="patch-updated-json"}, {["content-type"]="application/json"}) + assert.equal(200, status) + body = json.decode(response) + assert.same("patch-updated-json", body.name) + + api = body + end) + + it("[FAILURE] should return proper errors", function() + local _, status = http_client.patch(BASE_URL.."hello", {name="patch-updated"}) + assert.equal(404, status) + + response, status = http_client.patch(BASE_URL..api.id, {target_url=""}) + assert.equal(400, status) + assert.equal('{"target_url":"target_url is not a string"}\n', response) + end) + + end) + + describe("DELETE", function() + + it("[FAILURE] should return proper errors", function() + local _, status = http_client.delete(BASE_URL.."hello") + assert.equal(404, status) + end) + + it("[SUCCESS] should delete an API", function() + local response, status = http_client.delete(BASE_URL..api.id) + assert.equal(204, status) + assert.falsy(response) + end) + + end) + + describe("/apis/:api/plugins/", function() + local dao_plugins = spec_helper.get_env().dao_factory.plugins_configurations + + setup(function() + spec_helper.drop_db() + local fixtures = spec_helper.insert_fixtures { + api = {{ public_dns="mockbin.com", target_url="http://mockbin.com" }} + } + api = fixtures.api[1] + BASE_URL = BASE_URL..api.id.."/plugins/" + end) + + describe("POST", function() + + it("[FAILURE] should return proper errors", function() + send_content_types(BASE_URL, "POST", {}, + 400, '{"name":"name is required","value":"value is required"}') + end) + + it("[SUCCESS] should create a plugin configuration", function() + local response, status = http_client.post(BASE_URL, { + name = "keyauth", + ["value.key_names"] = {"apikey"} + }) + assert.equal(201, status) + local body = json.decode(response) + + local _, err = dao_plugins:delete(body.id) + assert.falsy(err) + + response, status = http_client.post(BASE_URL, { + name = "keyauth", + value = {key_names={"apikey"}} + }, {["content-type"]="application/json"}) + assert.equal(201, status) + body = json.decode(response) + + _, err = dao_plugins:delete(body.id) + assert.falsy(err) + end) + + end) + + describe("PUT", function() + + it("[FAILURE] should return proper errors", function() + send_content_types(BASE_URL, "PUT", {}, + 400, '{"name":"name is required","value":"value is required"}') + end) + + it("[SUCCESS] should create and update", function() + local response, status = http_client.put(BASE_URL, { + name = "keyauth", + ["value.key_names"] = {"apikey"} + }) + assert.equal(201, status) + local body = json.decode(response) + + local _, err = dao_plugins:delete(body.id) + assert.falsy(err) + + response, status = http_client.put(BASE_URL, { + name = "keyauth", + value = {key_names={"apikey"}} + }, {["content-type"]="application/json"}) + assert.equal(201, status) + body = json.decode(response) + + response, status = http_client.put(BASE_URL, { + id=body.id, + name = "keyauth", + value = {key_names={"updated_apikey"}} + }, {["content-type"]="application/json"}) + assert.equal(200, status) + body = json.decode(response) + assert.equal("updated_apikey", body.value.key_names[1]) + end) + + end) + + describe("GET", function() + + it("should retrieve all", function() + local response, status = http_client.get(BASE_URL) + assert.equal(200, status) + local body = json.decode(response) + assert.truthy(body.data) + assert.equal(1, table.getn(body.data)) + end) + + end) + + describe("/apis/:api/plugins/:plugin", function() + local BASE_URL = spec_helper.API_URL.."/apis/" + local api, plugin + + setup(function() + spec_helper.drop_db() + local fixtures = spec_helper.insert_fixtures { + api = {{ public_dns="mockbin.com", target_url="http://mockbin.com" }}, + plugin_configuration = {{ name = "keyauth", value = { key_names = { "apikey" }}, __api = 1 }} + } + api = fixtures.api[1] + plugin = fixtures.plugin_configuration[1] + BASE_URL = BASE_URL..api.id.."/plugins/" + end) + + describe("GET", function() + + it("should retrieve by id", function() + local response, status = http_client.get(BASE_URL..plugin.id) + assert.equal(200, status) + local body = json.decode(response) + assert.same(plugin, body) + end) + + it("should retrieve by name", function() + local response, status = http_client.get(BASE_URL..plugin.name) + assert.equal(200, status) + local body = json.decode(response) + assert.same(plugin, body) + end) + + end) + + describe("PATCH", function() + + it("[SUCCESS] should update a plugin", function() + local response, status = http_client.patch(BASE_URL..plugin.id, {["value.key_names"]={"key_updated"}}) + assert.equal(200, status) + local body = json.decode(response) + assert.same("key_updated", body.value.key_names[1]) + + response, status = http_client.patch(BASE_URL..plugin.name, {["value.key_names"]={"key_updated-json"}}, {["content-type"]="application/json"}) + assert.equal(200, status) + body = json.decode(response) + assert.same("key_updated-json", body.value.key_names[1]) + end) + + it("[FAILURE] should return proper errors", function() + local _, status = http_client.patch(BASE_URL.."hello", {}) + assert.equal(404, status) + + response, status = http_client.patch(BASE_URL..plugin.id, {["value.key_names"]="key_updated-json"}) + assert.equal(400, status) + assert.equal('{"value.key_names":"key_names is not a table"}\n', response) + end) + + end) + + describe("DELETE", function() + + it("[FAILURE] should return proper errors", function() + local _, status = http_client.delete(BASE_URL.."hello") + assert.equal(404, status) + end) + + it("[SUCCESS] should delete an API", function() + local response, status = http_client.delete(BASE_URL..plugin.id) + assert.equal(204, status) + assert.falsy(response) + end) + + end) + end) + end) + end) +end) diff --git a/spec/integration/admin_api/consumers_routes_spec.lua b/spec/integration/admin_api/consumers_routes_spec.lua new file mode 100644 index 000000000000..6302d3ac8e95 --- /dev/null +++ b/spec/integration/admin_api/consumers_routes_spec.lua @@ -0,0 +1,182 @@ +local json = require "cjson" +local http_client = require "kong.tools.http_client" +local spec_helper = require "spec.spec_helpers" +local send_content_types = require "spec.integration.admin_api.helpers" + +describe("Admin API", function() + + setup(function() + spec_helper.prepare_db() + spec_helper.start_kong() + end) + + teardown(function() + spec_helper.stop_kong() + end) + + describe("/consumers/", function() + local BASE_URL = spec_helper.API_URL.."/consumers/" + + describe("POST", function() + + it("[SUCCESS] should create a Consumer", function() + send_content_types(BASE_URL, "POST", { + username="consumer POST tests" + }, 201, nil, {drop_db=true}) + end) + + it("[FAILURE] should return proper errors", function() + send_content_types(BASE_URL, "POST", {}, + 400, + '{"custom_id":"At least a \'custom_id\' or a \'username\' must be specified","username":"At least a \'custom_id\' or a \'username\' must be specified"}') + + send_content_types(BASE_URL, "POST", { + username="consumer POST tests" + }, 409, '{"username":"username already exists with value \'consumer POST tests\'"}') + end) + + end) + + describe("PUT", function() + + it("[SUCCESS] should create and update", function() + local consumer = send_content_types(BASE_URL, "PUT", { + username="consumer PUT tests" + }, 201, nil, {drop_db=true}) + + consumer = send_content_types(BASE_URL, "PUT", { + id=consumer.id, + username="consumer PUT tests updated", + }, 200) + assert.equal("consumer PUT tests updated", consumer.username) + end) + + it("[FAILURE] should return proper errors", function() + send_content_types(BASE_URL, "PUT", {}, + 400, + '{"custom_id":"At least a \'custom_id\' or a \'username\' must be specified","username":"At least a \'custom_id\' or a \'username\' must be specified"}') + + send_content_types(BASE_URL, "PUT", { + username="consumer PUT tests updated", + }, 409, '{"username":"username already exists with value \'consumer PUT tests updated\'"}') + end) + + end) + + describe("GET", function() + + setup(function() + spec_helper.drop_db() + spec_helper.seed_db(10) + end) + + it("should retrieve all", function() + local response, status = http_client.get(BASE_URL) + assert.equal(200, status) + local body = json.decode(response) + assert.truthy(body.data) + assert.equal(10, table.getn(body.data)) + end) + + it("should retrieve a paginated set", function() + local response, status = http_client.get(BASE_URL, {size=3}) + assert.equal(200, status) + local body_page_1 = json.decode(response) + assert.truthy(body_page_1.data) + assert.equal(3, table.getn(body_page_1.data)) + assert.truthy(body_page_1.next) + + response, status = http_client.get(BASE_URL, {size=3,offset=body_page_1.next}) + assert.equal(200, status) + local body_page_2 = json.decode(response) + assert.truthy(body_page_2.data) + assert.equal(3, table.getn(body_page_2.data)) + assert.truthy(body_page_2.next) + assert.not_same(body_page_1, body_page_2) + + response, status = http_client.get(BASE_URL, {size=4,offset=body_page_2.next}) + assert.equal(200, status) + local body_page_3 = json.decode(response) + assert.truthy(body_page_3.data) + assert.equal(4, table.getn(body_page_3.data)) + -- TODO: fixme + --assert.falsy(body_page_3.next) + assert.not_same(body_page_2, body_page_3) + end) + + end) + + describe("/consumers/:consumer", function() + local consumer + + setup(function() + spec_helper.drop_db() + local fixtures = spec_helper.insert_fixtures { + consumer = {{ username="get_consumer_tests" }} + } + consumer = fixtures.consumer[1] + end) + + describe("GET", function() + + it("should retrieve by id", function() + local response, status = http_client.get(BASE_URL..consumer.id) + assert.equal(200, status) + local body = json.decode(response) + assert.same(consumer, body) + end) + + it("should retrieve by username", function() + local response, status = http_client.get(BASE_URL..consumer.username) + assert.equal(200, status) + local body = json.decode(response) + assert.same(consumer, body) + end) + + end) + + describe("PATCH", function() + + it("[SUCCESS] should update a Consumer", function() + local response, status = http_client.patch(BASE_URL..consumer.id, {username="patch-updated"}) + assert.equal(200, status) + local body = json.decode(response) + assert.same("patch-updated", body.username) + + consumer = body + + response, status = http_client.patch(BASE_URL..consumer.username, {username="patch-updated-json"}, {["content-type"]="application/json"}) + assert.equal(200, status) + body = json.decode(response) + assert.same("patch-updated-json", body.username) + + consumer = body + end) + + it("[FAILURE] should return proper errors", function() + local _, status = http_client.patch(BASE_URL.."hello", {username="patch-updated"}) + assert.equal(404, status) + + response, status = http_client.patch(BASE_URL..consumer.id, {username=""}) + assert.equal(400, status) + assert.equal('{"username":"username is not a string"}\n', response) + end) + end) + + describe("DELETE", function() + + it("[FAILURE] should return proper errors", function() + local _, status = http_client.delete(BASE_URL.."hello") + assert.equal(404, status) + end) + + it("[SUCCESS] should delete a Consumer", function() + local response, status = http_client.delete(BASE_URL..consumer.id) + assert.equal(204, status) + assert.falsy(response) + end) + + end) + end) + end) +end) diff --git a/spec/integration/admin_api/helpers.lua b/spec/integration/admin_api/helpers.lua new file mode 100644 index 000000000000..9e54fd0c1389 --- /dev/null +++ b/spec/integration/admin_api/helpers.lua @@ -0,0 +1,33 @@ +local json = require "cjson" +local http_client = require "kong.tools.http_client" +local spec_helper = require "spec.spec_helpers" +local assert = require "luassert" + +local function send_content_types(url, method, body, res_status, res_body, options) + if not options then options = {} end + + local form_response, form_status = http_client[method:lower()](url, body) + assert.equal(res_status, form_status) + + if options.drop_db then + spec_helper.drop_db() + end + + local json_response, json_status = http_client[method:lower()](url, body, {["content-type"]="application/json"}) + assert.equal(res_status, json_status) + + if res_body then + assert.same(res_body.."\n", form_response) + assert.same(res_body.."\n", json_response) + end + + local res_obj + local status, res = pcall(function() res_obj = json.decode(json_response) end) + if not status then + error(res, 2) + end + + return res_obj +end + +return send_content_types diff --git a/spec/integration/admin_api/kong_routes_spec.lua b/spec/integration/admin_api/kong_routes_spec.lua new file mode 100644 index 000000000000..202e8e701c04 --- /dev/null +++ b/spec/integration/admin_api/kong_routes_spec.lua @@ -0,0 +1,38 @@ +local json = require "cjson" +local http_client = require "kong.tools.http_client" +local spec_helper = require "spec.spec_helpers" + +describe("Admin API", function() + + setup(function() + spec_helper.prepare_db() + spec_helper.start_kong() + end) + + teardown(function() + spec_helper.stop_kong() + end) + + describe("Kong routes", function() + describe("/", function() + local constants = require "kong.constants" + + it("should return Kong's version and a welcome message", function() + local response, status = http_client.get(spec_helper.API_URL) + assert.are.equal(200, status) + local body = json.decode(response) + assert.truthy(body.version) + assert.truthy(body.tagline) + assert.are.same(constants.VERSION, body.version) + end) + + it("should have a Server header", function() + local _, status, headers = http_client.get(spec_helper.API_URL) + assert.are.same(200, status) + assert.are.same(string.format("%s/%s", constants.NAME, constants.VERSION), headers.server) + assert.falsy(headers.via) -- Via is only set for proxied requests + end) + + end) + end) +end) diff --git a/spec/spec_helpers.lua b/spec/spec_helpers.lua index d6354ffac252..899ab31c7a74 100644 --- a/spec/spec_helpers.lua +++ b/spec/spec_helpers.lua @@ -174,9 +174,9 @@ function _M.drop_db(conf_file) end end -function _M.seed_db(random_amount, conf_file) +function _M.seed_db(amount, conf_file) local env = _M.get_env(conf_file) - return env.faker:seed(random_amount) + return env.faker:seed(amount) end function _M.insert_fixtures(fixtures, conf_file) diff --git a/spec/unit/dao/cassandra_spec.lua b/spec/unit/dao/cassandra_spec.lua index d709624ce10a..82c9efac6936 100644 --- a/spec/unit/dao/cassandra_spec.lua +++ b/spec/unit/dao/cassandra_spec.lua @@ -176,7 +176,7 @@ describe("Cassandra DAO", function() assert.truthy(err) assert.is_daoError(err) assert.True(err.unique) - assert.are.same("name already exists with value "..api_t.name, err.message.name) + assert.are.same("name already exists with value '"..api_t.name.."'", err.message.name) assert.falsy(api) -- Duplicated name @@ -191,7 +191,7 @@ describe("Cassandra DAO", function() assert.truthy(err) assert.is_daoError(err) assert.True(err.unique) - assert.are.same("name already exists with value "..api_t.name, err.message.name) + assert.are.same("name already exists with value '"..api_t.name.."'", err.message.name) end) end) @@ -416,7 +416,7 @@ describe("Cassandra DAO", function() assert.truthy(err) assert.is_daoError(err) assert.True(err.unique) - assert.are.same("public_dns already exists with value "..api_t.public_dns, err.message.public_dns) + assert.are.same("public_dns already exists with value '"..api_t.public_dns.."'", err.message.public_dns) end) end)