Skip to content

Commit

Permalink
feature/implement-create-event
Browse files Browse the repository at this point in the history
- refactor database structure
- create event controller
- write tests for event controller
  • Loading branch information
Billmike committed Apr 17, 2018
1 parent 346967b commit 96c31a6
Show file tree
Hide file tree
Showing 13 changed files with 313 additions and 6 deletions.
5 changes: 5 additions & 0 deletions server/controllers/center.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ class CenterController {
centerDetails: center
});
}).catch((error) => {
if (error.errors[0].message === 'name must be unique') {
return response.status(409).json({
message: 'A center with this name already exists.'
});
}
return response.status(500).json({
message: error.message
});
Expand Down
68 changes: 68 additions & 0 deletions server/controllers/event.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import db from '../models';
import serverError from '../errorHandler/serverError';
import validateAddEvent from '../validators/validateAddEvent';

const { Event, Center } = db;

class Events {
static addEvent(request, response) {
const { errors, valid } = validateAddEvent(request.body);
if (!valid) {
return response.status(400).json(errors);
}
return Center.findOne({
where: {
name: request.body.venue
}
}).then((foundCenter) => {
if (!foundCenter) {
return response.status(400).json({
message: 'No center found with this name.'
});
}
Event.create({
name: request.body.name,
image: request.body.image,
date: request.body.date,
duration: request.body.duration,
organizer: request.userDetails.id,
venue: foundCenter.dataValues.id
}).then((event) => {
return response.status(201).json({
message: 'Event created successfully.',
eventDetails: {
name: event.name,
image: event.image,
date: event.date,
duration: event.duration,
venue: foundCenter.dataValues.name
}
});
});
}).catch((err) => {
return response.status(500).json({
message: serverError
});
});
}
static getEvents(request, response) {
return Event.findAndCountAll()
.then((allEvents) => {
const limit = 4;
return Event.findAll({
limit
}).then((events) => {
return response.status(200).json({
message: 'Fetched events successfully.',
eventDetails: events
});
});
}).catch((err) => {
return response.status(500).json({
message: err.message
});
});
}
}

export default Events;
1 change: 1 addition & 0 deletions server/migrations/20180408212631-create-center.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module.exports = {
type: Sequelize.INTEGER
},
name: {
unique: true,
allowNull: false,
type: Sequelize.STRING
},
Expand Down
10 changes: 10 additions & 0 deletions server/migrations/20180408214725-create-event.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ module.exports = {
key: 'id',
as: 'organizer'
}
},
venue: {
allowNull: false,
type: Sequelize.INTEGER,
onDelete: 'cascade',
references: {
model: 'Centers',
key: 'id',
as: 'venue'
}
}
});
},
Expand Down
1 change: 1 addition & 0 deletions server/models/center.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = (sequelize, DataTypes) => {
const Center = sequelize.define('Center', {
name: {
unique: true,
allowNull: false,
type: DataTypes.STRING
},
Expand Down
6 changes: 1 addition & 5 deletions server/models/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,9 @@ module.exports = (sequelize, DataTypes) => {
type: DataTypes.DATE
},
duration: {
allowNull: false,
type: DataTypes.INTEGER
},
venue: {
allowNull: false,
type: DataTypes.STRING
}
},
});
Event.associate = (models) => {
Event.belongsTo(models.Center, {
Expand Down
6 changes: 6 additions & 0 deletions server/routes/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import userController from '../controllers/user';
import centerController from '../controllers/center';
import sessionControl from '../middleware/SessionControl';
import eventController from '../controllers/event';

module.exports = (app) => {
app.get('/api', (request, response) =>
Expand All @@ -23,4 +24,9 @@ module.exports = (app) => {
sessionControl.isUser, centerController.deleteCenter
);
app.get('/api/v1/centers', centerController.getCenters);
app.post(
'/api/v1/events', sessionControl.isLoggedIn, sessionControl.isUser,
eventController.addEvent
);
app.get('/api/v1/events', eventController.getEvents);
};
52 changes: 52 additions & 0 deletions server/seeders/20180417193035-event-seed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
'use strict';

module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.bulkInsert('Centers', [
{
name: 'Muson Center',
description: 'LA\'s finest basketball center',
state: 'Los Angeles',
location: 'South LA',
capacity: '20000',
equipments: 'Seats\nCourts\nTrap',
availability: 'available',
price: '20000',
createdAt: '2018-03-05 12:01:18.936+01',
updatedAt: '2018-03-05 12:01:18.936+01'
},
{
name: 'Yaba Beach',
description: 'Best beach in lagos',
state: 'Los Angeles',
location: 'South LA',
capacity: '20000',
equipments: 'Seats\nCourts\nTrap',
availability: 'available',
price: '20000',
createdAt: '2018-03-05 12:01:18.936+01',
updatedAt: '2018-03-05 12:01:18.936+01'
}
]);
/*
Add altering commands here.
Return a promise to correctly handle asynchronicity.
Example:
return queryInterface.bulkInsert('Person', [{
name: 'John Doe',
isBetaMember: false
}], {});
*/
},

down: (queryInterface, Sequelize) => {
/*
Add reverting commands here.
Return a promise to correctly handle asynchronicity.
Example:
return queryInterface.bulkDelete('Person', null, {});
*/
}
};
138 changes: 138 additions & 0 deletions server/tests/event.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import supertest from 'supertest';
import { expect } from 'chai';
import app from '../app';
import eventSeed from './seed/eventSeed';
import dummyUser from './seed/userseed';

const request = supertest(app);
const eventApi = '/api/v1/events';

describe('Tests for Events API', () => {
describe('Tests for events creation', () => {
it('should fail to create an event if the user is not signed in', (done) => {
request.post(eventApi)
.set('Connection', 'keep alive')
.set('Content-Type', 'application/json')
.type('form')
.send(eventSeed)
.end((error, response) => {
expect(response.status).to.equal(401);
expect(response.body).to.be.an('object');
expect(response.body.message).to
.equal('Please sign into your account to access this resource.');
done();
});
});
it('should fail to create an event if no name is provided', (done) => {
const noName = { ...eventSeed };
noName.name = '';
request.post(`/api/v1/events?token=${dummyUser.token}`)
.set('Connection', 'keep alive')
.set('Content-Type', 'application/json')
.type('form')
.send(noName)
.end((error, response) => {
expect(response.status).to.equal(400);
expect(response.body).to.be.an('object');
expect(response.body.name).to.equal('Your event needs a name');
done();
});
});
it('should fail to create an event if no date is supplied', (done) => {
const noDate = { ...eventSeed };
noDate.date = '';
request.post(`/api/v1/events?token=${dummyUser.token}`)
.set('Connection', 'keep alive')
.set('Content-Type', 'application/json')
.type('form')
.send(noDate)
.end((error, response) => {
expect(response.body).to.be.an('object');
expect(response.status).to.equal(400);
expect(response.body.date).to
.equal('Please input a date for your event');
done();
});
});
it('should fail to create an event if no duration is supplied', (done) => {
const noDuration = { ...eventSeed };
noDuration.duration = '';
request.post(`/api/v1/events?token=${dummyUser.token}`)
.set('Connection', 'keep alive')
.set('Content-Type', 'application/json')
.type('form')
.send(noDuration)
.end((error, response) => {
expect(response.body).to.be.an('object');
expect(response.body.duration).to
.equal('Please enter a duration for your event');
expect(response.status).to.equal(400);
done();
});
});
it(
'should fail to create an event if the center does not exist',
(done) => {
const testEvent = { ...eventSeed };
testEvent.venue = 'Does not exist';
request.post(`/api/v1/events?token=${dummyUser.token}`)
.set('Connection', 'keep alive')
.set('Content-Type', 'application/json')
.type('form')
.send(testEvent)
.end((error, response) => {
expect(response.status).to.equal(400);
expect(response.body).to.be.an('object');
expect(response.body.message)
.to.equal('No center found with this name.');
done();
});
}
);
it('should handle a server error when one occurs', (done) => {
request.post(`/api/v1/events?token=${dummyUser.token}`)
.set('Connection', 'keep alive')
.set('Content-Type', 'application/json')
.type('form')
.send(dummyUser)
.end((error, response) => {
expect(response.status).to.equal(500);
done();
});
});
it(
'should create an event successfully if all values are supplied',
(done) => {
request.post(`/api/v1/events?token=${dummyUser.token}`)
.set('Connection', 'keep alive')
.set('Content-Type', 'application/json')
.type('form')
.send(eventSeed)
.end((error, response) => {
expect(response.body).to.be.an('object');
expect(response.body.message)
.to.equal('Event created successfully.');
expect(response.body.eventDetails).to.be.an('object');
expect(response.body.eventDetails.name).to.be.a('string');
expect(response.body.eventDetails.image).to.be.a('string');
expect(response.body.eventDetails.venue).to.be.a('string');
done();
});
}
);
});
describe('Get all events test', () => {
it('should fetch all the events in the application', (done) => {
request.get('/api/v1/events')
.set('Connection', 'keep alive')
.set('Content-Type', 'application/json')
.type('form')
.end((error, response) => {
expect(response.status).to.equal(200);
expect(response.body).to.be.an('object');
expect(response.body.eventDetails).to.be.an('array');
done();
});
});
});
});
1 change: 1 addition & 0 deletions server/tests/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import './user.test';
import './center.test';
import './event.test';
2 changes: 1 addition & 1 deletion server/tests/seed/centerSeed.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const centerSeed = {
id: '1',
id: '3',
name: 'Staples Center',
description: 'LA\'s finest basketball center',
state: 'Los Angeles',
Expand Down
8 changes: 8 additions & 0 deletions server/tests/seed/eventSeed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const eventSeed = {
name: 'Biker sports event',
duration: 2,
date: '2018-03-05 12:01:18.936+01',
venue: 'Yaba Beach'
};

export default eventSeed;
21 changes: 21 additions & 0 deletions server/validators/validateAddEvent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { isEmpty } from 'lodash';

const validateAddEvent = (eventData) => {
const errors = {};
if (eventData.name.trim() === '' || eventData.name === undefined) {
errors.name = 'Your event needs a name';
}
if (eventData.date.trim() === '' || eventData.date === undefined) {
errors.date = 'Please input a date for your event';
}
if (eventData.duration.trim() === '' || eventData.duration === undefined) {
errors.duration = 'Please enter a duration for your event';
}

return {
errors,
valid: isEmpty(errors)
};
};

export default validateAddEvent;

0 comments on commit 96c31a6

Please sign in to comment.