import supertest from 'supertest'; import should from 'should/as-function'; import db from '../db'; import UserModel from '../models/user'; describe('GET /users', () => { let server; before(done => { process.env.port = '2999'; process.env.NODE_ENV = 'test'; db.connect('test', done); }); beforeEach(done => { delete require.cache[require.resolve('../index')]; // prevent loading from cache server = require('../index'); db.drop(err => { // reset database if (err) return done(err); db.loadJson(require('../test/db.json'), done); }); }); afterEach(done => { server.close(done); }); it('returns all users', done => { supertest(server) .get('/users') .auth('admin', 'Abc123!#') .expect('Content-type', /json/) .expect(200) .end((err, res) => { if (err) done (err); const json = require('../test/db.json'); should(res.body).have.lengthOf(json.collections.users.length); should(res.body).matchEach(user => { should(user).have.only.keys('_id', 'email', 'name', 'level', 'location', 'device_name'); should(user).have.property('_id').be.type('string'); should(user).have.property('email').be.type('string'); should(user).have.property('name').be.type('string'); should(user).have.property('level').be.type('string'); should(user).have.property('location').be.type('string'); should(user).have.property('device_name').be.type('string'); }); done(); }); }); it('rejects requests from non-admins', done => { supertest(server) .get('/users') .auth('janedoe', 'Xyz890*)') .expect('Content-type', /json/) .expect(403) .end((err, res) => { if (err) done (err); should(res.body).be.eql({status: 'Forbidden'}); done(); }); }); it('rejects requests from an admin API key', done => { supertest(server) .get('/users?key=5ea131671feb9c2ee0aafc9a') .expect('Content-type', /json/) .expect(401) .end((err, res) => { if (err) done (err); should(res.body).be.eql({status: 'Unauthorized'}); done(); }); }); }); describe('GET /user/{name}', () => { let server; before(done => { process.env.port = '2999'; process.env.NODE_ENV = 'test'; db.connect('test', done); }); beforeEach(done => { delete require.cache[require.resolve('../index')]; // prevent loading from cache server = require('../index'); db.drop(err => { // reset database if (err) return done(err); db.loadJson(require('../test/db.json'), done); }); }); afterEach(done => { server.close(done); }); it('returns own user details', done => { supertest(server) .get('/user') .auth('janedoe', 'Xyz890*)') .expect('Content-type', /json/) .expect(200) .end((err, res) => { if (err) done (err); should(res.body).have.only.keys('_id', 'email', 'name', 'level', 'location', 'device_name'); should(res.body).have.property('_id').be.type('string'); should(res.body).have.property('email', 'jane.doe@bosch.com'); should(res.body).have.property('name', 'janedoe'); should(res.body).have.property('level', 'write'); should(res.body).have.property('location', 'Rng'); should(res.body).have.property('device_name', 'Alpha I'); done(); }); }); it('returns other user details for admin', done => { supertest(server) .get('/user/janedoe') .auth('admin', 'Abc123!#') .expect('Content-type', /json/) .expect(200) .end((err, res) => { if (err) done (err); should(res.body).have.only.keys('_id', 'email', 'name', 'level', 'location', 'device_name'); should(res.body).have.property('_id').be.type('string'); should(res.body).have.property('email', 'jane.doe@bosch.com'); should(res.body).have.property('name', 'janedoe'); should(res.body).have.property('level', 'write'); should(res.body).have.property('location', 'Rng'); should(res.body).have.property('device_name', 'Alpha I'); done(); }); }); it('rejects requests from non-admins for another user', done => { supertest(server) .get('/user/admin') .auth('janedoe', 'Xyz890*)') .expect('Content-type', /json/) .expect(403) .end((err, res) => { if (err) done (err); should(res.body).be.eql({status: 'Forbidden'}); done(); }); }); it('rejects requests from a user API key', done => { supertest(server) .get('/user?key=5ea0450ed851c30a90e70899') .expect('Content-type', /json/) .expect(401) .end((err, res) => { if (err) done (err); should(res.body).be.eql({status: 'Unauthorized'}); done(); }); }); it('rejects requests from an admin API key', done => { supertest(server) .get('/user/janedoe?key=5ea131671feb9c2ee0aafc9a') .expect('Content-type', /json/) .expect(401) .end((err, res) => { if (err) done (err); should(res.body).be.eql({status: 'Unauthorized'}); done(); }); }); }); describe('PUT /user/{name}', () => { let server; before(done => { process.env.port = '2999'; process.env.NODE_ENV = 'test'; db.connect('test', done); }); beforeEach(done => { delete require.cache[require.resolve('../index')]; // prevent loading from cache server = require('../index'); db.drop(err => { // reset database if (err) return done(err); db.loadJson(require('../test/db.json'), done); }); }); afterEach(done => { server.close(done); }); it('returns own user details', done => { supertest(server) .get('/user') .auth('janedoe', 'Xyz890*)') .expect('Content-type', /json/) .expect(200) .end((err, res) => { if (err) done (err); should(res.body).have.only.keys('_id', 'email', 'name', 'level', 'location', 'device_name'); should(res.body).have.property('_id').be.type('string'); should(res.body).have.property('email', 'jane.doe@bosch.com'); should(res.body).have.property('name', 'janedoe'); should(res.body).have.property('level', 'write'); should(res.body).have.property('location', 'Rng'); should(res.body).have.property('device_name', 'Alpha I'); done(); }); }); it('returns other user details for admin', done => { supertest(server) .get('/user/janedoe') .auth('admin', 'Abc123!#') .expect('Content-type', /json/) .expect(200) .end((err, res) => { if (err) done (err); should(res.body).have.only.keys('_id', 'email', 'name', 'level', 'location', 'device_name'); should(res.body).have.property('_id').be.type('string'); should(res.body).have.property('email', 'jane.doe@bosch.com'); should(res.body).have.property('name', 'janedoe'); should(res.body).have.property('level', 'write'); should(res.body).have.property('location', 'Rng'); should(res.body).have.property('device_name', 'Alpha I'); done(); }); }); it('rejects requests from non-admins for another user', done => { supertest(server) .get('/user/admin') .auth('janedoe', 'Xyz890*)') .expect('Content-type', /json/) .expect(403) .end((err, res) => { if (err) done (err); should(res.body).be.eql({status: 'Forbidden'}); done(); }); }); it('rejects requests from a user API key', done => { supertest(server) .get('/user?key=5ea0450ed851c30a90e70899') .expect('Content-type', /json/) .expect(401) .end((err, res) => { if (err) done (err); should(res.body).be.eql({status: 'Unauthorized'}); done(); }); }); it('rejects requests from an admin API key', done => { supertest(server) .get('/user/janedoe?key=5ea131671feb9c2ee0aafc9a') .expect('Content-type', /json/) .expect(401) .end((err, res) => { if (err) done (err); should(res.body).be.eql({status: 'Unauthorized'}); done(); }); }); }); describe('POST /user/new', () => { let server; before(done => { process.env.port = '2999'; process.env.NODE_ENV = 'test'; db.connect('test', done); }); beforeEach(done => { delete require.cache[require.resolve('../index')]; // prevent loading from cache server = require('../index'); db.drop(err => { // reset database if (err) return done(err); db.loadJson(require('../test/db.json'), done); }); }); afterEach(done => { server.close(done); }); it('returns the added user data', done => { supertest(server) .post('/user/new') .auth('admin', 'Abc123!#') .send({email: 'john.doe@bosch.com', name: 'johndoe', pass: 'Abc123!#', level: 'read', location: 'Rng', device_name: 'Alpha II'}) .expect('Content-type', /json/) .expect(200) .end((err, res) => { if (err) done (err); should(res.body).have.only.keys('_id', 'email', 'name', 'level', 'location', 'device_name'); should(res.body).have.property('_id').be.type('string'); should(res.body).have.property('email', 'john.doe@bosch.com'); should(res.body).have.property('name', 'johndoe'); should(res.body).have.property('level', 'read'); should(res.body).have.property('location', 'Rng'); should(res.body).have.property('device_name', 'Alpha II'); done(); }); }); it('stores the data', done => { supertest(server) .post('/user/new') .auth('admin', 'Abc123!#') .send({email: 'john.doe@bosch.com', name: 'johndoe', pass: 'Abc123!#', level: 'read', location: 'Rng', device_name: 'Alpha II'}) .expect(200) .end(err => { if (err) done (err); UserModel.find({name: 'johndoe'}).lean().exec( 'find', (err, data) => { if (err) return done(err); should(data).have.lengthOf(1); should(data[0]).have.only.keys('_id', 'name', 'pass', 'email', 'level', 'location', 'device_name', 'key', '__v'); should(data[0]).have.property('_id'); should(data[0]).have.property('name', 'johndoe'); should(data[0]).have.property('email', 'john.doe@bosch.com'); should(data[0]).have.property('pass').not.eql('Abc123!#'); should(data[0]).have.property('level', 'read'); should(data[0]).have.property('location', 'Rng'); should(data[0]).have.property('device_name', 'Alpha II'); done(); }); }); }); it('rejects a username already in use', done => { supertest(server) .post('/user/new') .auth('admin', 'Abc123!#') .send({email: 'j.doe@bosch.com', name: 'janedoe', pass: 'Abc123!#', level: 'read', location: 'Rng', device_name: 'Alpha II'}) .expect(400) .end((err, res) => { if (err) done (err); should(res.body).be.eql({status: 'Username already taken'}); UserModel.find({name: 'janedoe'}).lean().exec( 'find', (err, data) => { if (err) return done(err); should(data).have.lengthOf(1); done(); }); }); }); it('rejects requests from non-admins', done => { supertest(server) .post('/user/new') .auth('janedoe', 'Xyz890*)') .send({email: 'john.doe@bosch.com', name: 'johndoe', pass: 'Abc123!#', level: 'read', location: 'Rng', device_name: 'Alpha II'}) .expect('Content-type', /json/) .expect(403) .end((err, res) => { if (err) done (err); should(res.body).be.eql({status: 'Forbidden'}); done(); }); }); it('rejects requests from an admin API key', done => { supertest(server) .post('/user/new?key=5ea131671feb9c2ee0aafc9a') .send({email: 'john.doe@bosch.com', name: 'johndoe', pass: 'Abc123!#', level: 'read', location: 'Rng', device_name: 'Alpha II'}) .expect('Content-type', /json/) .expect(401) .end((err, res) => { if (err) done (err); should(res.body).be.eql({status: 'Unauthorized'}); done(); }); }); }); describe('POST /user/passreset', () => { let server; before(done => { process.env.port = '2999'; process.env.NODE_ENV = 'test'; db.connect('test', done); }); beforeEach(done => { delete require.cache[require.resolve('../index')]; // prevent loading from cache server = require('../index'); db.drop(err => { // reset database if (err) return done(err); db.loadJson(require('../test/db.json'), done); }); }); afterEach(done => { server.close(done); }); it('returns the ok response', done => { supertest(server) .post('/user/passreset') .send({ email: 'jane.doe@bosch.com', name: 'janedoe' }) .expect('Content-type', /json/) .expect(200) .end((err, res) => { if (err) done(err); should(res.body).be.eql({status: 'OK'}); done(); }); }); it('returns 404 for wrong username/email combo', done => { supertest(server) .post('/user/passreset') .send({ email: 'jane.doe@bosch.com', name: 'admin' }) .expect('Content-type', /json/) .expect(404) .end((err, res) => { if (err) done(err); should(res.body).be.eql({status: 'Not found'}); done(); }); }); it('returns 404 for unknown username', done => { supertest(server) .post('/user/passreset') .send({ email: 'jane.doe@bosch.com', name: 'admin' }) .expect('Content-type', /json/) .expect(404) .end((err, res) => { if (err) done(err); should(res.body).be.eql({status: 'Not found'}); done(); }); }); it('changes the user password', done => { UserModel.find({name: 'janedoe'}).lean().exec( 'find', (err, data: any) => { if (err) return done(err); const oldpass = data[0].pass; supertest(server) .post('/user/passreset') .send({ email: 'jane.doe@bosch.com', name: 'janedoe' }) .expect('Content-type', /json/) .expect(200) .end((err, res) => { if (err) done(err); should(res.body).be.eql({status: 'OK'}); UserModel.find({name: 'janedoe'}).lean().exec( (err, data: any) => { if (err) return done(err); should(data[0].pass).not.eql(oldpass); done(); }); }); }); }); });