CasperJS/PhantomJS : waitForSelector('svg') -> svg sometimes doesn't appear - javascript

So here another trouble. I have a script loading svg and waiting for it to appear which randomly fails. Sometimes phantom stay stuck loading svg (even with a waitTimeout at 2min, so the problem isn't here I think). script : http:// r.ccmbg.com/js.php?m=highchart=...
I could still load the page X times in a loop waiting for svg to appear, but I'd prefer another solution. If you have an idea, I'm all ears.
Simple example :
casper.test.begin('\n********* Navigation on directories : ***********', 8,{
setUp: function(test) {
//setLevel("normal");
},
tearDown: function(test) {
//getJSON();
},
test: function(test){
"use strict";
casper.start()
.thenOpen('http://www.linternaute.com/voyage/climat/paris/ville-75056/2013-2008')
.waitForResource(/m=highcharts&/, function(){
this.waitForSelector('svg',function(){
this.test.assertExists("tspan");
});
})
.waitForUrl(/2008/, function(){
this.test.assertSelectorHasText("h2", "maximales");
this.test.assertSelectorHasText("h2", "minimales");
this.test.assertSelectorHasText("h2", "Paris");
this.test.assertSelectorHasText("h2", "Le soleil");
this.test.assertSelectorHasText("h2", "La pluie");
this.test.assertExists("div.marB20");
this.test.assertNotEquals(this.fetchText("div.marB20 > table > thead > tr > th"), " ", "Table first data not empty");
})
.run(function() {
this.test.comment('--- Done ---\n');
test.done();
});
}
});

Well, when I don't know the script called or the API used (so I can't debug myself), I just check the ressource now.
this.waitForResource(/js\.php\?m=highcharts&v/, function(){
this.test.pass("ressource received (js -> API highcharts)");
});
Don't forget this event to get back page document error :
casper.on("page.error", function(msg, trace) {
this.echo("Page Error: " + msg, "ERROR");
});

Related

Handle errors when loading content into a Kendo UI KendoWindow

I have a KendoWindow that loads content into an iFrame from a JSP.
I've attached error-handlers at every position yet when the JSP isn't available, none of these error handlers are called.
What is the proper way to handle errors when loading content into a KendoWindow?
win.kendoWindow({
width : "860px",
modal : true,
height : "680px",
iframe : true,
resizable : false,
content : {
url: "access/lookup/Source.jsp",
failure: function(err) {
console.log(e.status);
console.log(e.xhr);
},
error: function(err) {
console.log(e.status);
console.log(e.xhr);
}
},
error: function(err) {
console.log(e.status);
console.log(e.xhr);
}
});
If you dig into the source code, you see:
if (!showIframe) {
// perform AJAX request
that._ajaxRequest(options);
} else {
iframe = element.find("." + KCONTENTFRAME)[0];
// Edited for clarity
iframe.src = url || iframe.src;
}
showIframe, if not set in options, is defined as:
showIframe = !isLocalUrl(url);
So only the code execution branch that does the ajax request uses your error handlers. The else branch just does an iframe and lets the browser handle it.
Adding iframe: false to the content options, as shown here, should help.

Cant get Asset2SD to work..:-/

