Problem with server export when testing React with Jest and Supertest - javascript

I'm testing a React app with an Express backend, using Jest and Supertest. In my current test, I need to stub the fetch, which I'm doing with Supertest. The problem is, I never get an answer from the agent get(), and thus never get any data back.
I think there is a problem with how I'm exporting my server. I've tried changing around the exports, from module.exports = app, to module.exports = {app}, to const server = app.listen(port, etc), and module.exports = server. So far none of the solutions I've found are working.
server.js:
const app = require('./app.js');
const port = process.env.PORT || 8080;
app.listen(port, () => console.log("Server running on port " + port));
app.js:
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const app = express();
const ews = require('express-ws')(app);
const WebSocket = require('ws');
...
app.get("/menus", (req, res) => {
const menus = MenuRepo.getMenus();
res.json(menus)
})
...
module.exports = app;
home-test.js
test("Test that dishes displays", async () => {
menuRepo.populateMenus();
overrideFetch(app);
const driver = mount(
<MemoryRouter>
<ShowMenus/>
</MemoryRouter>
);
const predicate = () => {
driver.update();
const tableSearch = driver.find('#menuTable');
const tableIsDisplayed = (tableSearch.length >= 1);
return tableIsDisplayed;
};
const displayedTable = await asyncCheckCondition(predicate, 3000, 200);
expect(displayedTable).toBe(true);
const menus = menuRepo.getMenus();
const html = driver.html();
for(let i=0; i<menus.length; i++){
expect(html).toContain(menus[i].dishes.day);
}
});
function I'm using to stub fetch:
function overrideFetch(app){
const agent = request.agent(app);
global.fetch = async (url, init) => {
let response;
if(!init || !init.method || init.method.toUpperCase() === "GET"){
try {
response = await agent.get(url);
} catch (e) {
console.log(e)
}
} else if(init.method.toUpperCase() === "POST"){
response = await agent.post(url)
.send(init.body)
.set('Content-Type', init.headers ? init.headers['Content-Type'] : "application/json");
} else if(init.method.toUpperCase() === "PUT"){
response = await agent.put(url)
.send(init.body)
.set('Content-Type', init.headers ? init.headers['Content-Type'] : "application/json");
} else if(init.method.toUpperCase() === "DELETE"){
response = await agent.delete(url);
} else {
throw "Unhandled HTTP method: " + init.method;
}
const payload = response.body;
return new Promise( (resolve, reject) => {
const httpResponse = {
status: response.statusCode,
json: () => {return new Promise(
(res, rej) => {res(payload);}
)}
};
resolve(httpResponse);
});
};
}
I'm expecting that the stubbed fetch will return a list of seven json menus.

Related

Argument passed in must be a string of 12 bytes or a string of 24 hex characters

I am new to coding. I am trying CRUD operation with express.js and MongoDB atlas for database on my project but when I am fetch for loading data for my client site server its error:
var _this = _super.call(this, message) || this;
BSONTypeError: Argument passed in must be a string of 12 bytes or a string of 24 hex characters or an integer
I am trying a lot but no result.
this is my code:
//this is client site code:
import React from 'react';
import { useEffect } from 'react';
import { useState } from 'react';
import { Link, useParams } from 'react-router-dom';
const MeetingDetail = () => {
const {meetingId} = useParams()
const [meeting, setMeeting] = useState({})
console.log(meeting)
useEffect(() => {
const url = `http://localhost:5000/meeting/${meetingId}`;
console.log(url)
fetch(url)
.then(res => res.json())
.then(data => setMeeting(data))
},[])
return (
<div className='mx-auto w-75'>
<h1>meetingID : {meeting.age}</h1>
<Link to='/checkout'><button className='btn btn-primary mx-auto'>
Process Checkout</button></Link>
</div>
);
};
export default MeetingDetail;
//this is server site code:
const express = require("express");
const cors = require("cors");
require("dotenv").config();
const port = process.env.PORT || 5000;
const { MongoClient, ServerApiVersion, ObjectId } = require("mongodb");
const app = express();
// middleware
app.use(cors());
app.use(express.json());
// from Mongodb
const uri = `mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASS}#cluster0.9nfwrgy.mongodb.net/?retryWrites=true&w=majority`;
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
serverApi: ServerApiVersion.v1,
});
console.log("mongo connected");
async function run() {
try {
await client.connect();
const meetingCollection = client.db("hotelRoom").collection("meeting");
// create main link for component data
app.get("/meeting", async (req, res) => {
const query = {};
const cursor = meetingCollection.find(query);
const meetings = await cursor.toArray();
res.send(meetings);
});
// create main link id for component data
app.get("/meeting/:id", async (req, res) => {
const id = req.params.id;
const query = {_id: ObjectId(id) };
const meeting = await meetingCollection.findOne(query);
res.send(meeting);
});
}
finally {
}
}
run().catch(console.dir);
app.get("/", (req, res) => {
res.send("starting server");
});
app.listen(port, () => {
console.log("CURD running", port);
});

