I have an issue with the following code. The mocha .send() function send a body but it's empty when my api.js received it. When I do a request with PostMan it works, but when I use Mocha, it doesn't work.
api.js :
const express = require("express");
const dbConnection = require("../db/mysqlConnector.js");
const router = express();
const Validator = require('validatorjs');
// POST (Create)
router.post("/tasks", async function (req, res) {
try {
let validation = new Validator({
name: req.body.name,
description: req.body.description,
state: req.body.state,
priority: req.body.priority,
created_by: req.body.created_by
}, {
name: 'required|string',
description: 'required|string',
state: 'required|boolean',
priority: 'required|between:1,3',
created_by: 'required:number'
});
if (validation.fails()) { return res.status(400).json(); }
var con = await dbConnection();
await con.query('INSERT INTO `tasks` (name, description, state, priority, created_by) VALUES (?,?,?,?,?)',
[req.body.name, req.body.description, req.body.state, req.body.priority, req.body.created_by], function (error, results, fields) {
con.release();
res.status(201).json();
});
} catch (error) {
console.log(error);
}
});
test.js :
const chai = require("chai");
const request = require("supertest");
const expect = chai.expect;
const api = require("../routes/api.js");
const faker = require("faker");
describe("Tasks", function () {
describe("POST /tasks", function () {
it("should return 201 OK and insert a new task", async function () {
const response = await request(api)
.post("/tasks")
.send({
name: faker.vehicle.vehicle(),
description: faker.lorem.lines(3),
state: faker.datatype.boolean(),
priority: faker.datatype.number({min:1, max:3}),
created_by: faker.datatype.number({min:1, max:10})
})
.expect(201)
});
});
});
Am I missing something ?
Thanks
Related
I already tried some possible solutions and even created and wrote the code again but I am still getting errors. I have created a diminute version of my whole code which connects to the database using Mongoose but after the Schema is created and I import the model in places-controllers my data that I write in POSTMAN goes directly to:
FYI: In this case I want POST request from createPlace to properly work.
Data entry: URL: http://localhost:5000/api/places/
{
"title": "Punta Arena Stfdsfdsfsdfop",
"description": "One stop Stop. Does not have tr12affic lights.",
"busrespect": "12ysdfdsfsfes",
"address": "Avenida Solunna",
"creator": "52peru soiflsdjf36"
}
OUTPUT:
{
"status": "error caught"
}
which is what I told the program to define if the try did not work.
IN app.js I have the following code:
const express= require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const placesRoutes = require("./routes/places-routes");
const HttpError = require ("./models/http-error");
const app = express();
app.use(bodyParser.json());
app.use('/api/places', placesRoutes);
app.use((req, res, next) => {
const error= new HttpError('Route not available. Try something different?', 404);
throw error;
});
app.use((error, req, res, next) =>{
if (res.headerSent) {
return next(error);
}
res.status(error.code || 500)
res.json({message: error.message || "An unknown error occured! Sorry" });
});
url = '<mongo_url>'
mongoose.connect(url, {useNewUrlParser: true}).then(()=>{
console.log("Connected to database")
app.listen(5000);
}).catch(erro => {
console.log(erro)
});
In places-routes.js I have the following code:
const express = require('express');
const {check} = require('express-validator')
const placesControllers=require('../controllers/places-controllers');
const router = express.Router();
router.get('/:pid', placesControllers.getPlaceById );
router.get('/user/:uid',placesControllers.getPlacesByCreatorId );
router.post('/' ,[
check('title')
.not()
.isEmpty(),
check('description').isLength({ min: 5 }),
check('address')
.not()
.isEmpty()
],
placesControllers.createPlace);
router.patch('/:pid', [
check('title')
.not()
.isEmpty(),
check('description').isLength({ min: 5 })
] , placesControllers.updatePlace );
router.delete('/:pid', placesControllers.deletePlace);
module.exports=router;
In places-controllers.js I have the following code:
const HttpError = require('../models/http-error');
const { validationResult } = require('express-validator');
//const getCoordsForAddress= require('../util/location');
const BusStop = require('../models/place');
let INITIAL_DATA = [
{
id: "p1",
title: "Samoa Stop",
description: "My first bus stop in Lima",
//location: {
// lat: 40.1382,
// lng:-23.23
// },
address: "Av. La Molina interseccion con calle Samoa",
busrespect: "yes",
creator: "u1"
}
];
const getPlaceById = (req, res, next) => {
const placeId = req.params.pid // Accessing the p1 in pid URL scrapping {pid:'p1'}
const place= INITIAL_DATA.find(p => { //find method goes over each element in the array, the argument p represents the element where find loop is
return p.id ===placeId
});
if (!place) {
const error= new HttpError('No bus stop found for the provided ID.', 404);
throw error;
}
res.json({place: place});
};
const getPlacesByCreatorId = (req, res, next)=> {
const userId = req.params.uid;
const places = INITIAL_DATA.filter(p=>{ //filter to retrieve multiple places, not only the first one
return p.creator ===userId;
});
if (!places || places.length===0) {
return next(
new HttpError('Could not find bus stops for the provide user id', 404)
);
}
res.json({places});
};
const createPlace = async (req, res,next) => {
const errors = validationResult(req);
if (!errors.isEmpty()){
return next(new HttpError ('Invalid bus stop please check your data', 422));
}
//const { title, description, busrespect, address, creator } = req.body; //erased location for now.
/* let place = new BusStop({
title: req.body.title,
description: req.body.description,
busrespect: req.body.busrespect,
address : req.body.address,
creator: req.body.creator
})
awaitplace.save()
.then(response=>{
res.json({
message : "Employee added sucessfully!"
})
})
.catch(err=>{
res.json({
message : "An error has occured!"
})
})
} */
const { title, description, busrespect, address, creator } = req.body;
try {
await BusStop.create({
title:title,
description: description,
busrespect:busrespect,
address: address,
creator: creator
});
res.send({status: "ok"});
} catch(error) {
res.send({status:"error caught"});
}
};
const updatePlace = (req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()){
console.log(errors);
throw new HttpError ("Invalid inputs passed, please check your data ", 422);
};
const { title, description } = req.body;
const placeId = req.params.pid;
const updatedPlace = { ...INITIAL_DATA.find(p => p.id === placeId)};
const placeIndex = INITIAL_DATA.findIndex(p => p.id === placeId);
updatedPlace.title = title;
updatedPlace.description = description;
INITIAL_DATA[placeIndex] = updatedPlace;
res.status(200).json({place: updatedPlace});
};
const deletePlace = (req, res, next) => {
const placeId = req.params.pid;
if (!INITIAL_DATA.find(p=> p.id ===placesId))
throw new HttpError('Could not find a bus stop for that ID ')
INITIAL_DATA = INITIAL_DATA.filter(p=> p.id !== placeId)
res.status(200).json({message: 'Deleted Place'});
};
exports.getPlaceById= getPlaceById;
exports.getPlacesByCreatorId = getPlacesByCreatorId;
exports.createPlace = createPlace;
exports.updatePlace = updatePlace;
exports.deletePlace = deletePlace;
Inside models folder I have two files: http-error.js which has this code:
class HttpError extends Error {
constructor(message, errorCode) {
super (message);
this.code = errorCode;
}
}
module.exports = HttpError;
The other file inside is the schema which is place.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const placeSchema = new Schema({
title: {
type: String
},
description: {
type: String
},
address: {
type: String
},
busrespect: {
type: String
},
creator: {
type: String
}
},
)
const BusStop = mongoose.model('BusStop', placeSchema)
module.exports= BusStop
Summary: somewhere in the try catch part from createPlace something is going wrong since my data entry is always going to the error status I indicated in that part.
I'm trying to add the Bearer in the header section in POST request while testing with Supertest. I tried many methods. I'm a beginner in testing. Please suggest some better ways to achieve this.
here is my sample code. What is wrong with this?
it('POST/userAuth', async (done) => {
const res = await request
.post('/v1/user/haha')
.set('Authorization', `bearer ${Token}`)
.send({
title: 'Some random text',
options: [
{ start: hello, end: world },
{ start: good, end: bye },
],
});
You can set a request header like this:
const request = require('supertest');
const express = require('express');
const app = express();
const TOKEN = 'some_token';
describe('POST /some-url', function() {
it('does something', function(done) {
request(app)
.post('/some-url')
.send({ body: 'some-body' })
.set('Authorization', `Bearer ${TOKEN}`)
.expect(200, done);
});
});
in superagent docs you can find specialized .auth method
interface Request extends Promise<Response> {
auth(user: string, pass: string, options?: { type: "basic" | "auto" }): this;
auth(token: string, options: { type: "bearer" }): this;
...
}
(supertest is using superagent under the hood)
I prefer to set auth in before function for all tests in the set.
import * as Koa from 'koa';
import * as http from 'http';
import { agent as superagent } from 'supertest';
import { UserController } from './user-controller';
const testBearerToken = 'test-bearer-token';
describe('user controller', async () => {
context('simple user', async () => {
it('should save user', async () => {
const response = await test
.post('/v1/user/haha')
// you can here, but rather set it in the before function
//.auth(testBearerToken, { type: 'bearer' });
.send({
title: 'Some random text',
options: [
{ start: 'hello', end: 'world' },
{ start: 'good', end: 'bye' },
],
});
// .expect(...)
// expect(response)...
});
});
let test;
before(async () => {
const app = new Koa();
const userController = new UserController();
app.use(userController.middleware());
test = superagent(http.createServer(app.callback()))
.auth(testBearerToken, { type: 'bearer' });
});
});
I'm using Mocha/Chai/Sinon to develop some unit tests on a Node.js application (Express). I made a fake request/response object to pass to the function that I'm trying to test. Inside one of my stubs, the value of the property statusCode of the response object is changed to 200. However, at the end of the test, Mocha reports it as being the default value for the property (500, in this case).
Here is the test code:
it('should return status 200 if product was saved', function(){
//fake objects
const fakeReq = {
flash(){return true},
body:{
title: '',
price: 0,
description: ''
},
file: {
path: 'path'
},
session: {
user: ''
}
}
const fakeRes = {
statusCode: 500,
redirect(){
this.statusCode = 200; //this successfully changes to 200
return this;
}
}
//fake methods
sinon.stub(expressValidator, 'validationResult').callsFake(fakeValidation);
sinon.stub(Product.prototype, 'save').callsFake(sinon.fake.resolves('ok'));
//expectations
adminController.postAddProduct(fakeReq, fakeRes, ()=>{});
sinon.restore();
expect(fakeRes.statusCode).to.equal(200); //test fails returning 500
});
Here is the method that I want to test, more specifically, the product.save() call, at the end:
exports.postAddProduct = (req, res, next) => {
const validationErrors = validationResult(req);
if (!validationErrors.isEmpty()) {
req.flash('validationErrors', validationErrors.array());
return res.status(422).redirect('/admin/add-product');
}
const title = req.body.title;
const image = req.file;
const price = req.body.price;
const description = req.body.description;
if(!image){
req.flash('validationErrors', [{param:'productImage', msg: 'Insira uma imagem vĂ¡lida!'}]);
return res.status(422).redirect('/admin/add-product');
}
const product = new Product({
title: title,
price: price,
imageUrl: image.path,
description: description,
userId: req.session.user
});
product.save()
.then(results => {
return res.redirect('/admin/products');
})
.catch(err => {
next(new Error(err));
});
};
EDIT:
Changed the test function to use a spy in order to check if the redirect method was being called, but it's always returning false. I'm thinking that it might be because Js doesn't pass by reference, unless the contents of the object gets changed. New testing code:
const fakeRes = {
status(code){
this.statusCode = code;
return this;
},
redirect(){return true;},
statusCode: 500
}
const redirectSpy = sinon.spy(fakeRes, 'redirect');
//fake methods
sinon.stub(expressValidator, 'validationResult').callsFake(fakeValidation);
sinon.stub(Product.prototype, 'save').callsFake(sinon.fake.resolves('ok'));
//expectations
adminController.postAddProduct(fakeReq, fakeRes, ()=>{});
sinon.restore();
expect(redirectSpy.withArgs('/admin/products').calledOnce).to.be.true;
});
I'm having an error "Error: socket hang up" and I don't know what causes this but it saves the data in database.
here's my code:
dataschema.js
const mongoose = require("mongoose");
const DataSchema = new mongoose.Schema({
data1: {
type: String
},
data2: {
type: String
},
data3: {
type: String
},
data4: {
type: String
},
});
const DataModel = mongoose.model("TEST123", DataSchema);
module.exports = DataModel;
routes.js
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const DataModel = require('./models/dataschema');
var bodyParser = require('body-parser');
app.use(bodyParser.json());
mongoose.connect(
"mongodb://localhost:27017/stocksmonitor?readPreference=primary&appname=MongoDB%20Compass%20Community&ssl=false",
{ useNewUrlParser: true }
);
app.post('/insert', (req, res) => {
const stock = new DataModel({
data1: req.body[0],
data2: req.body[1],
data3: req.body[2],
data4: req.body[3],
})
stock.save();
})
app.listen(3001, () => {
console.log("You are connected");
})
savedata.js
const axios = require('axios');
SaveInfo = () => {
const testdata = ["a", "b", "c", "d"]
axios({
method: 'post',
url: 'http://localhost:3001/insert',
data: testdata
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
SaveInfo();
I inspected the code and found that you did not return response for your controller. In the code below after the save add res.send() or res.json(). So express can return a proper response. Otherwise request will timed out, because it did not resolve and Express will cut the connection. Therefore axios is throwing Error: Socket hang up unexpectedly.
app.post('/insert', (req, res) => {
const stock = new DataModel({
data1: req.body[0],
data2: req.body[1],
data3: req.body[2],
data4: req.body[3],
})
stock.save();
})
Hi i tried to upload file with expo:
the console.log give me this error "Streaming file uploads via req.file() are only available over HTTP with Skipper" but when i tried it with postman it's workd.I use sailsJs for my back-end
this is my code for my expo react
const[imageUri, setImageUri]=useState()
const[imageUpload, setImageUpload]=useState()
const selectImage = async()=>{
try {
const result = await ImagePicker.launchImageLibraryAsync();
if(!result.cancelled)
setImageUri(result.uri)
setImageUpload(result)
} catch (error) {
console.log('Error running on image')
}
}
const handleSubmit = async () => {
const dataDemande = {
projectTitle: titre,
material: materiel,
description: description,
projectType: checked,
lieuRendezvous: value_3,
idClient: props.route.params.id,
model: imageUpload
};
console.log(dataDemande);
var res = await demandeClient(dataDemande);
console.log(res);
props.navigation.navigate("Tableau de bord - Client");
};
and this is the code from the back-end
findCouturierAndCreateDemande: async function (req, res) {
var recherche = req.body
req.file('model').upload({
adapter: require('skipper-gridfs'),
uri: 'mongodb://localhost:27017/image'
}, async function (err, filesUploaded) {
if (err) return res.serverError(err);
console.log(filesUploaded[0].fd)
var couturier = await Client.find({
where: {
isCouturier: true,
ville: { contains: recherche.ville },
adresse: { contains: recherche.adresse },
rue: { contains: recherche.rue },
},
})
var img = await Image.create(_.omit(filesUploaded[0], ['status', 'field', 'extra'])).fetch()
var newDemande = await Demande.create({
titre: recherche.projectTitle,
materiel: recherche.material,
description: recherche.description,
service: recherche.projectType,
positionActivity: recherche.lieuRendezvous,
client: recherche.idClient,
modelImage: img.id
}).fetch()
console.log(img)
return res.ok({couturier, newDemande})
});
}