node-phantom is not enabling javascript on web pages - javascript

I am using node-phantom to post items to a cart on a web site. The problem is that when I use page.open to navigate to the shopping cart page (after already having added an item to the cart), I get an html response saying that I need to enable javascript in my browser in order to view the shopping cart page. I've checked the settings.javascriptEnabled setting and found it to be set to 'true'. At this point I am confused, why does the page think that phantomjs does not have javascript enabled?
Here is my code:
var phantom = require('node-phantom');
phantom.create(function (err, ph) {
ph.createPage(function (err, page) {
page.get('settings', function(err, oldSettings) {
console.log('\r\n oldSettings: ' + JSON.stringify(oldSettings));
page.open('http://www.somesite.com/shoppingcart/default.cfm', function (err, status) {
page.injectJs(jqueryPath, function (err) {
setTimeout(function() {
page.evaluate(function (injectedSku) {
var localErr;
var skuInCart;
var checkoutLnkMsg;
var pageHTML;
try {
pageHTML = $("html").html();
// Get 'SKUs' input element.
skuInCart = $('input[name="SKUs"]').val();
if (injectedSku === skuInCart) {
var checkoutLnk = $('#cartAction_bottom a[alt="Checkout"');
checkoutLnk.on("click", function() {
checkoutLnkMsg = '"' + checkoutLnk.href + '" link has been clicked';
});
checkoutLnk.click();
} else {
throw new Error('Product not in cart');
}
} catch (e) {
localErr = e;
}
return {
pageHTML: pageHTML,
err: localErr,
skuInCart: skuInCart,
checkoutLnkMsg: checkoutLnkMsg,
injectedSku: injectedSku
};
}, function (err, result) {
if (result.err) {
callback(err);
//return ph.exit();
}
fs.writeFileSync("./html_log.txt", result.pageHTML);
console.log('\r\n checkout - page.evaluate - injectedSku: ' + result.injectedSku);
console.log('\r\n checkout - page.evaluate - result.skuInCart: ' + JSON.stringify(result.skuInCart));
console.log('\r\n checkout - page.evaluate - result.checkoutLnkMsg: ' + result.checkoutLnkMsg);
callback(null);
//return ph.exit();
}, sku);
}, 1250);
});
});
});
});
});

Replace
page.injectJs()
with
page.includeJs()
UPDATE
var phantom = require('node-phantom');
phantom.create(function (err, ph) {
ph.createPage(function (err, page) {
page.get('settings', function(err, oldSettings) {
//console.log('\r\n oldSettings: ' + JSON.stringify(oldSettings));
page.open('http://www.footlocker.com/shoppingcart/default.cfm?', function (err, status) {
console.log(status);
var sku = 234; // assign sku id here
page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js', function (err) {
setTimeout(function() {
page.evaluate(function (injectedSku) {
var localErr;
var skuInCart;
var checkoutLnkMsg;
var pageHTML;
try {
pageHTML = $("html").html();
// Get 'SKUs' input element.
skuInCart = $('input[name="SKUs"]').val();
if (injectedSku === skuInCart) {
var checkoutLnk = $('#cartAction_bottom a[alt="Checkout"');
checkoutLnk.on("click", function() {
checkoutLnkMsg = '"' + checkoutLnk.href + '" link has been clicked';
});
checkoutLnk.click();
} else {
throw new Error('Product not in cart');
}
} catch (e) {
localErr = e;
}
return {
pageHTML: pageHTML,
err: localErr,
skuInCart: skuInCart,
checkoutLnkMsg: checkoutLnkMsg,
injectedSku: injectedSku
};
}, function (err, result) {
if (result.err) {
// callback(err);
//return ph.exit();
}
// fs.writeFileSync("./html_log.txt", result.pageHTML);
console.log('\r\n checkout - page.evaluate - injectedSku: ' + result.injectedSku);
console.log('\r\n checkout - page.evaluate - result.skuInCart: ' + JSON.stringify(result.skuInCart));
console.log('\r\n checkout - page.evaluate - result.checkoutLnkMsg: ' + result.checkoutLnkMsg);
// callback(null);
ph.exit();
}, sku);
}, 1250);
});
});
});
})
});