I've been trying to have cordova plugins working for weeks now. Can't seem to have a simple one like Asset2SD workinf either.
Here is what I do (step by step)
I get the plugin via the CLI
$ cordova plugin add https://github.com/gkcgautam/Asset2SD.git
Then I add the name of the plugin to my confi.xml like so:
<plugin name="asset2sd.copyFile" />
Then I wrote this snipet that gets a uri of a clicked pdf file that should then be sent to sd card:
$('a[href$=\\.pdf]').click(function() {
var myuri = this.href ;
alert(myuri);
alert(this.href);
/* storing and opening the file */
asset2sd.copyFile(
{
asset_file: this.href,
destination_file: "Download/new.pdf"
},
function() { alert('success'); },
function() { alert('fail'); }
);
})
Nothing happens, except the first two alerts, that do give me the file's full path from the asset folder.
I don't even get the "fail" alert from the plugin.
I then tried to hardcode the "variable" to see if something was wrong with giving the full path (the example in github only gives a "www/... "path
$('a[href$=\\.pdf]').click(function() {
var myuri = this.href ;
alert(myuri);
alert(this.href);
/* storing and opening the file */
asset2sd.copyFile(
{
asset_file: "wwww/res/DOC140416-1.pdf",
destination_file: "Download/newdoc.pdf"
},
function() { alert('success'); },
function() { alert('fail'); }
);
})
Nothing changed either.
Any help apreciated!!!

Jquery elements not rebinding + HTMLDivElement unrecognized expression

I am creating a dynamic refresh feature for div elements on my site that need to be dynamically refreshed.
$(document).ready(function() {
function refreshDiv() {
var refreshUrl = window.location.pathname;
$('.refreshable').each(function() {
$(this).fadeOut("slow", function() {
$(this).hide().load(refreshUrl + " " + this, "").fadeIn("slow");
});
});
}
$(document.body).on("click", ".login_button.submit", function(e) {
e.preventDefault();
var username = $('#username').val();
var password = $('#password').val();
$.ajax({
type : "POST",
url : '/login',
data : {username:username, password:password},
success:function(response) {
if(response.status == 'success') {
$('#sb-site').animate({'opacity': '1'}, 300);
$('#login_form').toggle();
refreshDiv();
} else {
console.log('Something went wrong');
}
},
error:function(response) {
console.log('Something went wrong');
}
});
});
$(document.body).on("click", ".logout_button", function(e) {
e.preventDefault();
$.ajax({
type : "POST",
url : '/logout',
success:function(response) {
if(response.status == 'success') {
refreshDiv();
} else {
console.log('Something went wrong');
}
},
error:function(response) {
console.log('Something went wrong');
}
});
});
});
I have a few issues that have come up.
1) After logout is clicked, it calls the Laravel controller at /logout. After that, it loads up the page with the refreshed content, but the jquery click events wont rebind, so I have to refresh in order to log in again after a logout. The elements rebind fine after login happens, however. I figured using .on() would fix this, but it has not.
2) Elements are duplicated because I am having trouble implementing 'this' into the refreshDiv function. I get an error:
Uncaught Error: Syntax error, unrecognized expression: [object HTMLDivElement]
This doesn't happen if I do
$(this).hide().load(refreshUrl + " .refreshable>*", "").fadeIn("slow");
but I need it to reload each specific targeted element individually, or it overlaps the content with matching classes. I tried:
$(this).hide().load(refreshUrl + " " + this, "").fadeIn("slow");
My goal is to just be able to have a scalable solution to just add a .refresh class to a wrapper that needs to be dynamically refreshed.
It is hard to tell exactly what you want from this as shown in your call to .load(). The reason your error is showing up is because you are implicitly casting this to a string. The result is "[object HTMLDivElement]" which makes your call look like this
$(this).hide().load(refreshUrl + " " + "[object HTMLDivElement]", "").fadeIn("slow");
and that should clear up why the error occurs. What do you need from the div element in that spot?
In order to access the current div, just use prop or attr or native calls to get the information out from that point, such as this.className or this.id or $(this).data('location') etc.
However, as you have already started this chain off with $(this), making the call to .load will already apply the loaded content at refreshUrl to the current this element.
So really all you need to do is
$(this).hide().load(refreshUrl,function(){
$(this).fadeIn('slow'); // only fade in once content is loaded
});
Or perhaps you want the fade to occur while the data loads, in which case $(this).hide().load(refreshUrl).fadeIn("slow"); would be used.

Protractor: how to wait for full load of bootstrapped AngularJS

I have a bootstrapped Angular (1.2.6) app. This means it doesn't have an explicit ng-app. As such, I've run into all sorts of problems getting Protractor framework'd tests to work (using SauceLabs and grunt-protractor-runner).
The errors vary based on what I try, but generally:
Error: Angular could not be found on the page http://xxx:9000/ :
angular never provided resumeBootstrap
Or...
Error: Error while waiting for Protractor to sync with the page: {}
I've found a few proposed solutions which I've tried. Including those found in this rich thread, as well as here, too. Nothing I do, though, gets things working.
I've tried to use angular.resumeBootstrap in the bootstrapping like so (note I tried multiple variations of this to no avail, including trying to set an ng-app programatically on the document body):
angular.element( document ).ready( function() {
window.name = 'NG_DEFER_BOOTSTRAP!'
angular.bootstrap( document, [ 'app' ] );
setTimeout( angular.resumeBootstrap, 0 );
});
The error for this, as others have found, is weird:
UnknownError: unknown error: [ng:btstrpd] App Already Bootstrapped with this Element
'<body ng-app="" ng-controller="ApplicationController" class=" ng-scope pace-done">'
What's weird/annoying is that, at least looking in Sauce Labs session, it appears that this test is working... it's just weirdly thinking that it's been bootstrapped twice.
I've also tried using various combinations of waitForAngular, wait, and others in the test itself. Here's one variation I've tried:
it( 'should load the home page', function() {
ptor = protractor.getInstance();
ptor.waitForAngular();
ptor.driver.get( 'http://xxx:9000/' );
ptor.driver.wait( function() {
return ptor.getCurrentUrl().then( function() {
return ptor.isElementPresent( by.id( 'signIn' ) ).then( function() {
console.log('we are here!');
return true;
});
});
})
.then( function() {
expect( ptor.isElementPresent( by.id( 'signIn' ) ) ).toBe( true );
});
});
This results in errors like the following:
1) e2e: home should load the home page
Message: timeout: timed out after 20000 msec waiting for spec to complete
Stacktrace: undefined
I've also tried increasing various timeouts in the config file to no avail.
Any help would be much appreciated!
You should separate the test in two 'it'-steps. Like this:
it( 'should load angular', function() {
ptor = protractor.getInstance();
ptor.waitForAngular();
})
it( 'should load the home page', function() {
ptor.driver.get( 'http://xxx:9000/' );
ptor.driver.wait( function() {
return ptor.getCurrentUrl().then( function() {
return ptor.isElementPresent( by.id( 'signIn' ) ).then( function() {
console.log('we are here!');
return true;
});
});
})
.then( function() {
expect( ptor.isElementPresent( by.id( 'signIn' ) ) ).toBe( true );
});
});
The problem with protractor is that every command runs without waiting for the prior step to complete. So, ptor.waitForAngular() and ptor.driver.get( 'http://xxx:9000/' ) are running at almost the same time. If you separate these into two steps, protractor moves on after the first 'it'-step is done.

