timeout async callback testing with sinon jest supertest to simulate error 500 on express api - express

I am testing an api with all http 500 errors.
Here I try to use sinon.stub to test on a failing server and get a 500 error, but I get a timeOut async callback, or if I use my app a successfull 200 response statusCode as if sinon.stub has no effect. I must miss something and I am stucked...
would you see a horrifying error below ?
thanks for your precious help
process.env.NODE_ENV = "test";
const app = require("../../app");
const request = require("supertest");
const sinon = require("sinon");
// /************************** */
const usersRoute = require("../../routes/Users");
const express = require("express");
const initUsers = () => {
const app = express();
app.use(usersRoute);
return app;
};
describe("all 5xx errors tested with stub", function () {
it("should return a 500 when an error is encountered", async (done) => {
let secondApp;
sinon.stub(usersRoute, "post").throws(
new Error({
response: { status: 500, data: { message: "failed" } },
})
);
secondApp = initUsers(); //==========> Timeout Async Callback
//secondApp = require("../../app"); //==============> gives a 200 instead of 500
const fiveHundredError = await request(secondApp)
.post("/users/oauth?grant_type=client_credentials")
.send({
username: "digitalAccount",
password: "clientSecret",
});
expect(fiveHundredError.statusCode).toBe(500);
//sinon.restore();
done();
});
});
app is using express.Router to get users route :
const express = require("express");
const router = express.Router();
const axios = require("axios");
router.post("/users/oauth", async (req, res) => {
//if (all missing parts)
//else {
try {
if (req.fields) {
const response = await axios.post(
`${base_url}oauth/token?grant_type=${req.query.grant_type}`,
{},
{
auth: {
username: req.fields.username,
password: req.fields.password,
},
}
);
res.json(response.data);
}
} catch (error) {
return res.status(error.response.status).json(error.response.data);
}
}
});
module.exports = router;
See server.js :
const app = require("./app");
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`server starting on port ${port}!`));
and app.js :
// private environment:
require("dotenv").config();
const express = require("express");
const formidableMiddleware = require("express-formidable");
const cors = require("cors");
const app = express();
app.use(formidableMiddleware());
app.use(cors());
const usersRoute = require("./routes/Users");
app.use(usersRoute);
app.get("/", (req, res) => {
res.status(200).send("Welcome to Spark Admin back end!");
});
app.all("*", (req, res) => {
return res.status(404).json({ error: "Web url not found" });
});
module.exports = app;

I finally opted for 'nock' and deleted 'sinon'
const nock = require("nock");
const axios = require("axios");
describe("POST login: all 5xx errors tested with nock", function () {
it("should return a 500 when an error is encountered", async (done) => {
const scope = nock("http://localhost:5000")
.post(
"/users/oauth",
{},
{
username: "blibli",
password: "blabla",
}
)
.reply(500, {
response: {
statusCode: 500,
body: { error: "AN ERROR OCCURED" },
},
});
try {
await axios.post(
"http://localhost:5000/users/oauth",
{},
{
username: "blibli",
password: "blabla",
}
);
} catch (e) {
expect(e.response.status).toBe(500);
}
done();
});
});

Related

getting Can't find / on this server while deploying my app on localhost