Related

NodeJS if string contains execute script

I have a the following script:
function execute(){
require("fs").readFile("sometextfile.txt", function(err, cont) {
if (err)
throw err;
console.log("ALERT:"+(cont.indexOf("mystring")>-1 ? " " : " not ")+"found!");
});
}
setInterval(execute,9000);
I want to execute a javascript only if the string contains "Alert: found!"
The script:
var Prowl = require('node-prowl');
var prowl = new Prowl('API');
prowl.push('ALERT', 'ALERT2', function( err, remaining ){
if( err ) throw err;
console.log( 'I have ' + remaining + ' calls to the api during current hour. BOOM!' );
});
Help!
Are you asking how to combine the two?
const fs = require('fs');
const Prowl = require('node-prowl');
const prowl = new Prowl('API');
function alert() {
prowl.push('ALERT', 'ALERT2', function(err, remaining) {
if (err) throw err;
console.log('I have ' + remaining + ' calls to the API during current hour. BOOM!');
});
}
function poll() {
fs.readFile('sometextfile.txt', function(err, cont) {
if (err) throw err;
if (cont.indexOf('mystring') !== -1) {
alert();
}
});
}
setInterval(poll, 9000);

The async.queue never drains?

I am trying to query a flight api with my async queue in node but it appears as my queue never "drains" (simply run the drain method). I am using this library.
It runs every request just fine but then it just stops there and the content in the drain function never executes.
let flights = [];
let q = async.queue(function (airline, callback) {
const flight_search_url = 'http://someflightapi.com/search/' + airline.code + '?date=' + date + '&from=' + originAirportCode + '&to=' + destinationAirportCode;
request(flight_search_url, function(error, response, body) {
if (error) {
return callback(error);
}
if (res.statusCode !== 200) {
return callback(res.statusCode);
}
console.log(airline.code);
flights.push(JSON.parse(body));
callback();
});
}, 10);
q.drain(function(error) {
if (error) {
res.json({
error: "There was an error while calculating flights",
destinationAirportCode: destinationAirportCode,
originAirportCode: originAirportCode,
possibleOrigins: possibleOrigins,
possibleDestinations: possibleDestinations,
flights: flights
});
} else {
res.json(flights);
}
});
q.push(airlines);

Missing ) after argument list (Node)

I'm using Node to run this program, where is my error(s)? It's saying I'm missing ) after argument list. I can't find where this error is, I've tried putting the ) in various places. I'm using Node v5
var Twit = require('twit');
var T = new Twit(require('./config.js'));
var stream = T.stream('statuses/filter', {
track: 'xoxo, oi, i\m fine,'
});
(stream.on('tweet', function(tweet) {
console.log('#' + tweet.user.screen_name + ': ' + tweet.text);
if (tweet.text.indexOf('RT') > -1) {
return;
}
var replyString;
if (tweet.user.utc_offset === null) {
replyString = ' Ok';
} else {
replyString = ' Okay';
}
})
(T.post('statuses/update', {
status: '#' + tweet.user.screen_name + replyString,
in_reply_to_status_id: tweet.id_str
}, function(err, data, response) {
if (err) {
console.log(err);
return;
}
}
tweet.botReplyId = data.id_str);
db.tweets.insert(tweet);
});
(end)
})
setInterval(stream, 60000);
The code seems to be a bit all over the place with regards to scope and it makes it a bit difficult to follow.
Try using something like the following which annotates it a bit and should help avoid issues like this (as it seems to validate without any errors) :
// Define your variables
var Twit = require('twit');
var T = new Twit(require('./config.js'));
var stream = T.stream('statuses/filter', { track: 'xoxo, oi, i\'m fine,'});
// When a tweet occurs
(stream.on('tweet', function(tweet) {
// Log it
console.log('#' + tweet.user.screen_name + ': ' + tweet.text);
// Determine if it is a retweet and ignore
if (tweet.text.indexOf('RT') > -1) { return; }
// Set your reply
var replyString = (tweet.user.utc_offset === null) ? ' Ok' : ' Okay';
// Post your reply
T.post('statuses/update', { status: '#' + tweet.user.screen_name + replyString, in_reply_to_status_id: tweet.id_str}, function(err, data, response) {
// If an error occurs, log it
if (err) {
console.log(err);
return;
}
// Otherwise store your response and store it
tweet.botReplyId = data.id_str;
db.tweets.insert(tweet);
});
}));
// Check your stream every 10 minutes
setInterval(stream, 60000);

