Mocha - dynamic iteration in unit test - javascript

All I want is a dynamic unit test running on Linux/Debian.
I want to get an array of links from a website using "superagent" or whatever module can send a GET request, and then do some tests on each of these links (again sending GET request to each link) using "describe", "it".
I searched for loops in mocha & chai in stackoverflow but the answers assume you already have an array and want to test each of its values so you won't be needing to send GET request to get the array values before test.
my problem is, I don't even have that array to iterate over its values, the array should contain almost 100 links and first I need to get them by sending a GET request to a website (example.com), then I need to test content of each of these links.
test.js
var expect = require('chai').expect;
var request = require('request');
var superagent = require('superagent');
var cheerio = require('cheerio');
var uri = 'http://example.com';
function caller(schemaID){
url = uri + schemaID;
describe("schema "+schemaID, function schema() {
it("available", function schemaLoader(done) {
superagent.get(url)
.end(function(err, res) {
var $ = cheerio.load(res.res.text);
expect(true).to.be.true;
done();
});
});
});
}
superagent.get(uri).end(function(err, res) {
var $ = cheerio.load(res.res.text);
var array = [];
$('#tab-content1').find('a').each(function(){
array.push($(this).attr("href"));
})
array.forEach(val => {
caller(val);
});
});
When I run this in terminal:
mocha test.js
it does nothing!
How would Mocha test all 100 links after getting list of links from superagent?

Related

How I can mock an incoming http request in jest using node.js http?

I am making a handler library named handle_http.js:
module.exports.redirectHttpToHttps = (db,req,res)=>{
const sql = "SELECT * from redirect where use_in_http = 1 and exact_match = 1 and url_from = ? and exact_match=1 LIMIT 1";
// redirection logic
}
And I made a http server where consumes the library:
const http = require('node:http');
// A simple database connection generator
const db = require('./db.js');
const handler = require('./handle_http.js');
http.createServer((req,res){
handler.redirectHttpToHttps(db,req,res);
});
http.listen(80);
But before running into an actual code, I want to make some unit tests using jest (test_redirect.jest.js):
const db = require('../src/db.js');
const redirect = require('../src/handle_http.js');
test("redirect to https",()=>{
const dbHandler = db(':memory:');
database.exec(`
INSERT INTO redirect (url_from,url_to,method,http_status_code,use_in_http,exact_match) VALUES
('http://google.com/mytest','http://yahoo.com','GET',301,1,1),
('http://google.com/mytest2','http://yandex.com','GET',302,1,0),
('http://google.com?q=ikariam','http://yandex.com','GET',302,1,1),
('http://example.com/products','https://fakestoreapi.com/products','POST',308,1,1),
('http://example.net/products','https://fakestoreapi.com/products','POST',308,1,0),
('http://example.net','https://fakestoreapi.com/products','POST',308,1,0);
`,function(error){ err_callback(error); });
// need to make fake request so I can call the `redirectHttpToHttps`
redirect.redirectHttpToHttps(db,/*mocked_request*/,/*some way to assert the response*/)
});
As you can see, I am able to populate an in-memory database with fake data, but I do not know how:
How I can make a fake an incoming http request.
How I can assert that http response has appropriate status code and headers
The provided example does not cut in my case because I need to test the http handling logic in my own http server written in nodejs.
An approach is to use the supertest and create an http server on the fly:
const http = require('node:http');
const request = require('supertest');
const db = require('../src/db.js');
const redirect = require('../src/handle_http.js');
test("redirect to https",(done)=>{
const dbHandler = db(':memory:');
database.exec(`
INSERT INTO redirect (url_from,url_to,method,http_status_code,use_in_http,exact_match) VALUES
('http://google.com/mytest','http://yahoo.com','GET',301,1,1),
('http://google.com/mytest2','http://yandex.com','GET',302,1,0),
('http://google.com?q=ikariam','http://yandex.com','GET',302,1,1),
('http://example.com/products','https://fakestoreapi.com/products','POST',308,1,1),
('http://example.net/products','https://fakestoreapi.com/products','POST',308,1,0),
('http://example.net','https://fakestoreapi.com/products','POST',308,1,0);
`,function(error){ done(error); });
const server = http.createServer((req,res)=>{
redirect.redirectHttpToHttps(dbHandler,req,res)
});
request(server)
.get('/mytest')
.set('Host','google.com')
.expect(301,done);
});
Pay attention into the lines:
request(server)
.get('/mytest')
.set('Host','google.com')
.expect(301,done);
Using request function comming from supertest I provide a server instance that does not listen to any port:
const server = http.createServer((req,res)=>{
redirect.redirectHttpToHttps(dbHandler,req,res)
});
During testing, you can avoid the https at all and create pure non-ssl servers that call the http handling function you want to perform.
Miscelanous
Also, your code has an error at section:
database.exec(`
INSERT INTO redirect (url_from,url_to,method,http_status_code,use_in_http,exact_match) VALUES
('http://google.com/mytest','http://yahoo.com','GET',301,1,1),
('http://google.com/mytest2','http://yandex.com','GET',302,1,0),
('http://google.com?q=ikariam','http://yandex.com','GET',302,1,1),
('http://example.com/products','https://fakestoreapi.com/products','POST',308,1,1),
('http://example.net/products','https://fakestoreapi.com/products','POST',308,1,0),
('http://example.net','https://fakestoreapi.com/products','POST',308,1,0);
`,function(error){ err_callback(error); });
Function err_callback is not defined. Therfore I used the jest's done function as defined into documentation
So the refactored part of the test is:
database.exec(`
INSERT INTO redirect (url_from,url_to,method,http_status_code,use_in_http,exact_match) VALUES
('http://google.com/mytest','http://yahoo.com','GET',301,1,1),
('http://google.com/mytest2','http://yandex.com','GET',302,1,0),
('http://google.com?q=ikariam','http://yandex.com','GET',302,1,1),
('http://example.com/products','https://fakestoreapi.com/products','POST',308,1,1),
('http://example.net/products','https://fakestoreapi.com/products','POST',308,1,0),
('http://example.net','https://fakestoreapi.com/products','POST',308,1,0);
`,function(error){ done(error); });