Cannot POST /api/sentiment

I'm testing the endpoint for /api/sentiment in postman and I'm not sure why I am getting the cannot POST error. I believe I'm passing the correct routes and the server is listening on port 8080. All the other endpoints run with no issue so I'm unsure what is causing the error here.
server.js file
const express = require("express");
const cors = require("cors");
const dbConfig = require("./app/config/db.config");
const app = express();
var corsOptions = {
origin: "http://localhost:8081"
};
app.use(cors(corsOptions));
// parse requests of content-type - application/json
app.use(express.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({ extended: true }));
const db = require("./app/models");
const Role = db.role;
db.mongoose
.connect(`mongodb+srv://tami00:MEUxClWqUNbLz359#cluster0.gmvao.mongodb.net/test?retryWrites=true&w=majority`, {
useNewUrlParser: true,
useUnifiedTopology: true
})
.then(() => {
console.log("Successfully connect to MongoDB.");
initial();
})
.catch(err => {
console.error("Connection error", err);
process.exit();
});
// simple route
app.use('/api/favourite', require('./app/routes/favourite.routes'));
app.use('/api/review', require('./app/routes/review.routes'));
app.use('/api/sentiment', require('./app/routes/sentiment-analysis.routes'));
// routes
// require(".app/routes/favourite.routes")(app);
require("./app/routes/auth.routes")(app);
require("./app/routes/user.routes")(app);
// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
function initial() {
Role.estimatedDocumentCount((err, count) => {
if (!err && count === 0) {
new Role({
name: "user"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'user' to roles collection");
});
new Role({
name: "creator"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'creator' to roles collection");
});
new Role({
name: "watcher"
}).save(err => {
if (err) {
console.log("error", err);
}
console.log("added 'watcher' to roles collection");
});
}
});
}
sentiment-analysis routes file
const express = require('express');
const router = express.Router();
const getSentiment = require('../sentiment-analysis/sentimentAnalysis')
router.post('/api/sentiment', (req, res) => {
const data = req.body.data
const sentiment = getSentiment(data)
return res.send({sentiment})
})
module.exports = router;
sentimentAnalysis.js file
const aposToLexForm = require("apos-to-lex-form");
const {WordTokenizer, SentimentAnalyzer, PorterStemmer} = require("natural");
const SpellCorrector = require("spelling-corrector");
const stopword = require("stopword");
const tokenizer = new WordTokenizer();
const spellCorrector = new SpellCorrector();
spellCorrector.loadDictionary();
const analyzer = new SentimentAnalyzer('English', PorterStemmer, 'afinn')
function getSentiment(text){
if(!text.trim()) {
return 0;
}
const lexed = aposToLexForm(text).toLowerCase().replace(/[^a-zA-Z\s]+/g, "");
const tokenized = tokenizer.tokenize(lexed)
const correctSpelling = tokenized.map((word) => spellCorrector.correct(word))
const stopWordsRemoved = stopword.removeStopwords(correctSpelling)
console.log(stopWordsRemoved)
const analyzed = analyzer.getSentiment(stopWordsRemoved);
console.log(analyzed)
}
module.exports = getSentiment;
console.log(getSentiment("Wow this is fantaztic!"))
console.log(getSentiment("let's go together?"))
console.log(getSentiment("this is so bad, I hate it, it sucks!"))
I see that you use your routes like: app.use('/api/sentiment', require('./app/routes/sentiment-analysis.routes'));. But then in your sentiment-analysis you again use /api/sentiment so your request URL should be /api/sentiment/api/sentiment
Shouldn't it be:
const data = req.body.data