stoping async tasks running in parallel

I'm trying to run through (using foreach) an array of objects and then for each I'd like to call a function that uses request to get a file and then unzips it with zlib, but one at a time, given the nature of node this is currently done asynchronously.
I'd like it to be done something like this...
- foreach - first object
- call function for first object
- when function has completed
- go to the next object in the array
I have tried using the SYNC module to try and solve this but with no luck.
Any ideas on how I can achieve this?
// the function i am trying to run for each in sync
var downloadUnzipFile = function(mID) {
try {
// Read File
console.log("Started download/unzip of merchant: " + mID + " # " + new Date().format('H:i:s').toString());
request(linkConst(mID))
// Un-Gzip
.pipe(zlib.createGunzip())
// Write File
.pipe(fs.createWriteStream(fileName(mID)))
.on('error', function(err) {
console.error(err);
})
.on('finish', function() {
console.log("CSV created: " + fileName(mID));
console.log("Completed merchant: " + mID + " # " + new Date().format('H:i:s').toString());
//console.log("Parsing CSV...");
//csvReader(fileName);
});
} catch (e) {
console.error(e);
}
}
module.exports = function(sMerchants) {
var oMerchants = JSON.parse(JSON.stringify(sMerchants));
sync(function() {
oMerchants.forEach(function eachMerchant(merchant) {
downloadUnzipFile(merchant.merchant_aw_id);
})
})
};
var promiseQueue = (function() {
'use strict';
var promiseQueue = function() {
var queue = [Promise.resolve(true)];
var add = function(cb) {
var args = Array.prototype.slice.call(arguments);
args.shift();
queue.unshift(new Promise(function(resolve) {
queue[0].then(function() {
resolve(cb.apply(null, args));
queue.pop();
});
}));
};
return {
add: add
}
}
return promiseQueue;
}());
usage EXAMPLE:
This is the asynch function that will be called
var theFun = function (time, n) { // use whatever arguments you like that will be called with your function
return new Promise(function(resolve) {
//asynch function goes here INSTEAD of the setTimeout and it's contents, I repeat, INSTEAD of the setTimeout
setTimeout(function() { // this is for demonstrating ONLY
console.log('resolving', n, time); // this is for demonstrating ONLY
resolve(time); // this is for demonstrating ONLY
}, time); // this is for demonstrating ONLY
// remember to resolve("someValueNotImportantAsItIsntUsedAnywhere") on completion of your asynch function
});
}
This is how the items get added to the queue - I did it this way because of MY use case
var pq = promiseQueue();
for(var i = 0; i < 5; i++ ) {
var r = 1000 - i * 150;
console.log('adding ', i, r);
pq.add(theFun, r, i);
}
Hope you find this of some use
First, your function needs to take a callback so it can communicate when it has finished:
var downloadUnzipFile = function(mID, next) {
try {
// Read File
console.log("Started download/unzip of merchant: " + mID + " # " + new Date().format('H:i:s').toString());
request(linkConst(mID))
// Un-Gzip
.pipe(zlib.createGunzip())
// Write File
.pipe(fs.createWriteStream(fileName(mID)))
.on('error', function(err) {
console.error(err);
})
.on('finish', function() {
console.log("CSV created: " + fileName(mID));
console.log("Completed merchant: " + mID + " # " + new Date().format('H:i:s').toString());
//console.log("Parsing CSV...");
//csvReader(fileName);
next();
});
} catch (e) {
console.error(e);
next();
}
}
Then, we need to recursively call each one when the previous has finished:
module.exports = function(sMerchants, next) {
var oMerchants = JSON.parse(JSON.stringify(sMerchants));
var i = 0;
var run = function() {
if(i < oMerchants.length)
downloadUnzipFile(i++, run);
else
next();
};
};
Note that I also added a callback to the exported function, so it can communicate when it is finished. If this is unnecessary, you can drop it.
This may work for you, uses Promise. Need to add resolve and reject callbacks to your downloadUnzipFile-
var exports = (function () {
'use strict';
var pre = document.getElementById('out');
function log(str) {
pre.appendChild(document.createTextNode(str + '\n'));
}
function downloadUnzipFile(id, resolve, reject) {
log('Start: ' + id);
try {
setTimeout(function () {
resolve(id);
}, 3000);
} catch (e) {
reject(e);
}
}
function done(id) {
log('Done: ' + id);
}
function error(e) {
log(e.message);
}
function getPromise(mID) {
return new Promise(function (resolve, reject) {
downloadUnzipFile(mID, resolve, reject);
});
}
return function (sMerchants) {
JSON.parse(sMerchants).reduce(function (next, mID) {
if (!next) {
next = getPromise(mID);
} else {
next = next.then(function (id) {
done(id);
return getPromise(mID);
}, error);
}
return next;
}, null).then(done, error);
};
}());
exports(JSON.stringify([1, 2, 3, 4, 5]));
<script src="https://cdnjs.cloudflare.com/ajax/libs/json2/20150503/json2.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.1.7/es5-shim.min.js"></script>
<script src="https://rawgit.com/jakearchibald/es6-promise/master/dist/es6-promise.min.js"></script>
<pre id="out"></pre>
I added the browser shims to support older browsers that may be viewing this, you shouldn't need them on node.js but you may need to require a Promise shim if you are using an old node.js.

