Unable to access value of req.body - node.js

I am trying to do a PUT request to update my DB in Mongo using Axios so I can update the current week and season. In my route, I can access the req.body, but if I try to set the values, it says the values are undefined. I have tried many different things at this point. I ran into this issue as well: "Cast to Number failed".
Here is what the request looks like:
function currentWeek() {
const currentWeek =
"https://api.sportsdata.io/v3/nfl/scores/json/CurrentWeek?key=...";
axios.get(currentWeek).then((res) => {
const weekCheck = res.data;
const timeframeURL =
"https://api.sportsdata.io/v3/nfl/scores/json/Timeframes/current?key=...";
console.log(weekCheck);
axios.get(timeframeURL).then((res) => {
const timeframeWeek = res.data;
// console.log(timeframeWeek);
const thisWeek = timeframeWeek.filter(
(timeframeWeek) => timeframeWeek.Week === weekCheck
);
console.log(thisWeek);
const config = {
headers: {
"Content-Type": "application/json",
},
};
axios
.put("http://localhost:4000/api/currentweek/5ffce18e78d4742414cf279e", thisWeek, config)
.then((res) => console.log("working"))
.catch((err) => console.error(err));
console.log("Done!");
});
});
}
Here is my route:
router.put("/:_id", async (req, res) => {
const { Season, Week } = req.body;
const { _id } = req.params;
const weekField = {};
// SETING THE VALUES FROM REQ.BODY TO BE IN weekField
if (Season) weekField.Season = Season;
if (Week) weekField.Week = Week;
try {
let weekParam = await CurrentWeek.find({_id});
if (!weekParam) return res.stats(404).json({ msg: "ID in the Params does not exist" });
console.log(_id);
console.log(req.body) // RETURNS THE OBJECT CORRECTLY
console.log(weekField); // RETURNS AS AN EMPTY OBJECT
console.log("From Route ^^");
weekParam = await CurrentWeek.findOneAndUpdate(
_id,
{ $set: weekField },
{ new: true }
);
res.json(weekParam);
} catch (err) {
console.error(err.message);
res.status(500).send("Server Error");
}
});
Here is the model:
const mongoose = require('mongoose');
const CurrentWeekSchema = mongoose.Schema([{
Week: Number,
Season: Number
}]);
const CurrentWeek = module.exports = mongoose.model('currentweek', CurrentWeekSchema);
//^enables require from routes
module.exports.getCurrentWeek = function(callback, limit){
CurrentWeek.find(callback).limit(limit);
}
And here is an example of the object I am trying to take in:
[
{
SeasonType: 3,
Season: 2020,
Week: 2,
Name: 'Divisional Playoffs',
ShortName: 'Divisional',
StartDate: '2021-01-12T00:00:00',
EndDate: '2021-01-18T23:59:59',
FirstGameStart: '2021-01-16T16:35:00',
FirstGameEnd: '2021-01-16T20:35:00',
LastGameEnd: '2021-01-17T22:40:00',
HasGames: true,
HasStarted: true,
HasEnded: false,
HasFirstGameStarted: false,
HasFirstGameEnded: false,
HasLastGameEnded: false,
ApiSeason: '2020POST',
ApiWeek: '2'
}
]

I found out the issue and maybe this will be helpful for someone else in the future!
In my router file I need to change this:
const { Season, Week } = req.body;
const { _id } = req.params;
const weekField = {};
// SETING THE VALUES FROM REQ.BODY TO BE IN weekField
if (Season) weekField.Season = Season;
if (Week) weekField.Week = Week;
To this:
const data = req.body;
const { Season, Week } = data[0];
const { _id } = req.params;
const weekField = {};
// SETING THE VALUES FROM REQ.BODY TO BE IN weekField
if (Season) weekField.Season = Season;
if (Week) weekField.Week = Week;
The reason is because the data that the put request is receiving is coming in an array, so I had to set the req.body to the first object in the array.

Related

POST going directly to the catch error and not saving data using mongoose, MongoDB, NodeJS, and Express

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.

How to filter posts by category

