promises exercise in JS - javascript

I'm training on JS promises with a short URL generator exercise and I'm stuck. The console sends me back: Resultat: undefined.
I need help please !
import express from 'express';
import shortUrl from 'node-url-shortener';
const router = express.Router();
router.get('/', (req, res) => {
res.render('postUrl');
})
router.post('/test', (req, res) => {
const getShortUrl = () => {
return new Promise((resolve, reject) => {
const test = shortUrl.short('https://google.com', (err, url) => {
return url;
});
resolve(test)
})
}
getShortUrl()
.then((result) => {
console.log('Resultat : ' + result)
})
.catch((err) => {
console.log('Error : ' + err)
})
res.render('getShortUrl');
})
export { router }

Just move result(test) to inside the callback. Like this:
import express from 'express';
import shortUrl from 'node-url-shortener';
const router = express.Router();
router.get('/', (req, res) => {
res.render('postUrl');
})
router.post('/test', (req, res) => {
const getShortUrl = () => {
return new Promise((resolve, reject) => {
shortUrl.short('https://google.com', (err, url) => {
resolve(url);
});
})
}
getShortUrl()
.then((result) => {
console.log('Resultat : ' + result)
})
.catch((err) => {
console.log('Error : ' + err)
})
res.render('getShortUrl');
})
export { router }

Related

Unable to mock express controller in Vitest

I'm trying to test that a call to a certain backend route eventually hits the correct controller function in an express app.
I'm attempting to do this using Vitest & supertest - but I'm struggling to mock the controller function.
**metafieldsControllers.js**
// #route POST /metafields/save
// #desc Saves a new value for an app-owned metafield
export const appMetafieldSave = async (req, res, next) => {
<!-- stuff here -->
res.status(201).json({ message: "Save successful!", savedValue });
}
// #route GET /metafields/:namespace/:key
// #desc Gets an app owned metafield by namespace and key
export const appMetafieldRetrieve = async (req, res, next) => {
<!-- stuff here -->
res.status(200).json(appInstallationData.metafield);
}
Things I have tried that haven't worked in my Vitest test file are...
***controllers.test.js***
import request from "supertest";
import { describe, expect, test, vi } from "vitest";
import { serve } from "../../../server/__tests__/serve";
import * as metafieldsControllers from "../metafieldsControllers.js";
describe("metafieldsControllers", async () => {
const { app } = await serve(process.cwd(), false);
// Mock verify-request
vi.mock(`${process.cwd()}/server/middleware/verify-request.js`, () => ({
default: vi.fn(() => (req, res, next) => {
next();
}),
}));
// Mock appMetafieldSave
const controllerSpy = vi.spyOn(metafieldsControllers, "appMetafieldSave");
controllerSpy.mockImplementation(() => {
console.log("I'm running");
});
test("Call to metafields/save route hits the controller", async () => {
const response = await request(app).post("/metafields/save");
console.log("response", response);
expect(controllerSpy).toHaveBeenCalledTimes(1);
});
});
^ This fails with AssertionError: expected "appMetafieldSave" to be called 1 times. Logging out the response shows that the request hit the original un-mocked controller.
***controllers.test.js***
import request from "supertest";
import { describe, expect, test, vi } from "vitest";
import { serve } from "../../../server/__tests__/serve";
describe("metafieldsControllers", async () => {
const { app } = await serve(process.cwd(), false);
// Mock verify-request
vi.mock(`${process.cwd()}/server/middleware/verify-request.js`, () => ({
default: vi.fn(() => (req, res, next) => {
next();
}),
}));
// Mock appMetafieldSave
vi.mock(
`${process.cwd()}/server/controllers/metafieldsControllers.js`,
() => {
return {
appMetafieldSave: vi.fn(() => (req, res, next) => {
res.status(201);
}),
appMetafieldRetrieve: vi.fn(() => (req, res, next) => {
res.status(200);
}),
};
}
);
test("Call to metafields/save route hits the controller", async () => {
const response = await request(app).post("/metafields/save");
console.log("response", response);
expect(response.status).toEqual(201);
});
});
^ This fails with a timeout.
Any ideas what I'm doing wrong?

I can't upload an image using ESM for cloudinary

