I am sending request from form (using Angularjs) to create new user. It works and inserts data in my collection. But how i manage to update my data on backend part using node js express. For example i want to check if username is free. I am trying to console.log something when i send post request. But nothing is logging.
Here is my server.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const restify = require('express-restify-mongoose');
//const userRep = require('./front/core/repository/user/user.repository');
// Middleware
const head = require('./back/midleware/headers.config');
// Models
// TODO provide schema when it will be raedy
const userModel = require('./back/models/user.model');
const app = express();
const router = express.Router();
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/users');
// Body parser config
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Headers config
app.use(head.headerConfig);
// Endpoint configuration
restify.serve(router, userModel.UserModel, {
name: 'users',
});
app.use(router);
app.post('/users', (req, res) => {
console.log('req.post')
})
app.post('/users', (req, res) => {
console.log('req.post')
})
app.listen(2000, function () {
console.info('Server is locating on port 2000');
console.info('to access localhost:2000/api/v1');
});
Ajax Request:
import { UserRepository } from '../../core/repository/user/user.repository';
import * as _ from 'lodash';
class HttpExampleController {
constructor(UserRepository) {
this.repository = UserRepository;
this.allUsers = [];
this.user = {};
this.newUser = {
id: 4,
email: "new#email.com",
username: "newUserName",
name: "newName"
};
this.updatedUser = {
email: "updated#email.com",
name: "updatedUserName"
};
this.getAllUsers();
}
getAllUsers() {
this.repository.getAllUsers()
.then(userList => {
this.allUsers = userList;
});
}
// Discuss if we need this method
getUser(userId) {
this.repository.getUser(userId)
.then(user => {
this.user = user;
});
}
createUser(user) {
this.repository.createUser(user)
.then(res => {
this.allUsers.push(res);
});
}
updateUser(user, data) {
let index = _.indexOf(this.allUsers, _.find(this.allUsers, findUser => findUser._id === user._id));
this.repository.updateUser(user._id, data)
.then(res => {
this.allUsers[index] = res;
});
}
deleteUser(user) {
let index = _.indexOf(this.allUsers, _.find(this.allUsers, findUser => findUser._id === user._id));
this.repository.deleteItem(user._id)
.then(res => _.pull(this.allUsers, res));
}
testFunc() {
this.allUsers.shift();
}
}
export { HttpExampleController };
Related
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
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()
})
})
Its my first time trying to do a POST request with Postman using Koa in my application. I have the router and the body parser but for some reason i still get an error message sayng that my request body is undefined. I think the body parser is not working but i have no idea why.
routes.js
const Koa = require('koa');
const bodyParser = require('koa-body')
const Router = require('koa-router')
const app = new Koa()
const router = new Router()
const Topic = require('./models/topic')
router.post('/topics', bodyParser(), async (ctx) => {
console.log(JSON.stringify(ctx.request.body))
const { name } = ctx.request.body
newPost = {
name: {name}
}
let newTopic = new Topic(newPost)
await newTopic.save(function(error, newPost){
if (error) {
console.log(error)
} else {
res.status(201).json({
message : 'Name added!'
}).send(newPost)
}
})
return
})
app
.use(router.allowedMethods())
.use(router.routes())
module.exports = router
topic.js
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const TopicSchema = new Schema(
{
name: {type: String, required: true },
viewCount: {type: Number, default: 0 }
},
{
timestamps: true
}
)
module.exports = mongoose.model('two/Topic', TopicSchema)
Error message:
{}
Error: two/Topic validation failed: name: Cast to string failed for value "{ name: undefined }" at path "name"
at ValidationError.inspect (/home/node/app/node_modules/mongoose/lib/error/validation.js:47:26) ...
EDIT
Also adding in server.js for further reference
const Koa = require('koa');
const mongoose = require('mongoose');
const router = require('./routes');
const app = new Koa();
app.use(require('koa-body')());
app.use(router.routes());
mongoose.connect(process.env.MONGODB_URI, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
const listener = app.listen(process.env.APP_PORT || 3000, () =>
console.log('App started on port ' + listener.address().port)
)
})
.catch((error) => {
console.log(error)
process.exit(1)
})
// app.proxy = true;
module.exports = app;
I try to fetch an API and save the data to MongoDB, but i think i have some problem with my POST method..
I would like to store the data what i fetch from the API and then if i change data in the front i would like if it changed in the database
Here is my code snippet:
App.js file
class App extends React.Component {
state = {
name: "",
movie: [],
};
componentDidMount = () => {
this.getMovie();
this.displayMovie();
};
getMovie = () => {
axios.get("http://api.tvmaze.com/shows?page=1").then((response) => {
const data = response.data;
this.setState({
movie: data,
});
console.log("Data has been received");
console.log(this.state.movie);
});
};
displayMovie = () => {
axios({
url: "/",
method: "POST",
data: this.state.movie,
})
.then(() => {
console.log("Data has been sent to the server");
this.getMovie();
})
.catch((err) => {
console.log(err);
console.log("Internal server error");
});
};
render() {
return (
<div>
<form onSubmit={this.displayMovie}>
<button type="submit">Send</button>
<h2>Movie List</h2>
<div>
{this.state.movie.map((t) => {
return <p>{t.name}</p>;
})}
</div>
</form>
</div>
);
}
}
export default App;
server.js file
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const app = express();
const movieRouter = require("./routes/movie.routes");
const connect = () => {
return mongoose
.connect("mongodb://localhost:27017/movie", {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log("db connected"))
.catch((err) => console.log(err));
};
connect();
app.use(express.json());
app.use("/", movieRouter);
app.use(bodyParser.json({ limit: "50mb", extended: true }));
app.use(bodyParser.urlencoded({ limit: "50mb", extended: true }));
app.listen(5000, () => {
console.log("app is running on 5000");
});
model Schema
const mongoose = require("mongoose");
const movieSchema = new mongoose.Schema({
name: {
type: String,
},
});
const MovieSchema = mongoose.model("movieSchema", movieSchema);
module.exports = MovieSchema;
service js file
const MovieSchema = require("../models/movie.models");
const getMovie = async () => {
const movie = await MovieSchema.find();
return movie;
};
module.exports = {
getMovie,
};
controller file
const getMovie = async (req, res, next) => {
try {
const movie = await movieService.getMovie();
res.status(200).json({ result: movie });
} catch (err) {
next(err);
}
};
module.exports = {
getMovie,
};
router file
const express = require("express");
const router = express.Router();
const movieController = require("../controllers/movie.controllers");
router.get("/", movieController.getMovie);
module.exports = router;
What am i doing wrong ? I have POST http://localhost:3000/ 404 (Not Found) error message.
Thank you for help!
First of all your POST route handler is missing (ref: Andrew Nolan).
Secondly your react code App.js componentDidMount method is calling getMovie and straight after calling displayMovie. It has to wait till getMovie method returns the results. So i placed promises to solve it.
class App extends React.Component {
state = {
name: "",
movie: [],
};
async componentDidMount() {
try {
await this.getMovie();
this.displayMovie();
} catch (e) {
console.log(e);
}
};
getMovie = async () => {
return new Promise((resolve, reject) => {
axios.get("http://api.tvmaze.com/shows?page=1").then(({ data }) => {
this.setState({
movie: data,
});
resolve();
}).catch(e => reject(e));
});
};
displayMovie = async () => {
axios({
url: "/",
method: "POST",
data: this.state.movie,
})
.then(() => this.fetchMovie())
.catch((err) => console.log(err));
};
render() {
return (
<div>
<form onSubmit={this.displayMovie}>
<button type="submit">Send</button>
<h2>Movie List</h2>
<div>
{this.state.movie.map((t) => {
return <p>{t.name}</p>;
})}
</div>
</form>
</div>
);
}
}
export default App;
You don't need to send status code 200. json method will stringify the json object and attach 200 status code as default.
res.status(200).json({ result: movie }); // too long
res.json({ result: movie }); // better practice
res.json({ movie }); // even better
When you are creating mongoose schema, you don't need to explicitly declare type of the data in object literals unless you want to add other configurations.
const movieSchema = new mongoose.Schema({
name: {
type: String,
},
});
const movieSchema = new mongoose.Schema({
name: String // better
});
In your code, you have only specified a GET route for /. You also need to specify a POST route too.
const express = require("express");
const router = express.Router();
const movieController = require("../controllers/movie.controllers");
router.get("/", movieController.getMovie);
router.post("/", movieController.saveMovie);
module.exports = router;
I put in movieController.saveMovie as a placeholder for whatever gets invoked at this route. That part is up to you. I didn't see a method for it in your code snippets to save it.
You are also missing post controller
just like get, add post controller in controller file too.
const postMovie = async (req, res, next) => {
const {name} = req.body;
try {
const newMovie = new Movie({
name,
});
const movie = await newMovie.save();
res.status(200).json({ result: movie });
} catch (err) {
next(err);
}
};
module.exports = {
postMovie,
};
My /chat route works well through Post method with validation with Joi schema but when I send request through Get method, it show Sending Request and continue loading...
My index.js file:
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const chat = require('./db/ChatModel');
const app = express();
app.use(bodyParser.json());
app.get('/chat', (req, res) => {
chat.getAllMessages().then( (messages) => {
res.json(messages);
});
});
app.post('/chat', (req, res) => {
console.log(req.dody);
chat.createMessages(req.body).then((message) => {
res.json(message);
}).catch( (error) => {
res.status(500);
res.json(error);
});
});
const port = process.env.PORT || 8888;
app.listen(port, () => {
console.log(`Listening on port ${port}...`);
});
In connection.js I coded this
const monk = require('monk');
const connectionString = 'localhost/chatboard';
const db = monk(connectionString);
module.exports = db;
And ChatModal.js has the following code
const Joi = require('joi');
const db = require('./connection');
const schema = Joi.object().keys({
username: Joi.string().alphanum().min(4).max(16).required(),
subject: Joi.string().required(),
message:Joi.string().max(300).required(),
imgUrl: Joi.string().uri({
scheme: [ // https://github.com/hapijs/joi/blob/v14.3.1/API.md#stringurioptions
/https?/
]
})
});
const chat = db.get('chat');
function getAllMessages() {
return chat.find();
};
function createMessages(message) {
const result = Joi.validate(message, schema);
if (result.error == null) {
message.created = new Date();
return chat.insert(message);
} else {
return Promise.reject(result.error);
}
}
module.exports = {
createMessages,
getAllMessages
};
I can't understand why getAllMessages() doesn't work and postman continue loading when Get request applied like this http://prntscr.com/s0d9c5
ChatModal.js
function getAllMessages() {
try {
return chat.find();
} catch (err) {
return next(err);
}
index.js
app.get('/chat', (req, res, next) => {
try{
data = chat.getAllMessages()
} catch (err) {
return next(error);
}
res.json(data);
});
User try-catch in the ChatModal.js and also index.js then you can understand what is actual error, like bellow:
ChatModal.js
function getAllMessages() {
try {
chat.find();
} catch (err) {
return next(err);
}
I think, may be your data, i mean message list data so weight, in this case you get all message,res.json(messages); json method have long time to parse messages data