The following is the html I wanna tackle with.
I wanna post a query and see the weather reports for that city. I tried my codes:
var casper = require('casper').create();
var utils = require('utils');
casper.start('http://www.weather.com.cn/weather1d/101210101.shtml');
casper.waitForSelector('input', function()
{
this.fillXPath('div.search clearfix',{'//input[#id="txtZip"]':'shijiazhuang'},true);
});
casper.then(function()
{
utils.dump(this.getTitle());
});
casper.run();
It did not print the web paeg title on the console. I also tried this:
casper.waitForSelector('input', function()
{
this.fillSelectors('div.search clearfix',{'input[id="txtZip"]':'shijiazhuang'},true);
});
}
);
I did not get any web page title also. I got quite confused and did not what I had done wrong. Besides, it seems that this.fill method only tackles with name attributes to post information on CasperJS's official website. I need your help.
CasperJS script:
var casper = require('casper').create(), utils = require('utils');
casper
.start('http://www.weather.com.cn/weather1d/101210101.shtml',function(){
this
.wait(3000,function(){
this.capture('search.png');
utils.dump(this.getTitle());
})
.evaluate(function(){
document.getElementById('txtZip').value='shijiazhuang';
document.querySelector('input[type="button"]').click();
})
})
.run();
Result:
"【石家庄天气】石家庄今天天气预报,今天,今天天气,7天,15天天气预报,天气预报一周,天气预报15天查询"
search.png
You are doing it correct, you only have to modify your script a little bit.
Just modify the selector of the input field the actual don't seems to work, then you should get the correct result.
"this.fillXPath" only fills up the form and don't post it.
...
// fill the form
casper.waitForSelector('input', function() {
this.fillXPath('#txtZip', {
'//input[#id="txtZip"]': 'shijiazhuang'
}, true);
});
// trigger - post the form
casper.then(function() {
this.click('#btnZip');
});
// i can't speak chinese - wait for some specific change on this page
casper.wait(5000);
// take a screenshot of it
casper.then(function() {
this.capture("shijiazhuang_weather.png");
});
...
Related
The magiczoom documentation describes callbacks that will execute at given times, but it's unclear how to use or assign those callbacks.
For example, how would I print a console message onZoomReady?
The closest I've found is a MagicZoom.defaults.onready property, but it's unclear how to set it via javascript (my attempts aren't working as expected).
The callbacks are configured via mzOptions, for example:
var mzOptions = {
onZoomReady: function() { … } }
;
Or:
var mzOptions = {};
mzOptions.onZoomReady = function() { … };
You can do something like this:
MagicZoom.registerCallback('onUpdate',
function() {
console.log('onUpdated', arguments[0], arguments[1], arguments[2]);
});
That will log stuff in the console like this:
onUpdated (id-of-mz-wraper) (html of old element) (html of new element)
Other options that you can use are as per the documentation:
MagicZoom.registerCallback('onZoomReady', function() {
console.log('onReady', arguments[0]);
});
MagicZoom.registerCallback('onZoomIn', function() {
console.log('onZoomIn', arguments[0]);
});
MagicZoom.registerCallback('onZoomOut', function() {
console.log('onZoomOut', arguments[0]);
});
Following is a minimal casper script that does a Google query. I've added casper.on('click' ...) prior to running the script, but it doesn't appear to get triggered.
What am I missing?
// File: google_click_test.js
"use strict";
var casper = require('casper').create();
casper.on('click', function(css) {
casper.echo('casper.on received click event ' + css);
});
// ================================================================
// agenda starts here
casper.start('https://google.com', function g01() {
casper.echo('seeking main page');
});
casper.then(function a02() {
casper.waitForSelector(
'form[action="/search"]',
function() {
casper.echo("found search form");
},
function() {
casper.echo("failed to find search form");
casper.exit();
});
});
casper.then(function a03() {
casper.fillSelectors('form[action="/search"]', {
'input[title="Google Search"]' : 'casperjs'
}, false);
});
casper.then(function a04() {
casper.click('form[action="/search"] input[name="btnG"]')
casper.echo('clicked search button');
});
casper.run();
Output:
Here's the output. I would expect to see casper.on received click event somewhere, but it seems that it didn't get triggered:
$ casperjs --ignore-ssl-errors=true --web-security=no google_click_test.js
seeking main page
found search form
clicked search button
$
Although your example runs fine for me using casperjs 1.1.0-beta3 and phantomjs 1.9.8, I've been having similar issues in the last few months with casperjs. Sadly it seems that the author has stopped maintaining the project. More information here:
https://github.com/n1k0/casperjs/issues/1299
I would suggest moving to a different testing framework. In my case I chose a combination of mocha + chai + nightmarejs. This gist is a good starting point:
https://gist.github.com/MikaelSoderstrom/4842a97ec399aae1e024
This example in the CasperJS manual shows how to scrape urls from Google. It shows that the urls will come out nice and clean. However, when I run this example, my output looks like this:
20 links found:
- /url?q=http://casperjs.org/&sa=U&ei=_-TuU-KBC83-yQSu5YKQAg&ved=0CBQQFjAA&usg=AFQjCNH321k0JXrSx5WZp-fH6JwxX-O75Q
- /url?q=http://code4fun.fr/tutoriel-casperjs/&sa=U&ei=_-TuU-KBC83-yQSu5YKQAg&ved=0CBoQFjAB&usg=AFQjCNHreU-9mg7OZxK3TOl94HDPOnA_aQ
- /url?q=http://casperjs.readthedocs.org/&sa=U&ei=_-TuU-KBC83-yQSu5YKQAg&ved=0CCEQFjAC&usg=AFQjCNGzX6V5ZQtmCwHwZerHR3ftK3pHOw
- /url?q=https://github.com/n1k0/casperjs&sa=U&ei=_-TuU-KBC83-yQSu5YKQAg&ved=0CCcQFjAD&usg=AFQjCNEiGMDpYiPm1qXK7ZxDCwWwKjAStg
- /url?q=http://www.technologies-ebusiness.com/enjeux-et-tendances/casperjs-pour-des-tests-d-integration&sa=U&ei=_-TuU-KBC83-yQSu5YKQAg&ved=0CC4QFjAE&usg=AFQjCNFOGl1p6ApqP8TmAxhtQp33DHpbcQ
- /url?q=https://www.lullabot.com/blog/article/testing-front-end-casperjs&sa=U&ei=_-TuU-KBC83-yQSu5YKQAg&ved=0CDQQFjAF&usg=AFQjCNG53ZxHl8yZ0JGdzNbwKuZmPOLqCg
- /url?q=http://blog.newrelic.com/2013/06/04/simpler-ui-testing-with-casperjs-2/&sa=U&ei=_-TuU-KBC83-yQSu5YKQAg&ved=0CDoQFjAG&usg=AFQjCNFzlDb7R4Uv-jj_3S5IbJUpKF-7fA
- /url?q=https://www.npmjs.org/package/grunt-casperjs&sa=U&ei=_-TuU-KBC83-yQSu5YKQAg&ved=0CEEQFjAH&usg=AFQjCNGn-dwJpkX_XTQv8YnFZTClcLosJA
- /url?q=http://www.phase2technology.com/blog/behavorial-test-for-custom-entity-using-casperjs/&sa=U&ei=_-TuU-KBC83-yQSu5YKQAg&ved=0CEcQFjAI&usg=AFQjCNFG0KDAADmocesrDoqQTHW6PPO8KQ
- /url?q=http://blog.codeship.io/2013/03/07/smoke-testing-with-casperjs.html&sa=U&ei=_-TuU-KBC83-yQSu5YKQAg&ved=0CE4QFjAJ&usg=AFQjCNG5AsT2iKCnN-utrCGsthCZCpYKaQ
- /url?q=http://phantomjs.org/&sa=U&ei=_-TuU9yhG4iZyASb8oK4Dw&ved=0CBQQFjAA&usg=AFQjCNGXz7tw-UkfDOpqvYV89KlcJPGfHQ
- /url?q=http://phantomjs.org/download.html&sa=U&ei=_-TuU9yhG4iZyASb8oK4Dw&ved=0CB8QFjAB&usg=AFQjCNG_czKcYiFKskAvoRl1CceXuTJecA
- /url?q=http://www.mathieurobin.com/2013/04/phantomjs-chargez-et-jouez-avec-vos-sites-en-js-sans-quitter-la-console/&sa=U&ei=_-TuU9yhG4iZyASb8oK4Dw&ved=0CCUQFjAC&usg=AFQjCNEAtYz0zcsRVYy-37U9sJL7e9EqYQ
- /url?q=http://svay.com/blog/paris-js-10-introduction-a-phantomjs-un-navigateur-webkit-headless/&sa=U&ei=_-TuU9yhG4iZyASb8oK4Dw&ved=0CCsQFjAD&usg=AFQjCNE9dUuVQmNpK064a9GPJyOIetUWAA
- /url?q=https://github.com/ariya/phantomjs&sa=U&ei=_-TuU9yhG4iZyASb8oK4Dw&ved=0CDIQFjAE&usg=AFQjCNErqnWYxIVwBwXeUjaSd4SFicQqpw
- /url?q=https://github.com/gruntjs/grunt-lib-phantomjs&sa=U&ei=_-TuU9yhG4iZyASb8oK4Dw&ved=0CDkQFjAF&usg=AFQjCNHkRVx926JJkKhdoKxKsKVcQc-QTg
- /url?q=http://blog.octo.com/seo-spa-angular/&sa=U&ei=_-TuU9yhG4iZyASb8oK4Dw&ved=0CD8QFjAG&usg=AFQjCNFcj-ykUo-rSQKlcEZIy1qjSlW-oQ
- /url?q=https://www.npmjs.org/package/phantomjs&sa=U&ei=_-TuU9yhG4iZyASb8oK4Dw&ved=0CEYQFjAH&usg=AFQjCNGweWRdm8qjqxOOybFgtz5B8CnMDQ
- /url?q=http://code.google.com/p/phantomjs/&sa=U&ei=_-TuU9yhG4iZyASb8oK4Dw&ved=0CEwQFjAI&usg=AFQjCNEwvNx7NNMDAaiqHZ_y-3Bbf62W_w
- /url?q=http://casperjs.org/&sa=U&ei=_-TuU9yhG4iZyASb8oK4Dw&ved=0CE4QFjAJ&usg=AFQjCNGNEKkl1eWaFx9Sz6R7ZFVN9r1Bhw
Here's their code I ran:
var links = [];
var casper = require('casper').create();
function getLinks() {
var links = document.querySelectorAll('h3.r a');
return Array.prototype.map.call(links, function(e) {
return e.getAttribute('href');
});
}
casper.start('http://google.fr/', function() {
// search for 'casperjs' from google form
this.fill('form[action="/search"]', { q: 'casperjs' }, true);
});
casper.then(function() {
// aggregate results for the 'casperjs' search
links = this.evaluate(getLinks);
// now search for 'phantomjs' by filling the form again
this.fill('form[action="/search"]', { q: 'phantomjs' }, true);
});
casper.then(function() {
// aggregate results for the 'phantomjs' search
links = links.concat(this.evaluate(getLinks));
});
casper.run(function() {
// echo results in some pretty fashion
this.echo(links.length + ' links found:');
this.echo(' - ' + links.join('\n - ')).exit();
});
Can someone explain what is going on and why my urls are not clean like theirs?
The example is fine since you are getting the urls, but with a little bit of noise. It looks like google changed the hrefs in the mean time. So you can just add
links = links.map(function(link){
return link.substring(0, link.indexOf("&sa=U&ei=")).replace("/url?q=", "");
});
before joining the links in the last step.
I actually found a work around using a function called getLinks(). This works great and should be a bit more versatile for what I need. Using a combination of split() and pop() allows you to get what you want.
Code:
function getLinks() {
var links = document.querySelectorAll('h3.r a');
return Array.prototype.map.call(links, function(e) {
return e.getAttribute('href').split('/').pop();
});
}
casper.start(googleSearch, function() {
links = this.evaluate(getLinks);
});
casper.run(function() {
// echo results in some pretty fashion
this.echo(links.length + ' links found:');
this.echo(links.join('\n')).exit();
});
describe('my homepage', function() {
var ptor = protractor.getInstance();
beforeEach(function(){
// ptor.ignoreSynchronization = true;
ptor.get('http://localhost/myApp/home.html');
// ptor.sleep(5000);
})
describe('login', function(){
var email = element.all(protractor.By.id('email'))
, pass = ptor.findElement(protractor.By.id('password'))
, loginBtn = ptor.findElement(protractor.By.css('#login button'))
;
it('should input and login', function(){
// email.then(function(obj){
// console.log('email', obj)
// })
email.sendKeys('josephine#hotmail.com');
pass.sendKeys('shakalakabam');
loginBtn.click();
})
})
});
the above code returns
Error: Error while waiting for Protractor to sync with the page: {}
and I have no idea why this is, ptor load the page correctly, it seem to be the selection of the elements that fails.
TO SSHMSH:
Thanks, your almost right, and gave me the right philosophy, so the key is to ptor.sleep(3000) to have each page wait til ptor is in sync with the project.
I got the same error message (Angular 1.2.13). My tests were kicked off too early and Protractor didn't seem to wait for Angular to load.
It appeared that I had misconfigured the protractor config file. When the ng-app directive is not defined on the BODY-element, but on a descendant, you have to adjust the rootElement property in your protractor config file to the selector that defines your angular root element, for example:
// protractor-conf.js
rootElement: '.my-app',
when your HTML is:
<div ng-app="myApp" class="my-app">
I'm using ChromeDriver and the above error usually occurs for the first test. I've managed to get around it like this:
ptor.ignoreSynchronization = true;
ptor.get(targetUrl);
ptor.wait(
function() {
return ptor.driver.getCurrentUrl().then(
function(url) {
return targetUrl == url;
});
}, 2000, 'It\'s taking too long to load ' + targetUrl + '!'
);
Essentially you are waiting for the current URL of the browser to become what you've asked for and allow 2s for this to happen.
You probably want to switch the ignoreSynchronization = false afterwards, possibly wrapping it in a ptor.wait(...). Just wondering, would uncommenting the ptor.sleep(5000); not help?
EDIT:
After some experience with Promise/Deferred I've realised the correct way of doing this would be:
loginBtn.click().then(function () {
ptor.getCurrentUrl(targetUrl).then(function (newURL){
expect(newURL).toBe(whatItShouldBe);
});
});
Please note that if you are changing the URL (that is, moving away from the current AngularJS activated page to another, implying the AngularJS library needs to reload and init) than, at least in my experience, there's no way of avoiding the ptor.sleep(...) call. The above will only work if you are staying on the same Angular page, but changing the part of URL after the hashtag.
In my case, I encountered the error with the following code:
describe("application", function() {
it("should set the title", function() {
browser.getTitle().then(function(title) {
expect(title).toEqual("Welcome");
});
});
});
Fixed it by doing this:
describe("application", function() {
it("should set the title", function() {
browser.get("#/home").then(function() {
return browser.getTitle();
}).then(function(title) {
expect(title).toEqual("Welcome");
});
});
});
In other words, I was forgetting to navigate to the page I wanted to test, so Protractor was having trouble finding Angular. D'oh!
The rootElement param of the exports.config object defined in your protractor configuration file must match the element containing your ng-app directive. This doesn't have to be uniquely identifying the element -- 'div' suffices if the directive is in a div, as in my case.
From referenceConf.js:
// Selector for the element housing the angular app - this defaults to
// body, but is necessary if ng-app is on a descendant of <body>
rootElement: 'div',
I got started with Protractor by watching the otherwise excellent egghead.io lecture, where he uses a condensed exports.config. Since rootElement defaults to body, there is no hint as to what is wrong with your configuration if you don't start with a copy of the provided reference configuration, and even then the
Error while waiting for Protractor to sync with the page: {}
message doesn't give much of a clue.
I had to switch from doing this:
describe('navigation', function(){
browser.get('');
var navbar = element(by.css('#nav'));
it('should have a link to home in the navbar', function(){
//validate
});
it('should have a link to search in the navbar', function(){
//validate
});
});
to doing this:
describe('navigation', function(){
beforeEach(function(){
browser.get('');
});
var navbar = element(by.css('#nav'));
it('should have a link to home in the navbar', function(){
//validate
});
it('should have a link to search in the navbar', function(){
//validate
});
});
the key diff being:
beforeEach(function(){
browser.get('');
});
hope this may help someone.
I was getting this error:
Failed: Error while waiting for Protractor to sync with the page: "window.angular is undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping. See http://git.io/v4gXM for details"
The solution was to call page.navigateTo() before page.getTitle().
Before:
import { AppPage } from './app.po';
describe('App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should have the correct title', () => {
expect(page.getTitle()).toEqual('...');
})
});
After:
import { AppPage } from './app.po';
describe('App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
page.navigateTo();
});
it('should have the correct title', () => {
expect(page.getTitle()).toEqual('...');
})
});
If you are using
browser.restart()
in your spec some times, it throws the same error.
Try to use
await browser.restart()
i just came across this ajax upload plugin and i wish to use it inside a form as shown in the demo page example 3. For some reason i am not able to make it work. I am not sure what parameters come into the function. For example here is my sample code.
$(document).ready(function(){
var upload = new AjaxUpload('property_i',
{
action: 'submitproperty.php',
autoSubmit: false,
onSubmit : function(file , extension){
return false;
}
});
var upload_data = upload.setData({
'propertytype':'propertytype'
});
});
Now the ID used in the AjaxUpload function should be ID of the or of the Entire form. Also how do i use setData method. Any suggestions or links will be very helpful. Thanks
I got it to work with the following code:
new AjaxUpload('#uploader_button', {
action: 'filename.ashx',
autoSubmit: true,
onSubmit: function(file, ext) {
// --- stuff here
// --- add postdata parameters
this.setData({ id: 1, title: docTitle.val() });
},
onComplete: function(file, response) {
// --- stuff here too
}
});
it doesn't utilize the var but instead adds the custom data params in the onSubmit block. The only other difference is that I haven't wrapped the parameter key in quotes as it seems to serialize correctly. And I'm not using autoSubmit: false , but instead it's true...
The only way I could get this to work with autoSubmit: false is to add this outside any function:
var uploader;
var uploadFile;
then in the AjaxUpload(...
onChange: function(file, response){
uploader = this;
uploadFile = file;
},
then in the function to do the upload:
uploader.setData({session: session});
uploader.submit();
Hope this helps
I'm using uploadify and very useful.
http://www.uploadify.com/