Skip to content

Commit c940783

Browse files
committed
Add tests for auth endpoints.
1 parent e0a6bce commit c940783

File tree

3 files changed

+245
-21
lines changed

3 files changed

+245
-21
lines changed

package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"description": "",
55
"main": "index.js",
66
"scripts": {
7-
"start": "node server.js"
7+
"start": "node server.js",
8+
"test": "mocha"
89
},
910
"keywords": [],
1011
"author": "",
@@ -22,9 +23,9 @@
2223
"passport-jwt": "^2.2.1"
2324
},
2425
"devDependencies": {
25-
"chai": "^3.5.0",
26+
"chai": "^4.0.1",
2627
"chai-http": "^3.0.0",
2728
"faker": "^3.1.0",
28-
"mocha": "^3.2.0"
29+
"mocha": "^3.4.2"
2930
}
3031
}

test/test-auth.js

+208
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
global.DATABASE_URL = 'mongodb://localhost/jwt-auth-demo-test';
2+
const chai = require('chai');
3+
const chaiHttp = require('chai-http');
4+
const jwt = require('jsonwebtoken');
5+
6+
const {app, runServer, closeServer} = require('../server');
7+
const {User} = require('../users');
8+
const {JWT_SECRET} = require('../config');
9+
10+
const expect = chai.expect;
11+
12+
13+
// This let's us make HTTP requests
14+
// in our tests.
15+
// see: https://github.com/chaijs/chai-http
16+
chai.use(chaiHttp);
17+
18+
19+
describe('Auth endpoints', function() {
20+
const username = 'exampleUser';
21+
const password = 'examplePass';
22+
const firstName = 'Example';
23+
const lastName = 'User';
24+
25+
before(function() {
26+
return runServer();
27+
});
28+
29+
after(function() {
30+
return closeServer();
31+
});
32+
33+
beforeEach(function() {
34+
return User.hashPassword(password).then(password =>
35+
User.create({
36+
username,
37+
password,
38+
firstName,
39+
lastName
40+
})
41+
);
42+
});
43+
44+
afterEach(function() {
45+
return User.remove({});
46+
});
47+
48+
describe('/api/auth/login', function() {
49+
it('Should reject requests with no credentials', function() {
50+
return chai.request(app)
51+
.post('/api/auth/login')
52+
.then(() => expect.fail(null, null, 'Request should not succeed'))
53+
.catch(err => {
54+
if (err instanceof chai.AssertionError) {
55+
throw err;
56+
}
57+
58+
const res = err.response;
59+
expect(res).to.have.status(401);
60+
});
61+
});
62+
it('Should reject requests with incorrect usernames', function() {
63+
return chai.request(app)
64+
.post('/api/auth/login')
65+
.auth('wrongUsername', password)
66+
.then(() => expect.fail(null, null, 'Request should not succeed'))
67+
.catch(err => {
68+
if (err instanceof chai.AssertionError) {
69+
throw err;
70+
}
71+
72+
const res = err.response;
73+
expect(res).to.have.status(401);
74+
});
75+
});
76+
it('Should reject requests with incorrect passwords', function() {
77+
return chai.request(app)
78+
.post('/api/auth/login')
79+
.auth(username, 'wrongPassword')
80+
.then(() => expect.fail(null, null, 'Request should not succeed'))
81+
.catch(err => {
82+
if (err instanceof chai.AssertionError) {
83+
throw err;
84+
}
85+
86+
const res = err.response;
87+
expect(res).to.have.status(401);
88+
});
89+
});
90+
it('Should return a valid auth token', function() {
91+
return chai.request(app)
92+
.post('/api/auth/login')
93+
.auth(username, password)
94+
.then(res => {
95+
expect(res).to.have.status(200);
96+
expect(res.body).to.be.an('object');
97+
const token = res.body.authToken;
98+
expect(token).to.be.a('string');
99+
const payload = jwt.verify(token, JWT_SECRET, {
100+
algorithm: ["HS256"]
101+
});
102+
expect(payload.user).to.deep.equal({
103+
username,
104+
firstName,
105+
lastName
106+
});
107+
})
108+
});
109+
});
110+
111+
describe('/api/auth/refresh', function() {
112+
it('Should reject requests with no credentials', function() {
113+
return chai.request(app)
114+
.post('/api/auth/refresh')
115+
.then(() => expect.fail(null, null, 'Request should not succeed'))
116+
.catch(err => {
117+
if (err instanceof chai.AssertionError) {
118+
throw err;
119+
}
120+
121+
const res = err.response;
122+
expect(res).to.have.status(401);
123+
});
124+
});
125+
it('Should reject requests with an invalid token', function() {
126+
const token = jwt.sign({
127+
username,
128+
firstName,
129+
lastName
130+
}, 'wrongSecret', {
131+
algorithm: 'HS256',
132+
expiresIn: '7d'
133+
});
134+
135+
return chai.request(app)
136+
.post('/api/auth/refresh')
137+
.set('Authorization', `Bearer ${token}`)
138+
.then(() => expect.fail(null, null, 'Request should not succeed'))
139+
.catch(err => {
140+
if (err instanceof chai.AssertionError) {
141+
throw err;
142+
}
143+
144+
const res = err.response;
145+
expect(res).to.have.status(401);
146+
});
147+
});
148+
it('Should reject requests with an expired token', function() {
149+
const token = jwt.sign({
150+
user: {
151+
username,
152+
firstName,
153+
lastName
154+
},
155+
exp: Math.floor(Date.now() / 1000) - 10 // Expired ten seconds ago
156+
}, JWT_SECRET, {
157+
algorithm: 'HS256',
158+
subject: username
159+
});
160+
161+
return chai.request(app)
162+
.post('/api/auth/refresh')
163+
.set('authorization', `Bearer ${token}`)
164+
.then(() => expect.fail(null, null, 'Request should not succeed'))
165+
.catch(err => {
166+
if (err instanceof chai.AssertionError) {
167+
throw err;
168+
}
169+
170+
const res = err.response;
171+
expect(res).to.have.status(401);
172+
});
173+
});
174+
it('Should return a valid auth token with a newer expiry date', function() {
175+
const token = jwt.sign({
176+
user: {
177+
username,
178+
firstName,
179+
lastName
180+
},
181+
}, JWT_SECRET, {
182+
algorithm: 'HS256',
183+
subject: username,
184+
expiresIn: '7d'
185+
});
186+
const decoded = jwt.decode(token);
187+
188+
return chai.request(app)
189+
.post('/api/auth/refresh')
190+
.set('authorization', `Bearer ${token}`)
191+
.then(res => {
192+
expect(res).to.have.status(200);
193+
expect(res.body).to.be.an('object');
194+
const token = res.body.authToken;
195+
expect(token).to.be.a('string');
196+
const payload = jwt.verify(token, JWT_SECRET, {
197+
algorithm: ["HS256"]
198+
});
199+
expect(payload.user).to.deep.equal({
200+
username,
201+
firstName,
202+
lastName
203+
});
204+
expect(payload.exp).to.be.at.least(decoded.exp);
205+
});
206+
});
207+
});
208+
});