I have a problem in this part of my code,with COMMONJS and it's working, my question is how can I make it work on ESM,
I've tried this but not workiing :
import express from 'express';
const router = express.Router();
import cloudinary from 'cloudinary';
import { unlinkSync } from 'node:fs';
const router = require('express').Router();
const cloudinary = require('cloudinary');
const { unlinkSync } = require('node:fs');
// we will upload image on cloudinary
cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET
});
// Upload image only admin can use
router.post('/upload', (req, res) => {
try {
cloudinary.v2.uploader.upload(file.tempFilePath, { folder: 'test' }, async (err, result) => {
if (err) throw err;
removeTmp(file.tempFilePath);
res.json({ public_id: result.public_id, url: result.secure_url });
});
} catch (err) {
return res.status(500).json({ msg: err.message });
}
});
const removeTmp = (path) => {
unlinkSync(path, err => {
if(err) console.log('this is the error',err);;
});
console.log(`successfully deleted ${path}`);
};
module.exports = router;
Try this one :
import express from 'express';
import multer from 'multer';
import { v2 as cloudinary } from 'cloudinary';
import streamifier from 'streamifier';
import { isAdmin, isAuth } from '../utils.js';
const upload = multer();
const uploadRouter = express.Router();
uploadRouter.post(
'/',
isAuth,
isAdmin,
upload.single('file'),
async (req, res) => {
cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_API_KEY,
api_secret: process.env.CLOUDINARY_API_SECRET,
});
const streamUpload = (req) => {
return new Promise((resolve, reject) => {
const stream = cloudinary.uploader.upload_stream((error, result) => {
if (result) {
resolve(result);
} else {
reject(error);
}
});
streamifier.createReadStream(req.file.buffer).pipe(stream);
});
};
const result = await streamUpload(req);
res.send(result);
}
);
export default uploadRouter;

TypeError: signin.handleSignin is not a function

I"ve seen this question asked before, but I cannot quite figure out what it is I'm doing wrong. I have an endpoint: app.post('/signin', signin.handleSignin(db, bcrypt)) in my server.js file. The console is alerting me that signin.handleSignIn is not a function. This endpoint is linked to a file in my controllers folder that is signin.js that looks like this:
const handleSignin = (db, bcrypt) => (req, res) => {
const { email, password } = req.body;
if (!email || !password) {
return res.status(400).json('incorrect form submission');
}
db.select('email', 'hash').from('login')
.where('email', '=', email)
.then(data => {
const isValid = bcrypt.compareSync(password, data[0].hash);
if (isValid) {
return db.select('*').from('users')
.where('email', '=', email)
.then(user => {
res.json(user[0])
})
.catch(err => res.status(400).json('unable to get user'))
} else {
res.status(400).json('wrong credentials')
}
})
.catch(err => res.status(400).json('wrong credentials'))
}`enter code here`
export default handleSignin;
server.js code:
import express, { application, response } from "express";
import bcrypt, { hash } from "bcrypt-nodejs";
import cors from "cors";
import knex from "knex";
import signin from "./controllers/signin.js"
const db = knex({
client: "pg",
connection: {
host: "127.0.0.1",
port: 5432,
user: "postgres",
password: "test",
database: "smart-brain",
},
});
db.select("*")
.from("users")
.then((data) => {});
const app = express();
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
app.use(cors());
app.get("/", (req, resp) => {
resp.send(db.users);
});
app.post('/signin', signin.handleSignin(db, bcrypt))
app.post("/signin", (req, resp) => {
db.select("email", "hash")
.from("login")
.where("email", "=", req.body.email)
.then((data) => {
const isValid = bcrypt.compareSync(req.body.password, data[0].hash);
if (isValid) {
return db
.select("*")
.from("users")
.where("email", "=", req.body.email)
.then((user) => {
console.log(user);
resp.json(user[0]);
})
.catch((err) => resp.status(400).json("Unable to get user"));
} else {
resp.status(400).json("Wrong credentials");
}
})
.catch((err) => resp.status(400).json("Wrong credentials"));
});
app.post("/register", (req, resp) => {
const { name, email, password } = req.body;
const hash = bcrypt.hashSync(password);
db.transaction((trx) => {
trx
.insert({
hash: hash,
email: email,
})
.into("login")
.returning("email")
.then((loginemail) => {
trx("users")
.returning("*")
.insert({
name: name,
email: loginemail[0],
joined: new Date(),
})
.then((user) => {
resp.json(user[0]);
});
})
.then(trx.commit)
.catch(trx.rollback);
}).catch((err) => resp.status(400).json("unable to register"));
// bcrypt.hash(password, null, null, function (err, hash) {
// console.log(hash);
// });
});
app.get("/profile/:id", (req, resp) => {
const { id } = req.params;
db.select("*")
.from("users")
.where({ id })
.then((user) => {
if (user.length) {
resp.json(user[0]);
} else {
resp.status(400).json("Not found");
}
})
.catch((err) => resp.status(400).json("Error getting user"));
// if (!found) {
// resp.status(400).json("not found");
// }
});
app.put("/image", (req, resp) => {
const { id } = req.body;
db("users")
.where("id", "=", id)
.increment("entries", 1)
.returning("entries")
.then((entries) => {
resp.json(entries[0]);
})
.catch((err) => resp.status(400).json("Unable to get entries"));
});
app.listen(3001, () => {
console.log("App is running at port 3001");
});
You didn't exported signin from signin.js, you exported handleSignin.
so just import handleSignin and call it directly.
import handleSignin from "./controllers/signin.js"
...
app.post('/signin', handleSignin(db, bcrypt))