Test a POST Http request from a local node server in REACT

I need to make unit tests for some post requests but i dont understand how.I tried with mswjs but the test passes because i'm missing something and i dont know what.I tried to test the requests in an usual way but i wasnt able to put my conditions there and it was sending only 200 status code..
To start with,this is my folder structure:
+main folder
++nodeServer
+++public
+++routes
++public
++src
+++tests
This is my try for testing the post request to /subscribe endpoint,where i should send an email as a payload and get the response that the payload was received succesefully.
subscribeFetch.test.js:
import {setupServer} from 'msw/node'
import {rest} from 'msw'
const handlers = [
rest.post("/api/subscribe",(req,res,context)=>{
if (!req.body || !req.body.email) {
return res(context.status(400).json({ error: "Wrong payload" }));
}
if (req.body.email === 'forbidden#email.com') {
return res(context.status(422).json({ error: "Email is already in use" }));
}
return res(
context.status(200),
context.json({email:'gigi#gmail.com'})
)
})
]
const server = setupServer(...handlers)
beforeAll(()=>server.listen())
afterAll(()=>server.close())
afterEach(()=>server.resetHandlers())
test('should send post request to the server',async()=>{
server.use(
rest.post('/api/subscribe',(req,res,ctx)=>{
return res(
expect (ctx.status()).toBe(200)
)
}
)
)
})
//export {handlers,rest}
This is the subscribe post request function that i need to test:
import { validateEmail } from './email-validator.js'
export const sendSubscribe = (emailInput) => {
const isValidEmail = validateEmail(emailInput)
if (isValidEmail === true) {
sendData(emailInput)
}
}
export const sendHttpRequest = (method, url, data) => {
return fetch(url, {
method: method,
body: JSON.stringify(data),
headers: data
? {
'Content-Type': 'application/json'
}
: {}
}).then(response => {
if (response.status >= 400) {
return response.json().then(errResData => {
const error = new Error('Something went wrong!')
error.data = errResData
throw error
})
}
return response.json()
})
}
const sendData = (emailInput) => {
sendHttpRequest('POST', '/api/subscribe', {
email: emailInput
}).then(responseData => {
return responseData
}).catch(err => {
console.log(err, err.data)
window.alert(err.data.error)
})
}
Files from the server:
app.js:
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const indexRouter = require('./routes/index');
const communityRouter = require('./routes/community');
const analyticsRouter = require('./routes/analytics');
const app = express();
global.appRoot = path.resolve(__dirname);
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/community', communityRouter);
app.use('/analytics', analyticsRouter);
module.exports = app;
index.js from routes folder in the server folder:
const express = require('express');
const router = express.Router();
const FileStorage = require('../services/FileStorage');
/* POST /subscribe */
router.post('/subscribe', async function (req, res) {
try {
if (!req.body || !req.body.email) {
return res.status(400).json({ error: "Wrong payload" });
}
if (req.body.email === 'forbidden#email.com') {
return res.status(422).json({ error: "Email is already in use" });
}
const data = {email: req.body.email};
await FileStorage.writeFile('user.json', data);
await res.json({success: true})
} catch (e) {
console.log(e);
res.status(500).send('Internal error');
}
});
/* GET /unsubscribe */
router.post('/unsubscribe', async function (req, res) {
try {
await FileStorage.deleteFile('user.json');
await FileStorage.writeFile('user-analytics.json', []);
await FileStorage.writeFile('performance-analytics.json', []);
await res.json({success: true})
} catch (e) {
console.log(e);
res.status(500).send('Internal error');
}
});
module.exports = router;
Please guys,help me write unit test for subscribe endpoint to match the conditions from index.js file from routes folder in the server folder,thank you in advance!
So,i got the expected result without any library,but i dont know if its a good aproach,but at least it works :
const app = require('../../../personal-website-server/app')
const request = require('supertest')
describe('POST /subscribe', () => {
it('should give 400 status code when email is empty', async () => {
const email = { email: '' }
const response = await request(app).post('/subscribe').send(email)
if (!request.body || !request.body.email) {
expect(response.status).toBe(400)
}
})
it('should give 422 status code when email is forbidden', async () => {
const email = { email: 'forbidden#gmail.com' }
const response = await request(app).post('/subscribe').send(email)
if (request.body === 'forbidden#gmail.com') {
expect(response.status).toBe(422)
}
})
it('should give 200 status code when email is valid', async () => {
const email = { email: 'gigi#gmail.com' }
const response = await request(app).post('/subscribe').send(email)
expect(response.error).toBe(false)
expect(response.status).toBe(200)
expect(response.body.body).not.toBeNull()
})
})