I tried to filter posts by category but it's not working on frontend
I want when a user clicks on a particular category to get posts in that category
this is my backend (NODEJS)
exports.getMovies = async (req, res) => {
const { pageNo = 0, limit = 10 } = req.query;
// filter category
let filter = {};
if (req.query.categories) {
filter = { category: req.query.categories.split(",") };
}
const movies = await Movie.find(filter)
.populate("category comments")
.sort({ createdAt: -1 })
.skip(parseInt(pageNo) * parseInt(limit))
.limit(parseInt(limit));
const results = movies.map((movie) => ({
id: movie._id,
title: movie.title,
poster: movie.poster?.url,
responsivePosters: movie.poster?.responsive,
category: movie.category,
comments: movie.comments,
genres: movie.genres,
status: movie.status,
}));
res.json({ movies: results });
};
The front end API
export const getMovies = async (pageNo, limit, filter) => {
const token = getToken();
try {
const { data } = await client(
`/movie/movies?pageNo=${pageNo}&limit=${limit}&filter=${filter}`,
{
headers: {
authorization: "Bearer " + token,
"content-type": "multipart/form-data",
},
}
);
return data;
} catch (error) {
return catchError(error);
}
};
The front end CATEGORY COMPONENT
I want the user to filter the post by category by clicking on the category
export default function AllCategory() {
const [allCategories, setAllCategories] = useState([]);
const fetchCategories = async () => {
const res = await getCategoryForUsers();
setAllCategories(res);
};
useEffect(() => {
fetchCategories();
}, []);
return (
<div className=''>
<ul className=' space-x-4 '>
{allCategories.map((c, index) => {
return <li key={index}>{c.title}</li>;
})}
</ul>
</div>
);
}
Remove the ``` as that is not how to post code here.
You'll want to use a filter first in another function
const [selectedCategories, setCurrentlySelectedCategories] = useState([]);
const handleSelectCategory = (category) => {
const currentlySelected = allCategories.filter((item) => item.category == category);
setCurrentlySelectedCategories(currentlySelected);
}
Now just call map on the selectedCategories

How to update data in mongodb database and show in ui

Client-side code...!!!
I want to update the quantity by clicking the Delivered button...
In this section have quantity that i'm show bring database.
const [reload, setReload] = useState(true);
const [stock, setStock] = useState({});
const { _id, quantity } = stock;
useEffect(() => {
const url = `http://localhost:5000/stock/${inventoryId}`;
fetch(url)
.then((res) => res.json())
.then((data) => setStock(data));
}, [reload]);
In this function I want to update quantity that i'm decrising by clicking button
const handleDelivered = () => {
const updateQuantity = parseInt(quantity) - 1; // *actually I want to decrise quantity by clicking Delivered button*
const url = `http://localhost:5000/stock/${inventoryId}`;
fetch(url, {
method: 'PUT',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify(updateQuantity), // *I don't know it's right or wrong and it's so important*
})
.then((res) => res.json())
.then((data) => {
setReload(!reload);
setStock(data);
console.log(data);
});
};
return <button onClick={handleDelivered}>Delivered</button>
Server-side code...!!!
On server-side I want to update just the quantity value...
app.put('/stock/:id', async (req, res) => {
const id = req.params.id;
const updateQuantity = req.body;
const filter = { _id: ObjectId(id) };
const options = { upsert: true };
const updateDoc = {
$set: {
updateQuantity, // *I'm not sure how to set it database. But I want to update quantity value*
},
};
const result = await stockCollection.updateOne(filter, updateDoc, options);
res.send(result);
});
You need to set the updatedQuantity on the "quantity" field of the database. You need to change the "updateDoc" object like this in your server-side code:
const updateDoc = {
$set: {
quantity: updateQuantity,
},
};
Hope this should work.
Client-side code
const handelUpload = (e) => {
e.preventDefault();
const storeQuantity = parseInt(product?.quantity);
const newQuantity = parseInt(e.target.quantity.value);
const quantity = storeQuantity + newQuantity;
if (quantity > 0) {
fetch(`http://localhost:5000/stock/${inventoryId}`, {
method: "PUT",
headers: {
"Content-type": "application/json; charset=UTF-8",
},
body: JSON.stringify({ quantity }),
})
.then((response) => response.json())
.then((data) => {
console.log("success", data);
alert("users added successfully!!!");
e.target.reset();
setIsreload(!isReload);
});
} else {
console.log("input number");
}
};
Server side code api
app.put("/stock/:id", async (req, res) => {
const id = req.params.id;
const updatedProduct = req.body;
console.log(updatedProduct.quantity);
console.log(typeof updatedProduct.quantity);
const filter = { _id: ObjectId(id) };
const options = { upsert: true };
const updatedDoc = {
$set: {
// name: updatedProduct.name,
// email: updatedProduct.email,
quantity: updatedProduct.quantity,
// price: updatedProduct.price,
},
};
const result = await stockCollection.updateOne(filter,updatedDoc,options
);
res.send(result);
});

I can't figure where is the problem with my graphql request

