Test express render with locals - node.js

Here is my sample code:
File: index.js
var express = required('express');
var app = express();
app.get("/", function(req, res){
...
...
res.render("/index", {
list: data
});
});
File: test.js
var chai = require('chai');
var chaiHttp = require('chai-http');
var server = require('../index');
var should = chai.should();
chai.use(chaiHttp);
describe('Homepage', function(done){
it('should render index view', function(done){
chai.request(server.app)
.get("/")
.end(function(err, res){
console.log(res.body);
});
});
});
The console.log(res.body) shows output as {}. How can I get the local list variable to show in the output? I want to test if this local list variable has any data in my test.js file.

Option 1. You should use res.json([body]) to send the list data to your test case.
E.g.
index.js:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
const data = ['a', 'b'];
res.json({ list: data });
});
module.exports = { app };
index.test.js:
var chai = require('chai');
var chaiHttp = require('chai-http');
var server = require('./index');
var should = chai.should();
chai.use(chaiHttp);
describe('Homepage', function (done) {
it('should render index view', function (done) {
chai
.request(server.app)
.get('/')
.end(function (err, res) {
console.log(res.body);
done();
});
});
});
test result:
Homepage
{ list: [ 'a', 'b' ] }
✓ should render index view
1 passing (28ms)
Option 2. You should assert the view rendered correctly with your list data.
index.js:
var express = require('express');
var path = require('path');
var app = express();
app.set('views', path.resolve(__dirname, './views'));
app.set('view engine', 'ejs');
app.get('/', function (req, res) {
const data = ['a', 'b'];
res.render('index', { list: data });
});
module.exports = { app };
views/index.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<% for (let v of list) { %>
<p><%= v %></p>
<% } %>
</body>
</html>
index.test.js:
const { expect } = require('chai');
var chai = require('chai');
var chaiHttp = require('chai-http');
var server = require('./index');
var should = chai.should();
chai.use(chaiHttp);
describe('Homepage', function (done) {
it('should render index view', function (done) {
chai
.request(server.app)
.get('/')
.end(function (err, res) {
console.log(res.text);
done();
});
});
});
test result:
Homepage
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>a</p>
<p>b</p>
</body>
</html>
✓ should render index view
1 passing (32ms)

Related

How to populate the data scraped from API in node js into EJS template

My index.js file on root directory
const express = require("express");
const app = express();
const path = require("path");
const axios = require("axios").default;
const cors = require("cors");
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "/views"));
app.use(
cors({
origin: "http://localhost:3000",
})
);
fetchData = async () => {
const data = await axios.get(
"https://nepse-data-api.herokuapp.com/data/todaysprice"
);
console.log(data);
return data;
};
app.get("/", (req, res) => {
const nepseData = fetchData();
res.render("home.ejs", { nepseData });
});
app.listen(3000, () => {
console.log("listening to port 3000");
});
My home.ejs file on views directory
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<%= nepseData %>
</body>
</html>
The browser is displaying this when I run the server
The API is sending this type of data
I want to show the name and prices on my ejs file. What should I do now??
You have to add await there:
app.get("/", async (req, res) => {
const nepseData = await fetchData();
res.render("home.ejs", { nepseData });
});
And then you can iterate over the data:
<% nepseData.forEach(function(row){ %>
<%= row.companyName %> <%= row.minPrice %>
<% }); %>

Passing variables to React compiled app from Index.html to controller.js