yarn.lock

+33-18
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,20 @@ chai-http@^3.0.0:
9999
qs "^6.2.0"
100100
superagent "^2.0.0"
101101

102-
chai@^3.5.0:
103-
version "3.5.0"
104-
resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247"
102+
chai@^4.0.1:
103+
version "4.0.1"
104+
resolved "https://registry.yarnpkg.com/chai/-/chai-4.0.1.tgz#9e41e808e17a7f10807721e2ac5a589d5bb09082"
105105
dependencies:
106106
assertion-error "^1.0.1"
107-
deep-eql "^0.1.3"
108-
type-detect "^1.0.0"
107+
check-error "^1.0.1"
108+
deep-eql "^2.0.1"
109+
get-func-name "^2.0.0"
110+
pathval "^1.0.0"
111+
type-detect "^4.0.0"
112+
113+
check-error@^1.0.1:
114+
version "1.0.2"
115+
resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82"
109116

110117
combined-stream@^1.0.5:
111118
version "1.0.5"
@@ -175,11 +182,11 @@ debug@2.6.4, debug@^2.2.0:
175182
dependencies:
176183
ms "0.7.3"
177184

178-
deep-eql@^0.1.3:
179-
version "0.1.3"
180-
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2"
185+
deep-eql@^2.0.1:
186+
version "2.0.2"
187+
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-2.0.2.tgz#b1bac06e56f0a76777686d50c9feb75c2ed7679a"
181188
dependencies:
182-
type-detect "0.1.1"
189+
type-detect "^3.0.0"
183190

184191
delayed-stream@~1.0.0:
185192
version "1.0.0"
@@ -309,6 +316,10 @@ fs.realpath@^1.0.0:
309316
version "1.0.0"
310317
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
311318

319+
get-func-name@^2.0.0:
320+
version "2.0.0"
321+
resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41"
322+
312323
glob@7.1.1:
313324
version "7.1.1"
314325
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
@@ -527,9 +538,9 @@ mkdirp@0.5.1:
527538
dependencies:
528539
minimist "0.0.8"
529540

530-
mocha@^3.2.0:
531-
version "3.3.0"
532-
resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.3.0.tgz#d29b7428d3f52c82e2e65df1ecb7064e1aabbfb5"
541+
mocha@^3.4.2:
542+
version "3.4.2"
543+
resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.4.2.tgz#d0ef4d332126dbf18d0d640c9b382dd48be97594"
533544
dependencies:
534545
browser-stdout "1.3.0"
535546
commander "2.9.0"
@@ -682,6 +693,10 @@ path-to-regexp@0.1.7:
682693
version "0.1.7"
683694
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
684695

696+
pathval@^1.0.0:
697+
version "1.1.0"
698+
resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0"
699+
685700
pause@0.0.1:
686701
version "0.0.1"
687702
resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d"
@@ -824,13 +839,13 @@ topo@1.x.x:
824839
dependencies:
825840
hoek "2.x.x"
826841

827-
type-detect@0.1.1:
828-
version "0.1.1"
829-
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822"
842+
type-detect@^3.0.0:
843+
version "3.0.0"
844+
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-3.0.0.tgz#46d0cc8553abb7b13a352b0d6dea2fd58f2d9b55"
830845

831-
type-detect@^1.0.0:
832-
version "1.0.0"
833-
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2"
846+
type-detect@^4.0.0:
847+
version "4.0.3"
848+
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.3.tgz#0e3f2670b44099b0b46c284d136a7ef49c74c2ea"
834849

835850
type-is@~1.6.14:
836851
version "1.6.15"

0 commit comments

Comments
 (0)