How to send Headers ('Authorization','Bearer token') in Mocha Test cases - javascript

I am writing a test case to test my API . When I try to test for any open API, it is working fine. But When I try to send Authorization Token along with my API, it is not working. Here is the code:
The way i am sending headers is:
.set("Authorization", "Bearer " + token)
Is it the correct way of sending?
I have tried to send the Authorization token in Auth. But not able to get the same. But when I tried to consume same in Postman, it is working fine.
it("Get some random Info", function(done) {
chai
.request(baseUrl)
.get("/someRandomApi")
.set("Authorization", "Bearer " + token)
.end(function(err, res) {
expect(res).to.have.status(200);
done();
});
});

I like to set up my tests in the following way:
let baseUrl = 'http://localhost:9090'
let token = 'some_authorization_token'
First I would instantiate my variables baseUrl and token at the very top of the test, right after use() part.
Next to come is the setup of the test.
it("Get some random Info", function(done) {
chai.request(baseUrl)
.get('/someRandomApi')
.set({ "Authorization": `Bearer ${token}` })
.then((res) => {
expect(res).to.have.status(200)
const body = res.body
// console.log(body) - not really needed, but I include them as a comment
done();
}).catch((err) => done(err))
});
Now, .set() doesn't necessarily have to be like mine, works in your case as well.

You can use the auth function to set the Authorization header.
it("Get some random Info", function(done) {
chai
.request(baseUrl)
.get("/someRandomApi")
.auth(token, { type: 'bearer' })
.end(function(err, res) {
expect(res).to.have.status(200);
done();
});
});

chai-http has auth function to send the Authorization Bearer token.
Accroding to chai-http code on Github, token can be pass using:
.auth(accessToken, { type: 'bearer' })
The code would be like:
it("Get some random Info", function(done) {
chai.request(baseUrl)
.get('/someRandomApi')
.set(token,{ type: 'bearer' }) //token is actual token data
.then((res) => {
expect(res).to.have.status(200)
done();
}).catch((err) => done(err))
});

Try calling .get() after you call .set():
it("Get some random Info", function(done) {
chai
.request(baseUrl)
.set("Authorization", "Bearer " + token) //set the header first
.get("/someRandomApi") //then get the data
.end(function(err, res) {
expect(res).to.have.status(200);
done();
});
});

Related

How to test req.query using supertest node.js?

I have this code on supertest framework for tests:
it('GET normal pending transfer with receiverId', (done) => {
supertest(app)
.get('/transfers/pending')
.set('Accept', 'application/json')
.expect(200)
.query({
senderId: clientSenderId,
})
.expect('Content-Type', 'application/json; charset=utf-8')
.then((res) => {
console.log('res.body', res.body);
done();
})
.catch(done);
});
This endpoint - /transfers/pending takes query this way:
const { receiverId, senderId } = req.query;
As you can see, this is req.query and I want to send this query in my test's code.
I was trying to use this:
.get('/transfers/pending?senderId=${clientSenderId}')
And this:
.query({
senderId: clientSenderId,
})
And nothing of this isn't working. I mean, I got 500 and, the most important, I get an error in message, that belongs to other endpoint. It looks like my code triggers other endpoint, not that /transfers/pending.
My question is, how can I send queries in tests. With params and bodies everything works just fine, but not with queries.

Storing API response in session

On POST of a page I'm trying to GET information from an API, return the output and store the results so it can be used across all pages. The method in which the API is called isn't the best but it's just for proof of concept rather than production quality. So here is the code at the moment:
router.post('/page-one/', function (req, res) {
var options = {
'method': 'GET',
'url': 'https://api.information.service.com/company/<value>',
'headers': {
'Authorization': 'Basic <key>'
}
}
request(options, function (error, response) {
if (error) throw new Error(error)
console.log(response.body)
})
res.redirect('/page-two/')
})
So this works fine, the console returns the right information. How would I then take this and use it across all pages? Say on page 2 my get is:
router.get('/page-two/', function (req, res) {
res.render('/page-two/', {
})
})
I'm using Express, Express Session, Express Writer and Nunjucks.

Sending an image with axios to Node.js and then using it further