How can you test values passed to EJS file rendered by Express?

I am trying to test my express web application using mocha and chai, but I am unable to figure out how to test the HTTP requests being handled by express. I am using ejs as my view engine so most of my route handlers look like this:
const someRouteHandlerForGETRequest = async (request, response) => {
// usually some DB queries to get data to display in view
const someQuery = await pool.query('SELECT * FROM table');
var sampleData = someQuery.rows;
response.render('ejspage', {
user: request.session.username,
sampleData: sampleData
});
}
Because of this, I believe that my response.body is just an html file / html string (using postman I was trying to see what was in the response, it appeared to just be the html for the view)
How do I test the data being passed to the ejs file (in this example; sampleData) that is being returned from the node-pg database query?
My current attempt at testing is this:
const { assert } = require('chai');
const chai = require('chai');
const chaiHttp = require('chai-http');
const app = require('../index');
chai.should();
chai.use(chaiHttp);
describe('/GET activeorders', () => {
it('it should GET active orders', (done) => {
chai.request('http://localhost:3000')
.get('/activeorders')
.end((err, res) => {
res.should.have.status(200);
done();
});
})
})
Basically the only this I can test is the response status, beyond that I can't figure out to test any of the values that are being returned from database queries.
I have also tried separating the model from the controller by removing the queries to the database from the route handler and instead having the route handler call a function that returns the results. This doesn't solve my problem though because using chai-http to test a HTTP request still doesn't give me access to the data since the route handler is simply rendering the ejs page with the data.

Cheerio not working. What am I doing wrong?

