JQuery include in phantomjs is not working - phantomjs

My code is:
var url = 'https://search.yahoo.com/',
page = new WebPage(),
fs = require('fs');
page.settings.userAgent = 'Mozilla/5.0 (platform; rv:geckoversion) Gecko/geckotrail appname/appversion';
page.onConsoleMessage = function (msg) {
console.log(msg);
};
page.open(url, function(status) {
if (status !== 'success')
{
console.log('Unable to access network');
phantom.exit();
return;
}
else
{
page.includeJs("https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js", function()
{
page.evaluate(function()
{
$('#yschsp').val("ask question");
$(".sbb").click();
});
page.onLoadFinished = function(status) {
var content = page.content;
fs.write('1.html', content, 'w');
console.log($('#link-1').val());
phantom.exit();
};
});
}
});
JQuery works perfect in page.evaluate but does not work in page.onLoadFinished. I get an error
Can't get variable: $
That means that in function page.onLoadFinished jquery is not working. But I can not understand why?

Since jQuery is loaded into the page context, you can only use there. The only function that interfaces with the page context is evaluate (and the other evaluate functions).
So this line
console.log($('#link-1').val());
must be inside of an evaluate callback. Since you have a page.onConsoleMessage event handler you will receive the console message from the page context.
The other thing is that adding an page.onLoadFinished event handler after the page has loaded isn't doing anything useful. You can remove the handler surrounding your code since the page load is finished when the page.open callback is called.
If #link-1 is not yet loaded, you should either log the value after a static timeout (setTimeout) or use waitFor.

Related

Interacting with iframe with empty src attribute

I'm trying to test an a page with an external component which contains a following iframe:
<iframe id="iframe1" src="about:blank" ... >
This iframe has an empty body initially but is populated with content after some actions.
When trying to run the following piece of code:
.expect(myIFrameSelector().visible).ok()
.switchToIframe(myIFrameSelector())
.expect(firstRowSelector()).eql("Hello")
I receive the following error on line 3:
The content of the iframe in which the test is currently operating did not load.
I tried waiting for the contents to appear with wait() and I checked it with debug() too.
Any ideas what could be the problem?
I assume that this is because the content was probably populated using JS, so can I somehow tell testcafe that the content is actually ready?
You can try to wait and check if the document in the iframe is loaded using ClientFunction.
For example:
import { Selector, ClientFunction } from 'testcafe';
const waitForIframeLoad = ClientFunction((iframeSelector) => new Promise((resolve, reject) => {
var i = 0;
var intervalId = null;
intervalId = window.setInterval(() => {
var iframeElement = document.querySelector(iframeSelector);
if (iframeElement
&& iframeElement.contentWindow
&& iframeElement.contentWindow.location.href !== 'about:blank'
&& iframeElement.contentDocument) {
window.clearInterval(intervalId);
resolve();
}
if (i > 60) {
window.clearInterval(intervalId);
reject(new Error('Iframe content loading timeout'))
}
i++;
}, 1000);
}));
fixture`fixture`
.page`http://example.com`;
test('test', async t => {
const iframeSelector = '#simulatorFrame';
await waitForIframeLoad(iframeSelector);
await t
.switchToIframe(iframeSelector)
.click(Selector('button'));
});

in phantomjs,how to pass variables from page context to outside the page context

consider the following snippet.how can i access the value of the page url outside the page context?globally accessing the value was not working either.callbacks wasn't clear to me in approach.
page.onUrlChanged = function(targetUrl) {
console.log('New URL: ' + targetUrl);
};
page.onConsoleMessage = function (msg) {
console.log(msg);
};
var abc=page.open(url,function(status){
page.evaluate(function(){
//some code;
})
return page.url;
});
console.log(abc);
the code always gives undefined page url.
PhantomJS documents are very much recommended: http://phantomjs.org/api/webpage/method/evaluate.html
page.open(url,function(status){
var current_url = page.evaluate(function(){
return document.location.href;
})
console.log(current_url);
});

Using a json file to store configurations for a dojo application

I am writing a fontend web app using dojo that does a lot of calls to rest endpoints using xhr. I would like to have a place to store configurations for things like endpoint locations and html tag references. I thought I would use an xhr call to a json file to do this, but I am having trouble getting my functions to trigger in the right order/at all. Below is my main js file which has an init() function that I am passing as the callback to my conf initializer ("ebs/conf") module, also below. I have used the Chrome debugger to set breakpoints within my conf.get() method, and it looks as though it never gets called.
Can someone give me some advice please?
Main JS File:
// module requirements
require([ "dojo/dom", "dojo/on", "ebs/prices", "ebs/cart", "ebs/conf",
"dojo/ready" ], function(dom, on, prices, cart, conf, ready) {
ready(function() {
conf.get("/js/config.json", init());
function init(config) {
on(dom.byId("height"), "keyup", function(event) {
prices.calculate(config);
});
on(dom.byId("width"), "keyup", function(event) {
prices.calculate(config);
});
on(dom.byId("qty"), "keyup", function(event) {
prices.calculate(config);
});
on(dom.byId("grills"), "change", function(event) {
prices.calculate(config);
});
cart.putSampleCart();
cart.load(config);
}
});
});
And here is my 'conf' module ("ebs/conf"):
define(["dojo/json", "dojo/request/xhr"], function(json, xhr) {
return {
get : function(file, callback) {
// Create config object from json config file
var config = null;
xhr(file, {
handleAs : "json"
}).then(function(config) {
callback(config);
}, function(error) {
console.error(error);
return error;
});
}
}
});
Your are not passing the function as the callback. You are executing it and passing the result as the second argument.
conf.get("/js/config.json", init());
should be
conf.get("/js/config.json", init);

