Uncaught AssertionError: expected 404 to equal 405 - node.js

I'm trying to test a server I have running. What I need to do is perform mocha testing on the response that the server gives. I am very new to this, so please forgive any errors that have been made.
Test is supposed to be passing, however it is not. I am very new to this, so I have not tried any alternative solutions. Thank you.
In Index.js I have:
console.log('index.js executing!');
var express = require('express');
var app = express();
app.get('/', function(req,res) {
res.send('Hello, World!');
});
app.get('/', function(req,res){
res.send('status.METHOD_NOT_ALLOWED');
});
var port = 3000;
app.listen(port,function() {
console.log('Listening on port ' + port);
});
And I am testing it with mocha :
console.log('test/test.js executing');
const chai = require('chai');
const expect = chai.expect;
const request = require('superagent');
const status = require('http-status');
const apiRoot = 'http://localhost:3000/';
describe('hello API', function(){
it('GET request returns text "Hello, World!".',function(done){
request.get(apiRoot)
.end(function(err,res){
expect(err).to.not.be.an('error');
expect(res.statusCode).to.equal(status.OK);
expect(res.text).to.equal('Hello, World!');
done();
});
});
it('POST request is not allowed',function(done){
request.post(apiRoot)
.end(function(err,res){
expect(err).to.be.an('error');
expect(res.statusCode).to.equal(status.METHOD_NOT_ALLOWED);
done();
});
});
});
The test is expected to pass.
The actual result that I am getting is:
Uncaught AssertionError: expected 404 to equal 405
+ expected - actual
-404
+405
at /home/plc/cs2410/test/test.js:26:27
at Request.callback (node_modules/superagent/lib/node/index.js:826:3)
at IncomingMessage.parser (node_modules/superagent/lib/node/index.js:1036:18)
at endReadableNT (_stream_readable.js:1129:12)
at processTicksAndRejections (internal/process/next_tick.js:76:17)
Lines 26 and 27 are:
expect(res.statusCode).to.equal(status.METHOD_NOT_ALLOWED);
done();

You're getting a 404 because your Express server is not listening for a POST to that endpoint. If you look, you've defined two GETs for that endpoint. You're also responding to the second request with a string that says status.METHOD_NOT_ALLOWED, not an actual 405 status code. You need to change your second app.get to something like this:
app.post('/', function(req,res){
res.send(405, 'Method Not Allowed');
});

Related

Node js(Express framework): not able to print number API from external server to client browser

I am trying to retrieve weather API from external server and when I am console logging particular data of weather API, it's also showing on my command prompt.
But when I am using get method to show that data on browser I am only able send string data like "description": moderate rain and not number data like "temp": 27
it the crash the app.
Node js code:
//jshint esversion:6
const express = require("express");
const app = express();
const https = require("https");
app.get("/", function(req, res) {
const url = "https://api.openweathermap.org/data/2.5/weather?q=mumbai&appid=d88391210768983e6be06cdd76bdcde3&units=metric";
https.get(url, function(response) {
console.log(response.statusCode);
response.on("data", function(data) {
const weatherData = JSON.parse(data);
const temp= weatherData.main.temp;
const description= weatherData.weather[0].description;
console.log(temp);
console.log(description);
res.send(temp);
});
});
});
app.listen(3000, function() {
console.log("Server is running on port: 3000");
});
You should ideally return a json.
It can be:
res.send({temp: temp, description: description});
The res.send has to return a string/object/array/buffer.
You could do something like:
res.status(200).send(temp)
But sending json response is preferable, and you can scale it as well.
Another hack kind of solution is:
res.send("" + temp)

How to recieve a file using request.get()?

I am writing a server that is meant to serve and receive files. It is written in node.js, using express.js. I also have a client, also written in node, which is meant to send a request to the server and receive the files on the server.
Server-side
const express = require("express");
const app = express();
const file = "./samplefiles/Helloworld.txt";
app.get("/", (res)=>{
res.download(file);
});
module.exports = app; //this exports to server.js
const http = require("http");
const app = require("./app.js);
const port = 8080;
const server = http.createServer(app);
server.listen(port, () => {
console.clear();
console.log("server running");
})
Client-side
const request = require("request");
request.get("http://localhost:8080/", (req, body) => {
console.log(body);
console.log(res);
});
If I try to access it by my browser I am asked what I want to do with the file, it works. However, Is I run my client-side code it prints the body and the res(being null). I expected the file name and it's content to be in the body but only the content of the file was in the body.
I want to receive the whole file, is possible, or at least get the name of it so that I can "make" a copy of it on the client-side.
Change code your server side to:
const port = 8080;
const express = require("express");
const app = express();
const path = require('path');
app.get("/", function(req, res){
res.sendFile(path.join(__dirname, 'app.js'));
});
app.listen(port, () => {
console.clear();
console.log("server running");
});
Change code your client-side to:
var request = require('request');
request('http://localhost:8080/', function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print data of your file
});
You need to install request npm i request for client side
You can serve up any files you want with express static method:
app.use(express.static('public'))
in this case just put all the files you want to serve in folder called public and then you can access it by localhost:8080/Helloworld.txt.
I ended up working around it.
I sent the file name as a header and was thus able to create a replica of the file I wanted to download using the body info and the filenameheader.

Node.js + React: How to POST