when I tried to connect my application with API I'm getting error in my localhost saying
"status": "fail",
"message": "Can't find / on this server",
"error": { statusCode: 404, status: "fail", isOperational: true },
"stack": "Error: Can't find / on this server\n at C:\\Users/*/*app.js:66",
here is my app.js
const express = require("express");
const morgan = require("morgan");
const rateLimit = require("express-rate-limit");
const helmet = require("helmet");
const mongoSanitize = require("express-mongo-sanitize");
const xss = require("xss-clean");
const hpp = require('hpp');
const AppError = require("./API/Utils/appError");
const globalErrorHsndler = require("./API/controllers/errorController");
const usersRouter = require("./API/routes/usersRoute");
const app = express();
app.use(express.json({ limit: "10kb" }));
// DATA SANITIZATION against NoSQL query injection
app.use(mongoSanitize());
// DATA SANITIZATION against site script XSS
app.use(xss());
// PREVENT PARAMETER POPULATION
app.use(
hpp({
whitelist: [
"duration",
"difficulty",
"price",
"maxGroupSize",
"ratingsAverage",
"ratingsQuantity",
],
})
);
// SECURE HEADER HTTP
app.use(helmet());
//RATE LIMIT
const apiLimiter = rateLimit({
windowMs: 60 * 60 * 1000, // 15 minutes
max: 100, // limit each IP to 100 requests per windowMs
message: "Too many requests, please try again later"
});
// apply to specific routes
app.use("/api", apiLimiter);
app.use(morgan("dev"));
//CUSTOM MIDDLE WARE
app.use((req, res, next) => {
console.log("Hey i am from middleware function 👋");
next();
});
app.use((req, res, next) => {
req.requestTime = new Date().toISOString();
next();
});
app.use("/api/v1/users", usersRouter);
//ERROR SECTION
app.all("*", (req, res, next) => {
console.log(`Received request for url: ${req.originalUrl}`);
const error = new AppError(`Can't find ${req.originalUrl} on this server`, 404);
console.log(`Data inside next AppError: ${error}`);
next(error);
});
//GLOBAL ERROR HANDLEING
app.use(globalErrorHsndler);
module.exports = app;
here is my userRouter.js
const express = require("express");
const userControllers = require("./../controllers/userControllers");
const authController = require("./../controllers/authController");
const router = express.Router();
router.post("/signup", authController.signup);
router.post("/login", authController.login);
router.post("/forgotPassword", authController.forgotPassword);
router.patch("/resetPassword/:token", authController.resetPassword);
router.patch("/updateMyPassword", authController.protect, authController.updatePassword);
router.patch("/updateMe", authController.protect, userControllers.updateMe);
router.delete("/deleteMe", authController.protect, userControllers.deleteMe);
//ROUTERS USERS
router
.route("/")
.get(userControllers.getAllUsers)
.post(userControllers.createUser);
router
.route("/:id")
.get(userControllers.getSingleUser)
.patch(userControllers.updateUser)
.delete(userControllers.deleteUser);
module.exports = router;
and here is server.js
const dotenv = require("dotenv");
const mongoose = require("mongoose");
const app = require("./app");
const next = require("next");
const port = process.env.PORT || 3000;
const dev = process.env.NODE_ENV !== "production";
const server = next({ dev });
const handle = server.getRequestHandler();
process.on("uncaughtException", err=>{
console.log("uncaughtException Shutting down Application");
console.log(err.name, err.message);
process.exit(1);
});
dotenv.config({ path: "./config.env" });
const DB = process.env.DATABASE.replace(
"<PASSWORD>",
process.env.DATABASE_PASSWORD
);
mongoose
.connect(DB, {
useCreateIndex: true,
useFindAndModify: false,
useNewUrlParser: true,
})
.then((con) => {
console.log("DB Connection Successfully");
})
server.prepare().then(() => {
app.get("*", (req, res) => {
return handle(req, res);
});
app.listen(port, () => {
console.log(`App running on port ${port}....`);
});
});
process.on("unhandledRejection", (err) => {
console.log("unhandledRejection Shutting down Application");
console.log(err.name, err.message);
server.close(() => {
process.exit(1);
});
});
I need to ask from experts as I'm new to this

Shopify node.js and react.js plugin with vite.js not working