How to find out if dgrid has finished with loading data from store

does anybody know how can I find out if dgrid has finished loading data from the store?
I've been trying to find a way to do this in dgrid's OnDemandList.js but unfortunately it's above my current knowledge of dojo.
Thanks
I came up with this solution some time ago, for dgrid v0.3.0, but looking at sources it seems nothing changed so far, so I will try to adapt my solution for v0.3.3.
See it in action: http://jsfiddle.net/phusick/FkANy/
The problem is that dgrid/_StoreMixin::_trackError does not define success callback when returning Deferred::when, therefore you need to override that method, define success callback and fire refresh event there.
_RefreshMixin module:
define(["dojo/_base/declare", "dojo/_base/lang", "dojo/_base/Deferred", "dojo/on"], function(declare, lang, Deferred, listen) {
function emitError(err){
if(typeof err !== "object"){
err = new Error(err);
}
err.grid = this;
if(listen.emit(this.domNode, "dgrid-error", {
grid: this,
error: err,
cancelable: true,
bubbles: true })){
console.error(err);
}
}
var _RefreshMixin = declare(null, {
_trackError: function(func){
var result;
if(typeof func == "string"){ func = lang.hitch(this, func); }
try{
result = func();
}catch(err){
emitError.call(this, err);
}
return Deferred.when(
result,
// success callback instead of `null` in _StoreMixin:
lang.hitch(this, function() {
// fire 'refresh' event
listen.emit(this.domNode, "refresh", {
cancelable: true,
bubbles: true
});
}),
lang.hitch(this, emitError)
);
}
});
return _RefreshMixin;
});
Declare your own grid class and instantiate it:
var MyGrid = declare([OnDemandGrid, _RefreshMixin]);
var grid = new MyGrid({ /* params here*/ });
Now you can listen to refresh event:
grid.on("refresh", function(event) {
// your handler
});
On dgrid 0.3.5 you can listen to dgrid-refresh-complete event, emitted when results finish rendering.
OnDemandList/Grid wiki page: https://github.com/SitePen/dgrid/wiki/OnDemandList-and-OnDemandGrid

Exposing variables from PhantomJS call to injectJS

I've followed examples for injecting jQuery from the getting started page and that works just fine. I have a local copy of jQuery in the same directory, and do something like...
if(page.injectJs('jquery.min.js')) {
page.evaluate(function(){
//Use jQuery or $
}
}
When I try to inject my own script(s), none of the functions are available to me. Say I have a script called myScript.js that just has
function doSomething() {
// doing something...
}
I cannot then use doSomething like...
if(page.injectJs('myScript.js')) {
console.log('myScript injected... I think');
page.evaluate(function() {
doSomething();
});
} else {
console.log('Failed to inject myScript');
}
I've tried
window.doSomething = function() {};
and
document.doSomething = function() {};
as well with no luck, as well as trying to call them with window.doSomething() or document.doSomething() in the subsequent page.evaluate().
The following works for me, maybe some other part of your app logic is wrong:
inject.coffee
page = require('webpage').create()
page.onConsoleMessage = (msg) -> console.log msg
page.open "http://www.phantomjs.org", (status) ->
if status is "success"
page.includeJs "http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js", ->
if page.injectJs "do.js"
page.evaluate ->
title = echoAndReturnTitle('hello')
console.log title
phantom.exit()
do.coffee:
window.echoAndReturnTitle = (arg) ->
console.log "echoing '#{arg}'"
console.log $(".explanation").text()
return document.title
Result:
> phantomjs inject.coffee
echoing 'hello'
PhantomJS is a headless WebKit with JavaScript API.
It has fast and native support for various web standards:
DOM handling, CSS selector, JSON, Canvas, and SVG.
PhantomJS is created by Ariya Hidayat.
PhantomJS: Headless WebKit with JavaScript API
or if you prefer JavaScript (they're auto-generated and a little ugly):
`inject.js':
// Generated by CoffeeScript 1.3.1
(function() {
var page;
page = require('webpage').create();
page.onConsoleMessage = function(msg) {
return console.log(msg);
};
page.open("http://www.phantomjs.org", function(status) {
if (status === "success") {
return page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js", function() {
if (page.injectJs("do.js")) {
page.evaluate(function() {
var title;
title = echoAndReturnTitle('hello');
return console.log(title);
});
return phantom.exit();
}
});
}
});
}).call(this);
do.js:
// Generated by CoffeeScript 1.3.1
(function() {
window.echoAndReturnTitle = function(arg) {
console.log("echoing '" + arg + "'");
console.log($(".explanation").text());
return document.title;
};
}).call(this);