I am trying to upload an image from the front-end, post it with axios to back-end (node.js) and then from there post it again to the GroupMe image service.
The main thing is to avoid using the API token in the front-end and so I was trying to first send a request to the back-end and then send the actual API request to the GroupMe image service which expects to get FormData of an image and sends back converted image URL.
I have tried to send FormData directly to the GroupMe image service from the front-end and everything works fine. However, in order to do so, I had to store the token in the front-end, which is not a good idea I believe.
The working code below:
let config = {
headers : {
'X-Access-Token': myToken,
'Content-Type' : 'multipart/form-data'
}
}
let fd = new FormData()
fd.append('name', 'image')
fd.append('file', fileToUpload)
axios.post'(https://image.groupme.com/pictures', fd, config)
.then((response)=>{
console.log(response)
})
.catch(err =>{
console.log(err.response)
})
What I need to happen instead is to send the request to the back-end like so:
axios.post(process.env.baseUrl+'/messengerRequests/upload-file/', fd, config)
.then((response)=>{
console.log(response)
})
.catch(err =>{
console.log(err.response)
})
And now in the back-end somehow be able to get that FormData and then create another post request to the GroupMe image service as I initially did in the front-end.
sendMessage: async(req, res) => {
axios.post('https://image.groupme.com/pictures', ???, config)
.then((response)=>{
res.send(response)
})
.catch(err =>{
console.log(err.response)
})
}
I do not know where it appears in the axios request. There is nothing in the req.body or req.params so I am not able to simply pass it further for the next post.
Is there a way somehow pass this FormData again?
Or maybe there is a way to safely use the token in the frond-end?
So, it should be relatively straightforward to post the image to GroupMe using Node.js and Express / Multer / Request. I've gone for Request rather than Axios on the backend since I'm more familiar with the API, but it's the same difference really.
Node.js Code (index.js)
const request = require("request");
const express = require("express");
const multer = require("multer");
const upload = multer();
const app = express();
const port = 3000;
const myToken = "" // Your API token goes here.
app.use(express.static("./"));
/* Here we take the image from the client and pass it on to GroupMe */
app.post("/uploadFile", upload.any(), (req, res) => {
sendImageToGroupMe(req, res);
});
function sendImageToGroupMe(req, res) {
const options = {
uri: "https://image.groupme.com/pictures",
body: req.files[0].buffer,
method: "POST",
headers: {
"X-Access-Token" : myToken
}
}
request(options, (err, response, body) => {
console.log("Request complete: Response: ", body);
if (err) {
console.error("Request err: ", err);
res.status(500).send("Upload failed: ", err.message);
} else {
res.status(201).send("Upload successful: GroupMe response: " + body);
}
});
}
app.listen(port);
Client side
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
function uploadFile() {
var fileToUpload = document.querySelector('input[type=file]').files[0];
let config = {
headers : {
'Content-Type' : 'multipart/form-data'
}
}
let fd = new FormData()
fd.append('name', 'image')
fd.append('file', fileToUpload)
axios.post('http://localhost:3000/uploadFile', fd, config)
.then((response)=>{
console.log("Image posted successfully: ", response);
showOutput("Image posted successfully: " + response.data);
})
.catch(err =>{
console.error("Image post failed: ", err)
showOutput("Image post failed!");
})
}
function showOutput(html) {
document.getElementById("output").innerHTML = html;
}
</script>
</head>
<body style="margin:50px">
<input type="file" onchange="uploadFile()"><br>
<p id="output"></p>
</body>
</html>
All files go in the same directory. You can go to http://localhost:3000/ to test the index.html code, this will be served by the Node.js server as a static file.
I get a response like below from the GroupMe API:
{
"payload": {
"url": "https://i.groupme.com/157x168.png.940f20356cd048c98478da2b181ee971",
"picture_url": "https://i.groupme.com/157x168.png.940f20356cd048c98478da2b181ee971"
}
}
We'll serve locally on port 3000, so to start the server:
node index.js
If you are using Express, you will need something to process the FormData. I have used multer for something similar before. I had to save the files into local storage, then resend the file with axios.

React Native Fetch Requests are not getting sent to my Node Js backend for some users

I've built a react native app that has a Node js backend. Users can sign In, sign up and view a profile page.
All my users can sign In but some of them can't view the profile page.
When I look at the request made to my backend, I get:
POST /UserRouter/SignIn 200 212.537 ms - 130342
Signing in works, it finds the user, returns the JWT token. When it's in the app no other requests are made. I get JSON Parse error: Unexpected EOF
Once you sign in, its supposed to immediately make a request to get your profile. With some accounts, this doesn't happen
My initial hypothesis of this problem is that the token for some users has expired, so they are not able to access protected routes. I use p***assport-jwt*** for my tokens. Hence, the backend not registering any requests.
Please find my code below:
_fetchData = () => {
AsyncStorage.getItem('jwt', (err, token) => {
fetch(`${backendUri }/UserRouter/Profile`, {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: token
}
})
.then((response) => response.json())
.then((json) => {
this.setState({name:json.name})
})
.catch((error) => {
console.log(error)
alert('There was an error ')
})
.done()
})
}
Here is my node JS code
app.get('/UserRouter/profile', passport.authenticate('jwt1', { session: false }), function (req, res) {
const token = req.headers.authorization
const decoded = jwt.decode(token.substring(4), config.secret)
User.findOne({
_id: decoded._id
},
function (err, user) {
if (err) throw err
res.json({ email: user.email, name: user.fName})
})
})
Thank you
This was the answer: https://stackoverflow.com/a/33617414/6542299
Turns out I was encoding my token with the users' document. the users' document was too large. so I just needed to reduce it

Setting Basic Auth in Mocha and SuperTest

I'm trying to set us a test to verify the username and password of a path blocked by the basic auth of a username and password.
it('should receive a status code of 200 with login', function(done) {
request(url)
.get("/staging")
.expect(200)
.set('Authorization', 'Basic username:password')
.end(function(err, res) {
if (err) {
throw err;
}
done();
});
});
Using the auth method
SuperTest is based on SuperAgent which provides the auth method to facilitate Basic Authentication:
it('should receive a status code of 200 with login', function(done) {
request(url)
.get('/staging')
.auth('the-username', 'the-password')
.expect(200, done);
});
Source: http://visionmedia.github.io/superagent/#basic-authentication
PS: You can pass done straight to any of the .expect() calls
The username:password part must be base64 encoded
You can use something like
.set("Authorization", "basic " + new Buffer("username:password").toString("base64"))

Categories