How do I test an Express.js app with AVA? - express

I can test my models fine with AVA, but I would like to also test the routes.
I feel it should be possible to access the Express app object, and pass it a URL, then see what comes back, but I do not know how to get the Express object to use it.

After some playing around and referencing the supertest repo, I was able to get the following working:
const test = require("ava");
const request = require("supertest");
const express = require("express");
test("test express handler with supertest", async t => {
// in async tests, it's useful to declare the number of
// assertions this test contains
t.plan(3);
// define (or import) your express app here
const app = express();
app.get("/", (req, res) => {
res.json({
message: "Hello, World!",
});
});
// make a request with supertest
const res = await request(app).get("/").send();
// make assertions on the response
t.is(res.ok, true);
t.is(res.type, "application/json");
t.like(res.body, {
message: "Hello, World!",
});
});
I tend to run AVA with the following shell command:
yarn ava --verbose --watch

Related

AXIOS GET request to instagram not working in prod

I am stuck for a few hours and I can't find an answer.
It's a very simple request that works fine in the browser (it returns a JSON answer), for example :
https://www.instagram.com/eurosportfr/channel/?__a=1
In dev the code:
const express = require('express');
const axios = require('axios');
const cors = require('cors');
const app = express();
app.use(cors());
app.get('/instagram', (req, res) => {
async function getInstagramFeed() {
await axios
.get('https://www.instagram.com/eurosportfr/?__a=1')
.then((response) => {
console.log(response);
res.write(`${JSON.stringify(response.data)}`);
res.end();
})
.catch((err) => {
console.log(err.response);
res.write('<h1>ERROR GRAVE</h1>');
res.write(err.response);
res.end();
});
}
getInstagramFeed();
});
const PORT = process.env.PORT || 8000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));
The result in DEV ENV is JSON data with all what I need.
But in production, it doesn't return me the JSON. Instead it returns me an HTML page...
You can try it here: (I display in the body the result)
https://corsmiddleware.vercel.app/instagram
When I try another api request with another API client, it works just fine in prod, example :
https://corsmiddleware.vercel.app/test
Any idea ??
Thanks
This request now requires authentification. It was working in the past, and it's still actually working here in Morocco where I am, but this solution is not reliable.
The solution is to follow the instructions on facebook :
https://developers.facebook.com/docs/instagram-basic-display-api/

Key passed but validation fails in postman