I am trying to scrape a classified ad search result page.
I have tried console logging everything I can to make sure I am getting a response, which I am, but when I actually use cheerio to query something I don't get anything back. For instance if I just query for how many children using $('.listing-group').children('section').length I get back 0 instead of 24 when I console log it.
Here is what I'm doing. Pardon the long URL.
const request = require("request");
const cheerio = require("cheerio");
const app = express();
app.get("/scrape", function(req, res) {
url =
"http://classifieds.ksl.com/search/?keyword=code&category%5B%5D=Books+and+Media&zip=&miles=25&priceFrom=&priceTo=&city=&state=&sort=";
request(url, function(error, response, html) {
if (!error) {
let $ = cheerio.load(html);
let test = $("#search-results").find("section").length
console.log(test);
} else {
console.log("there has been an error");
}
res.send("Check the console.");
});
});
app.listen("8081");
console.log("check localhost:8081/scrape");
exports = module.exports = app;
I'm new to cheerio so I'm assuming I'm probably making a simple error, but with all the tutorials I've checked, I can't seem to find an answer.
Ultimately I want to grab each result on the page (found in the 'section' tags) to display the data for a personal project I'm working on.
It looks like:
JSON.parse(html.match(/listings: (\[.*\])/)[1])

Node Stream Ending: Write after end

There is the error i am facing when i am sending the input to the child-process written in python.
When i send the data for first time it gives output but with the second input i send me error. Hint that the pipe to covers is ended just after the first output i receive.
Can you help me.
here is the node code.
var bodyParse = require('body-parser');
var urlencodedParser = bodyParse.urlencoded({extended: false});
var spawn = require('child_process').spawn
var py = spawn('python', ['dialogue_management_model.py'])
module.exports = function(app) {
app.get('/', function(req, res) {
res.render('index');
});
app.post('/', urlencodedParser, function(req, res) {
var typed = (JSON.stringify(req.body).substring(2, JSON.stringify(req.body).indexOf(":") - 1));
console.log(typed)
module.exports.typed = typed
var data = typed;
dataString = '';
// Handling the Input data from the Front End With the Post request.
// taking computed/operated data from the python file
py.stdout.on('data', function(data){
dataString += data.toString();
});
// Simply logging it to the Console
py.stdout.on('end', function(){
console.log(dataString);
res.send(dataString);
});
// python doesn't understand the data without string format
py.stdin.write(data);
py.stdin.end();
})
}
Just Server is started in other file and is passing full control to here and from here i am calling python code to take input do computation and pass me the result.
You are ending the input stream entirely after the first call. Move var py = spawn('python', ['dialogue_management_model.py']) into the post request handler, so each request will spawn a child process, write the data, end the input stream, wait for a response, and return a result when the output stream ends.
This gives you the added benefit of making it more thread safe. That is to say, if you have two requests come in at the same time, both will end up adding listeners for py.stdout.on('data', ..., resulting in both getting a mixture of output. Also I'm fairly certain py.stdout.on('end', would only trigger for once, so any request that comes in after the stdout.end callback runs from the first request(s) would hang until they timeout.
Also, unrelated to your question, but when you do:
var typed = (JSON.stringify(req.body).substring(2, JSON.stringify(req.body).indexOf(":") - 1))
you should assign the JSON.stringify() to a variable so you don't have to run it twice.
ie. var payload = JSON.stringify(req.body); var typed = (payload.substring(2, payload.indexOf(":") - 1))
But even then, if you just need the first key you can do Object.keys(req.body)[0] rather than converting the object to a string and parsing the string.

Uncaught ReferenceError: request is not defined

i am working on simple node js module ...
a module that, when i give an ID and a request rate, returns a readable stream which emits location data for the corresponding satellite...
i am trying to implement by using sub classing ReadableStream
http://nodejs.org/api/stream.html#stream_class_stream_readable
i am using this api
https://api.wheretheiss.at/v1/satellites/25544
providing my code below..
http://jsfiddle.net/omb3rwqn/1/
var request = require('request');
var url = 'https://api.wheretheiss.at/v1/satellites/25544'
var reader = request(url);
readable.on('readable', function() {
console.log('got %d characters of string data');
})
did you on accident in your app.js end-point do
app.post('/api/v1/something',function(req,res)
{
var ip = req.headers['x-forwarded-for'];
**var a = request.connection.remoteAddress**
in which case the 'request' in your code is a red herring. what you are really looking for is the fact that your end-point defines 'req' (or anything other than request)

Categories

Resources