How do you nest routes in express?

I am new to express and node and I have this situation:
controller:
exports.find_by_IDN_post = (req, res) => {
console.log('init')
accidentDetail.findOne({ idn: req.body.idn }, (err, data) => {
if (err) {
res.status(500).send(err)
}
console.log(data)
res.status(200).send(data)
})
}
exports.find_by_name_post = (req, res) => {
accidentDetail.findOne({$or: [{'firstName': req.body.name}, {'middleName': req.body.name}, {'surname': req.body.name}]}, (err, data) => {
if (err) {
res.status(500).send(err)
}
res.status(200).send(data)
})
}
exports.find_by_date_post = (req, res) => {
accidentDetail.findOne({firstReg: req.body.firstReg}, (err, data) => {
if (err) {
res.status(500).send(err)
}
res.status(200).send(data)
})
}
exports.find_by_accident_type_post = (req,res) => {
accidentDetail.findOne({accidentType: req.body.accidentType}, (err, data) => {
if (err) {
res.status(500).send(err)
}
res.status(200).send(data)
})
}
route:
const express = require('express')
const router = express.Router()
const query_controller = require('../controllers/QueryController')
router.post('/idn', query_controller.find_by_IDN_post)
router.post('/name', query_controller.find_by_name_post)
router.post('/date', query_controller.find_by_date_post)
router.post('/accidentType', query_controller.find_by_accident_type_post)
module.exports = router
app
const queryRouter = require('./routes/query')
app.use('/query', queryRouter)
How do I nest the routes? I want to be able to access the routes like this:
localhost:3001/query/idn
localhost:3001/query/name
...
At the moment, I can't receive the console.log('init') when trying to access localhost:3001/query/idn.

Why is the Query from getInitialProps empty?

I want to fetch some data using query parameters on the server for a page.
However, my query is empty inside getInitialProps when rendered through server. Why could this be happening?
Moreover, I have noticed this only happens in production server and not in the dev or prod env on my local.
Here's some code
import React from 'react';
import Config from 'component/Config';
import { withAuthSync } from 'util/auth';
import apiUrl from 'util/apiUrl';
function ResourceConfigPage({ data }) {
return <Config data={data} />;
}
ResourceConfigPage.getInitialProps = async ctx => {
const { resourceId } = ctx.query;
try {
const response = await fetch(`${apiUrl}/resource/config?resourceId=${resourceId}`, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
}
});
if (response.ok) {
const data = await response.json();
return { data };
}
}
return {};
};
export default withAuthSync(ResourceConfigPage);
My next app uses a custom express server and here's how it looks.
const express = require('express');
const next = require('next');
const compression = require('compression');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app
.prepare()
.then(() => {
const server = express();
app.setAssetPrefix(dev ? '' : 'https://example.com');
server.use(compression());
server.get('/healthcheck', (req, res) => {
res.status(200).json({});
});
server.get('/', (req, res) => {
if (req.cookies.sessionId) {
res.redirect('/dashboard');
}
res.redirect('/login');
});
server.get('*', (req, res) => {
return handle(req, res);
});
server.listen(3000, err => {
if (err) throw err;
console.log('> Ready on http://localhost:3000');
});
})
.catch(ex => {
console.error(ex.stack);
process.exit(1);
});

Categories