I have this patch request where I update certain information depending on object of a document. When I send request using Postman(form-data) I get validation error saying "_id" is required.
Here's how it looks in Postman,
The route looks similar to this,
router.patch("/update", async (req, res) => {
try{
await updateValidation(req.body);
// whatever stuff processed with the data
} catch (err) {
res.status(400).send({ message: err.details[0].message });
}
}
The validation function looks like this,
const updateValidation = (data) => {
const schema = Joi.object({
_id: Joi.string().required(),
// other whatever validation possible
});
return schema.validateAsync(data);
};
Am I missing something here? I think I do, please point it out.
Besides using var bodyParser = require('body-parser'); in server side, it will still return empty req.body that will lead to errors because you have validation in place. The reason it is returning empty req.body when you sending PATCH request using form-data in Postman is because body-parser can't handle multipart/form-data. You need a package that can handle multipart/form-data like multer.
at the first to install the body-parser and multer, go to your terminal and use −
npm install --save body-parser multer
so add this code to in server.js
var express = require('express');
var bodyParser = require('body-parser');
var multer = require('multer');
var upload = multer();
var app = express();
at the next time use this middelware:
// for parsing application/json
app.use(bodyParser.json());
// for parsing application/xwww-
app.use(bodyParser.urlencoded({ extended: true }));
//form-urlencoded
// for parsing multipart/form-data
app.use(upload.array());
app.use(express.static('public'));
After importing the body parser and multer, we will use the body-parser for parsing json and x-www-form-urlencoded header requests, while we will use multer for parsing multipart/form-data.

Here-API 401 : "Invalid app_id app_code combination"

I am using an Angular front-end with a Nodejs backend. Im currently proxying all my front-end requests through my express server. However when I make my http request to the Here API I am rejected due to an invalid combination of app_id and app_code.
angular service
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http'
import { HttpParams } from '#angular/common/http'
#Injectable({
providedIn: 'root'
})
export class GetReqPlaces {
constructor(private http: HttpClient) { }
getPlaces(wLong,sLat,eLong,nLat){
// let obj = {params: {westLong: wLong, southLat: sLat, eastLong:eLong, northLat:nLat }};
let params = new HttpParams().set("westLong" , '-97.783').set("southLat", '30.231').set( "eastLong" , '-97.740').set("northLat", '30.329');
return this.http.get( 'api/find/places', { params : params}).subscribe(res=>console.log(res))
}
}
server.js
const express = require("express")
const bodyParser = require("body-parser")
const cors = require("cors")
const path = require("path")
const app = express();
const request = require("request")
const environment= require('./keys')
app.use(cors());
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
let reqPath = __dirname.substring(0,__dirname.length-7)
app.use(express.static(path.join(reqPath, '/dist/angular-places-search')));
app.get('/api/find/places', (req, res) => {
let appId = environment.environment.appId;
let appCode = environment.environment.appCode;
let URL= `https://places.cit.api.here.com/places/v1/discover/search?app_id={${appId}}&app_code={${appCode}}&in=${req.query.westLong},${req.query.southLat},${req.query.eastLong},${req.query.northLat}&pretty`;
console.log(URL)
request(URL, function (error, response, body) {
let data={
body:body,
};
console.log(error,response)
res.send(data);
});
});
app.get('/test', (req, res) => res.send('Well this route was a hit! Bada....tsss'));
// CATCH ALL
app.get('*', (req, res) => {
res.sendFile(path.join(reqPath, 'dist/angular-places-search/index.html'));
});
app.listen(4000, () => console.log(`Express server running on port 4000`));
Before this I was running into CORS and request issues but I think I sorted those out. Based on my research on this same error code (In the context of the framework that Im working in), people overwhelmingly suggest to wait for tokens to register with Here API. Waiting two days is enough I think, still doesnt work. Then there is the very popular solution of just scratching the Here freemium and starting a new project, which I did, and which did not solve my issue. Very few things I have 100% certainty on but I did copy my keys correctly and the URL path built is according to the required Here syntax.
If anyone has any insight you will be my Hero, and also the catalyst for my continued learning :D. Happy Sunday!
In addition the incoming message I get through express is :
method: 'GET',
path: '/places/v1/discover/search?app_id=%notmyid%7D&app_code=%normycode%7D&in=-97.783,30.231,-97.740,30.329&pretty'
However i dont know why it is setting the app_id=% instead of using {}, when i console log the URL it is correct, with my app_id and app_code
The %7D is the url encoded value of the symbol } (urlencoding) which is done by most libraries. For using the HERE API you should not enclose the app_id/app_code between {}. They should be provided directly as strings, check the examples

Jest promise not resolving

I am testing my express server in Jest. All test pass but Jest doesn't close or exit. I have no idea why but I believe my server is closing after the test runs. I tried running yarn jest --detectOpenHandles and the response came back saying "Jest has detected the following 1 open handle potentially keeping Jest from exiting:
Promise"
Here is my code...
const request = require('supertest');
const app = require('../server');
const server = app.listen(8000, '127.0.0.1');
afterAll(() => {
server.close();
});
describe('GET /', () => {
it('should respond with JSON (list of all users)', async () => {
try {
const response = await request(server).get('/')
.expect('Content-Type', /json/);
expect(response.statusCode).toBe(200);
} catch (e) {
console.log(e);
}
});
});
I can't seem to understand why the promise isn't resolving if that's actually the issue. My express app is pulling data from Firebase and returning the data once a get request is made. Any ideas on what's going on?
In Server.js file I connect to Firebase maybe this is the issue?
const db = admin.database();
const ref = db.ref('users');
app.get('/', (req, res) => {
// Attach an asynchronous callback to read the data at our posts reference
ref.on('value', function(snapshot) {
res.send(parseUsers(snapshot.val()));
res.status(200);
}, function (errorObject) {
res.send([],'The read failed: ' + errorObject.code);
res.status(500);
});
} );

Is supertest compatible with express.js 2.5.8?

I am using express.js version 2.5.8 (from legacy code) and am looking to test route loading using supertest. I am having an issue with the server running, but not stopping. I run my tests using jasmine-node, which indicates that my assertion succeeds. However, the console shows that the process is still running.
var request = require('supertest')
, express = require('express');
describe('Example Test', function() {
var app;
beforeEach(function() {
app = express.createServer();
app.configure(function() {
app.set('port', process.env.PORT || 3000);
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
});
app.get('/', function(req, res){
res.send(200);
});
});
it('index should return 200', function(done) {
request(app)
.get('/')
.expect(200)
.end(function(err, res) {
expect(err).toBe(null);
done();
});
});
});
This example is adapted from one likely using express.js 3.x.x. My assumption is that the express server behaves differently, leading to it not closing when the request terminates inside the test. I am uncertain how to correct this issue.
The server is still running because you aren't closing it anywhere. Just add app.close() to your end(function(){}) to stop the express server. If you also want to exit from node use process.exit().