I'm getting bad request code every time i try to send data query in graphql,
and I can't figure if the problem from the resolver or from the input,
below is the resolver :
const addTranslationTableAdminResolver = async (args, context, info) => {
checkAuth(context);
const videocardId = args.input.videoCardId;
const videoLink = args.input.videoLink;
const orgId = args.input.orgId;
await context.dao.createTranslationTable({
id,
orgId,
videocardId,
dateTime,
videoLink,
});
return {
statusMessage: 'SUCCESS',
};
};
and the data-object access as below:
const createTranslationTable = async ({ orgId, videocardId, videoLink }) => {
const queryString = `INSERT INTO translation_table (org_id, video_id,request_date,video_link)
VALUES ($1, $2, $3, $4) RETURNING *`;
const dateTime = new Date();
const values = [orgId, videocardId, dateTime, videoLink];
const result = await query(queryString, values);
if (result && result.rows.length === 1) {
return getAllTranslationObject(result.rows[0]);
}
};
when I'm trying to send data query i'm getting the same error as above.
const createTransaltionVideoCard = (orgId, videoCardId, videoLink) => {
return gqBackOfficeClient.mutate({
mutation: gql`
mutation {
createTranslationTable(input: {
orgId: ${orgId},
videocardId: ${videoCardId},
videoLink :"${videoLink}"
}) {
statusMessage
}
}
`,
});
};
const handleTranslationButtonClick = (orgId, videoCardId, videoLink) => {
setIsTranslationButtonClicked(true);
createTransaltionVideoCard({
orgId,
videoCardId,
videoLink,
}).then((res) => {
console.log(res);
});
};
just to update , solved this issue, it was a problem with resolvers, and now its working fine –

How can I make Jasmine wait before my expect calls, in order to wait for the code that's executed after data is returned to be run?

I just added a route in one of my node router files and would like to add the appropriate unit test for it. The route is the following:
router.post('/addtradables', checkIsAdmin, async function(req, res, next) {
const SteamApp = require('../models/steamapp.model');
const Tradable = require('../models/tradable.model');
const User = require('../models/user.model');
const postedTradables = req.body.tradables;
if(postedTradables) {
res.json({ success: true, result: constants.PROCESS_STARTED, textResult: 'The tradables are being added' });
const adminUser = await User.findOne({ steamId: ADMIN_ID }).exec();
for(let currentKey in postedTradables) {
if(postedTradables.hasOwnProperty(currentKey)) {
const currentTradable = postedTradables[currentKey];
const appFound = currentTradable.sku ? await SteamApp.findOne({ appid: currentTradable.sku }).exec() : null;
await new Tradable( { /* object data here */ } ).save();
}
}
} else {
return res.json({ success: false, result: constants.INVALID_FORMAT, textResult: 'No tradable found, check the format' });
}
} );
As you can see, it returns an object with a code and text message so that the front end can know if the process was started or not. This is because the insertion process can take a while, depending on the input data.
Here is my Jasmine spec file:
const app = require('../../app');
const request = require('supertest');
const MongoDbTest = require('../../lib/mongodb-tests.lib');
const jwt = require('jsonwebtoken');
const SteamApp = require('../../models/steamapp.model');
const Tradable = require('../../models/tradable.model');
const User = require('../../models/user.model');
const JWT_TOKEN = process.env.JTW_KEY;
const ADMIN_ID = process.env.MASTER_STEAMID;
const constants = require('../../config/constants');
const adminUser = {
role: 'admin',
steamId: ADMIN_ID
};
const testTradable = {
sku: 1234,
barterId: 83838,
extra: 2,
type: 'gift',
title: 'Les patates volent!'
};
describe("route /addtradables", () => {
const mongod = new MongoDbTest();
let testOwner;
beforeAll(async () => {
await mongod.connect();
await new SteamApp({ appid: 1234, name: 'patate' }).save();
testOwner = await new User(adminUser).save();
} );
afterAll(async () => {
await SteamApp.deleteMany({});
await User.deleteMany({});
await mongod.close();
} );
it("devrait retourner un message indiquant que le format est incorrect lorsque c'est le cas", async () => {
const userToken = jwt.sign(adminUser, JWT_TOKEN, { algorithm: 'HS256' });
const response = await request(app).post(`/api/addtradables`).send({ patate: 'pouelle' }).set('Authorization', `Bearer ${userToken}`).expect('Content-Type', /json/);
expect(response.statusCode).toBe(200);
expect(response.body.success).toBe(false);
expect(response.body.result).toBe(constants.INVALID_FORMAT);
} );
it("devrait retourner un message indiquant que le processus a débuté lorsque le format est correct", async () => {
const userToken = jwt.sign(adminUser, JWT_TOKEN, { algorithm: 'HS256' });
const response = await request(app).post(`/api/addtradables`).send({ tradables: { 9837489374: testTradable } }).set('Authorization', `Bearer ${userToken}`).expect('Content-Type', /json/);
expect(response.statusCode).toBe(200);
expect(response.body.success).toBe(true);
/*
I WANT TO WAIT HERE! If I don't wait for the router.post call to finish the data will not be available in the database
*/
const insertedTradable = await Tradable.findOne({ appid: 1234 }).exec();
expect(insertedTradable.barterId).toBe(testTradable.barterId);
expect(insertedTradable.isGift).toBe(true);
expect(insertedTradable.copies).toBe(testTradable.extra);
expect(insertedTradable.name).toBe(testTradable.title);
} );
} );
Is there a way to spy on the router.post call and check when everything is completed so that I can extract data from the database and check that the data was inserted properly? Short of that, what would be the best way to sleep / stop execution in the jasmine test routine while the the router.post call wraps up? I've looked at using a done function but since the code is inside the router I don't see how I could use done in this scenario.

Resources