casperjs - How to skip part of code on die? - javascript

How to skip part of a code on die? The script has to jump to the next label(for example, they all have name LABEL1)
casper.start('http://google.com');
casper.waitForSelector("input[name='q']",
function success() {
this.echo('Google.com page loaded');
},
function fail() {
this.die('Google.com page WAS NOT loaded'); //meet die() function,
//need to jump on LABEL1 without stopping script
});
casper.then(function(){
this.fillSelectors('body', {
"input[name='q']": 'stackoverflow',
}, true);
this.echo('Filled form with search word - stackoverflow');
});
//here can be random number of casper steps
casper.then(function() {
this.captureSelector("search_results.png", "html");
});
//steps, steps
casper.then(function() {
this.echo("search_results.png");
});
//LABEL1
casper.thenOpen('http://wikipedia.org', function() {
this.echo('HELLO');
});
casper.run();
I can't use suites for this purpose, because I have a custom casper module.

You could probably try emitting a custom event which would execute your required step instead of calling a die(). http://docs.casperjs.org/en/latest/events-filters.html#emitting-you-own-events

Related

AJAX on Button Click runs incrementally

I've implemented a simple AJAX call that is bound to a button. On click, the call takes input from an and forwards the value to a FLASK server using getJSON. Using the supplied value (a URL), a request is sent to a website and the html of a website is sent back.
The issue is the AJAX call seems to run multiple times, incrementally depending on how many times it has been clicked.
example;
(click)
1
(click)
2
1
(click)
3
2
1
Because I am sending requests from a FLASK server to another website, it effectively looks like I'm trying to DDOS the server. Any idea how to fix this?
My AJAX code;
var requestNumber = 1; //done for testing purposes
//RUNS PROXY SCRIPT
$("#btnProxy").bind("click", function() . //#btnProxy is the button
{
$.getJSON("/background_process", //background_process is my FLASK route
{txtAddress: $('input[name="Address"]').val(), //Address is the input box
},
console.log(++requestNumber), //increment on function call
function(data)
{$("#web_iframe").attr('srcdoc', data.result); //the FLASK route retrieves the html of a webpage and returns it in an iframe srcdoc.
});
return false;
});
My FLASK code (Though it probably isn't the cause)
#app.route('/background_process')
def background_process():
address = None
try:
address = request.args.get("txtAddress")
resp = requests.get(address)
return jsonify(result=resp.text)
except Exception, e:
return(str(e))
Image of my tested output (I've suppressed the FLASK script)
https://snag.gy/bikCZj.jpg
One of the easiest things to do would be to disable the button after the first click and only enable it after the AJAX call is complete:
var btnProxy = $("#btnProxy");
//RUNS PROXY SCRIPT
btnProxy.bind("click", function () //#btnProxy is the button
{
btnProxy.attr('disabled', 'disabled');//disable the button before the request
$.getJSON("/background_process", //background_process is my FLASK route
{
txtAddress: $('input[name="Address"]').val(), //Address is the input box
},
function (data) {
$("#web_iframe").attr('srcdoc', data.result); //the FLASK route retrieves the html of a webpage and returns it in an iframe srcdoc.
btnProxy.attr('disabled', null);//enable button on success
});
return false;
});
You can try with preventDefault() and see if it fits your needs.
$("#btnProxy").bind("click", function(e) {
e.preventDefault();
$.getJSON("/background_process",
{txtAddress: $('input[name="Address"]').val(),
},
console.log(++requestNumber),
function(data)
{$("#web_iframe").attr('srcdoc', data.result);
});
return false;
});
Probably you are binding the click event multiple times.
$("#btnProxy").bind("click", function() { ... } );
Possible solutions alternatives:
a) Bind the click event only on document load:
$(function() {
$("#btnProxy").bind("click", function() { ... } );
});
b) Use setTimeout and clearTimeout to filter multiple calls:
var to=null;
$("#btnProxy").bind("click", function() {
if(to) clearTimeout(to);
to=setTimeout(function() { ... },500);
});
c) Clear other bindings before set your calls:
$("#btnProxy").off("click");
$("#btnProxy").bind("click", function() { ... } );

Asynchronous call is not hit when running jasmine test case

I want to test a javascript click event handler in which I have a ajax(asynchronous) GET call which fetches the data from the server.
And I have all the business logic inside the done() function. When I keep debug pointer while running the jasmine test cases, I am seeing it is not at all hitting the done() logic .
How to handle this in Jasmine?
$('#setup').click(function () {
$("div#spinner").addClass('spinner show');
$.ajax({
type: "GET",
url: "http://localhost:3000/setup.cgi",
}).done(function () {
$("div#divLoadingSpinner").removeClass('spinner show');
$('#setup').attr('disabled', 'disabled');
});
});
it("should disable clicking of Edit setup", function () {
setup = $("#setup");
setup.click();
console.log(">>" + setup[0].attributes.length);
expect(setup.attr('disabled')).toBeTruthy();
});
You can use deferred objects and resolve them to hit your success (done) scenario. See a sample below. Need not be exact, you can modify it as per your requirement.
spyOn($, 'ajax').and.callFake(function (request) {
var d = $.Deferred();
d.resolve(put your expected data here);
return d.promise();
});

