Skip to content

Commit

Permalink
Added tests for module 3
Browse files Browse the repository at this point in the history
  • Loading branch information
Soham Kamani authored and Soham Kamani committed May 20, 2020
1 parent 43e475b commit 9aceed8
Show file tree
Hide file tree
Showing 13 changed files with 458 additions and 12 deletions.
35 changes: 24 additions & 11 deletions client.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const url = require("url")
const express = require("express")
const bodyParser = require("body-parser")
const axios = require("axios").default
const { randomString } = require("./utils")
const { randomString, timeout } = require("./utils")

const config = {
port: 9000,
Expand All @@ -20,6 +20,7 @@ let state = ""
const app = express()
app.set("view engine", "ejs")
app.set("views", "assets/client")
app.use(timeout)
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))

Expand All @@ -42,7 +43,6 @@ app.get("/callback", (req, res) => {
res.status(403).send("Error: state mismatch")
return
}

const { code } = req.query
axios({
method: "POST",
Expand All @@ -61,23 +61,23 @@ app.get("/callback", (req, res) => {
res.status(500).send("Error: something went wrong")
return
}

return axios({
method: "GET",
url: config.userInfoEndpoint,
headers: {
authorization: "bearer " + response.data.access_token,
},
}).then((response) => {
if (response.status !== 200) {
res
.status(403)
.send("Error: could not get data from protected resource")
return
}
res.render("welcome", { user: response.data })
})
})
.then((response) => {
if (response.status !== 200) {
res.status(403).send(
"Error: could not get data from protected resource"
)
return
}
res.render("welcome", { user: response.data })
})
.catch((err) => {
console.error(err)
res.status(500).send("Error: something went wrong")
Expand All @@ -89,3 +89,16 @@ const server = app.listen(config.port, "localhost", function () {
var port = server.address().port
console.log("OAuth Client is listening at http://%s:%s", host, port)
})

// for testing purposes

module.exports = {
app,
server,
getState() {
return state
},
setState(s) {
state = s
},
}
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"mocha": "^7.1.2",
"moxios": "^0.4.0",
"sinon": "^9.0.2",
"supertest": "^4.0.2"
}
Expand Down
2 changes: 2 additions & 0 deletions protected-resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ function getUserInfoFromAccessToken(req) {
return userInfo
}

// for testing purposes

module.exports = {
app,
server,
Expand Down
20 changes: 20 additions & 0 deletions test/module3/01-create-authorization-route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const assert = require("assert")
const request = require("supertest")

const { app, server } = require("../../client")

it("serves an empty authorization route @client-create-authorization-route", () => {
return request(app)
.get("/authorize")
.then((res) => {
assert.notEqual(
res.status,
404,
"The `/authorize` route doesn't exist"
)
})
})

afterEach(() => {
server.close()
})
32 changes: 32 additions & 0 deletions test/module3/02-declare-state.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const assert = require("assert")
const request = require("supertest")

const { app, server, getState, setState } = require("../../client")

it("assigns a random value to the state @client-declare-state", () => {
setState("")
return request(app)
.get("/authorize")
.then((res) => {
assert.equal(
[408, 302].indexOf(res.status) >= 0,
true,
"The `/user-info` route should not return an error status code"
)
const state = getState()
assert.strictEqual(
typeof state,
"string",
"/authorize should assign a random string to state"
)
assert.strictEqual(
state.length > 0,
true,
"/authorize should assign a non-empty string to state"
)
})
})

afterEach(() => {
server.close()
})
55 changes: 55 additions & 0 deletions test/module3/03-redirect-user.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const assert = require("assert")
const request = require("supertest")
const url = require("url")
const querystring = require("querystring")

const { app, server, getState, setState } = require("../../client")

it("redirects user to authorization endpoint @client-redirect-user-to-authorization-endpoint", () => {
setState("")
return request(app)
.get("/authorize")
.then((res) => {
assert.equal(
res.status,
302,
"The `/user-info` route should return a redirect status code"
)
const redirectUrl = url.parse(res.headers.location)
const query = querystring.parse(redirectUrl.query)
assert.equal(
query.response_type,
"code",
'redirect URL response_type should be "code"'
)
assert.equal(
query.client_id,
"my-client",
"redirect URL should contain the correct client_id param"
)
assert.equal(
query.client_secret,
"zETqHgl0d7ThysUqPnaFuLOmG1E=",
"redirect URL should contain the correct client_secret param"
)
assert.equal(
query.redirect_uri,
"http://localhost:9000/callback",
"redirect URL should contain the correct redirect_uri param"
)
assert.equal(
query.scope,
"permission:name permission:date_of_birth",
"redirect URL should contain the correct scope param"
)
assert.equal(
query.state,
getState(),
"redirect URL should contain the correct state param"
)
})
})

afterEach(() => {
server.close()
})
20 changes: 20 additions & 0 deletions test/module3/04-create-callback-route.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const assert = require("assert")
const request = require("supertest")

const { app, server } = require("../../client")

it("serves an empty callback route @client-create-callback-route", () => {
return request(app)
.get("/callback")
.then((res) => {
assert.notEqual(
res.status,
404,
"The `/callback` route doesn't exist"
)
})
})

afterEach(() => {
server.close()
})
65 changes: 65 additions & 0 deletions test/module3/05-verify-state.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const assert = require("assert")
const request = require("supertest")
const sinon = require("sinon")
const axios = require("axios")
const moxios = require("moxios")

const { app, server, getState, setState } = require("../../client")

before(function () {
moxios.install()
})

it("verifies state with current stored state @client-callback-verify-state", () => {
setState("mystate")

moxios.wait(() => {
moxios.wait(() => {
const req = moxios.requests.mostRecent()
if (!req) {
return
}
req.respondWith({
status: 200,
response: {
access_token: "mytoken",
},
})
})

const req = moxios.requests.mostRecent()
if (!req) {
return
}
req.respondWith({
status: 200,
response: {
access_token: "mytoken",
},
})
})

return request(app)
.get("/callback?code=mycode&state=mystate")
.then((res) => {
assert.equal(
[408, 200].indexOf(res.status) >= 0,
true,
"The `/callback` route should not return an error status code"
)

return request(app).get("/callback?code=mycode&state=fakestate")
})
.then((res) => {
assert.equal(
res.status,
403,
"/callback should return a 403 status if the states don't match"
)
})
})

after(() => {
moxios.uninstall()
server.close()
})
82 changes: 82 additions & 0 deletions test/module3/06-request-access-token.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
const assert = require("assert")
const request = require("supertest")
const sinon = require("sinon")
const axios = require("axios")
const moxios = require("moxios")

const { app, server, getState, setState } = require("../../client")

before(function () {
moxios.install()
})

it("/callback requests access token from the token endpoint @client-callback-request-access-token", () => {
setState("mystate")
let called = false
moxios.wait(() => {
moxios.wait(() => {
const req = moxios.requests.mostRecent()
if (!req) {
return
}
req.respondWith({
status: 200,
response: {
access_token: "mytoken",
},
})
})

const req = moxios.requests.mostRecent()
if (!req) {
return
}
called = true
assert.equal(
req.config.url,
"http://localhost:9001/token",
"the request to the token endpoint should be made to the correct URL"
)
assert.equal(
req.config.data,
'{"code":"mycode"}',
"the request made to the token endpoint should contain the correct authorization code in the request body"
)
assert.equal(
req.config.method,
"post",
"the request made to the token endpoint should be a POST request"
)
assert.equal(
req.config.headers.Authorization,
"Basic bXktY2xpZW50OnpFVHFIZ2wwZDdUaHlzVXFQbmFGdUxPbUcxRT0=",
"the request made to the token endpoint should contain the correct auth credentials"
)
req.respondWith({
status: 200,
response: {
access_token: "mytoken",
},
})
})

return request(app)
.get("/callback?code=mycode&state=mystate")
.then((res) => {
assert.equal(
[408, 200].indexOf(res.status) >= 0,
true,
"The `/callback` route should not return an error status code"
)
assert.equal(
called,
true,
"/callback needs to make an HTTP call to request for the access token"
)
})
})

after(() => {
moxios.uninstall()
server.close()
})
Loading

0 comments on commit 9aceed8

Please sign in to comment.