Casperjs cannot access same global objects as in from browsers console - phantomjs

I am new to Casperjs, phantomjs .I have been trying hard to create some page automation to login and take some steps in a CMS but i am having issues with accessing the global window variables from casperjs evaluate() function. the below example is just checking jquery on Google. Jquery exists in the page and some other global functions but i can't access them from casperjs.
casper.start('https://www.google.ca/#hl=en', function() {
// search for 'casperjs' from google form
this.fill('form[action="/search"]', { q: 'casperjs' }, false);
});
casper.then(function() {
this.evaluate(function jquery() {
console.log('looking for jquery ---');
console.log($ + 'exists');
});
});
getting error - `ReferenceError: Can't find variable: $
How can i fix this ?
Any help is appreciated :)

For use jQuery in casperjs
inject script in page, something like:
var casper = require('casper').create({
some code here,
clientScripts: ['/path/to/jquery.js'],
});

Related

Cypress - run test in iframe

I'm trying to find elements in iframe but it doesn't work.
Is there anyone who have some system to run tests with Cypress in iframe? Some way to get in iframe and work in there.
It's a known issue mentioned here. You can create your own custom cypress command which mocks the iframe feature. Add following function to your cypress/support/commands.js
Cypress.Commands.add('iframe', { prevSubject: 'element' }, ($iframe, selector) => {
Cypress.log({
name: 'iframe',
consoleProps() {
return {
iframe: $iframe,
};
},
});
return new Cypress.Promise(resolve => {
resolve($iframe.contents().find(selector));
});
});
Then you can use it like this:
cy.get('#iframe-id')
.iframe('body #elementToFind')
.should('exist')
Also, because of CORS/same-origin policy reasons, you might have to set chromeWebSecurity to false in cypress.json (Setting chromeWebSecurity to false allows you to access cross-origin iframes that are embedded in your application and also navigate to any superdomain without cross-origin errors).
This is a workaround though, it worked for me locally but not during CI runs.
This works for me locally and via CI. Credit: Gleb Bahmutov iframes blog post
export const getIframeBody = (locator) => {
// get the iframe > document > body
// and retry until the body element is not empty
return cy
.get(locator)
.its('0.contentDocument.body').should('not.be.empty')
// wraps "body" DOM element to allow
// chaining more Cypress commands, like ".find(...)"
// https://on.cypress.io/wrap
.then(cy.wrap)
}
spec file:
let iframeStripe = 'iframe[name="stripe_checkout_app"]'
getIframeBody(iframeStripe).find('button[type="submit"] .Button-content > span').should('have.text', `Buy me`)
that is correct. Cypress doesn't support Iframes. It is simple not possible at the moment. You can follow (and upvote) this ticket: https://github.com/cypress-io/cypress/issues/136

Concern regarding automation using Protractor

Am new to protractor. I found some errors while automating the URL using protractor. And I can access the URL manually and does not find any issues. Please find the code mentioned below and kindly clarify my concern.
Screenshot of cmd while executing the code
exports.config={
specs: ['try.js'],
//seleniumArgs: ['-browserTimeout=60']
capabilities:{
'browserName':'chrome',
},
baseUrl:'',
allScriptsTimeout:3000,
//getPageTimeout:5000,
framework:'jasmine2',
jasmineNodeOpts: {
defaultTimeoutInterval:56000,
isVerbose: true,
}
}
spec: try.js
===========
describe('first try',function(){
var EW=protractor.ExpectedConditions;
beforeEach(function(done){
ignoreSynchronization=true;
browser.get('');
});
it('open PO',function(){
//clicking login button
var login=element(by.linkText('Login'));
browser.wait(EW.presenceOf(login),10000);
login.click();
//clicking open Po dashboard icon/link
var po=element(by.linkText('Open PO'));
browser.wait(EW.presenceOf(po),20000);
po.click();
//entering value 100 in the fiter field
var e=element.all(by.repeater('colFilter in col.filters')).get(00).element(by.tagName('input'));
browser.wait(EW.presenceOf(e),10000);
e.sendKeys(100);
//selecting the filterd values and printing it in console
element.all(by.repeater('col in colContainer.renderedColumns track by col.uid').column('Entity')).getText().then(console.log);
});
});
Make sure you have ng-app defined on all of your pages. Protractor requires it to run. If the page has redirects or just takes some time before it loads, try something like this:
browser.get(websiteUrl);
browser.wait(function () {
return browser.executeScript('return !!window.angular');
}, 10000, 'Error: Angular was not found on the page within ten seconds');
This will wait up to ten seconds for angular to load up, and fail if it is not there.

How do you fix PhantomJs's lack of bind error?

Just crawling a web page like github.com I hit the famous TypeError: 'undefined' is not a function.
var page = require('webpage').create();
page.open('https://github.com', function() {
phantom.exit();
});
See https://groups.google.com/forum/#!msg/phantomjs/r0hPOmnCUpc/uxusqsl2LNoJ
So exactly how do you fix this problem for someone totally new to PhantomJS?
Do I git clone curjojs/poly and then wrap all my PhantomJS code under poly/function like https://stackoverflow.com/a/19521355/230884?
I don't see any official documentation on solving this particular issue.

Open URL from file system using PhantomJS

In page.open I can read about how to open a page using http.
How do use the WebPage module to open an url from the file system?
I have tried to omit http:// and have an url with ../some_dir/foo.html, but it seems to fail.
I Have tried this:
var page = require('webpage').create();
var fs = require('fs');
fs.changeWorkingDirectory('../foo/bar');
page.open('file://index.html', function(status)
{
console.log(status);
//console.log(document.title);
phantom.exit();
});
which outputs "fail".
I got the advice to test an absolute path, trying this:
var page = require('webpage').create();
var fs = require('fs');
page.open('file:///absolute/path/to/index.html', function(status)
{
console.log(page.title);
console.log($('body').length);
phantom.exit();
});
(with and without the call to changeWorkingDirectory, but with the same result)
I get a page title, but phantomjs reports that $ is undefined, jQuery is included in my html file (that is too large to post here). It is included like this:
<script type="text/javascript" src="js/jquery-1.11.1.min.js"></script>
Trying to run functions also produces errors like
CanĀ“t find variable: function_name
Does the page/file you are opening already have jquery embedded on the page? If not, you will need to use either injectJs or includeJs on the page object before you can use the $ operator.
http://phantomjs.org/page-automation.html
If you are just doing a simple DOM selection, I would recommend just calling
document.querySelector('body').length
As these functions already exist within the Phantom instance.

Navigating site (including forms) with PhantomJS

I'm trying to automate an application that uses form security in order to upload a file and then scrape data from the returned HTML.
I started out using the solution from this question. I can define my steps and get through the entire workflow as long as the last step is rendering the page.
Here are the two steps that are the meat of my script:
function() {
page.open("https://remotesite.com/do/something", function(status) {
if ('success' === status) {
page.uploadFile('input[name=file]', 'x.csv');
page.evaluate(function() {
// assignButton is used to associate modules with an account
document.getElementById("assignButton").click();
});
}
});
},
function() {
page.render('upload-results.png');
page.evaluate(function() {
var results = document.getElementById("moduleProcessingReport");
console.log("results: " + results);
});
},
When I run the script, I see that the output render is correct. However, the evaluate part isn't working. I can confirm that my DOM selection is correct by running it in the Javascript console while on the remote site.
I have seen other questions, but they revolve around using setTimeout. Unfortunately, the step strategy from the original approach already has a timeout.
UPDATE
I tried a slightly different approach, using this post and got similar results. I believe that document uses an older PhantomJS API, so I used the 'onLoadFinished' event to drive between steps.
i recomend you use casperjs or if you use PJS's webPage.injectScript() you could load up jquery and then your own script to do form input/navigation.