PJAX/DJAX- rerun scripts after pjax load

I'm using RequireJS to structure my JS and DJAX (basically PJAX) as a way to dynamically load content without a full page reload.
The issue I have is that after DJAX has finished loading the content I need to rerun my scripts (e.g. a script that adds multiple images into a carousel) so that the new page renders correctly. I thought the best way to do this would be to simply rerun the function I'm running on $(document).ready(); but I'm getting this output in the console:
Uncaught TypeError: Cannot read property 'djaxLoad' of undefined
which is referring to this line in load-posts.js
bootstrap.init();
I'm guessing I'm writing something incorrectly.
Here is bootstrap.js which is my main file which fires on document.ready and initialises all my modules
require(['base/responsive', 'base/main-menu', 'base/social-share', 'base/randomise-colours', 'base/infinite-scroll', 'base/load-posts', 'base/image-fade', 'base/carousel', 'base/misc'],
function(responsive, main_menu, social_share, randomise_colours, infinite_scroll, load_posts, image_fade, carousel, misc) {
var $ = jQuery;
function djaxLoad() {
//If page has JS (detected with Modernizr) then hide content until the
//doc is ready to avoid flash of unstyled content
$('#djax-container').css('display', 'block');
main_menu.init();
social_share.init();
randomise_colours.init();
load_posts.init();
image_fade.init();
infinite_scroll.init();
carousel.init();
misc.init();
responsive.init();
}
$(document).ready(djaxLoad);
}
);
And this is load-posts.js which handles DJAX for me. DJAX works, I just need to get the scripts to fire again.
define(['djax', 'base/bootstrap'], function(djax, bootstrap) {
var $ = jQuery,
$body = $('body');
return {
init: function() {
if($body.length >= 1) {
this.setUp();
} else {
return false;
}
},
setUp: function() {
this.pjaxLinks();
},
pjaxLinks: function() {
//Initialise DJAX, but stop it from running on pagination links (URL is /page...)
$('body').djax('.updateable', ['page']);
//When clicking a djax link
$(window).bind('djaxClick', $.proxy(function() {
this.addLoader();
},this));
//When the new content has loaded in
$(window).bind('djaxLoad', $.proxy(function() {
this.removeLoader();
},this));
},
addLoader: function() {
$body.addClass('loader-visible');
},
removeLoader: function() {
$body.removeClass('menu-visible');
$('html, body').scrollTop(0);
function removeLoaderDelay() {
$body.removeClass('loader-visible');
bootstrap.djaxLoad();
}
setTimeout(removeLoaderDelay, 1000);
}
};
});
The djaxClick function runs on a link click, and the djaxLoad function runs after the content has been loaded in. I'm adding a loader overlay to the page, then removing it after the content has loaded in.
A bit late but for future reference: In the documentation at https://github.com/beezee/djax you'll find the djaxLoad-event. This is specifically made for your usecase. You can use it as follows:
$(window).bind('djaxLoad', function(e, data) {
// your scripts to run on ajax-calls
});
The site further explains: "the data object passed with the event contains the requested url, the page title for the requested page, and the contents of the requested page as a string".
$(window).bind('djaxLoad', function(e, data) {
var responseObj = $('<div>'+data.response+'</div>');
//do stuff here
});

Categories