Skip to content

Commit

Permalink
feat: added DELETE /api/subsystems/subsystemId endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
DdeHoog authored and mvegter committed Jun 6, 2020
1 parent ec08049 commit 0dd0c35
Show file tree
Hide file tree
Showing 9 changed files with 312 additions and 1 deletion.
38 changes: 38 additions & 0 deletions lib/server/controllers/subsystems.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
const {
subsystem: {
CreateSubsystemUseCase,
DeleteSubsystemUseCase,
GetAllSubsystemsUseCase,
GetSubsystemUseCase,
},
Expand Down Expand Up @@ -111,8 +112,45 @@ const create = async (request, response, next) => {
});
};

/**
* Delete subsystem.
*
* @param {Object} request The *request* object represents the HTTP request and has properties for the request query
* string, parameters, body, HTTP headers, and so on.
* @param {Object} response The *response* object represents the HTTP response that an Express app sends when it gets an
* HTTP request.
* @param {Function} next The *next* object represents the next middleware function which is used to pass control to the
* next middleware function.
* @returns {undefined}
*/
const deleteSubsystem = async (request, response, next) => {
const value = await dtoValidator(GetSubsystemDto, request, response);
if (!value) {
return;
}

const logs = await new DeleteSubsystemUseCase()
.execute(value);

if (logs === null) {
response.status(404).json({
errors: [
{
status: '404',
title: `Subsystem with this id (${value.params.subsystemId}) could not be found`,
},
],
});
} else {
response.status(200).json({
data: logs,
});
}
};

module.exports = {
create,
deleteSubsystem,
index,
read,
};
6 changes: 6 additions & 0 deletions lib/server/routers/subsystems.router.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ module.exports = {
method: 'get',
path: ':subsystemId',
controller: SubsystemsController.read,
children: [
{
method: 'delete',
controller: SubsystemsController.deleteSubsystem,
},
],
},
],
};
45 changes: 45 additions & 0 deletions lib/usecases/subsystem/DeleteSubsystemUseCase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* @license
* Copyright CERN and copyright holders of ALICE O2. This software is
* distributed under the terms of the GNU General Public License v3 (GPL
* Version 3), copied verbatim in the file "COPYING".
*
* See http://alice-o2.web.cern.ch/license for full licensing information.
*
* In applying this license CERN does not waive the privileges and immunities
* granted to it by virtue of its status as an Intergovernmental Organization
* or submit itself to any jurisdiction.
*/

const {
repositories: {
SubsystemRepository,
},
utilities: {
QueryBuilder,
TransactionHelper,
},
} = require('../../database');

/**
* DeleteSubsystemUseCase
*/
class DeleteSubsystemUseCase {
/**
* Executes this use case.
*
* @param {Object} dto The GetAllSubsystems DTO which contains all request data.
* @returns {Promise} Promise object represents the result of this use case.
*/
async execute(dto = {}) {
const queryBuilder = new QueryBuilder();
const { params } = dto;
const { subsystemId } = params;

queryBuilder.where('id').is(subsystemId);

return TransactionHelper.provide(() => SubsystemRepository.removeOne(queryBuilder));
}
}

module.exports = DeleteSubsystemUseCase;
2 changes: 2 additions & 0 deletions lib/usecases/subsystem/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@
* or submit itself to any jurisdiction.
*/
const CreateSubsystemUseCase = require('./CreateSubsystemUseCase');
const DeleteSubsystemUseCase = require('./DeleteSubsystemUseCase');
const GetAllSubsystemsUseCase = require('./GetAllSubsystemsUseCase');
const GetSubsystemUseCase = require('./GetSubsystemUseCase');

module.exports = {
CreateSubsystemUseCase,
DeleteSubsystemUseCase,
GetAllSubsystemsUseCase,
GetSubsystemUseCase,
};
12 changes: 12 additions & 0 deletions spec/openapi-source.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,18 @@ paths:
$ref: '#/components/responses/NotFound'
tags:
- subsystem
delete:
operationId: deleteSubsystem
summary: Deletes a subsystem by Id
responses:
'200':
$ref: '#/components/responses/Subsystem'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
tags:
- subsystem
/tags:
get:
operationId: listTags
Expand Down
16 changes: 15 additions & 1 deletion spec/openapi.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated on Sat, 06 Jun 2020 15:06:58 GMT
# Generated on Sat, 06 Jun 2020 15:08:25 GMT

openapi: 3.0.0
info:
Expand Down Expand Up @@ -166,6 +166,20 @@ paths:
$ref: '#/components/responses/UnexpectedError'
tags:
- subsystem
delete:
operationId: deleteSubsystem
summary: Deletes a subsystem by Id
responses:
'200':
$ref: '#/components/responses/Subsystem'
'400':
$ref: '#/components/responses/BadRequest'
'404':
$ref: '#/components/responses/NotFound'
default:
$ref: '#/components/responses/UnexpectedError'
tags:
- subsystem
/tags:
get:
operationId: listTags
Expand Down
127 changes: 127 additions & 0 deletions test/e2e/subsystems.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ const path = require('path');
const chai = require('chai');
const request = require('supertest');
const chaiResponseValidator = require('chai-openapi-response-validator');
const {
dtos: {
CreateSubsystemDto,
},
} = require('../../lib/domain');
const {
subsystem: {
CreateSubsystemUseCase,
},
} = require('../../lib/usecases');

const { expect } = chai;

Expand Down Expand Up @@ -302,4 +312,121 @@ module.exports = () => {
});
});
});