display string on client side by fetching data from server side

I was trying to display a string on the client-side by fetching the result from serverside but for some reason, it is not displaying the fetched data. When I console log the variable straight on the js file the server successfully prints the string. The program is not exporting the variable to the client-side to display it. I can't figure out where I went wrong. Any help is appreciated. Thanks in advance.
const router = require("express").Router();
const {
callName
} = require("pathJs");
router.route("PathRoute").get(async(req, res) => {
const Result = await callName();
return res.json(Result);
});
module.exports = router;
function name() {
const liner = "this works"
console.log(liner)
//updated
return liner;
}
async function callName() {
const data1 = await name()
return data1;
}
callName()
<p id="insertHere" style="color: white;"></p>
<script>
async function caller() {
await fetch(`http://localhost:5000/api/PATH`)
.then((res) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(res.json())
}, 1000)
})
}).then((response) => {
console.log(response)
document.getElementById("insertHere").innerHTML = response.liner
}
)
}
</script>
const express = require("express");
const cors = require("cors");
const routePath = require("./routePath");
const {
response
} = require("express");
require("dotenv").config({
debug: process.env.DEBUG
});
const port = process.env.PORT || 5000;
const app = express();
app.use(cors());
app.use(express.json());
app.use("/api", routePath);
app.listen(port, () => {
console.log(`server is running on port: http://localhost:${port}`);
});
There is no export in pathJs and you want name() to return an object containing liner. You need
function name() {
const liner = "this works"
console.log(liner)
//updated
return {liner};
}
async function callName() {
const data1 = await name()
return data1;
}
callName()
module.exports = { callName };
The backend is probably crashing with TypeError: callName is not a function while handling the request and therefore doesn't send a response.

fs database will not save for some reason?

I'm trying to generate a code, add it to a database, and then return it to the request server. I'm getting no errors, but the database remains empty, nothing gets added. I'm using glitch as a temporary host, my json file is just {}
My code:
const Discord = require('discord.js')
const rbx = require('noblox.js')
const fs = require("fs")
const express = require("express")
const app = express()
app.use(express.json())
const client = new Discord.Client()
client.verificationCodes = require("./codes.json")
require("dotenv").config()
const port = process.env.PORT
const serverKey = process.env.SERVER_KEY
const cookie = process.env.COOKIE
function randomString(length, chars) {
var result = '';
for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
return result;
}
client.on("ready", () => {
console.log("Client is ready.")
})
app.post("/getVerificationCode", function(req,res,next) {
console.log("Recieved")
if (req.body.serverKey !== serverKey) {
console.log("Invalid serverKey supplied.")
return res.status(403).json({
error: "You do not have permission to use this."
})
}
let verificationCode = randomString(4,'0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ').toUpperCase()
const userID = parseInt(req.body.userid)
console.log(verificationCode)
client.verificationCodes[userID] = {
code: verificationCode
}
fs.writeFile("./codes.json", JSON.stringify(client.verificationCodes,null,4), err => {
if (err) throw err
})
return res.status(200).json({
VerificationCode: verificationCode
})
})
app.get("/*", function(req,res,next) {
return res.status(200).json({})
})
app.listen(port)
console.log(`App listening on port ${port}`)
function rbxLogin(newCookie) {
try {
rbx.setCookie(newCookie)
} catch(err) {
console.log(`Invalid cookie supplied, or expired. ${err}`)
}
}
// rbxLogin(cookie)
client.login(process.env.BOT_TOKEN)
I watched a video on how to use an fs database. I appreciate any help!

Categories