So I've been working on this project of mine for some time now, but I can never really figure out how to get my testing to work. I've tried testing my API in a variety of different ways, however each time I changed things it just seemed to just make more problems. At this point I am stumped, I need some fresh eyes to check it out.
FYI the API actually works fine, I can call all of my routes and get the proper results with no issue, I've been using httpie to sort of "test" things without actually writing any tests.
So anyways, here is some of the code I've been running:
const chai = require('chai');
const expect = chai.expect;
const superagent = require('superagent');
const User = require('../model/User.js');
const url = process.env.API_URL;
const testUser = {
email: 'exampleuser@test.com',
password: '123'
};
const newUser = {
email: 'newuser@test.com',
password: '321'
};
describe('POST: /api/signup', () => {
describe('with valid credentials', () => {
afterEach(() => User.deleteOne({'email': testUser.email}));
console.log(`${url}/api/signup`);
it('should return a status code of 200', () => {
superagent.post(`${url}/api/signup`)
.send(testUser)
.then((res) => {
expect(res).to.be.an('object');
expect(res.status).to.equal(200);
})
.catch((err) => console.error(err));
});
});
});
I've tried using done as well, it looked something like this:
describe('POST: /api/signup', () => {
describe('with valid credentials', () => {
afterEach((done) => {
User.deleteOne({'email': testUser.email})
.then(() => done())
.catch((err) => done(err));
});
console.log(`${url}/api/signup`);
it('should return a status code of 200', (done) => {
superagent.post(`${url}/api/signup`)
.send(testUser)
.end((res, err) => {
if(err) return done(err);
expect(res).to.be.an('object');
expect(res.status).to.equal(200);
})
.then(() => done())
.catch((err) => console.error(err));
});
});
});
but every time I run it, you can see it finishes the test and moves on to the next case before everything is called and returned:
Backend-Portfolio:server.js running on port: 8000 +0ms
USER_ROUTES
POST: /api/signup
with valid credentials
1) should return a status code of 200
Backend-Portfolio:user-router.js POST: /api/signup +0ms
2) "after each" hook for "should return a status code of 200"
GET: /api/login
with valid credentials
Backend-Portfolio:user-router.js POST: /api/signup +2s
Backend-Portfolio:user-router.js setting up new user +50ms
Backend-Portfolio:User.js generatePasswordHash:normal +0ms
Backend-Portfolio:User.js generateToken +158ms
Backend-Portfolio:User.js generateFindHash +1ms
Backend-Portfolio:user-router.js setting up new user +462ms
Backend-Portfolio:User.js generatePasswordHash:normal +295ms
Backend-Portfolio:User.js generateToken +101ms
Backend-Portfolio:User.js generateFindHash +0ms
Here is the route and the methods that are called if anyone is curious:
You can see here where the method chain is called, I turned this route into a promise just to try a different way of testing.
userRouter.post('/api/signup', jsonParser, (req, res) => {
debug('POST: /api/signup');
let password = req.body.password;
delete req.body.password;
return new Promise((resolve, reject) => {
User.findOne({'email': req.body.email})
.then((user) => {
if(user){
if(user.authenticated){
// NOTE: maybe update all error codes and texts to be very specific
reject(createError(400, 'this email is already used, please log in with your password'));
}else{
user.generatePasswordHash('normal', password)
.then((user) => user.generateToken())
.then((token) => resolve(res.json(token)))
.catch((err) => reject(console.error(err)));
}
}
else{
debug('setting up new user');
let user = new User({
googlePermissions: {authenticated: false, password: null},
facebookPermissions: {authenticated: false, password: null},
twitterPermissions: {authenticated: false, password: null},
authenticated: true,
email: req.body.email
});
user.generatePasswordHash('normal', password)
.then((user) => user.generateToken())
.then((token) => resolve(res.json(token)))
.catch((err) => reject(console.error(err)));
}
})
.catch((err) => reject(console.error(err)));
});
});
The rest of this is probably a bit unnecessary, but here ya go:
generatePasswordHash:
userSchema.methods.generatePasswordHash = function(type, password){
debug(`generatePasswordHash:${type}`);
return new Promise((resolve, reject) => {
if(!password) reject(createError(400, 'no password was provided'));
bcrypt.hash(password, 10, (err, hash) => {
if(err) return reject(err);
switch(type){
case 'normal':
this.password = hash;
resolve(this);
break;
case 'googlePermissions':
this.googlePermissions.password = hash;
resolve(this);
break;
case 'facebookPermissions':
this.facebookPermissions.password = hash;
resolve(this);
break;
case 'twitterPermissions':
this.twitterPermissions.password = hash;
resolve(this);
break;
default:
return reject(createError(400, `unrecognized password type: ${type}`));
}
});
});
};
generateToken:
userSchema.methods.generateToken = function(){
debug('generateToken');
return new Promise((resolve, reject) => {
this.generateFindHash()
.then((findHash) => resolve(jsonwebtoken.sign({token: findHash}, process.env.APP_SECRET)))
.catch((err) => reject(err));
});
};
generateFindHash:
userSchema.methods.generateFindHash = function(){
debug('generateFindHash');
return new Promise((resolve, reject) => {
this.findHash = crypto.randomBytes(32).toString('hex');
this.save()
.then(() => resolve(this.findHash))
.catch((err) => reject(err));
});
};
Thanks to anyone who's made it this far.
Aucun commentaire:
Enregistrer un commentaire