Follow on from this question: Axios can GET but not POST to the same URL
I've been trying to figure this out for too long now.
I want to POST from my React app to a .JSON file. Can anyone tell me what I'm doing wrong?
My AJAX POST function using axios always returns a 404. I'm listening for it on the node server but app.post never fires.
Thanks.
POST request from my React app:
postJson = (postJsonData) => {
axios.post('./postJson/', {
postJsonData
})
.then(function (response) {
console.log("success!");
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
app.js (node server):
/*========== Default Setup for node server copied from node website ==========*/
const http = require('http');
const hostname = '127.0.0.1';
const port = 3001;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
/*========== Listen for POST (Trying to get the data from my REACT app
- will then assign it to "obj" below) ==========*/
var express = require("express");
var myParser = require("body-parser");
var app = express();
app.post("./postJson/", function(request, response) {
console.log("MURRRR");
console.log(request.body); //This prints the JSON document received (if it is a JSON document)
/*=== JSON Stuff ===*/
var jsonfile = require('jsonfile')
var file = './scene-setup.json'
var obj = {name: 'JP'}
jsonfile.writeFile(file, obj, function (err) {
console.error(err)
})
});
//Start the server and make it listen for connections on port 3000
app.listen(3000, function(){
console.log("server is listening to 3000");
});
Two things I noticed:
Your post endpoint doesn't need a leading "." I would make it just "/postJson"
Make sure you are posting to "http://localhost:3000/postJson"
Make sure you have the network tab open to see the actual URL you are requesting to.
Cheers
Turns out both react and my node server were running on localhost:3000 simultaneously which is apparently not okay.
Running my node server on localhost:3001 from a new command line window allowed me to do both at the same time.
Not sure how this would work when making a production build though.

Express.js/Node.js Responses Before Query Finishes

I have a local server that is fully functioning when POSTs and GETs are sent from Postman or chrome rest apps etc. However, whenever I send it from an ESP8266 it fails as it follows:
This is my server side code:
router.get('/', function (req, res) {
var person = req.query.id;
console.log("1");
Person.find({person: personID} ,function (err, station) {
if(err) console.log(err.message);
console.log("3");
res.send('test');
console.log("4");
});
console.log("2");
});
Lines below are from console when request is sent from Chrome.
1
2
3
4
GET /api?id=ABKWTltz6Ug 200 21.829 ms - -
And the lines below are from console when request is sent from ESP8266.
1
2
GET /api?id=ABKWTltz6Ug - - ms - -
3
4
As you may notice logs 3 and 4 are after GET response line. My ESP8266 TCP connection lines match the HTTP Message Format:
GET /api HTTP/1.1
Host: *SERVER_IP_ADDRESS*
The problem raised when we switched from PHP to NodeJS backend server. ESP8266 used to connect and operate without problems back then. And FYI, everything also works fine if I remove the Person.find code block and move the res.send('test'); outside.
Another freshly written backend code to hopefully spot the error is below. This is the whole code. Which also returns the same error I've mentioned earlier above:
var express = require('express');
var app = express();
var router = express.Router();
var mongoose = require('mongoose');
var morgan = require('morgan');
app.use(morgan('dev'));
mongoose.connect('mongodb://localhost/test');
//mongoose.Promise = Promise;
var Test = mongoose.model('Test', { name: String });
router.get('/test', function (req, res) {
console.log("1");
var test1 = new Test({
name: "Name"
});
var query = test1.save();
query.then(function (doc) {
res.send('1').end();
console.log('3');
});
console.log("2");
});
app.use('/api', router);
var port = 9000;
app.listen(port,function(){
console.log('server started on', port);
});

Cannot get node js test to fail

my file structure is like this
folder_main
-server.js
-folder_tests
--serverTest.js
var expect = require("chai").expect;
var http = require('http')
describe('/', function(){
var server;
beforeEach(function () {
server = require('../server');
});
afterEach(function () {
server.close();
});
it('should return 200 status code', function(){
http.get("http://localhost:8080", function(res) {
console.log("Got response: " + res.statusCode);
expect(res.statusCode).to.equal("This isnt even a number")
})
})
})
and server.js is
var express = require('express');
var app = express();
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io').listen(server);
var port = 8080;
server.listen(port);
console.log("listening on port " + port)
// router
app.get('/', function (req, res){
res.writeHead(200, {"Content-Type": "text/plain"});
res.end("Hello World\n");
});
module.exports = server;
when I run "mocha test" from the cmd line I get
✓ should return 200 status code
1) "after each" hook
1 passing (277ms) 1 failing
1) / "after each" hook:
Uncaught Error: connect ECONNRESET
at errnoException (net.js:904:11)
at Object.afterConnect [as oncomplete] (net.js:895:19)
I am confused
The first test should fail because it compares to "This isnt even a number".
I am not sure what is happening with Uncaught Error: connect ECONNRESET
Mocha tests need to use the done() callback if you are testing asynchronous code otherwise mocha will complete before your assertions run and no failures will be detected.
it('should return 200 status code', function(done){
http.get("http://localhost:8080", function(res) {
console.log("Got response: " + res.statusCode);
expect(res.statusCode).to.equal("This isnt even a number")
done()
})
})
done is setup as the first parameter to your testing function, which you then call after your assertions. If the done function is not called, mocha will timeout the test after the default of 2 seconds.
This will probably resolve your ECONNRESET issue too as your server is not being shutdown mid test/request.
It can help to always make use of done(), even when testing synchronous code so you don't fall into this trap in the future. False positives can cause hours of trouble shooting pain.

Resources