I'm trying to pass variables from index.html to my react app which is compiled and running on express/node server locally. I tried using the window object but node.js don't recognize the window object.
Basically once the app is loaded index.html get user info from query string and send data to userController. See code below
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="telephone=no" name="format-detection">
<meta content="no" name="msapplication-tap-highlight">
<meta content="user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,width=device-width" name="viewport">
<title>App Frontend</title>
</head>
<body>
<div id="root"></div>
<script src="js/compiledscript.js"></script>
<script>
new AppCode({
root: document.getElementById('root'),
host: 'http://localhost:3500',
endpoints: {
folder: '/api/folder',
file: '/api/file'
},
headers: {
'Content-Type': 'application/json'
}
});
//Get iframe data query from parent
function getParamValue(paramName)
{
var url = window.location.search.substring(1); //get rid of "?" in querystring
var qArray = url.split('&'); //get key-value pairs
for (var i = 0; i < qArray.length; i++)
{
var pArr = qArray[i].split('='); //split key and value
if (pArr[0] == paramName)
return pArr[1]; //return value
}
}
var userData = {
username: getParamValue('username'),
userid: getParamValue('userid')
}
window.userData = userData;
//console.log(getParamValue('username'));
//console.log(getParamValue('userid'));
</script>
</body>
</html>
userController.js
const mongoose = require('mongoose');
const path = require('path');
const fs = require('fs');
const User = mongoose.model('User');
//const users = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'data', 'users.json'), 'utf-8'));
/*
const users = window.userData;
const userid = users.userid;
exports.userid = userid;
*/
exports.getAll = async (req, res) => {
const users = await User.find();
res.json(users);
};
exports.bang = async (req, res, next) => {
await User.remove();
next();
};
exports.addNewUser = async (req, res, next) => {
await User.create(users);
// next();
};
If you are sending the HTML file as static file,
You Can do this solution:
Solution:
install ejs by running the command npm i ejs then change your file from index.html to index.ejs,
add this line to your app
app.set('view engine', 'ejs');
and send the file by
res.render('index.ejs', {
// here data to pass
});
then you can pass data to index.ejs and it will get rendered
you can read the docs in here it will clarify the image more.
if you can use server-side rendering
then redux would be the solution

GET http://localhost: postman

I'm using MEAN stack as my back-end. this is my server js file
const users = require('./routes/users');
app.get('/', (req, res) => {
res.send('Invalid endpoint');
});
This is my routes file users.js
router.get('/jobdetail', function(req,res) {
console.log('fetching jobs');
jobDetails.find({}, (err,jobs) => {
if(err) {
console.log(err);
}
else {
res.json(jobs);
}
});
});
when I run it the postman bu url:
localhost:3000/api/jobdetail
Instead of the data from MongoDB I get the response as
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
<script type="text/javascript" src="http://gc.kis.v2.scr.kaspersky-labs.com/D11634C0-514E-C94E-9DFD-54EBD0B16E5F/main.js" charset="UTF-8"></script>
</head>
<body>
<pre>Cannot GET /api/jobdetail</pre>
</body>
</html>
var api = require('../routes/users.js');
app.use('/api', api);
in your routes/users.js file :
var mongoose =require('mongoose');
var router = require('express').Router();
var conn = mongoose.connection;
conn.once("open", () => {
router.get('/jobdetail', function(req, res) {
jobDetails.find({}, (err,jobs) => {
if(err) {
console.log(err);
}
else {
res.json(jobs);
}
});
});
});
module.exports = router;

Socket.IO and Express with emit data

So I trying to deposit data to user as a call made, and I have two problems.
First, when user connect its spams "user connected"
Second, I dont get any data on the page.
Here's the code:
bin/www:
var app = require('../app');
var debug = require('debug')('myapp:server');
var http = require('http');
var socketHandler = require('../handlers/sockethandler');
var io = socketHandler.io;
var server = http.createServer(app);
io.attach(server);
sockethandler.js:
var socket_io = require('socket.io');
var io = socket_io();
var socketHandler = {};
socketHandler.io = io;
io.on('connection', (socket) => {
console.log('a user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
});
module.exports = socketHandler;
emit data post:
var socketHandler = require('./sockethandler');
var io = socketHandler.io;
var exten = evt.exten, statustext = evt.statustext;
io.emit('extenstate', {exten, statustext});
client.js:
var socket = io("http://192.168.168.49:3000");
socket.on('extenstate', function(state) {
var li = document.createElement('li');
console.log(state.exten);
var Extension = document.createElement('h4');
var Status = document.createElement('h4');
Extension.textContent = 'Extension:' + state.exten;
Status.textContent = 'Status:' + state.statustext;
li.appendChild(Extension);
li.appendChild(Status);
document.getElementById('phone-calls').appendChild(li);
});
route:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('data', { title: 'Realtime Sender' });
});
module.exports = router;
ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Lonestar - <%= title %></title>
</head>
<body>
<div id="phone-calls"></div>
<script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>
<script src="client.js"></script>
</body>
</html>