asynchronous execution in protractor end to end tests

I have written a function , which is returning a value. In my main i am calling the function like this:
var fn_return_val = lesson.select_lesson(lesson1_text);
console.log("returned value is : " + fn_return_val);
And my function implementation is like(other file.js) :
module.exports = {
select_lesson:
function select_lesson(lesson_name) {
console.log('\n ************************* Lessson name: ' + lesson_name);
var desiredOption, status;
var repeter = element.all(by.repeater('item in items'));
repeter.then(function (items) {
items.forEach(function (icon) {
console.log('\n ************************* item');
icon.getText().then(function (txt) {
if (txt == lesson_name) {
desiredOption = icon;
}
})
}).then(function clickOption() {
if (desiredOption) {
var el = desiredOption.all(by.css('[ng-click="launchActivity()"]'));
var el_progress = desiredOption.all(by.css('.pna-progress'));
var abc = el.getAttribute('value').then(function (txt) {
status = txt;
return status
});
el_progress.getAttribute('style').then(function (progress) {
console.log('\n ************************* Lessson progress : ' + progress);
});
el.click();
}
});
});
}
};
The problem is function is returning "undefined" value, and the print statement console.log("returned value is : " + fn_return_val);
is executing before the function implementation
Can anyone help me on resolving this?
This is all about promises and protractor's Control Flow.
You need to resolve the promise and log the results inside then:
lesson.select_lesson(lesson1_text).then(function(fn_return_val) {
console.log("returned value is : " + fn_return_val);
});
And you also need to return from a function:
function select_lesson(lesson_name) {
...
// return here
return repeter.then(function (items) {
...
}).then(function clickOption() {
...
});
});
}

Categories