How do you test req.flash() in express? - node.js

I currently have an express/node application I want to test, and but responses that it gives are in the form of req.flash('warn', 'message goes here');
Unfortunately, the documentation on express.js does not describe how this message travels to the client very thoroughly.
I know expresso has an assert.response() function that tests response objects. I was wondering where the flash message goes, and how I can test it in a similar way (or if it's not possible, and I should be sending everything through the response object).

i don't think this is supposed to work like that. you can't just use req.flash()as your only way to respond to a request.
it's more like an easy way to flash messages to the user on your normal templates - e.g. after inserting/creating an article you can either say:
req.flash('error', 'could not insert because .... ');
or
req.flash('info', 'article added successfully!');
for my last project i then added two dynamic helpers to my app:
app.dynamicHelpers({
info: function (req, res) {
return req.flash('info');
},
error: function (req, res) {
return req.flash('error');
}
});
so that i can just say sth like this in my view:
<% if (info !== undefined && info != "") { %>
<div class="infoBubble">
<%= info %>
</div>
<% } %>
<% if (error !== undefined && error != "") { %>
<div class="errorBubble">
<strong>Fehler</strong>: <%= error %>
</div>
<% } %>
result looks like this:

Related

ExpressJS, EJS: Uncaught SyntaxError: Unexpected token '<' (at file.js 1:1

I have a ExpressJS server with ejs template engine runs a Blockly app and a threejs map in a web page. My problem is that, when I go to /applications/newApp, app.ejs works well but when I go to /applications/:slug (this is a request to load a saved application) the app.ejs crashes with error below:
Uncaught SyntaxError: Unexpected token '<' (at file.js:1:1)
Uncaught SyntaxError: Unexpected token '<' (at anotherFile.js:1:1)
Here is my ejs codes:
<p hidden id="pageName">
<% if(page_name=="savedApp" ) { %>
savedApp
<% } else { %>
newApp
<% } %>
</p>
<p hidden id="slug">
<% if(page_name=="savedApp" ) { %>
<%= slug %>
<% } else { %>
none
<% } %>
</p>
these both calles same file but one works well while another crashes. These are also how server responses;
exports.getNewApp = (req, res) => {
res.render('app', {
page_name: 'newApp',
});
};
exports.loadApplication = async (req, res) => {
try {
res.render('a', {
page_name: 'savedApp',
slug: req.params.slug,
});
} catch (err) {
console.log(err);
res.status(500);
}
};
WHAT I TRIED:
I checked the opened <% %> tags, there is no error in here
I am using public files like that:
app.use(express.static(path.join(__dirname + 'public')));
app.use('/applications', express.static(path.join(__dirname + 'public/blocklyApplication')));
And I also checked following questions:
Express.js, Node.js, EJS - Uncaught SyntaxError: Unexpected token <
SyntaxError: Unexpected token ; while compiling ejs
SyntaxError: Unexpected token ,while compiling ejs
I don't get that, they are both responses same page with common url, one works well other doesnt. What should I check?
I don't know why, after trying some changes in code, adding
app.use(
'/applications/:slug',
express.static(path.join(__dirname + '/public/blocklyApplication'))
);
in my code makes everything work.
EDIT: and also in here Express-js can't GET my static files, why? there is a detailed answer about routed public.

How to res.render/send a variable after a redirect?

I want to send a message variable that says something like succeeded or failed wihtout the use of passport or sessions.
When it fails I can just do this:
res.status(401).render('register', {
message: 'Your username/email or password is incorrect.'
})
So I was thinking this was possible:
res.redirect('/');
res.render('', { message: 'Login success.'});
But it turns out it isn't:
Error: Cannot set headers after they are sent to the client
Are there any simple sollutions?
I tried making a router.get('/message/redirect :route') but I realised I ran into the same problem there too.
You are redirecting before rendering. So the render method can't send headers because you have already redirected them. You need to call either redirect or render, not both at once. you can do it like this.
res.render('/', { message: 'Login success.'});
remove this line
res.redirect('/');
In your EJS file just call <%= message %> to access the message. There is a better way of dealing with confirmation/error messages. Use Flash.
npm install express-flash
Then before rendering, call the flash. Flash takes two arguments, a name of the message and the message itself, Like this
req.flash("MessageName", "Login success");
res.redirect(pathName);
Make sure to use flash
const flash = require('express-flash');
app = express();
app.use(flash());
app.use((req, res, next) => {
res.locals.MessageName= req.flash("MessageName");
next();
});
To access the message in EJS file just call <%= MessageName %>
Here is sample from my code:
In the server file:
req.flash("error", "Something went wrong");
res.redirect('back');
In the EJS file:
<div class="flash">
<% if(error && error.length > 0){ %>
<div class="flash_error">
<h1 class="flash_error--text"><%= error %></h1>
</div>
<% } %>
</div>
Read this for more information

Display flash message from router to a ejs view

I am setting up flash message to be displayed on view whenever the message is sent from the router to the view
if (err) {
console.log(err);
} else {
req.flash('success', 'You are now registered and can Log in')
res.redirect('/users/login');
// res.render('users/login',{
// success_message:'Account created successfully'
// });
}
is there a way to get this displayed on the view when the page loads without having to do it manually as the one commented, because that one works, but I'd like to get it automatically shown. I have checked some submissions available on the forum, I am still not able to find one that really gets the message displayed
use connect-flash for the session used for storing messages.
const flash = require('connect-flash');
Use middleware in express js
app.use(flash());
Append flash message in request render
res.render('/users/login', { message: req.flash('Restistration succesfully.') });
To show the flash message in html/ejs
<% if (message.length > 0) { %>
<div class="alert alert-danger"><%= message %></div>
<% } %>

Render app views per user agent in EJS

I'm working on a Node.js/Express that uses EJS and trying to render certain views on desktop or mobile.
I've added the following middleware to return the user agent in my app.js:
app.use(function(req, res, next) {
res.locals.ua = req.get('User-Agent');
next();
});
Next, if I echo <%= ua %> in my view, I successfully get the user agent, but I'm not sure how to actually check specific agents.
I tried <$ if(ua.match(/iPhone)) { %> as a quick example, but got a syntax error. Any help would be appreciated!
Several errors:
1) You started with a $ inside your embedded script. You should instead use a %.
2) You need to close out your regex with a /.
Something like this:
<% if(ua.match(/Intel/)) { %>
<%= ua %>
<% } %>

How do I make socket.io + ejs + mongoose work properly?

My goal is whenever someone press accept button it will, automatically increment the notifications on the navbar.
The logic
1) An admin press an accept button
2) User's navbar will listen to notify event and will increment the number of the count and append the message to the li element.
Here's the picture of the notification that Im hoping socket.io will update
However I don't see any real-time updates
Here's the code
the socket.io client side
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
<script>
var socket = io.connect('http://localhost:3000');
$('form').submit(function(){
var companyName = $("#companyName").val();
var notification = "Accepted by " + companyName;
var user_id = $('#candidate_id').val();
var notificationCount = parseInt($('#notification').html());
noticationCount += 1;
socket.emit('notify', {notification: notification, userId: user_id, count: notificationCount});
});
socket.on('notify', function(msg){
$('#notification').html(msg.count);
$('#addNotification').append($('<li>').text(msg.notification));
});
</script>
The HTML (EJS) codes -- this is where it supposed to update.
<li class="dropdown notifications-menu">
<span id='notification' class="label label-warning"><%= user.notifications.length %></span>
</a>
<ul class="dropdown-menu">
<li>
<ul class="menu" id="addNotification">
<% for(var i=0; i < user.notifications.length; i++) { %>
<li><!-- start notification -->
<a href="#">
<i class="fa fa-users text-aqua"></i> <%= user.notifications[i] %>
</a>
</li>
<% } %>
</ul>
</li>
</ul>
</li>
Serverside
io.on('connection', function(socket){
socket.on('notify', function(msg){
User.findById({ _id: msg.userId}, function(err, found) {
if (typeof found === 'undefined') {
// Do something but what should I do?s
} else {
found.notifications.push(msg.notification);
found.save(function(err) {
console.log(msg.notification); // Doesnt even console.log the data.
});
}
});
});
});
Again my goal is
1) Someone submit a button and it will emit all the hidden input values according to its tag's id like id="user_id".
2) socket.on('notify') --> Will listen and update it in real time via id of the targeted html tags
3) Save the data in the database.
However the above implementation, I have to refresh it then I can see the result.
But if I add this line to socket.io clientside code
var notificationCount = parseInt($('#notification').html());
noticationCount += 1;
It won't even save it to the database, where else to update it in real-time. I
Please lend me your real-time knowledge :)
1) You should not include socket.js file from cdn, it is should be loaded like
<script src="http://localhost:3000/socket.io/socket.io.js"></script>
you don't need to save socket.io.js file anywhere in the project folder, this is handled by socket.io module
2) I see code to receive client message to server, not from there back to clients. It will look like this (for broadcast)
io.on('connection', function(socket){
socket.on('notify', function(msg){
// pass notification & count to client
io.emit('notify', {notification:msg.notification, count:your_msg_count});
....
I am not going deeper into your code, hope this will fix your issues.

Resources