diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..1bc0c1575b968932e3a14cb588c029cf1cd795f4 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,23 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## Unreleased + +## 0.1.0 - 2016-10-10 +### Added +**Database** +- MonetDB connection middleware +- MongoDB connection middleware +- query_exec custom middleware (promise that executes an SQL query with optional parameters) +- This version depends on the version 0.1.0 of [MonetDB schema](https://gitlab.c3sl.ufpr.br/simcaq/monetdb) + +**Enrollments** +- Enrollments route with all sub dependencies + +**Middlewares** +- parseParams middleware to parse HTTP GET params +- query middleware that serves as an interface between squel generated sql and the query execution +- response middleware that gives a standard response (json, csv or xml) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8e649c4e017254a3cdc008cbcc2597a4da3fe740..6e7b10c10b205cca5712e6ef1542ba5c99b5c13a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,6 +17,7 @@ Bugs are reported and tracked at [simcaq/SCRUM](https://gitlab.c3sl.ufpr.br/simc * **development**: default branch * **issue/??**: issue branch - a branch created to solve a issue * **feature_????**: feature branch - a branch created to add a feature +* **release_vM.m.f**: release branch - a branch created to merge with master and set a release. The verion follows the [semantic versioning](http://semver.org) ## Styleguide diff --git a/config.json.example b/config.json.example index 0a0603ceb48168697a2ab94fff013b0198fedc53..fa9c64ea2e2fb5eeddcce58e4746b1bc456d03b4 100644 --- a/config.json.example +++ b/config.json.example @@ -1,22 +1,71 @@ { - "port": 3000, - "ip": "127.0.0.1", - "debug" : false, - "monetdb": { - "host": "simcaqdb1", - "port": 50000, - "dbname": "simcaq_dev", - "user": "monetdb", - "password":"monetdb", - "nrConnections": "16" + "development": + { + "port": 3000, + "ip": "127.0.0.1", + "debug" : true, + "monetdb": { + "host": "simcaqdb1", + "port": 50000, + "dbname": "simcaq_dev", + "user": "monetdb", + "password":"monetdb", + "nrConnections": "16" + }, + "mongodb" : { + "uri": "mongodb://localhost/users", + "secret": "SimCAQC3SL" + }, + "default": { + "api": { + "version" : "v1" + } + } }, - "mongodb" : { - "uri": "mongodb://localhost/users" - "secret": "SimCAQC3SL" + "test": + { + "port": 3000, + "ip": "127.0.0.1", + "debug" : true, + "monetdb": { + "host": "simcaqdb1", + "port": 50000, + "dbname": "simcaq_dev", + "user": "monetdb", + "password":"monetdb", + "nrConnections": "16" + }, + "mongodb" : { + "uri": "mongodb://localhost/test_users", + "secret": "SimCAQC3SL" + }, + "default": { + "api": { + "version" : "v1" + } + } }, - "default": { - "api": { - "version" : "v1" + "production": + { + "port": 3000, + "ip": "127.0.0.1", + "debug" : true, + "monetdb": { + "host": "simcaqdb1", + "port": 50000, + "dbname": "simcaq_dev", + "user": "monetdb", + "password":"monetdb", + "nrConnections": "16" + }, + "mongodb" : { + "uri": "mongodb://localhost/users", + "secret": "SimCAQC3SL" + }, + "default": { + "api": { + "version" : "v1" + } } } } diff --git a/src/libs/app.js b/src/libs/app.js index 39b3a6488e561d1bb51e3d1d7e24cb73d297715a..fa685039b525ff430eca6841908666b40d8b0300 100644 --- a/src/libs/app.js +++ b/src/libs/app.js @@ -10,7 +10,9 @@ const libs = `${process.cwd()}/libs`; const log = require(`${libs}/log`)(module); -const config = require('./config'); +process.env.NODE_ENV = process.env.NODE_ENV || 'development'; +const config = require(`${libs}/config`); +const cache = require('apicache').options({ debug: config.debug }).middleware; const app = express(); diff --git a/src/libs/config.js b/src/libs/config.js index 5aea5a9ca50efd0dac2253dd23690229431236dc..2c07d19e94ba2505205d613a9ac6d5596c388502 100644 --- a/src/libs/config.js +++ b/src/libs/config.js @@ -1,8 +1,5 @@ -const nconf = require('nconf'); +let conf = require(`${process.cwd()}/config.json`); -// Exports the config.json as an object with get functions -nconf.argv() - .env() - .file({ file: `${process.cwd()}/config.json` }); +conf = conf[process.env.NODE_ENV]; -module.exports = nconf; +module.exports = conf; diff --git a/src/libs/db/monet.js b/src/libs/db/monet.js index dd7e620adcf5b6a1dbe29358697fa71a3970ea03..d19fb37dfac5ed68cc15c1762a822818dbbc82da 100644 --- a/src/libs/db/monet.js +++ b/src/libs/db/monet.js @@ -6,16 +6,16 @@ const config = require(`${libs}/config`); // Connection options const poolOptions = { - nrConnections: config.get('monetdb:nrConnections'), + nrConnections: config.monetdb.nrConnections, }; // Configuration options const options = { - host: config.get('monetdb:host'), - port: config.get('monetdb:port'), - dbname: config.get('monetdb:dbname'), - user: config.get('monetdb:user'), - password: config.get('monetdb:password'), + host: config.monetdb.host, + port: config.monetdb.port, + dbname: config.monetdb.dbname, + user: config.monetdb.user, + password: config.monetdb.password, }; // Connection singleton diff --git a/src/libs/db/mongoose.js b/src/libs/db/mongoose.js index 4188f5c439039613e20ebcd62a2e4c5cc684c016..400898c67fc7d43cfa0cf3f2b9faa9176166a088 100644 --- a/src/libs/db/mongoose.js +++ b/src/libs/db/mongoose.js @@ -9,7 +9,8 @@ const mongoose = require('mongoose'); mongoose.Promise = global.Promise; module.exports = () => { - const mongoUri = process.env.MONGO_URI || config.get('mongodb:uri'); + // Get mongodb URI (ip and port) in config file + const mongoUri = process.env.MONGO_URI || config.mongodb.uri; log.debug(`Connecting to MongDB on URI ${mongoUri}`); // Connection singleton const db = mongoose.connect(mongoUri); diff --git a/src/libs/log.js b/src/libs/log.js index fbe7b1394464e06611cbcd91d69e33c022846923..ddf0303f8481514b047aa6678894316500d25a96 100644 --- a/src/libs/log.js +++ b/src/libs/log.js @@ -47,7 +47,7 @@ function logger(module) { ], exitOnError: false, }); - if (!config.get('debug')) { + if (!config.debug) { log.remove('debug-log'); } return log; diff --git a/src/libs/models/simulation.js b/src/libs/models/simulation.js new file mode 100644 index 0000000000000000000000000000000000000000..e70c93a9f88dea76d017744b15f3b3fe61b5ca21 --- /dev/null +++ b/src/libs/models/simulation.js @@ -0,0 +1,115 @@ +const mongoose = require('mongoose') + +const libs = `${process.cwd()}/libs`; +const log = require(`${libs}/log`)(module); + +const Schema = mongoose.Schema; + +// Should define this somewhere else +const MAX_SIMULATION_TIME = 10; + + +let SimulationSchema = new Schema({ + name: { + type: String, + required: true, + }, + location: Object, + time: Number, + failure_rate: Array, + goals_care: Array, + goals_inclusion: Array, + enrollments: Array, + timestamp: Date, +}); + +SimulationSchema.methods.setTime = function (t) { + t = parseInt(t, 10); + if (!t || t > MAX_SIMULATION_TIME) { + // Throw an error? + return false; + } + this.time = t; + return true; +}; +SimulationSchema.methods.setLocation = function (l) { + // Should sanitize + this.location = l; + return true; +}; +SimulationSchema.methods.setFailureRate = function (fr) { + // Should sanitize + this.failure_rate = fr; + return true; +}; +SimulationSchema.methods.setCareGoals = function (g) { + // Should sanitize + this.goals_care = g; + return true; +}; +SimulationSchema.methods.setInclusionGoals = function (g) { + // Should sanitize + this.goals_inclusion = g; + return true; +}; +SimulationSchema.methods.setEnrollments = function (e) { + try{ + e = JSON.parse(e); + } catch (err) { + return false; + } + let success = true; + for(let i=0; i<e.length; i++){ + if(!(e[i] instanceof Array)){ + return false; + } + if(e[i].length !== this.time){ + return false; + } + e[i].forEach((n, i, array) => { + if(n !== parseInt(n, 10)){ + success = false; + } + }); + + } + if (success) this.enrollments = e; + + return success; +} +SimulationSchema.methods.update = function (property, value) { + let success = true; + switch(property){ + case 'time': + if (!this.setTime(value)) success = false; + break; + case 'location': + if (!this.setLocation(value)) success = false; + break; + case 'failure_rate': + if (!this.setFailureRate(value)) success = false; + break; + case 'goals_care': + if (!this.setCareGoals(value)) success = false; + break; + case 'goals_inclusion': + if (!this.setInclusionGoals(value)) success = false; + break; + case 'enrollments': + if (!this.setEnrollments(value)) success = false; + break; + case 'name': + this.name = value; + break; + } + return success; +}; + +SimulationSchema.methods.run = function () { + /* Runs the Simulation with given parameters */ + // if (!this.name || !this.location || !this.time) { + // console.log('This is supposed to be an error.'); + // } +}; + +module.exports = mongoose.model('Simulation', SimulationSchema); diff --git a/src/libs/routes/api.js b/src/libs/routes/api.js index 7ae5b3e898d35c9072057efc48b3bafe0fe8deab..2c259bab8c800180d240d20a525b0c908868422e 100644 --- a/src/libs/routes/api.js +++ b/src/libs/routes/api.js @@ -6,7 +6,7 @@ const libs = `${process.cwd()}/libs`; const config = require(`${libs}/config`); -const cache = require('apicache').options({ debug: config.get('debug') }).middleware; +const cache = require('apicache').options({ debug: config.debug }).middleware; const enrollment = require('./enrollment'); @@ -18,6 +18,8 @@ const city = require('./city'); const school = require('./school'); +const simulation = require('./simulation'); + const user = require('./user'); api.get('/', (req, res) => { @@ -25,7 +27,9 @@ api.get('/', (req, res) => { }); // mount API routes + api.use('/user', user); +api.use('/simulation', simulation); api.use('/enrollment', cache('1 day'), enrollment); api.use('/state', cache('15 day'), state); api.use('/region', cache('15 day'), region); diff --git a/src/libs/routes/simulation.js b/src/libs/routes/simulation.js new file mode 100644 index 0000000000000000000000000000000000000000..16c7dcf848e0851c71a5c5015d554087a6f4e1b6 --- /dev/null +++ b/src/libs/routes/simulation.js @@ -0,0 +1,148 @@ +const express = require('express'); + +const simulationApp = express(); + +const libs = `${process.cwd()}/libs`; + + +const log = require(`${libs}/log`)(module); + +const squel = require('squel'); + +const query = require(`${libs}/middlewares/query`); + +const response = require(`${libs}/middlewares/response`); + +const Simulation = require(`${libs}/models/simulation`); + +simulationApp.get('/', (req, res) => { + let out = { success: true, msg: 'controller working' }; + out.result = new Array() + Simulation.find({}, function(err, sims) { + sims.forEach((sim) => { + out.result.push(sim); + }); + res.send(out); + }); +}); + +simulationApp.post('/', (req, res, next) => { + // This method must associate new entry with user. + /* Creates a new simulation. Requires a name. */ + if (!req.body.name) { + res.send({ success: false, msg: 'Must send a name for new entry' }); + } else { + next(); + } +}, (req, res) => { + let currentdate = new Date(); + let newSimulation = new Simulation({ + name: req.body.name, + timestamp: currentdate.getDate(), + }); + newSimulation.save((err) => { + if (err) { + res.send({ success: false, msg: err }); + } else { + res.send({ + success: true, + msg: 'new sim created', + id: newSimulation._id, + }); + } + }); +}); + +simulationApp.get('/:id', (req, res) => { + /* Can be used to check simulation construction status */ + Simulation.findById(req.params.id, (err, simulation) => { + log.debug(req.params.id); + if (err) { + res.send({ success: false, msg: err }); + return; + } + + if (!simulation) { + res.send({ success: false, msg: 'Entry not found' }); + } else { + res.send(simulation); + } + }); +}); + +simulationApp.post('/:id', (req, res, next) => { + if (!Object.keys(req.body).length) { + res.send({ success: false, msg: 'No field informed to update' }); + } else { + next(); + } +}, (req, res, next) => { + let simulation = Simulation.findById(req.params.id, (err, simulation) => { + if (err) { + res.send({ success: false, msg: err }); + } else { + if (!simulation) { + res.send({ success: false, msg: 'Entry not found' }); + } else { + req.simulation = simulation; + next(); + } + } + }); +}, (req, res) => { + for (let property in req.body) { + if (Simulation.schema.tree.hasOwnProperty(property)) { + if(!req.simulation.update(property, req.body[property])){ + res.send({ + success: false, + msg: 'Invalid format for ' + property, + }); + return ; + } + } else { + res.send({ + success: false, + msg: 'Unknown property ' + property, + }); + return ; + } + } + req.simulation.save((err) => { + if (err) { + res.send({ success: false, msg: err }); + } else { + res.send({ + success: true, + msg: 'sim updated', + id: req.simulation._id, + }); + } + }); +}); + +simulationApp.delete('/:id', (req, res, next) => { + let simulation = Simulation.findById(req.params.id, (err, simulation) => { + if (err) { + res.send({ success: false, msg: err }); + } else { + if (!simulation) { + res.send({ success: false, msg: 'Entry not found' }); + } else { + next(); + } + } + }); +}, (req, res) => { + Simulation.remove({"_id": req.params.id}, (err) => { + if (err) { + res.send({ success: false, msg: err }); + } else { + res.send({ + success: true, + msg: 'sim removed', + }); + } + }); +}); + +module.exports = simulationApp; diff --git a/src/server.js b/src/server.js index 0eef8dfa5fb4764522f0b1c0be02da239603d347..4e097f28a4053050757c6329e19e225e0424b961 100644 --- a/src/server.js +++ b/src/server.js @@ -8,12 +8,14 @@ const log = require(`${libs}/log`)(module); const app = require(`${libs}/app`); +// Set default port: first environment variable PORT, then configuration and last 3000 +app.set('port', process.env.PORT || config.port || 3000); process.env.NODE_ENV = process.env.NODE_ENV || 'development'; -app.set('port', process.env.PORT || config.get('port') || 3000); +app.set('port', process.env.PORT || config.port || 3000); // Set default ip: first environment variable IOP, then configuration and last '127.0.0.1' -app.set('ip', process.env.IP || config.get('ip') || '127.0.0.1'); +app.set('ip', process.env.IP || config.ip || '127.0.0.1'); const server = app.listen(app.get('port'), () => { log.info(`Express server listening on port ${server.address().port}`); diff --git a/src/test/test.js b/src/test/test.js index 066b7b77c9651dbde50b97cd6ab730c78053d27b..5529e056fa9303f731a416d2845b096f434a28a8 100644 --- a/src/test/test.js +++ b/src/test/test.js @@ -22,6 +22,9 @@ const libs = `${process.cwd()}/libs`; const server = require(`${libs}/app`); +const mongoose = require('../libs/db/mongoose'); +const Simulation = require('../libs/models/simulation'); + chai.use(chaiHttp); describe('API is running', () => { @@ -396,3 +399,382 @@ describe('test response', () => { }); }); }); + +describe('Requires a simulation', () => { + let newSimulation; + + beforeEach(() => { + Simulation.remove({}, (err) => { + console.log('Test collection purged'); + }); + }); + + it('should create a new simulation', (done) => { + chai.request(server) + .post('/api/v1/simulation') + .set('content-type', 'application/x-www-form-urlencoded') + .set('x-apicache-bypass', 'true') + .send({ name: 'test_entry' }) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('id'); + res.body.id.should.be.a('string'); + Simulation.findById(res.body.id, (err, simulation) => { + simulation.should.have.property('name'); + simulation.name.should.be.a('string'); + simulation.name.should.equal('test_entry'); + done(); + }); + }); + }); + it('should not create a nameless simulation', (done) => { + chai.request(server) + .post('/api/v1/simulation') + .set('content-type', 'application/x-www-form-urlencoded') + .set('x-apicache-bypass', 'true') + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.not.have.property('id'); + res.body.should.have.property('success'); + res.body.success.should.equal(false); + Simulation.findById(res.body.id, (err, simulation) => { + expect(simulation).to.not.exist; + done(); + }); + }); + }); + it('should find an existing simulation', (done) => { + newSimulation = new Simulation(); + newSimulation.name = 'test'; + newSimulation.save((err, sim) => { + let id = sim._id; + chai.request(server) + .get(`/api/v1/simulation/${id}`) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('_id'); + res.body._id.should.be.a('string'); + res.body.should.have.property('name'); + res.body._id.should.be.a('string'); + done(); + }); + }); + }); + it('should not find an unexisting simulation', (done) => { + newSimulation = new Simulation(); + let id = newSimulation._id; + chai.request(server) + .get(`/api/v1/simulation/${id}`) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('success'); + res.body.success.should.equal(false); + done(); + }); + }); + it('should update an existing simulation\'s location', (done) => { + newSimulation = new Simulation(); + newSimulation.name = 'test'; + newSimulation.save((err, sim) => { + let id = sim._id; + chai.request(server) + .post(`/api/v1/simulation/${id}`) + .send({ location: 5 }) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('id'); + res.body.id.should.be.a('string'); + Simulation.findById(res.body.id, (err, simulation) => { + simulation.should.have.property('name'); + simulation.name.should.be.a('string'); + simulation.name.should.equal('test'); + simulation.should.have.property('location'); + simulation.location.should.be.a('number'); + simulation.location.should.equal(5); + done(); + }); + }); + }); + }); + it('should update multiple fields on a single request', (done) => { + newSimulation = new Simulation(); + newSimulation.name = 'test'; + newSimulation.save((err, sim) => { + let id = sim._id; + chai.request(server) + .post(`/api/v1/simulation/${id}`) + .send({ + name: 'new_name', + location: 5, + time: 3, + failure_rate: [0.1, 0.2, 0.3], + goals_care: [0.3, 0.2, 0.1], + goals_inclusion: [0.8, 0.9, 1] + }) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('id'); + res.body.id.should.be.a('string'); + Simulation.findById(res.body.id, (err, simulation) => { + simulation.should.have.property('name'); + simulation.name.should.be.a('string'); + simulation.name.should.equal('new_name'); + simulation.should.have.property('location'); + simulation.location.should.be.a('number'); + simulation.location.should.equal(5); + simulation.should.have.property('time'); + simulation.time.should.be.a('number'); + simulation.time.should.equal(3); + simulation.should.have.property('failure_rate'); + simulation.failure_rate.should.be.a('array'); + simulation.failure_rate.length.should.equal(3); + simulation.should.have.property('goals_care'); + simulation.goals_care.should.be.a('array'); + simulation.goals_care.length.should.equal(3); + simulation.should.have.property('goals_inclusion'); + simulation.goals_inclusion.should.be.a('array'); + simulation.goals_inclusion.length.should.equal(3); + done(); + }); + }); + }); + }); + it('should not update an unexisting simulation', (done) => { + newSimulation = new Simulation(); + let id = newSimulation._id; + chai.request(server) + .post(`/api/v1/simulation/${id}`) + .send({ location: 5 }) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('success'); + res.body.success.should.equal(false); + done(); + }); + }); + it('should update an existing simulation\'s time', (done) => { + newSimulation = new Simulation(); + newSimulation.name = 'test'; + newSimulation.save((err, sim) => { + let id = sim._id; + chai.request(server) + .post(`/api/v1/simulation/${id}`) + .send({ time: 5 }) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('id'); + res.body.id.should.be.a('string'); + Simulation.findById(res.body.id, (err, simulation) => { + simulation.should.have.property('name'); + simulation.name.should.be.a('string'); + simulation.should.have.property('time'); + simulation.time.should.be.a('number'); + simulation.time.should.equal(5); + done(); + }); + }); + }); + }); + it('should not change results for empty post requests', (done) => { + newSimulation = new Simulation(); + newSimulation.name = 'test'; + newSimulation.save((err, sim) => { + let id = sim._id; + chai.request(server) + .post(`/api/v1/simulation/${id}`) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('success'); + res.body.success.should.equal(false); + done(); + }); + }); + }); + it('should not update in case of invalid field', (done) => { + newSimulation = new Simulation(); + newSimulation.name = 'test'; + newSimulation.save((err, sim) => { + let id = sim._id; + chai.request(server) + .post(`/api/v1/simulation/${id}`) + .send({ + name: 'other_name', + totally_not_valid_value_for_an_entry: 'not hacking this api', + }) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('success'); + res.body.success.should.equal(false); + Simulation.findById(id, (err, simulation) => { + simulation.name.should.equal('test'); + done(); + }); + }); + }); + }); + it('should include consistent enrollment tables', (done) => { + newSimulation = new Simulation(); + newSimulation.name = 'test'; + newSimulation.save((err, sim) => { + let id = sim._id; + chai.request(server) + .post(`/api/v1/simulation/${id}`) + .send({ + time: 5, + enrollments: "[[100, 150, 200, 250, 300]]", + }) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('id'); + res.body.id.should.be.a('string'); + Simulation.findById(res.body.id, (err, simulation) => { + simulation.should.have.property('name'); + simulation.name.should.be.a('string'); + simulation.should.have.property('time'); + simulation.time.should.be.a('number'); + simulation.time.should.equal(5); + done(); + }); + }); + }); + }); + it('should not accept an invalid time', (done) => { + newSimulation = new Simulation(); + newSimulation.name = 'test'; + newSimulation.save((err, sim) => { + let id = sim._id; + chai.request(server) + .post(`/api/v1/simulation/${id}`) + .send({ + time: "I'm an inocent time entry, don't mind me", + }) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('success'); + res.body.success.should.equal(false); + }); + done(); + }); + }); + it('should not accept enrollments table different than provided time', (done) => { + newSimulation = new Simulation(); + newSimulation.name = 'test'; + newSimulation.save((err, sim) => { + let id = sim._id; + chai.request(server) + .post(`/api/v1/simulation/${id}`) + .send({ + time: 5, + enrollments: "[[1,2,3]]", + }) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('success'); + res.body.success.should.equal(false); + done(); + }); + }); + }); + it('should not include arrays of non arrays as enrollments', (done) => { + newSimulation = new Simulation(); + newSimulation.name = 'test'; + newSimulation.save((err, sim) => { + let id = sim._id; + chai.request(server) + .post(`/api/v1/simulation/${id}`) + .send({ + time: 5, + enrollments: "[\"Tomato\"]", + }) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('success'); + res.body.success.should.equal(false); + done(); + }); + }); + }); + it('should not accept non array enrollments', (done) => { + newSimulation = new Simulation(); + newSimulation.name = 'test'; + newSimulation.save((err, sim) => { + let id = sim._id; + chai.request(server) + .post(`/api/v1/simulation/${id}`) + .send({ + time: 5, + enrollments: "Am I still wanted here?", + }) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('success'); + res.body.success.should.equal(false); + done(); + }); + }); + }); + it('should not accept an enrollment with anything other than a number', (done) => { + newSimulation = new Simulation(); + newSimulation.name = 'test'; + newSimulation.save((err, sim) => { + let id = sim._id; + chai.request(server) + .post(`/api/v1/simulation/${id}`) + .send({ + time: 5, + enrollments: "[[1,2,\"malicious payload\",4,5]]", + }) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('success'); + res.body.success.should.equal(false); + done(); + }); + }); + }); + it('should delete an entry', (done) => { + newSimulation = new Simulation(); + newSimulation.name = 'test'; + newSimulation.save((err, sim) => { + let id = sim._id; + chai.request(server) + .delete(`/api/v1/simulation/${id}`) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('success'); + res.body.success.should.equal(true); + done(); + }); + }); + }); + it('should not delete an unexisting entry', (done) => { + let sim = new Simulation(); + let id = sim._id; + chai.request(server) + .delete(`/api/v1/simulation/${id}`) + .end((err, res) => { + res.should.have.status(200); + res.should.be.json; + res.body.should.have.property('success'); + res.body.success.should.equal(false); + done(); + }); + }); +});