I have been running into some issues with supertest, mocha, and node with parsing status code 400.
Here is my index.js code:
var express = require('express');
var app = express();
app.get('/api/tweets', function(req, res) {
var userId = req.query.userId;
if (!userId) {
return res.sendStatus(400);
}
});
module.exports = app;
when I do mocha test.js this is the printout I get:
Test:
1) respond with status code 400 for GET /api/tweets with missing userId
0 passing (75ms)
1 failing
1) Test: respond with status code 400 for GET /api/tweets with missing userId:
Uncaught TypeError: Cannot read property 'status' of undefined
at net.js:1419:10
Here is the code for test.js:
var request = require('supertest')
describe('Test:', function() {
var server = require('./index')
it('respond with status code 400 for GET /api/tweets with missing userId', function(done) {
request(server)
.get('/api/tweets?userId')
.expect(400, done)
})
})
Are there any pointers that could be given? I'm not sure why node/supertest are giving me such an odd error.
My setup is as follows:
NVM is installed, but it is using the system node version (0.12.3).
Thanks in advance for your help!
-Stu.
Supertest ... Cannot read property 'status' of undefined
I got this above error when testing over a secure connection. I fixed it by adding NODE_TLS_REJECT_UNAUTHORIZED=0 as an env var on the test run.
For those wondering why this happens, it can happen because '127.0.0.1' is not listed as a valid IP in your certificate. The underlying error is:
Hostname/IP doesn't match certificate's altnames: "IP: 127.0.0.1 is not in the cert's list:
However, you will not see this error message, just the spurious and much disliked "Cannot read property 'status' of undefined".
Are you using the latest version of supertest and express? There were some big changes with supertest 1.0.0 by way of a new version of superagent that changed how "error" responses were handled for non 2xx responses.
This test worked for me using express 4.12.2 and supertest 1.0.1
var request = require('supertest')
, express = require('express');
var app = express();
app.get('/api/tweets', function(req, res) {
var userId = req.query.userId;
if (!userId) {
return res.sendStatus(400);
}
res.sendStatus(200);
});
describe.only('GET /api/tweets', function() {
it('should respond with HTTP 400 for missing userId', function(done) {
request(app)
.get('/api/tweets?userId')
.expect(400, done);
});
it('should respond with HTTP 200 with userId', function(done) {
request(app)
.get('/api/tweets?userId=100')
.expect(200, done);
});
});
Related
I'm trying to make a post request using appwrite SDK in Node JS express and Vue JS. The SDK requires me to create an api post request to create new storage bucket in appwrite. The DOCs for this particular request isn't explaining really how to create the api in node JS express. I'm really new to Node JS and I already succeeded at creating get request but whenever I create the post request I get 404 not found error.
Node JS express file (server.js):
In this file there is get users request API which works perfectly fine.
And there is create bucket post request which when being called in frontend it comes back with a 404
const express = require("express");
const path = require("path");
const app = express(),
bodyParser = require("body-parser");
port = 3080;
// Init SDK
const sdk = require("node-appwrite");
let client = new sdk.Client();
let users = new sdk.Users(client);
let storage = new sdk.Storage(client);
client
.setEndpoint("http://localhost/v1") // Your API Endpoint
.setProject("tailwinder") // Your project ID
.setKey(
"Secrer Key!"
); // Your secret API key
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, "../appwrite-app/build")));
//This get request works fine
//get user by ID
app.get("/v1/users/:id", (req, res) => {
let promise = users.get(req.params.id);
promise.then(
function (response) {
res.json(response);
},
function (error) {
console.log(error);
}
);
});
//This one isn't recognised in frontend
app.post("/v1/storage/buckets", function (req, res) {
let promise = storage.createBucket("bucket_id", "bucket_name", "file");
promise.then(
function (response) {
res.json(response);
},
function (error) {
console.log(error);
}
);
});
app.listen(port, () => {
console.log(`Server listening on the port::${port}`);
});
bucketsServices.js:
Here I'm using fetch post request to the api endpoint but it's not working.
export async function createBucket() {
const response = await fetch("/v1/storage/buckets", {
method: "POST",
});
return await response.json();
}
Addcomponent.vue:
Here I'm calling out the createBucket function from vue js file
bucketTesting() {
createBucket().then((response) => {
console.log(response);
});
},
The error which I assume it means that it's not reading my node js express post API:
bucketsService.js?993b:2 POST http://localhost:8080/v1/storage/buckets 404 (Not Found)
Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
A screenshot of the same error:
Something is missing here and I can't really figure it out.
You are making request to localhost:8080 meanwhile your server is running at localhost:3080
I believe your vue is running at port 8080 that's why /v1/storage/buckets gets prefixed by localhost:8080
Try to provide full URL while making request
export async function createBucket() {
const response = await fetch("localhost:3080/v1/storage/buckets", {
method: "POST",
});
return await response.json();
}
Better way might be to add proxy to automatically redirect request to correct URL, but this should work for now. This article might help with how to setup proxy in vue
Req.body is not accessible in the routes while making a post request. It would be highly appreciative of someone if he/she help me getting through it. Here is screenshot of my microservice.test.js file. Am I missing something?
import request from "supertest";
import mongoose from "mongoose";
import config from "../config/env";
import routes from "../server/routes";
import { parseResponse, doRequest } from "../server/utils/helperFunctions";
const app = express();
app.use("/", routes);
jest.setTimeout(30000);
The code provided doesn't provide much insight, as I would expect all of the handling of the request to be in your route handler. Is the issue that you are unable to access the body when running tests with supertest? Or that it isn't working at all. More information would be very helpful.
If it is a supertest issue, I would recommend checking out the docs for good examples. Here is one I pulled directly from the NPM site where they POST some data with a request body and then verify the response body:
describe('POST /user', function() {
it('user.name should be an case-insensitive match for "john"', function(done) {
request(app)
.post('/user')
.send('name=john') // x-www-form-urlencoded upload
.set('Accept', 'application/json')
.expect(function(res) {
res.body.id = 'some fixed id';
res.body.name = res.body.name.toLowerCase();
})
.expect(200, {
id: 'some fixed id',
name: 'john'
}, done);
});
});
Also, if you are trying to test your server you should probably import your server code instead of creating a new express instance. For example, in your server code you'll have something like this:
server.js
const express = require('express');
const app = express();
app.use('/', ...) // middleware/route config
...
module.exports = app;
Your server would then use this server like this:
index.js
const app = require('./server')
const port = 4000
app.listen({ port }, () => {
const location = `http://localhost:${port}`
logger.info(`🚀 Server ready at ${location}`)
})
module.exports = app
Now that you have structured your code this way, in your test you can import your server as well (so you are testing your actual server, not a new server that you made up):
server.test.js
const app = require('../../../server');
const request = require('supertest')(app);
describe('Server', () => {
it('does a thing', async () => {
const { body } = await request
.post('http://path/to/test')
.send({ data: 'some data' })
.set('Content-Type', 'application/json')
.set('Accept', 'application/json')
.expect(200);
expect(body.thing).toBeTrue();
});
});
expressjs version lower than 4 include body parsing middleware
import bodyParser from 'body-parser';
app.use(bodyParser());
example test
it('.post should work with data', function (done) {
var app = express();
app.use(bodyParser());
app.post('/', function(req, res){
res.send(req.body.name);
});
request(app)
.post('/')
.send({ name: 'tobi' })
.expect('tobi', done);
})
I am new and fail to make supertest work for me. I am wondering:
Why is the body undefined?
Is there a trick from the command line to show and inspect objects in the console?
Why doesn't the test logs "hello"?
"use strict";
const request = require('supertest');
const express = require('express');
const https = require('https');
const fs = require('fs');
const path = require('path');
const certPath = path.resolve(path.resolve(), './certs');
const app = express();
//This line is from the Node.js HTTPS documentation.
const options = {
key : fs.readFileSync(certPath+'/server-key.pem'),
cert : fs.readFileSync(certPath+'/server-crt.pem'),
ca : fs.readFileSync(certPath+'/ca-crt.pem')
};
// service
app.post('/failService', function(req, res) {
console.log('failService: '+req.body); // failService: undefined
res.send('hello');
});
describe('trial not working', function() {
it('responds with json', function(done) {
request(app)
.post('/failService')
.send({name: 'john'})
.set('Accept', /json/)
.expect(200)
.end(function(err, res) {
if (err) return done(err);
console.log('response: '+res.body); // response: [object Object]
done();
});
});
});
.... shows
$ mocha supertest.js
trial not working
failService: undefined
response: [object Object]
√ responds with json (125ms)
1 passing (171ms)
Please note that the certificates (not included) are self signed.
When isolating my code above I missed the options. As a result it does not use SSL. Sorry for that.
I fell back to starting the server and the use of a client in my test case. For that I had to fix:
CORS
The actual problem of this post by using a body parser
This is due to the self signed certificate.
i also faced similar issue there are two possible solutions
Create http server instead of https server for test environment
Replace supertest with superrequest npm package and set strictSsl as false.
I'm trying to build a test set for my API, which was developed with nodejs/express, with mocha/chai. Basically, the index returns a simple string that I know it's working because I can see on my browser:
router.get('/', function(req, res, next) {
res.send('Hello World from Eclipse');
});
Then I followed this tutorial to build this test:
var supertest = require("supertest");
var should = require("should");
// This agent refers to PORT where program is runninng.
var server = supertest.agent("http://localhost:5000");
// UNIT test begin
describe("SAMPLE unit test",function(){
// #1 should return home page
it("should return home page",function(done){
// calling home page api
server
.get("/")
.expect("Content-type",/json/)
.expect(200) // THis is HTTP response
.end(function(err,res){
// HTTP status should be 200
res.status.should.equal(200);
// Error key should be false.
res.body.error.should.equal(false);
done();
});
});
});
I can see on the log of my server that the address is been called, however, the test always say that it cannot read property 'should' of undefined, on the line where I have 'res.status.should.equal(200);'. Probably because 'res' is undefined. In other words, no answer from the API.
Am I missing something here? I running mocha with no arguments...
Try something like this:
var expect = require('chai').expect;
var request = require('supertest');
var uri = 'your url';
describe('Profile',function(){
it('Should return a users profile',function(done){
request
.get(uri + '/api/1.0/profile')
.query({app_id:'12345'})
.end(function(err,res){
var body = res.body;
expect(body.first_name).to.equal('Bob');
expect(body.last_name).to.equal('Smith');
done()
});
});
});
Make sure you have the correct requires included.
You should check for errors in .end():
.end(function(err, res) {
if (err) return done(err);
...
});
The test case is expecting the content type to match /json/, which it doesn't, so it should be set (and res will be undefined because of that).
I'm trying to build a RESTful API for a node app.
I built the routes and everything is running fine. But when I try to test it, it cant get the DELETE method to work, despite of it working normally not under tests.
Here are the codes for the server and test.
Server:
// set up
var express = require('express');
var app = express(); // create our app w/ express
var path = __dirname; //root path
// configuration
app.configure(function() {
app.use(express.static(path));
//app.use(express.logger('dev')); // log every request to the console
app.use(express.json());
app.use(express.urlencoded()); // pull information from html in POST
app.use(express.methodOverride()); // simulate DELETE and PUT
});
function start() {
// routes
require('./app/routes.js')(app);
// listen (start app with node server.js)
app.listen(process.env.PORT || 5000);
console.log("Server listening for incoming conections..");
}
//************************
exports.start = start;
exports.server = app;
Test:
var should = require('should');
var assert = require('assert');
var request = require('supertest');
var mongoose = require('mongoose');
var express = require('express');
var server = require(__dirname + './../index.js');
describe('Routing', function() {
var url = 'http://localhost:5000';
it('should return status 200 after DELETING a bus', function(done) {
request(url)
.delete('/api/buses/' + bus.id)
.end(function(err, res) {
if (err) {
throw err;
}
res.should.have.status(200);
done();
});
});
});
And this is the error message it throws:
Routing
1) should return status 200 after DELETING a bus
✖ 1 of 1 test failed:
1) Routing should return status 200 after DELETING a bus:
TypeError: Object #<Object> has no method 'delete'
at Context.<anonymous> (/home/roger/Documents/Buse/test/test.js:63:16)
at Test.Runnable.run (/home/roger/Documents/Buse/node_modules/mocha/lib/runnable.js:196:15)
at Runner.runTest (/home/roger/Documents/Buse/node_modules/mocha/lib/runner.js:351:10)
at /home/roger/Documents/Buse/node_modules/mocha/lib/runner.js:397:12
at next (/home/roger/Documents/Buse/node_modules/mocha/lib/runner.js:277:14)
at /home/roger/Documents/Buse/node_modules/mocha/lib/runner.js:286:7
at next (/home/roger/Documents/Buse/node_modules/mocha/lib/runner.js:234:23)
at Object._onImmediate (/home/roger/Documents/Buse/node_modules/mocha/lib/runner.js:254:5)
at processImmediate [as _immediateCallback] (timers.js:330:15)
make: *** [test] Error 1
Just to be clear there is no method delete with supertest but the correct method is del.
so a delete request should be tested like this:
var app=require('./app')
var request=require('supertest')
//with mocha for instance.
describe('test delete',function(){
it('should respond 200',function(done){
request(app).del('/path').expect(200).end(done);
})
});
And one needs to pass the app (express app) , not a url or a string.
Take a look at the supertest GitHub-page.
You may pass an http.Server, or a Function to request()
You are passing a string to the function request. Try passing your express-server object as the function parameter.
EDIT: as seen in comments and #mpm:s answer, the issue was the usage of reserved function delete() instead of package-specific function del().