import should from 'should/as-function'; import ConditionModel from '../models/condition'; import TestHelper from "../test/helper"; describe('/condition', () => { let server; before(done => TestHelper.before(done)); beforeEach(done => server = TestHelper.beforeEach(server, done)); afterEach(done => TestHelper.afterEach(server, done)); describe('GET /condition/{id}', () => { it('returns the right condition', done => { TestHelper.request(server, done, { method: 'get', url: '/condition/700000000000000000000001', auth: {basic: 'janedoe'}, httpStatus: 200, res: {_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'B1', parameters: {material: 'copper', weeks: 3}, treatment_template: '200000000000000000000001'} }); }); it('returns the right condition for an API key', done => { TestHelper.request(server, done, { method: 'get', url: '/condition/700000000000000000000001', auth: {key: 'janedoe'}, httpStatus: 200, res: {_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'B1', parameters: {material: 'copper', weeks: 3}, treatment_template: '200000000000000000000001'} }); }); it('rejects an invalid id', done => { TestHelper.request(server, done, { method: 'get', url: '/condition/70000000000t000000000001', auth: {basic: 'janedoe'}, httpStatus: 404 }); }); it('rejects an unknown id', done => { TestHelper.request(server, done, { method: 'get', url: '/condition/000000000000000000000001', auth: {basic: 'janedoe'}, httpStatus: 404 }); }); it('rejects unauthorized requests', done => { TestHelper.request(server, done, { method: 'get', url: '/condition/700000000000000000000001', httpStatus: 401 }); }); }); describe('PUT /condition{id}', () => { it('returns the right condition', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000001', auth: {basic: 'janedoe'}, httpStatus: 200, req: {}, res: {_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'B1', treatment_template: '200000000000000000000001', parameters: {material: 'copper', weeks: 3}} }); }); it('keeps unchanged properties', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000001', auth: {basic: 'janedoe'}, httpStatus: 200, req: {parameters: {material: 'copper', weeks: 3}} }).end((err, res) => { if (err) return done(err); should(res.body).be.eql({_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'B1', treatment_template: '200000000000000000000001', parameters: {material: 'copper', weeks: 3}}); ConditionModel.findById('700000000000000000000001').lean().exec((err, data) => { if (err) return done(err); should(data).have.property('status', 10); done(); }); }); }); it('keeps only one unchanged parameter', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000001', auth: {basic: 'janedoe'}, httpStatus: 200, req: {parameters: {material: 'copper'}} }).end((err, res) => { if (err) return done(err); should(res.body).be.eql({_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'B1', treatment_template: '200000000000000000000001', parameters: {material: 'copper', weeks: 3}}); ConditionModel.findById('700000000000000000000001').lean().exec((err, data) => { if (err) return done(err); should(data).have.property('status', 10); done(); }); }); }); it('changes the given properties', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000001', auth: {basic: 'janedoe'}, httpStatus: 200, req: {parameters: {material: 'hot air', weeks: 10}} }).end((err, res) => { if (err) return done(err); should(res.body).be.eql({_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'B1', treatment_template: '200000000000000000000001', parameters: {material: 'hot air', weeks: 10}}); ConditionModel.findById('700000000000000000000001').lean().exec((err, data: any) => { if (err) return done(err); should(data).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template', 'status', '__v'); should(data.sample_id.toString()).be.eql('400000000000000000000001'); should(data).have.property('number', 'B1'); should(data.treatment_template.toString()).be.eql('200000000000000000000001'); should(data).have.property('status', 0); should(data).have.property('parameters'); should(data.parameters).have.property('material', 'hot air'); should(data.parameters).have.property('weeks', 10); done(); }); }); }); it('allows changing only one parameter', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000001', auth: {basic: 'janedoe'}, httpStatus: 200, req: {parameters: {weeks: 8}}, res: {_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'B1', treatment_template: '200000000000000000000001', parameters: {material: 'copper', weeks: 8}} }); }); it('rejects not specified parameters', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000001', auth: {basic: 'janedoe'}, httpStatus: 400, req: {parameters: {xx: 13}}, res: {status: 'Invalid body format', details: '"xx" is not allowed'} }); }); it('rejects a parameter not in the value range', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000001', auth: {basic: 'janedoe'}, httpStatus: 400, req: {parameters: {material: 'xxx'}}, res: {status: 'Invalid body format', details: '"material" must be one of [copper, hot air]'} }); }); it('rejects a parameter below minimum range', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000001', auth: {basic: 'janedoe'}, httpStatus: 400, req: {parameters: {weeks: -10}}, res: {status: 'Invalid body format', details: '"weeks" must be larger than or equal to 1'} }); }); it('rejects a parameter above maximum range', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000001', auth: {basic: 'janedoe'}, httpStatus: 400, req: {parameters: {weeks: 11}}, res: {status: 'Invalid body format', details: '"weeks" must be less than or equal to 10'} }); }); it('rejects a new treatment_template', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000001', auth: {basic: 'janedoe'}, httpStatus: 400, req: {treatment_template: '200000000000000000000002'}, res: {status: 'Invalid body format', details: '"treatment_template" is not allowed'} }); }); it('rejects editing a condition for a write user who did not create this condition', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000003', auth: {basic: 'janedoe'}, httpStatus: 403, req: {parameters: {weeks: 8}} }); }); it('accepts editing a condition of another user for a maintain/admin user', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000001', auth: {basic: 'admin'}, httpStatus: 200, req: {parameters: {material: 'hot air', weeks: 10}}, res: {_id: '700000000000000000000001', sample_id: '400000000000000000000001', number: 'B1', treatment_template: '200000000000000000000001', parameters: {material: 'hot air', weeks: 10}} }); }); it('rejects an API key', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000001', auth: {key: 'janedoe'}, httpStatus: 401, req: {parameters: {material: 'hot air', weeks: 10}} }); }); it('rejects requests from a read user', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000001', auth: {basic: 'user'}, httpStatus: 403, req: {parameters: {material: 'hot air', weeks: 10}} }); }); it('rejects unauthorized requests', done => { TestHelper.request(server, done, { method: 'put', url: '/condition/700000000000000000000001', httpStatus: 401, req: {parameters: {material: 'hot air', weeks: 10}} }); }); }); // TODO: how to deal with template changes? Template versioning? // TODO: rewrite delete methods -> set status for every database collection describe('DELETE /condition/{id}', () => { it('sets the status to deleted', done => { TestHelper.request(server, done, { method: 'delete', url: '/condition/700000000000000000000002', auth: {basic: 'janedoe'}, httpStatus: 200 }).end((err, res) => { if (err) return done(err); should(res.body).be.eql({status: 'OK'}); ConditionModel.findById('700000000000000000000002').lean().exec((err, data: any) => { if (err) return done(err); should(data).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template', 'status', '__v'); should(data.sample_id.toString()).be.eql('400000000000000000000002'); should(data).have.property('number', 'B1'); should(data.treatment_template.toString()).be.eql('200000000000000000000001'); should(data).have.property('status', -1); should(data).have.property('parameters'); should(data.parameters).have.property('material', 'copper'); should(data.parameters).have.property('weeks', 3); done(); }); }); }); it('rejects a deleting a condition referenced by measurements'); // TODO it('rejects an invalid id', done => { TestHelper.request(server, done, { method: 'delete', url: '/condition/70000000000w000000000002', auth: {basic: 'janedoe'}, httpStatus: 404 }); }); it('rejects an API key', done => { TestHelper.request(server, done, { method: 'delete', url: '/condition/700000000000000000000002', auth: {key: 'janedoe'}, httpStatus: 401 }); }); it('rejects requests from a read user', done => { TestHelper.request(server, done, { method: 'delete', url: '/condition/700000000000000000000002', auth: {basic: 'user'}, httpStatus: 403 }); }); it('rejects a write user deleting a condition belonging to a sample of another user', done => { TestHelper.request(server, done, { method: 'delete', url: '/condition/700000000000000000000003', auth: {basic: 'janedoe'}, httpStatus: 403 }); }); it('accepts an maintain/admin user deleting a condition belonging to a sample of another user', done => { TestHelper.request(server, done, { method: 'delete', url: '/condition/700000000000000000000002', auth: {basic: 'admin'}, httpStatus: 200 }).end((err, res) => { if (err) return done(err); should(res.body).be.eql({status: 'OK'}); done(); }); }); it('returns 404 for an unknown id', done => { TestHelper.request(server, done, { method: 'delete', url: '/condition/00000000000w000000000002', auth: {basic: 'janedoe'}, httpStatus: 404 }); }); it('rejects unauthorized requests', done => { TestHelper.request(server, done, { method: 'delete', url: '/condition/700000000000000000000002', httpStatus: 401 }); }); }); describe('POST /condition/new', () => { // TODO: sample number generation it('returns the right condition', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 200, req: {sample_id: '400000000000000000000002', number: 'B2', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'} }).end((err, res) => { if (err) return done(err); should(res.body).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template'); should(res.body).have.property('_id').be.type('string'); should(res.body).have.property('sample_id', '400000000000000000000002'); should(res.body).have.property('number', 'B2'); should(res.body).have.property('treatment_template', '200000000000000000000001'); should(res.body).have.property('parameters'); should(res.body.parameters).have.property('material', 'hot air'); should(res.body.parameters).have.property('weeks', 10); done(); }); }); it('stores the condition', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 200, req: {sample_id: '400000000000000000000002', number: 'B2', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'} }).end((err, res) => { if (err) return done(err); ConditionModel.findById(res.body._id).lean().exec((err, data: any) => { if (err) return done(err); should(data).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template', 'status', '__v'); should(data.sample_id.toString()).be.eql('400000000000000000000002'); should(data).have.property('number', 'B2'); should(data.treatment_template.toString()).be.eql('200000000000000000000001'); should(data).have.property('status', 0); should(data).have.property('parameters'); should(data.parameters).have.property('material', 'hot air'); should(data.parameters).have.property('weeks', 10); done(); }); }); }); it('rejects an invalid sample id', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 400, req: {sample_id: '4000000000h0000000000002', number: 'B2', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'}, res: {status: 'Invalid body format', details: '"sample_id" with value "4000000000h0000000000002" fails to match the required pattern: /[0-9a-f]{24}/'} }); }); it('rejects a sample id not available', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 400, req: {sample_id: '000000000000000000000002', number: 'B2', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'}, res: {status: 'Sample id not available'} }); }); it('rejects an invalid treatment_template id', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 400, req: {sample_id: '400000000000000000000002', number: 'B2', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000h00000000001'}, res: {status: 'Invalid body format', details: '"treatment_template" with value "200000000000h00000000001" fails to match the required pattern: /[0-9a-f]{24}/'} }); }); it('rejects a treatment_template which does not exist', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 400, req: {sample_id: '400000000000000000000002', number: 'B2', parameters: {material: 'hot air', weeks: 10}, treatment_template: '000000000000000000000001'}, res: {status: 'Treatment template not available'} }); }); it('rejects a condition number already in use for this sample', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 400, req: {sample_id: '400000000000000000000001', number: 'B1', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'}, res: {status: 'Condition number already taken'} }); }); it('rejects not specified parameters', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 400, req: {sample_id: '400000000000000000000002', number: 'B2', parameters: {material: 'hot air', weeks: 10, xx: 12}, treatment_template: '200000000000000000000001'}, res: {status: 'Invalid body format', details: '"xx" is not allowed'} }); }); it('rejects missing parameters', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 400, req: {sample_id: '400000000000000000000002', number: 'B2', parameters: {material: 'hot air'}, treatment_template: '200000000000000000000001'}, res: {status: 'Invalid body format', details: '"weeks" is required'} }); }); it('rejects a parameter not in the value range', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 400, req: {sample_id: '400000000000000000000002', number: 'B2', parameters: {material: 'xxx', weeks: 10}, treatment_template: '200000000000000000000001'}, res: {status: 'Invalid body format', details: '"material" must be one of [copper, hot air]'} }); }); it('rejects a parameter below minimum range', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 400, req: {sample_id: '400000000000000000000002', number: 'B2', parameters: {material: 'hot air', weeks: -10}, treatment_template: '200000000000000000000001'}, res: {status: 'Invalid body format', details: '"weeks" must be larger than or equal to 1'} }); }); it('rejects a parameter above maximum range', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 400, req: {sample_id: '400000000000000000000002', number: 'B2', parameters: {material: 'hot air', weeks: 11}, treatment_template: '200000000000000000000001'}, res: {status: 'Invalid body format', details: '"weeks" must be less than or equal to 10'} }); }); it('rejects a missing sample id', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 400, req: {number: 'B2', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'}, res: {status: 'Invalid body format', details: '"sample_id" is required'} }); }); it('rejects a missing treatment_template', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 400, req: {sample_id: '400000000000000000000002', number: 'B2', parameters: {material: 'hot air', weeks: 10}}, res: {status: 'Invalid body format', details: '"treatment_template" is required'} }); }); it('rejects a missing number', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 400, req: {sample_id: '400000000000000000000002', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'}, res: {status: 'Invalid body format', details: '"number" is required'} }); }); it('rejects adding a condition to the sample of an other user for a write user', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'janedoe'}, httpStatus: 403, req: {sample_id: '400000000000000000000003', number: 'B2', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'} }); }); it('accepts adding a condition to the sample of an other user for a maintain/admin user', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'admin'}, httpStatus: 200, req: {sample_id: '400000000000000000000002', number: 'B2', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'} }).end((err, res) => { if (err) return done(err); should(res.body).have.only.keys('_id', 'sample_id', 'number', 'parameters', 'treatment_template'); should(res.body).have.property('_id').be.type('string'); should(res.body).have.property('sample_id', '400000000000000000000002'); should(res.body).have.property('number', 'B2'); should(res.body).have.property('treatment_template', '200000000000000000000001'); should(res.body).have.property('parameters'); should(res.body.parameters).have.property('material', 'hot air'); should(res.body.parameters).have.property('weeks', 10); done(); }); }); it('rejects an API key', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {key: 'janedoe'}, httpStatus: 401, req: {sample_id: '400000000000000000000002', number: 'B2', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'} }); }); it('rejects requests from a read user', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', auth: {basic: 'user'}, httpStatus: 403, req: {sample_id: '400000000000000000000002', number: 'B2', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'} }); }); it('rejects unauthorized requests', done => { TestHelper.request(server, done, { method: 'post', url: '/condition/new', httpStatus: 401, req: {sample_id: '400000000000000000000002', number: 'B2', parameters: {material: 'hot air', weeks: 10}, treatment_template: '200000000000000000000001'} }); }); }); });