From 1383d59f60105ba5a713827d59052e40f7cb1705 Mon Sep 17 00:00:00 2001 From: Darryl Morton Date: Fri, 29 Apr 2022 18:03:34 +0100 Subject: [PATCH 1/4] cleanup, renaming functions for consistency, tests for invalid uuids as request path parameters --- app/api-v1/api-doc.js | 34 ++-- app/api-v1/routes/profiler/project.js | 25 ++- app/api-v1/routes/profiler/project/{id}.js | 38 +++-- app/api-v1/services/apiService.js | 40 ++--- .../getProjectsResponseValidator.js | 21 --- .../deleteProjectResponseValidator.js | 14 +- .../getProjectByIdResponseValidator.js | 10 +- .../project/getProjectsResponseValidator.js | 30 ++++ .../postProjectResponseValidator.js | 8 +- .../putProjectResponseValidator.js | 10 +- app/db.js | 20 +-- test/helper/projectRouteHelper.js | 6 +- test/helper/seeds/project.js | 8 +- test/integration/projectRoutes.test.js | 161 +++++++++--------- 14 files changed, 225 insertions(+), 200 deletions(-) delete mode 100644 app/api-v1/validators/getProjectsResponseValidator.js rename app/api-v1/validators/{ => project}/deleteProjectResponseValidator.js (57%) rename app/api-v1/validators/{ => project}/getProjectByIdResponseValidator.js (67%) create mode 100644 app/api-v1/validators/project/getProjectsResponseValidator.js rename app/api-v1/validators/{ => project}/postProjectResponseValidator.js (72%) rename app/api-v1/validators/{ => project}/putProjectResponseValidator.js (73%) diff --git a/app/api-v1/api-doc.js b/app/api-v1/api-doc.js index b4e0e5d..915044a 100644 --- a/app/api-v1/api-doc.js +++ b/app/api-v1/api-doc.js @@ -82,46 +82,46 @@ const apiDoc = { required: ['firstName', 'lastName', 'company', 'role'], }, GetProject: { - description: 'GET project', + description: 'Schema for retrieving a project', type: 'object', properties: { id: { - description: 'Project id', + description: 'Id of the project', type: 'string', format: 'uuid', }, clientId: { - description: 'Project client id', + description: 'Client id of the project', type: 'string', format: 'uuid', }, name: { - description: 'Project Name', + description: 'Name of the project', type: 'string', }, description: { - description: 'Project Description', + description: 'Description of the project', type: 'string', }, startDate: { - description: 'Project start date', + description: 'Start date of the project', type: 'object', format: 'startDate', nullable: true, }, endDate: { - description: 'Project end date', + description: 'End date of the project', type: 'object', format: 'endDate', nullable: true, }, budget: { - description: 'Project budget', + description: 'Budget of the project', type: 'number', nullable: true, }, documentUrl: { - description: 'Project document url', + description: 'Document url of the project', type: 'string', nullable: true, }, @@ -129,41 +129,41 @@ const apiDoc = { required: ['id', 'clientId', 'name', 'description'], }, PostAndPutProject: { - description: 'POST/PUT project', + description: 'Schema for creating/updating a project', type: 'object', properties: { clientId: { - description: 'Project client id', + description: 'Client id of the project', type: 'string', format: 'uuid', }, name: { - description: 'Project Name', + description: 'Name of the project', type: 'string', }, description: { - description: 'Project Description', + description: 'Description of the project', type: 'string', }, startDate: { - description: 'Project start date', + description: 'Start date of the project', type: 'string', format: 'date-time', nullable: true, }, endDate: { - description: 'Project end date', + description: 'End date of the project', type: 'string', format: 'date-time', nullable: true, }, budget: { - description: 'Project budget', + description: 'Budget of the project', type: 'number', nullable: true, }, documentUrl: { - description: 'Project document url', + description: 'Document url of the project', type: 'string', nullable: true, }, diff --git a/app/api-v1/routes/profiler/project.js b/app/api-v1/routes/profiler/project.js index 7b0ef12..a4db940 100644 --- a/app/api-v1/routes/profiler/project.js +++ b/app/api-v1/routes/profiler/project.js @@ -1,13 +1,26 @@ -const { GET_PROJECTS_RESPONSES } = require('../../validators/getProjectsResponseValidator') -const { POST_PROJECT_RESPONSES, validatePostProjectResponse } = require('../../validators/postProjectResponseValidator') +const { + GET_PROJECTS_RESPONSES, + validateGetProjectsResponse, +} = require('../../validators/project/getProjectsResponseValidator') +const { + POST_PROJECT_RESPONSES, + validatePostProjectResponse, +} = require('../../validators/project/postProjectResponseValidator') module.exports = function (apiService) { const doc = { GET: async function (req, res) { const { statusCode, result } = await apiService.getProjects() - res.status(statusCode).json(result) - return + const validationErrors = validateGetProjectsResponse(statusCode, result) + + if (validationErrors) { + res.status(statusCode).json(validationErrors) + return + } else { + res.status(statusCode).json(result) + return + } }, POST: async function (req, res) { const { statusCode, result } = await apiService.postProject(req.body) @@ -25,13 +38,13 @@ module.exports = function (apiService) { } doc.GET.apiDoc = { - summary: 'GET projects', + summary: 'Retrieve projects', responses: GET_PROJECTS_RESPONSES, tags: ['projects'], } doc.POST.apiDoc = { - summary: 'POST project', + summary: 'Create project', requestBody: { content: { 'application/json': { diff --git a/app/api-v1/routes/profiler/project/{id}.js b/app/api-v1/routes/profiler/project/{id}.js index b476860..5976570 100644 --- a/app/api-v1/routes/profiler/project/{id}.js +++ b/app/api-v1/routes/profiler/project/{id}.js @@ -1,12 +1,15 @@ const { validateGetProjectByIdResponse, GET_PROJECT_BY_ID_RESPONSES, -} = require('../../../validators/getProjectByIdResponseValidator') -const { PUT_PROJECT_RESPONSES, validatePutProjectResponse } = require('../../../validators/putProjectResponseValidator') +} = require('../../../validators/project/getProjectByIdResponseValidator') +const { + PUT_PROJECT_RESPONSES, + validatePutProjectResponse, +} = require('../../../validators/project/putProjectResponseValidator') const { DELETE_PROJECT_RESPONSES, validateDeleteProjectResponse, -} = require('../../../validators/deleteProjectResponseValidator') +} = require('../../../validators/project/deleteProjectResponseValidator') module.exports = function (apiService) { const doc = { @@ -40,7 +43,7 @@ module.exports = function (apiService) { }, DELETE: async function (req, res) { const { id } = req.params - const { statusCode, result } = await apiService.deleteProjectById(id) + const { statusCode, result } = await apiService.deleteProject(id) const validationErrors = validateDeleteProjectResponse(statusCode, result) @@ -48,21 +51,24 @@ module.exports = function (apiService) { res.status(statusCode).json(validationErrors) return } else { - res.status(statusCode).json(result) + res.status(statusCode).send() return } }, } doc.GET.apiDoc = { - summary: 'Get project by id', + summary: 'Retrieve project by id', parameters: [ { - description: 'Project id', + description: 'Id of the project', in: 'path', required: true, name: 'id', - allowEmptyValue: false, + schema: { + type: 'string', + format: 'uuid', + }, }, ], responses: GET_PROJECT_BY_ID_RESPONSES, @@ -73,11 +79,14 @@ module.exports = function (apiService) { summary: 'Update project', parameters: [ { - description: 'ID of the project', + description: 'Id of the project', in: 'path', required: true, name: 'id', - allowEmptyValue: false, + schema: { + type: 'string', + format: 'uuid', + }, }, ], requestBody: { @@ -94,14 +103,17 @@ module.exports = function (apiService) { } doc.DELETE.apiDoc = { - summary: 'Delete project', + summary: 'Remove project', parameters: [ { - description: 'Project id', + description: 'Id of the project', in: 'path', required: true, name: 'id', - allowEmptyValue: false, + schema: { + type: 'string', + format: 'uuid', + }, }, ], responses: DELETE_PROJECT_RESPONSES, diff --git a/app/api-v1/services/apiService.js b/app/api-v1/services/apiService.js index 43c6664..738f3de 100644 --- a/app/api-v1/services/apiService.js +++ b/app/api-v1/services/apiService.js @@ -1,9 +1,9 @@ const { - getProjectsDb, - getProjectByNameDb, - postProjectDb, - getProjectByIdDb, - deleteProjectByIdDb, + findProjectsDb, + findProjectByNameDb, + addProjectDb, + findProjectByIdDb, + removeProjectDb, updateProjectDb, addClientDb, findClientsDb, @@ -59,39 +59,39 @@ async function deleteClient(id) { } async function getProjects() { - const result = await getProjectsDb() + const result = await findProjectsDb() return { statusCode: 200, result } } async function getProjectById(id) { - const projectsByIdResult = await getProjectByIdDb(id) + const findResult = await findProjectByIdDb(id) - if (projectsByIdResult.length === 1) { - return { statusCode: 200, result: projectsByIdResult[0] } + if (findResult.length === 1) { + return { statusCode: 200, result: findResult[0] } } else { return { statusCode: 404, result: {} } } } async function postProject(reqBody) { - const projectByNameResult = await getProjectByNameDb(reqBody.name) + const findResult = await findProjectByNameDb(reqBody.name) - if (projectByNameResult.length === 0) { - const createdProject = await postProjectDb(reqBody) + if (findResult.length === 0) { + const result = await addProjectDb(reqBody) - return { statusCode: 201, result: createdProject[0] } + return { statusCode: 201, result: result[0] } } else { return { statusCode: 409, result: {} } } } async function putProject(id, reqBody) { - const projectByIdResult = await getProjectByIdDb(id) + const findResult = await findProjectByIdDb(id) - if (projectByIdResult.length === 0) { + if (findResult.length === 0) { return { statusCode: 404, result: {} } - } else if (projectByIdResult[0].name !== reqBody.name) { + } else if (findResult[0].name !== reqBody.name) { const result = await updateProjectDb(id, reqBody) return { statusCode: 200, result: result[0] } @@ -100,11 +100,11 @@ async function putProject(id, reqBody) { } } -async function deleteProjectById(id) { - const result = await getProjectByIdDb(id) +async function deleteProject(id) { + const result = await findProjectByIdDb(id) if (result.length === 1) { - await deleteProjectByIdDb(id) + await removeProjectDb(id) return { statusCode: 204, result: {} } } else { @@ -121,6 +121,6 @@ module.exports = { getProjects, postProject, getProjectById, - deleteProjectById, + deleteProject, putProject, } diff --git a/app/api-v1/validators/getProjectsResponseValidator.js b/app/api-v1/validators/getProjectsResponseValidator.js deleted file mode 100644 index 46865c3..0000000 --- a/app/api-v1/validators/getProjectsResponseValidator.js +++ /dev/null @@ -1,21 +0,0 @@ -const apiDocResponses = require('../api-doc-responses') -const apiDoc = require('../api-doc') - -const GET_PROJECTS_RESPONSES = { - 200: { - description: 'Get projects', - content: { - 'application/json': { - schema: { - type: 'array', - items: apiDoc.components.schemas.GetProject, - }, - }, - }, - }, - default: apiDocResponses.default, -} - -module.exports = { - GET_PROJECTS_RESPONSES, -} diff --git a/app/api-v1/validators/deleteProjectResponseValidator.js b/app/api-v1/validators/project/deleteProjectResponseValidator.js similarity index 57% rename from app/api-v1/validators/deleteProjectResponseValidator.js rename to app/api-v1/validators/project/deleteProjectResponseValidator.js index f60dfe1..12751a7 100644 --- a/app/api-v1/validators/deleteProjectResponseValidator.js +++ b/app/api-v1/validators/project/deleteProjectResponseValidator.js @@ -1,16 +1,10 @@ -const OpenAPIResponseValidator = require('openapi-response-validator').default +const { default: OpenAPIResponseValidator } = require('openapi-response-validator') -const apiDocResponses = require('../api-doc-responses') -const apiDoc = require('../api-doc') +const apiDocResponses = require('../../api-doc-responses') const DELETE_PROJECT_RESPONSES = { - 201: { - description: '', - content: { - 'application/json': { - schema: apiDoc.components.schemas.GetProject, - }, - }, + 204: { + description: 'Deleted project', }, 404: apiDocResponses['404'], default: apiDocResponses.default, diff --git a/app/api-v1/validators/getProjectByIdResponseValidator.js b/app/api-v1/validators/project/getProjectByIdResponseValidator.js similarity index 67% rename from app/api-v1/validators/getProjectByIdResponseValidator.js rename to app/api-v1/validators/project/getProjectByIdResponseValidator.js index d0dc6d0..4789728 100644 --- a/app/api-v1/validators/getProjectByIdResponseValidator.js +++ b/app/api-v1/validators/project/getProjectByIdResponseValidator.js @@ -1,18 +1,18 @@ -const OpenAPIResponseValidator = require('openapi-response-validator').default +const { default: OpenAPIResponseValidator } = require('openapi-response-validator') -const apiDocResponses = require('../api-doc-responses') -const apiDoc = require('../api-doc') +const apiDocResponses = require('../../api-doc-responses') +const apiDoc = require('../../api-doc') const GET_PROJECT_BY_ID_RESPONSES = { 200: { - description: 'Get projects by id', + description: 'Retrieved project by id', content: { 'application/json': { schema: apiDoc.components.schemas.GetProject, }, }, }, - 404: apiDoc.components.responses['404'], + 404: apiDocResponses['404'], default: apiDocResponses.default, } diff --git a/app/api-v1/validators/project/getProjectsResponseValidator.js b/app/api-v1/validators/project/getProjectsResponseValidator.js new file mode 100644 index 0000000..7d0ac9e --- /dev/null +++ b/app/api-v1/validators/project/getProjectsResponseValidator.js @@ -0,0 +1,30 @@ +const { default: OpenAPIResponseValidator } = require('openapi-response-validator') + +const apiDocResponses = require('../../api-doc-responses') +const apiDoc = require('../../api-doc') + +const GET_PROJECTS_RESPONSES = { + 200: { + description: 'Retrieved projects', + content: { + 'application/json': { + schema: { + type: 'array', + items: apiDoc.components.schemas.GetProject, + }, + }, + }, + }, + default: apiDocResponses.default, +} + +const validateGetProjectsResponse = (statusCode, result) => { + const responseValidator = new OpenAPIResponseValidator({ responses: GET_PROJECTS_RESPONSES }) + + return responseValidator.validateResponse(statusCode, result) +} + +module.exports = { + GET_PROJECTS_RESPONSES, + validateGetProjectsResponse, +} diff --git a/app/api-v1/validators/postProjectResponseValidator.js b/app/api-v1/validators/project/postProjectResponseValidator.js similarity index 72% rename from app/api-v1/validators/postProjectResponseValidator.js rename to app/api-v1/validators/project/postProjectResponseValidator.js index 231daa5..c19a70a 100644 --- a/app/api-v1/validators/postProjectResponseValidator.js +++ b/app/api-v1/validators/project/postProjectResponseValidator.js @@ -1,11 +1,11 @@ -const OpenAPIResponseValidator = require('openapi-response-validator').default +const { default: OpenAPIResponseValidator } = require('openapi-response-validator') -const apiDocResponses = require('../api-doc-responses') -const apiDoc = require('../api-doc') +const apiDocResponses = require('../../api-doc-responses') +const apiDoc = require('../../api-doc') const POST_PROJECT_RESPONSES = { 201: { - description: 'Post Project', + description: 'Created project', content: { 'application/json': { schema: apiDoc.components.schemas.GetProject, diff --git a/app/api-v1/validators/putProjectResponseValidator.js b/app/api-v1/validators/project/putProjectResponseValidator.js similarity index 73% rename from app/api-v1/validators/putProjectResponseValidator.js rename to app/api-v1/validators/project/putProjectResponseValidator.js index 2cd12f7..445908c 100644 --- a/app/api-v1/validators/putProjectResponseValidator.js +++ b/app/api-v1/validators/project/putProjectResponseValidator.js @@ -1,19 +1,19 @@ const OpenAPIResponseValidator = require('openapi-response-validator').default -const apiDocResponses = require('../api-doc-responses') -const apiDoc = require('../api-doc') +const apiDocResponses = require('../../api-doc-responses') +const apiDoc = require('../../api-doc') const PUT_PROJECT_RESPONSES = { 200: { - description: 'Update Project', + description: 'Updated project', content: { 'application/json': { schema: apiDoc.components.schemas.GetProject, }, }, }, - 400: apiDoc.components.responses['400'], - 404: apiDoc.components.responses['404'], + 400: apiDocResponses['400'], + 404: apiDocResponses['404'], default: apiDocResponses.default, } diff --git a/app/db.js b/app/db.js index cc58156..ff7858a 100644 --- a/app/db.js +++ b/app/db.js @@ -54,7 +54,7 @@ async function removeClientDb(id) { return client('clients').del().where({ id }) } -async function postProjectDb(reqBody) { +async function addProjectDb(reqBody) { return client('projects') .insert({ client_id: reqBody.clientId, @@ -77,7 +77,7 @@ async function postProjectDb(reqBody) { ]) } -async function getProjectsDb() { +async function findProjectsDb() { return client('projects AS p').select([ 'p.id', 'p.client_id AS clientId', @@ -90,11 +90,11 @@ async function getProjectsDb() { ]) } -async function getProjectByNameDb(name) { +async function findProjectByNameDb(name) { return client('projects').select('name').where({ name }) } -async function getProjectByIdDb(id) { +async function findProjectByIdDb(id) { return client('projects') .select([ 'id', @@ -109,7 +109,7 @@ async function getProjectByIdDb(id) { .where({ id }) } -async function deleteProjectByIdDb(id) { +async function removeProjectDb(id) { return client('projects').where('id', id).del() } @@ -138,10 +138,10 @@ module.exports = { addClientDb, updateClientDb, removeClientDb, - getProjectsDb, - getProjectByNameDb, - postProjectDb, - getProjectByIdDb, - deleteProjectByIdDb, + findProjectsDb, + findProjectByNameDb, + addProjectDb, + findProjectByIdDb, + removeProjectDb, updateProjectDb, } diff --git a/test/helper/projectRouteHelper.js b/test/helper/projectRouteHelper.js index a03d7bc..ace2063 100644 --- a/test/helper/projectRouteHelper.js +++ b/test/helper/projectRouteHelper.js @@ -61,7 +61,7 @@ async function putProjectRoute(id, project, { app }) { }) } -async function deleteProjectByIdRoute(id, { app }) { +async function deleteProjectRoute(id, { app }) { return request(app) .delete(`/${API_MAJOR_VERSION}/profiler/project/${id}`) .set('Accept', 'application/json') @@ -70,7 +70,7 @@ async function deleteProjectByIdRoute(id, { app }) { return response }) .catch((err) => { - console.error(`getProjectsErr ${err}`) + console.error(`deleteProjectErr ${err}`) return err }) } @@ -80,5 +80,5 @@ module.exports = { postProjectRoute, getProjectByIdRoute, putProjectRoute, - deleteProjectByIdRoute, + deleteProjectRoute, } diff --git a/test/helper/seeds/project.js b/test/helper/seeds/project.js index dab48f4..5e8a168 100644 --- a/test/helper/seeds/project.js +++ b/test/helper/seeds/project.js @@ -18,10 +18,10 @@ const seed = async () => { await client('clients').insert([ { id: clientId, - first_name: 'Steve', - last_name: 'Davies', - company: 'MyCompany', - role: 'Manager', + first_name: 'First name 1', + last_name: 'Last name 1', + company: 'Company 1', + role: 'Role 1', }, ]) } diff --git a/test/integration/projectRoutes.test.js b/test/integration/projectRoutes.test.js index 4ccf572..5af29b6 100644 --- a/test/integration/projectRoutes.test.js +++ b/test/integration/projectRoutes.test.js @@ -1,5 +1,6 @@ const { describe, test, before } = require('mocha') const { expect } = require('chai') +const moment = require('moment') const { createDefaultProject, @@ -14,10 +15,9 @@ const { getProjectsRoute, postProjectRoute, putProjectRoute, - deleteProjectByIdRoute, + deleteProjectRoute, } = require('../helper/projectRouteHelper') const { seed, cleanup } = require('../helper/seeds/project') -const moment = require('moment') describe('Project routes', function () { let app @@ -38,13 +38,13 @@ describe('Project routes', function () { await cleanup('projects') }) - test('POST Project with all fields', async function () { + test('POST Project all request body parameters', async function () { const expectedResult = defaultProject - const response = await postProjectRoute(defaultProject, app) + const actualResponse = await postProjectRoute(defaultProject, app) - expect(response.status).to.equal(201) - assertPostProjectParams(response.body, expectedResult) + expect(actualResponse.status).to.equal(201) + assertPostProjectParams(actualResponse.body, expectedResult) }) test('POST Project with only required request body parameters', async function () { @@ -57,87 +57,70 @@ describe('Project routes', function () { documentUrl: null, } - const response = await postProjectRoute(project, app) + const actualResponse = await postProjectRoute(project, app) - expect(response.status).to.equal(201) - assertPostProjectRequiredParams(response.body, expectedResult) + expect(actualResponse.status).to.equal(201) + assertPostProjectRequiredParams(actualResponse.body, expectedResult) }) test('POST Project missing client id', async function () { - const project = createProject({ name: 'Project 1', description: 'Project 1 description' }) + const invalidProject = createProject({ name: 'Project 1', description: 'Project 1 description' }) - const response = await postProjectRoute(project, app) + const actualResponse = await postProjectRoute(invalidProject, app) - expect(response.status).to.equal(400) - expect(response.body).deep.equal({}) + expect(actualResponse.status).to.equal(400) + expect(actualResponse.body).deep.equal({}) }) test('POST invalid project', async function () { - const response = await postProjectRoute({}, app) + const actualResponse = await postProjectRoute({}, app) - expect(response.status).to.equal(400) - expect(response.body).deep.equal({}) + expect(actualResponse.status).to.equal(400) + expect(actualResponse.body).deep.equal({}) }) test('POST duplicate project', async function () { await postProjectRoute(defaultProject, app) - const response = await postProjectRoute(defaultProject, app) + const actualResponse = await postProjectRoute(defaultProject, app) - expect(response.status).to.equal(409) - expect(response.body).deep.equal({}) + expect(actualResponse.status).to.equal(409) + expect(actualResponse.body).deep.equal({}) }) test('GET projects', async function () { const expectedResult = [defaultProject] await postProjectRoute(defaultProject, app) - const response = await getProjectsRoute(app) + const actualResponse = await getProjectsRoute(app) - expect(response.status).to.equal(200) - assertGetProjects(response.body, expectedResult) + expect(actualResponse.status).to.equal(200) + assertGetProjects(actualResponse.body, expectedResult) }) test('GET project by id', async function () { const expectedResult = defaultProject - const projectResponse = await postProjectRoute(defaultProject, app) - const response = await getProjectByIdRoute(projectResponse.body.id, app) + const response = await postProjectRoute(defaultProject, app) + const actualResponse = await getProjectByIdRoute(response.body.id, app) - expect(response.status).to.equal(200) - assertPostProjectRequiredParams(response.body, expectedResult) + expect(actualResponse.status).to.equal(200) + assertPostProjectRequiredParams(actualResponse.body, expectedResult) }) test('GET project by id with invalid path id parameter', async function () { - const response = await getProjectByIdRoute(invalidId, app) + const actualResponse = await getProjectByIdRoute('123', app) - expect(response.status).to.equal(404) + expect(actualResponse.status).to.equal(400) }) - test('PUT project with only required fields', async function () { - const project = createProject({ clientId, name: 'Project 1', description: 'Project 1 description' }) - const projectUpdate = createProject({ clientId, name: 'Project 2', description: 'Project 2 description' }) - const expectedResult = projectUpdate - - const projectResponse = await postProjectRoute(project, app) - const response = await putProjectRoute(projectResponse.body.id, projectUpdate, app) + test('GET project by id with non-existing project', async function () { + const actualResponse = await getProjectByIdRoute(invalidId, app) - expect(response.status).to.equal(200) - assertPostProjectRequiredParams(response.body, expectedResult) + expect(actualResponse.status).to.equal(404) }) - test('PUT project with existing name', async function () { - const project = createProject({ clientId, name: 'Project 1', description: 'Project 1 description' }) - const projectUpdate = createProject({ clientId, name: 'Project 1', description: 'Project 2 description' }) - - const projectResponse = await postProjectRoute(project, app) - const response = await putProjectRoute(projectResponse.body.id, projectUpdate, app) - - expect(response.status).to.equal(409) - expect(response.body).to.deep.equal({}) - }) - - test('PUT project with invalid id path parameter', async function () { - const project = createProject({ + test('PUT project with all request body parameters', async function () { + const updatedProject = createProject({ clientId, name: 'Project 2', description: 'Project 2 description', @@ -146,55 +129,69 @@ describe('Project routes', function () { budget: 200000.0, documentUrl: 'http://digitalcatapult.org.uk/document/url', }) + const expectedResult = updatedProject - const response = await putProjectRoute(invalidId, project, app) + const response = await postProjectRoute(defaultProject, app) + const actualResponse = await putProjectRoute(response.body.id, updatedProject, app) - expect(response.status).to.equal(404) + expect(actualResponse.status).to.equal(200) + assertPostProjectParams(actualResponse.body, expectedResult) }) - test('PUT project with missing required client id path parameter', async function () { - const project = createProject({ - name: 'Project 2', - description: 'Project 2 description', - startDate: moment().startOf('day').toISOString(), - endDate: moment().endOf('day').toISOString(), - budget: 200000.0, - documentUrl: 'http://digitalcatapult.org.uk/document/url', - }) + test('PUT project with only required fields', async function () { + const project = createProject({ clientId, name: 'Project 1', description: 'Project 1 description' }) + const updatedProject = createProject({ clientId, name: 'Project 2', description: 'Project 2 description' }) + const expectedResult = updatedProject - const response = await putProjectRoute(invalidId, project, app) + const response = await postProjectRoute(project, app) + const actualResponse = await putProjectRoute(response.body.id, updatedProject, app) - expect(response.status).to.equal(400) - expect(response.body).deep.equal({}) + expect(actualResponse.status).to.equal(200) + assertPostProjectRequiredParams(actualResponse.body, expectedResult) }) - test('PUT project with all request body parameters', async function () { - const project = createProject({ - name: 'Project 2', - description: 'Project 2 description', - startDate: moment().startOf('day').toISOString(), - endDate: moment().endOf('day').toISOString(), - budget: 200000.0, - documentUrl: 'http://digitalcatapult.org.uk/document/url', - }) + test('PUT project with existing name', async function () { + const response = await postProjectRoute(defaultProject, app) + const actualResponse = await putProjectRoute(response.body.id, defaultProject, app) + + expect(actualResponse.status).to.equal(409) + expect(actualResponse.body).to.deep.equal({}) + }) + + test('PUT project with non-existing project', async function () { + const actualResponse = await putProjectRoute(invalidId, defaultProject, app) + + expect(actualResponse.status).to.equal(404) + }) - const response = await putProjectRoute(invalidId, project, app) + test('PUT project with missing required client id path parameter', async function () { + const invalidProject = createProject({ name: 'Project 2', description: 'Project 2 description' }) + + const actualResponse = await putProjectRoute(invalidId, invalidProject, app) - expect(response.status).to.equal(400) - expect(response.body).deep.equal({}) + expect(actualResponse.status).to.equal(400) + expect(actualResponse.body).deep.equal({}) }) test('DELETE project', async function () { - const projectResponse = await postProjectRoute(defaultProject, app) - const response = await deleteProjectByIdRoute(projectResponse.body.id, app) + const response = await postProjectRoute(defaultProject, app) + const actualResponse = await deleteProjectRoute(response.body.id, app) - expect(response.status).to.equal(204) - expect(response.body).deep.equal({}) + expect(actualResponse.status).to.equal(204) + expect(actualResponse.body).deep.equal({}) }) test('DELETE project with invalid id path parameter', async function () { - const response = await deleteProjectByIdRoute(invalidId, app) + const actualResponse = await deleteProjectRoute('123', app) + + expect(actualResponse.status).to.equal(400) + expect(actualResponse.body).deep.equal({}) + }) + + test('DELETE project with non-existing project', async function () { + const actualResponse = await deleteProjectRoute(invalidId, app) - expect(response.status).to.equal(404) + expect(actualResponse.status).to.equal(404) + expect(actualResponse.body).deep.equal({}) }) }) From 1ad950b6c83e529f34e0d7650d92d14269abd196 Mon Sep 17 00:00:00 2001 From: Darryl Morton Date: Fri, 29 Apr 2022 18:19:26 +0100 Subject: [PATCH 2/4] single custom js-date format usage --- app/api-v1/api-doc.js | 4 ++-- app/server.js | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/app/api-v1/api-doc.js b/app/api-v1/api-doc.js index ff098ba..efea814 100644 --- a/app/api-v1/api-doc.js +++ b/app/api-v1/api-doc.js @@ -106,13 +106,13 @@ const apiDoc = { startDate: { description: 'Start date of the project', type: 'object', - format: 'startDate', + format: 'js-date', nullable: true, }, endDate: { description: 'End date of the project', type: 'object', - format: 'endDate', + format: 'js-date', nullable: true, }, budget: { diff --git a/app/server.js b/app/server.js index 95a7f84..e1d13cc 100644 --- a/app/server.js +++ b/app/server.js @@ -38,10 +38,7 @@ async function createHttpServer() { apiService: v1ApiService, }, customFormats: { - startDate: function (input) { - return moment(input, moment.ISO_8601).isValid() - }, - endDate: function (input) { + 'js-date': function (input) { return moment(input, moment.ISO_8601).isValid() }, }, From 3da56f95193c331c526993cdc00966f0bb8751ad Mon Sep 17 00:00:00 2001 From: Darryl Morton Date: Tue, 3 May 2022 09:33:14 +0100 Subject: [PATCH 3/4] version bump --- helm/adcp-profiler-service/Chart.yaml | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/helm/adcp-profiler-service/Chart.yaml b/helm/adcp-profiler-service/Chart.yaml index e241741..25cbc1a 100644 --- a/helm/adcp-profiler-service/Chart.yaml +++ b/helm/adcp-profiler-service/Chart.yaml @@ -1,8 +1,8 @@ apiVersion: v2 name: adcp-profiler-service -appVersion: '0.0.3' +appVersion: '0.0.4' description: A Helm chart for adcp-profiler-service -version: '0.0.3' +version: '0.0.4' type: application maintainers: - name: digicatapult diff --git a/package-lock.json b/package-lock.json index 32a79bd..e5ac127 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@digicatapult/adcp-profiler-service", - "version": "0.0.3", + "version": "0.0.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@digicatapult/adcp-profiler-service", - "version": "0.0.3", + "version": "0.0.4", "license": "Apache-2.0", "dependencies": { "body-parser": "^1.20.0", diff --git a/package.json b/package.json index af694b4..369aaa5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@digicatapult/adcp-profiler-service", - "version": "0.0.3", + "version": "0.0.4", "description": "Insert repo description", "main": "app/index.js", "scripts": { From d90af2f18f848d4b32ef66aba7e3b0fdcdbfa676 Mon Sep 17 00:00:00 2001 From: Darryl Morton Date: Tue, 3 May 2022 09:35:48 +0100 Subject: [PATCH 4/4] helm values version bump --- helm/adcp-profiler-service/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helm/adcp-profiler-service/values.yaml b/helm/adcp-profiler-service/values.yaml index 351ae63..d0b236d 100644 --- a/helm/adcp-profiler-service/values.yaml +++ b/helm/adcp-profiler-service/values.yaml @@ -3,5 +3,5 @@ config: image: repository: ghcr.io/digicatapult/adcp-profiler-service pullPolicy: IfNotPresent - tag: 'v0.0.3' + tag: 'v0.0.4' pullSecrets: ['ghcr-digicatapult']