Nodejs spawn remote tail and socket-io to client

I'm fairly new to Nodejs and I'm building an app that ssh to a remote machine and get a tail -f of a log file.
The lines of the log file I'm receiving I'm sending to the client via socket-io (ver. 2.0.3)
Now I'm facing a problem that when a second browser tries to tail a different log, the new log is sent to both of the browsers instead of only the one who made the request.
I'm not sure if it's a problem with my socket-io code or the child_process.
Here's the server:
const express = require('express'),
app = express(),
path = require('path'),
bodyParser = require('body-parser'),
logger = require('morgan'),
server = require('http').Server(app),
io = require('socket.io')(server),
spawn = require('child_process').spawn,
events = require('events'),
eventEmitter = new events.EventEmitter();
// Fix body of requests
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
// Log the requests
app.use(logger('dev'));
// Serve static files
app.use(express.static(path.join(__dirname, '.')));
// Add a basic route – index page
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
});
io.on('connection', (socket) => {
console.log(`client connected ${socket.client.id}`);
eventEmitter.on('tail', (data) => {
socket.tail = spawn('ssh', ['root#' + 'quality-p.company.com', 'tail -f', data.service], { shell: true });
socket.tail.stdout.on('data', (data) => {
console.log(`got new data ${data.toString()}`);
socket.emit('newLine', {line: data.toString().replace(/\n/g, '<br />')});
});
});
});
app.get('/tail', (req, res) => {
eventEmitter.emit('tail', req.query);
res.sendStatus(200);
});
// Bind to a port
server.listen(3005, () => {
console.log('running on localhost:' + 3005);
});
Client:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./node_modules/socket.io-client/dist/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
$(() => {
let socket = io();
socket.on('connect', () => {
console.log('connected');
});
socket.on('newLine', (data) => {
console.log(`new data: ${data.line}`);
$("#tailing").append(data.line);
});
$('#tail').click(() => {
$.get('/tail', {
service: $('#service').val()
});
});
});
</script>
<title>Title</title>
</head>
<body>
<select id="service">
<option id="tnet" value="/var/log/tnet">tnet</option>
<option id="consul" value="/var/log/consul">consul</option>
</select>
<button id="tail">tail</button>
<div id="tailing" style="background-color: antiquewhite;">
</div>
</body>
</html>
Server
const express = require('express'),
app = express(),
path = require('path'),
bodyParser = require('body-parser'),
logger = require('morgan'),
server = require('http').Server(app),
io = require('socket.io')(server),
spawn = require('child_process').spawn;
// Fix body of requests
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
// Log the requests
app.use(logger('dev'));
// Serve static files
app.use(express.static(path.join(__dirname, '.')));
// Add a basic route – index page
app.get('/', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
});
var tails = {};
io.on('connection', (socket) => {
console.log(`client connected ${socket.client.id}`);
socket.on('tail', (data) => {
socket.join(data.service);
if (typeof tails[data.service] == "undefined") {
tails[data.service] = spawn('ssh', ['root#' + 'quality-p.company.com', 'tail -f', data.service], {
shell: true
});
tails[data.service].stdout.on('data', (data) => {
console.log(`got new data ${data.toString()}`);
io.to(data.service).emit('newLine', {
line: data.toString().replace(/\n/g, '<br />')
});
});
}
});
});
// Bind to a port
server.listen(3005, () => {
console.log('running on localhost:' + 3005);
});
Client
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="./node_modules/socket.io-client/dist/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
$(() => {
let socket = io();
socket.on('connect', () => {
console.log('connected');
});
socket.on('newLine', (data) => {
console.log(`new data: ${data.line}`);
$("#tailing").append(data.line);
});
$('#tail').click(() => {
socket.emit('tail', {
service: $('#service').val()
});
});
});
</script>
<title>Title</title>
</head>
<body>
<select id="service">
<option id="tnet" value="/var/log/tnet">tnet</option>
<option id="consul" value="/var/log/consul">consul</option>
</select>
<button id="tail">tail</button>
<div id="tailing" style="background-color: antiquewhite;">
</div>
</body>
</html>

Resources