describe('DELETE /api/subsystems/:subsystemId', () => {
let createdSubsystem;

beforeEach(async () => {
const createSubsystemDto = await CreateSubsystemDto.validateAsync({
body: {
text: `SUBSYSTEM#${new Date().getTime()}`,
},
});

createdSubsystem = await new CreateSubsystemUseCase()
.execute(createSubsystemDto);
});

it('should return 400 if the subsystem id is not a number', (done) => {
request(server)
.delete('/api/subsystems/abc')
.expect(400)
.end((err, res) => {
if (err) {
done(err);
return;
}

// Response must satisfy the OpenAPI specification
expect(res).to.satisfyApiSpec;

const { errors } = res.body;
const error = errors.find((err) => err.source.pointer === '/data/attributes/params/subsystemId');
expect(error.detail).to.equal('"params.subsystemId" must be a number');

done();
});
});

it('should return 400 if the subsystem id is not positive', (done) => {
request(server)
.delete('/api/subsystems/-1')
.expect(400)
.end((err, res) => {
if (err) {
done(err);
return;
}

// Response must satisfy the OpenAPI specification
expect(res).to.satisfyApiSpec;

const { errors } = res.body;
const error = errors.find((err) => err.source.pointer === '/data/attributes/params/subsystemId');
expect(error.detail).to.equal('"params.subsystemId" must be a positive number');

done();
});
});

it('should return 400 if the subsystem id is not a whole number', (done) => {
request(server)
.delete('/api/subsystems/0.5')
.expect(400)
.end((err, res) => {
if (err) {
done(err);
return;
}

// Response must satisfy the OpenAPI specification
expect(res).to.satisfyApiSpec;

const { errors } = res.body;
const error = errors.find((err) => err.source.pointer === '/data/attributes/params/subsystemId');
expect(error.detail).to.equal('"params.subsystemId" must be an integer');

done();
});
});

it('should return 404 if the subsystem could not be found', (done) => {
request(server)
.delete('/api/subsystems/999999999')
.expect(404)
.end((err, res) => {
if (err) {
done(err);
return;
}

// Response must satisfy the OpenAPI specification
expect(res).to.satisfyApiSpec;

expect(res.body.errors[0].title).to.equal('Subsystem with this id (999999999) could not be found');

done();
});
});

it('should return 200 in all other cases', (done) => {
request(server)
.delete(`/api/subsystems/${createdSubsystem.id}`)
.expect(200)
.end((err, res) => {
if (err) {
done(err);
return;
}

// Response must satisfy the OpenAPI specification
expect(res).to.satisfyApiSpec;

expect(res.body.data.id).to.equal(createdSubsystem.id);
expect(res.body.data.text).to.equal(createdSubsystem.text);

done();
});
});
});
};
65 changes: 65 additions & 0 deletions test/usecases/subsystem/DeleteSubsystemUseCase.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/**
* @license
* Copyright CERN and copyright holders of ALICE O2. This software is
* distributed under the terms of the GNU General Public License v3 (GPL
* Version 3), copied verbatim in the file "COPYING".
*
* See http://alice-o2.web.cern.ch/license for full licensing information.
*
* In applying this license CERN does not waive the privileges and immunities
* granted to it by virtue of its status as an Intergovernmental Organization
* or submit itself to any jurisdiction.
*/

const { repositories: { SubsystemRepository } } = require('../../../lib/database');
const { subsystem: { CreateSubsystemUseCase, DeleteSubsystemUseCase } } = require('../../../lib/usecases');
const { dtos: { CreateSubsystemDto } } = require('../../../lib/domain');
const chai = require('chai');

const { expect } = chai;

module.exports = () => {
let createdSubsystem;

beforeEach(async () => {
const createSubsystemDto = await CreateSubsystemDto.validateAsync({
body: {
name: `SYSTEM#${new Date().getTime()}`,
},
});

createdSubsystem = await new CreateSubsystemUseCase()
.execute(createSubsystemDto);
});

it('should remove a subsystem', async () => {
const nSubsystemsBefore = await SubsystemRepository.count();

await new DeleteSubsystemUseCase()
.execute({
params: {
subsystemId: createdSubsystem.id,
},
});

const nSubsystemsAfter = await SubsystemRepository.count();
expect(nSubsystemsAfter).to.be.lessThan(nSubsystemsBefore);
});

it('should return the removed subsystem', async () => {
const nSubsystemsBefore = await SubsystemRepository.count();

const result = await new DeleteSubsystemUseCase()
.execute({
params: {
subsystemId: createdSubsystem.id,
},
});

const nSubsystemsAfter = await SubsystemRepository.count();
expect(nSubsystemsAfter).to.be.lessThan(nSubsystemsBefore);

expect(result.id).to.equal(createdSubsystem.id);
expect(result.name).to.equal(createdSubsystem.name);
});
};
2 changes: 2 additions & 0 deletions test/usecases/subsystem/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
*/

const CreateSubsystemUseCase = require('./CreateSubsystemUseCase.test');
const DeleteSubsystemUseCase = require('./DeleteSubsystemUseCase.test');
const GetAllSubsystemsUseCase = require('./GetAllSubsystemsUseCase.test');
const GetSubsystemUseCase = require('./GetSubsystemUseCase.test');

module.exports = () => {
describe('CreateSubsystemUseCase', CreateSubsystemUseCase);
describe('DeleteSubsystemUseCase', DeleteSubsystemUseCase);
describe('GetAllSubsystemsUseCase', GetAllSubsystemsUseCase);
describe('GetSubsystemUseCase', GetSubsystemUseCase);
};

0 comments on commit 0dd0c35

Please sign in to comment.