How to parse iframe on a website with CasperJS

I want obtain informations on a website with iframe.
When I parse this website with casperjs with this command :
casper.then(function() {
casper.waitFor(function() {
return this.withFrame('mainframe', function() {});
}, function() {
this.withFrame('mainframe', function() {
console.log(this.echo(this.getHTML()));
});
});
});
My problem is the result, I have content of one iframe only.
How I can obtain a result of any iframe present on my website?
CasperJS doesn't specifically provide a function to wait for an iframe to load. However, you can use the waitForResource() step function to wait for the iframe resource and then act on it.
casper.waitForResource(function check(res){
var iframeSrc = this.getElementAttribute("iframe[name='mainframe']", "src");
return res.url.indexOf(iframeSrc) > -1;
}, function(){
// success
});
When the resource is received, then you can wait inside of the iframe for a specific selector in order to continue with your script as soon as the iframe is fully loaded:
casper.waitForResource(function check(res){
var iframeSrc = this.getElementAttribute("iframe[name='mainframe']", "src");
return res.url.indexOf(iframeSrc) > -1;
}).withFrame('mainframe', function(){
this.waitForSelector("someSelectorForAnElement thatIsLoadedAtTheEnd", function(){
this.echo(this.getHTML());
});
});
casper.waitFor(function() {
return this.withFrame('mainframe', function() {});
}, function() {
This code doesn't wait at all. CasperJS supports a Fluent API, so that you can chain multiple step functions together like this:
casper.start(url)
.then(function(){...})
.wait(3000)
.then(function(){...})
.run();
This means that the result of withFrame() is the casper object which is evaluated to true for that check function. There is no waiting going on.
console.log(this.echo(this.getHTML()));
doesn't make sense, because casper.echo() already prints to the console. Use either
console.log(this.getHTML());
or
this.echo(this.getHTML());
but not both.

casperjs button click doesn't navigate to next page

I have a page that contains the HTML form with javascript setup like if you click on a button with someid, the form gets submitted. I verified this by firing this in browser console:
document.getElementById("arcotsubmit").click()
As soon as it gets fired, the url changes and form gets submitted.
Now i tried to replicate this with casper.js:
var casper = require('casper').create({});
casper.start('https://cib.icicibank.com/corp/BANKAWAY?Action.CorpUser.Init1.001=Y&AppSignonBankId=ICI&AppType=corporate', function() {
this.echo(this.getTitle());
});
casper.then(function(){
this.click("#arcotsubmit");
});
casper.then(function(){
console.log(this.getCurrentUrl())
});
casper.run();
It stays on the same URL and downloads the same page. I want to download the html that appears after the button gets clicked by casper. The URL is live and can be tested directly.
My point is if i can use this command in browser console
document.getElementById("arcotsubmit").click()
and make it redirect, why i am unable to do it with
this.click("#arcotsubmit") in casperjs?
It is submit instead click for redirecting. The default event for input[type=image] is submit so that try this:
casper.test.begin('Test page.', 2, function suite(test) {
casper.start(
'https://cib.icicibank.com/corp/BANKAWAY?Action.CorpUser.Init1.001=Y&AppSignonBankId=ICI&AppType=corporate',
function() {
this.echo(this.getTitle());
test.assertUrlMatch(/BANKAWAY?/, 'Current location is ' + this.getCurrentUrl());
}
);
casper.then(function(){
this.fill('#rt', {}, true);
this.wait(2000, function() {
test.assertUrlMatch(/BANKAWAY;/, 'New location is ' + this.getCurrentUrl());
});
});
casper.run(function() {
test.done();
});
});
It will be passed.
Test Result Screen Shot
Possible quick fix. If Casper's click isn't working, but your code works in console of the browser, try using Casper's evaluate function.
casper.then(function() {
this.evaluate(function() {
document.getElementById("arcotsubmit").click();
});
});

CasperJS and alert boxes

How do I test that an alert box on my page was called? Can I grab the text of the alert box and evaluate it?
My click in CasperJS is done like this:
casper.waitForSelector('a[href="javascript:UserLogin()"]',
function success() {
this.test.comment("Submiting the bad login info");
this.test.assertExists('a[href="javascript:UserLogin()"]');
this.click("a#h_login");
},
function fail() {
this.test.assertExists('a[href="javascript:UserLogin()"]');
});
The UserLogin function checks and in this case, returns this:
alert('Login has failed.');
How do I check this?
You have to listen to the remote.alert event:
casper.on('remote.alert', function(message) {
this.echo('alert message: ' + message);
// or if you want to test it
this.test.assertMatch(message, /Login has failed/);
});
An attempt to make it a bit more synchronous:
function testAlert(message) {
this.test.assertMatch(message, /Login has failed/);
}
casper.then(function() {
// temporarily registering listener
this.on('remote.alert', testAlert);
});
casper.waitForSelector('#login', function success() {
this.test.pass('selector was found');
this.click("#login");
}, function fail() {
this.test.fail('selector was found');
});
casper.then(function() {
this.removeListener('remote.alert', testAlert);
});
Version 1.1-beta4 provides the casper.waitForAlert function. With it you can write nicer tests when you need to react to different alerts on the page.

Categories

Resources