I've created a plugin in shopify using node.js & vite.js.
shopify app create node
After running using npm run dev, it generates a url like this: https://b136-0000-7400-56-bc78-5000-178b-d6f3-6000.ngrok.io/login?shop=shopname.myshopify.com
When I open this link, it start reloading infinite with error
This is my index.js:
import { resolve } from "path";
import express from "express";
import cookieParser from "cookie-parser";
import { Shopify, LATEST_API_VERSION } from "#shopify/shopify-api";
import "dotenv/config";
import applyAuthMiddleware from "./middleware/auth.js";
import verifyRequest from "./middleware/verify-request.js";
const USE_ONLINE_TOKENS = true;
const TOP_LEVEL_OAUTH_COOKIE = "shopify_top_level_oauth";
const PORT = parseInt(process.env.PORT || "8081", 10);
const isTest = process.env.NODE_ENV === "test" || !!process.env.VITE_TEST_BUILD;
Shopify.Context.initialize({
API_KEY: process.env.SHOPIFY_API_KEY,
API_SECRET_KEY: process.env.SHOPIFY_API_SECRET,
SCOPES: process.env.SCOPES.split(","),
HOST_NAME: process.env.HOST.replace(/https:\/\//, ""),
API_VERSION: LATEST_API_VERSION,
IS_EMBEDDED_APP: true,
// This should be replaced with your preferred storage strategy
SESSION_STORAGE: new Shopify.Session.MemorySessionStorage(),
});
// Storing the currently active shops in memory will force them to re-login when your server restarts. You should
// persist this object in your app.
const ACTIVE_SHOPIFY_SHOPS = {};
Shopify.Webhooks.Registry.addHandler("APP_UNINSTALLED", {
path: "/webhooks",
webhookHandler: async (topic, shop, body) => {
delete ACTIVE_SHOPIFY_SHOPS[shop];
},
});
// export for test use only
export async function createServer(
root = process.cwd(),
isProd = process.env.NODE_ENV === "production"
) {
const app = express();
app.set("top-level-oauth-cookie", TOP_LEVEL_OAUTH_COOKIE);
app.set("active-shopify-shops", ACTIVE_SHOPIFY_SHOPS);
app.set("use-online-tokens", USE_ONLINE_TOKENS);
app.use(cookieParser(Shopify.Context.API_SECRET_KEY));
applyAuthMiddleware(app);
app.post("/webhooks", async (req, res) => {
try {
await Shopify.Webhooks.Registry.process(req, res);
console.log(`Webhook processed, returned status code 200`);
} catch (error) {
console.log(`Failed to process webhook: ${error}`);
if (!res.headersSent) {
res.status(500).send(error.message);
}
}
});
app.get("/products-count", verifyRequest(app), async (req, res) => {
const session = await Shopify.Utils.loadCurrentSession(
req,
res,
app.get("use-online-tokens")
);
const { Product } = await import(
`#shopify/shopify-api/dist/rest-resources/${Shopify.Context.API_VERSION}/index.js`
);
const countData = await Product.count({ session });
res.status(200).send(countData);
});
app.post("/graphql", verifyRequest(app), async (req, res) => {
try {
const response = await Shopify.Utils.graphqlProxy(req, res);
res.status(200).send(response.body);
} catch (error) {
res.status(500).send(error.message);
}
});
app.use(express.json());
app.use((req, res, next) => {
const shop = req.query.shop;
if (Shopify.Context.IS_EMBEDDED_APP && shop) {
res.setHeader(
"Content-Security-Policy",
`frame-ancestors https://${shop} https://admin.shopify.com;`
);
} else {
res.setHeader("Content-Security-Policy", `frame-ancestors 'none';`);
}
next();
});
app.use("/*", (req, res, next) => {
const { shop } = req.query;
// Detect whether we need to reinstall the app, any request from Shopify will
// include a shop in the query parameters.
if (app.get("active-shopify-shops")[shop] === undefined && shop) {
res.redirect(`/auth?${new URLSearchParams(req.query).toString()}`);
} else {
next();
}
});
/**
* #type {import('vite').ViteDevServer}
*/
let vite;
if (!isProd) {
vite = await import("vite").then(({ createServer }) =>
createServer({
root,
logLevel: isTest ? "error" : "info",
server: {
port: PORT,
hmr: {
protocol: "ws",
host: "localhost",
port: 64999,
clientPort: 64999,
},
middlewareMode: "html",
},
})
);
app.use(vite.middlewares);
} else {
const compression = await import("compression").then(
({ default: fn }) => fn
);
const serveStatic = await import("serve-static").then(
({ default: fn }) => fn
);
const fs = await import("fs");
app.use(compression());
app.use(serveStatic(resolve("dist/client")));
app.use("/*", (req, res, next) => {
// Client-side routing will pick up on the correct route to render, so we always render the index here
res
.status(200)
.set("Content-Type", "text/html")
.send(fs.readFileSync(`${process.cwd()}/dist/client/index.html`));
});
}
return { app, vite };
}
if (!isTest) {
createServer().then(({ app }) => app.listen(PORT));
}
The app is installing fine but it's getting refreshed again and again due to failed connection to ws (as mentioned in the screenshot). I tried a few things around changing the settings of the HMR but doesn't seem to be connecting.

how to pass req.params in a {mergeparams} for a post request express

I am trying to make a post request in a nested route but i keep getting 404 on postman.
app.js to handle my routes
app.use("/channel", controllers.channelController);
app.use("/channelentry", controllers.channelEntryController);
channelcontroller
const Express = require('express');
const router = Express.Router();
const channelEntry = require('./channelentrycontroller')
router.use('/:channelId', channelEntry)
channelEntryController
const Express = require('express');
const channelEntry = Express.Router({mergeParams: true});
channelEntry.get("/", async (req, res) => {
const channelId = req.params.channelId
try {
const messages = await models.ChannelEntryModel.findAll({
include: [{
model: models.ChannelModel,
where: { channelId: channelId }
}],
});
res.status(200).json({messages})
} catch (err) {
res.status(500).json({error: err})
}
});
channelEntry.post("/create", validateJWT, async (req, res) => {
const {entry} = req.body.channelentry
const channelId = req.params.channelId
const channelMessage = {
entry,
userId: req.user.userId,
channelId: channelId
}
try {
const currentChannelId = await models.ChannelModel.findOne({
where: {
channelId: channelId
}
})
const newChannel = await models.ChannelEntryModel.create(channelMessage, currentChannelId);
res.status(200).json(newChannel)
} catch (err) {
console.log(err)
res.status(500).json({error: err})
}
})
my get request works but sends an empty array because i have no entrys.
I ended up answering my own question.
I commented out:
app.use("/channelentry", controllers.channelEntryController);
I guess it was conflicting with my other route.

Express. Failed to load resource: the server responded with a status of 404

I am trying to make a post request using router.post and I keep getting " the server responded with a status of 404.
I have a routes folder with the file usersRoute.js :
const express = require("express");
const router = express.Router();
const User = require("../models/userModel");
router.post("/login", async(req, res) => {
const { username, password } = req.body;
try {
const user = await User.findOne({ username, password });
if (user) {
res.send(user);
} else {
return res.status(400).json(error);
}
} catch (error) {
return res.status(400).json(error);
}
});
router.post("/register", async (req, res) => {
try {
const newuser = new User(req.body);
await newuser.save();
res.send("User registered successfully");
} catch (error) {
return res.status(400).json(error);
}
});
module.exports = router;
I'm also using this method to make a get request to another endpoint in a carsRoute.js file which looks like this (the get request works) :
const express = require("express");
const router = express.Router();
const Car = require("../models/carModel");
router.get("/getallcars", async(req,res) => {
try {
const cars = await Car.find()
res.send(cars)
} catch (error) {
return res.status(400).json(error);
}
})
module.exports = router;
Finally, I export them into server.js which looks like this :
const express = require('express');
const app = express();
const port = process.env.port || 5000;
const dbConnect = require('./db');
app.use(express.json())
app.use('/api/cars/' , require('./routes/carsRoute'))
app.use('/api/users/', require('./routes/usersRoute'))
app.get('/', (req,res) => res.send('Hello World') )
app.listen(port, () => console.log(`Node Js Server Started on port ${port}`))
I do not think i missed any "/" or have any additional ones.

401: unauthorized (it contains bearer token)

Login module is working and creating users with token 201 created
Receipts route had worked with the same code before but now response is 401
using Postman (Authorization & Bearer: xcvbnm) has been put
Here is my code
server.js
const express = require('express')
require('./db/mongoose')
const userRouter = require('./routes/user')
const receiptRouter = require('./routes/receipt')
const app = express()
const port = process.env.PORT || 4003
app.use(express.json())
app.use(userRouter)
app.use(receiptRouter)
app.listen(port, () => {
console.log('Server is up on port ' + port)
})
const Receipt = require('./models/receipt')
const User = require('./models/user')
Receipts Route
router.post('/receipts', auth, async (req, res) => {
const receipt = new Receipt({
...req.body,
owner: req.user._id
})
try {
await receipt.save()
res.status(201).send(receipt)
} catch (e) {
res.status(400).send(e)
}
})
Receipt Schema
const Receipt = mongoose.model('Receipt', {
description: {
type: String,
required: true,
trim: true
},
})
Auth module
const auth = async (req, res, next) => {
try {
const token = req.header('Authorization').replace('Bearer', '')
const decoded = jwt.verify(token, 'Mango#123')
const user = await User.findOne({ _id: decoded._id, 'tokens.token': token })
if (!user) {
throw new Error()
}
req.token = token
req.user = user
next()
} catch (e) {
res.status(401).send({ error: 'Please authenticate.' })
}
}