travist / jquery.go.js

An easy-to-use web testing and automation tool that uses the jQuery interface within Node.js to interact with the Phantom.js browser.
MIT License
150 stars 35 forks source link

Unable to click links #7

Open stevemacn opened 10 years ago

stevemacn commented 10 years ago

I am trying to click the logout link test the functionality.

I have tried a few things:

$("#log").click(function(e){ e.stopPropagation() ... })

$("#log")[0].click()

Not sure what else to try. Any suggestions?

mootzville commented 10 years ago

Maybe this will work for you...

var $ = require('./lib/jquery.go.js');

$.visit('http://yoursite.com', function(){ $('#log')[0].click(function(){ $.close(); }); });

Remember it's async, so you can't just treat it the way you would in a browser...everything has a callback.

Also, if that doesn't work maybe try this one...

var async = require('async'); var $ = require('./lib/jquery.go.js'); var series_array = [ $.go('visit', 'http://www.somesite.com'), $('#log').go('click'), function (cb) {$.close(); cb();} ];

async.series(series_array);

I hope that helps...

stevemacn commented 10 years ago

Neither works, I was using the "click" for buttons on forms and those work completely fine. It appears that the object returned by this instance of jquery and the array returned by normal jquery are different.

$('#log')[0] returns null

$('#log') returns

{ selector: '#log', context: undefined, instance: 1, index: -1, length: 1 }

Hopefully I am missing something obvious!

mootzville commented 10 years ago

Could you copy and paste some of the relevant source code?

stevemacn commented 10 years ago

Okay maybe this will help clarify something. I wrote a function for logging out. I also wrote a function to captureImages() which just appends a value to each image because I take like 5-10 images per full test.


<a href="location" id="log">log out</a> //roughly how the html looks

logout(testLogin)

var logout = function (cb) {
     $.visit(server, function () {
           $.waitForPage(function() {
                  captureImage()
                  $("#log").text(function(t){
                          console.log(t) // t contains "log out"
                  })
                  $('#log')[0].click(function() {
                       console.log($(this))
                       $.waitForPage(function() {
                              setTimeout(function() {
                                  cb()
                              }, 2500)
                        })
                  })
             })
        })
}

//==========================
//Test ability to login
//==========================

function testLogin () {
     $.visit(server+'/login', function(){
             $.waitForPage(function(){
                  captureImage()
                  $('#user').val(user, function() {
                      $('#pwd').val(pwd, function () {
                          captureImage()
                          $('#submit').click(function() {
                              testHomepage()
                          })
                      })
                  })
              })
       })
}

//==========================
//Test ability to access homepage
//==========================
...

I also set a timeout because I noticed waitForPage has only seemed to work for me after the visit command but not after redirects etc.

Sorry for all the callbacks, I realize you guys use async to prevent the nested functions but I am not really comfortable with async yet.

travist commented 10 years ago

You can try using the sizzle selector of #log:eq(0) which should work since I think the issue here is the selecting a certain element.

So, try this...

$.visit('http://yoursite.com', function(){
  $('#log:eq(0)').click(function(){
    $.close();
  });
});
travist commented 10 years ago

Also, why do you need to use eq(0)? Do you have more than one element on the page that has the ID of #log? If not, then just use the single selector... Also, you should try async.js and then extending jQuery Go with your methods... it may make your code look cleaner... like this.

var async = require('async');
var $ = require('jquerygo');

$.login = function(user, pass, done) {
  async.series([
    $.go('visit', server+'/login'),
    $.go('waitForPage'),
    $('#user').go('val', user),
    $('#pass').go('val', pass),
    $('#submit').go('click')
  ], done);
};

async.series([
  $.go('login', 'admin', 'password')
], function() {
  $.close();
});
stevemacn commented 10 years ago

This still returns "log out" in console.log(t) as before but still no dice about actually following the link.

If you look at my login part it is similar to yours and it works completely fine. There appears to be some problem with following links in anchors rather than with buttons.

This was my original reason for doing the

e.stopPropagation()

and

$('#log')[0]

Though neither approach worked either. I am rather new to jquery so maybe I am missing something obvious.

ghost commented 10 years ago

Hi Travis, Loving the library but I'm having the same problem as stevmacn. Taking the makemeasandwich as base, I'm testing using one of my sites, and if I capture the login page before the username/password and then after the click it looks like the page either doesn't get the click or at least doesn't respond to it. The captures show the login page, empty fields, then the login page fields filled, instead of the expected next page in the login process. Any debugging help would be appreciated. Thanks

var login9 = function(done) { async.series([ print('Logging in.'), $.go(false, 'visit', 'http://9energies.com/wp-login.php'), print('Loaded.'), $.go(false, 'waitForElement', '#user_login'), print('Login.'), $.go('capture','/tmp/9ebefore.png'), setNoConfigInput('#user_login', 'mrcfisher', true), setNoConfigInput('#user_pass', 'xxxxxxxxxx', true), $('#wp-submit').go('click'), print('Submit.'), $.go('capture','/tmp/9ecomplete.png'), $.go(false, 'waitForElement', '[name="add-new-h2"]'), print('Successfully logged in.') ], done); };

travist commented 10 years ago

I just tried this code with your example and it actually did click the submit button because I got a password error which should probably only show up if the login was submitted.

var $ = require('jquerygo');
var async = require('async');
var login9 = function(done) {
    async.series([
        $.go('print', 'Login...'),
        $.go(false, 'visit', 'http://9energies.com/wp-login.php'),
        $.go(false, 'waitForElement', '#user_login'),
        $.go('print', 'Loaded...'),
        $.go('capture','9ebefore.png'),
        $('#user_login').go('val', 'mrcfisher'),
        $('#user_pass').go('val', 'xxxxxxxxxx'),
        $.go('capture', '9eafter.png'),
        $('#wp-submit').go('click'),
        $.go('waitForPage'),
        $.go('capture', '9eloggedin.png')
    ], done);
};

login9(function() {
  $.close();
});

FYI: I just pushed up a print function so you can now use $.go('print', 'Login') now instead of the custom method print.

travist commented 10 years ago

The error may be in your setNoConfigInput method.

ghost commented 10 years ago

Hmm, OK, Thanks for looking, here's the noconfig though

var setNoConfigInput = function(selector, val, direct) { direct = !!direct; return function(done) { if (direct) { input(selector, val, done); } else { get(param, function(err, value) { input(selector, value, done); }); } }; };

I'll try with the input directly.

PS THANKS you again.

ghost commented 10 years ago

Thanks Travis,

Is there a donate button anywhere?

From: Travis Tidwell [mailto:notifications@github.com] Sent: Saturday, February 22, 2014 7:19 AM To: travist/jquery.go.js Cc: mrcfisher Subject: Re: [jquery.go.js] Unable to click links (#7)

The error may be in your setNoConfigInput method.

— Reply to this email directly or view it on GitHub https://github.com/travist/jquery.go.js/issues/7#issuecomment-35804982 . https://github.com/notifications/beacon/6185846__eyJzY29wZSI6Ik5ld3NpZXM6QmVhY29uIiwiZXhwaXJlcyI6MTcwODYxNTE2MCwiZGF0YSI6eyJpZCI6MjM0NDI0NjB9fQ==--a0f262782f9e7dd22e61e75477f22df9e92529c7.gif

travist commented 10 years ago

Ha... no there isn't, but I do use PayPal if you feel compelled. travist349 at gmail.com.

Thanks!

ghost commented 10 years ago

Ok great, progress at last! Thanks.

rustingibbs commented 10 years ago

What was the resolution? I am facing the same issue--clicking anchor links doesn't seem to do anything. Do I need the helper functions from the makemeasandwich code?

ghost commented 10 years ago

Travis' version worked for me, but I needed to grab the latest source for the print function. And yes I started with the makemeasandwich code and changed it as above.

rustingibbs commented 10 years ago

Ok. Well, I modified the code sample as follows, but it isn't working. All I want to do is click on an link and go to another page. Am I missing something?

var $ = require('jquerygo'); var async = require('async'); var recorder = function(done) { async.series([ $.go(false, 'visit', 'http://recorder.co.clark.nv.us/RecorderEcommerce/default.aspx'), $.go(false, 'waitForElement', '#ctl00_TrackMyOrderLink'), $.go('print', 'Loaded...'), $.go('capture','9ebefore.png'), $('#ctl00_TrackMyOrderLink').go('click'), $.go('waitForPage'), $.go('capture', '9eafter.png') ], done); };

recorder(function() { $.close(); });

ghost commented 10 years ago

Replacing the waitForPage with

$.go(false,'waitForElement','ctl00_ContentPlaceHolder1_CheckOrder'),

Hangs waiting…

Martin

From: rustingibbs [mailto:notifications@github.com] Sent: Thursday, February 27, 2014 1:54 PM To: travist/jquery.go.js Cc: mrcfisher Subject: Re: [jquery.go.js] Unable to click links (#7)

Ok. Well, I modified the code sample as follows, but it isn't working. All I want to do is click on an link and go to another page. Am I missing something?

var $ = require('jquerygo'); var async = require('async'); var recorder = function(done) { async.series([ $.go(false, 'visit', 'http://recorder.co.clark.nv.us/RecorderEcommerce/default.aspx'), $.go(false, 'waitForElement', '#ctl00_TrackMyOrderLink'), $.go('print', 'Loaded...'), $.go('capture','9ebefore.png'), $('#ctl00_TrackMyOrderLink').go('click'), $.go('waitForPage'), $.go('capture', '9eafter.png') ], done); };

recorder(function() { $.close(); });

— Reply to this email directly or view it on GitHub https://github.com/travist/jquery.go.js/issues/7#issuecomment-36296216 . https://github.com/notifications/beacon/6185846__eyJzY29wZSI6Ik5ld3NpZXM6QmVhY29uIiwiZXhwaXJlcyI6MTcwOTA3MDgxNSwiZGF0YSI6eyJpZCI6MjM0NDI0NjB9fQ==--80421100ced26b847e27314beb6c53fc97bb4ca5.gif

travist commented 10 years ago

One thing that I can say is that I went to try and click on that link manually and got a 500 error on the server, so maybe that has something to do with it.

Also, another thing to note is that if you already have jQuery on the website you are testing, it is probably helpful to add $.config.addJQuery = false; which tells the library to not manually add another version of jQuery on that page (since it already has it). Like this.

var $ = require('jquerygo');

$.config.addJQuery = false;

...

After you do that and it still doesn't work, try typing the following in your Browsers terminal and see if it works..

$('#ctl00_TrackMyOrderLink').click();

This is doing the same thing that this library does so if that doesn't work then it is a problem with your site you are testing.

Hope this helps.

mootzville commented 10 years ago

var async = require('async'); var $ = require('./lib/jquery.go.js'); $.config.addJQuery = false;

// Create an array of tasks to run... var tasks = [ function (cb) {console.log('Opening http://9energies.com/wp-login.php'); cb();}, $.go('visit', 'http://9energies.com/wp-login.php'), function (cb) {console.log('Page Loaded...'); cb();}, function (cb) {console.log('Adding username & password'); cb();}, $('#user_login').go('val', 'enlightenedOne'), $('#user_pass').go('val', 'password'), function (cb) {console.log('Capturing \'before\' Screenshot'); cb();}, function (cb) {$.capture(dirname + '/before.png'); setTimeout(cb, 2000);}, function (cb) {console.log('before.png captured'); cb();}, function (cb) {console.log('Submitting Login'); cb();}, $('#loginform').go('submit'), $.go('waitForPage'), function (cb) {console.log('Capturing \'after\' Screenshot'); cb();}, function (cb) {$.capture(dirname + '/after.png'); setTimeout(cb, 2000);}, function (cb) {console.log('All done...'); cb();} ]

// Run the tasks... async.series(tasks, $.close);

mootzville commented 10 years ago

@mrcfisher The code I posted above works just fine for your 9energies login...

Also, capturing an image takes time, so even though things are running asynchronous you need to give the $.capture() method time to finish.

Use this pattern for capturing in your async series arrays:

function (cb) {$.capture('/path/to/save/file.png'); setTimeout(cb, 2000);}

It basically lets you delay, so you can give your image time to finish. I used 2000ms above, but it can be whatever works for you...

mootzville commented 10 years ago

@rustingibbs

It's not exactly what you asked, but I assume this is what you want to do:

var async = require('async'); var $ = require('./lib/jquery.go.js'); $.config.addJQuery = false;

// Create an array of tasks to run... var tasks = [ function (cb) {console.log('Opening http://recorder.co.clark.nv.us/RecorderEcommerce/TrackMyOrder.aspx'); cb();}, $.go('visit', 'http://recorder.co.clark.nv.us/RecorderEcommerce/TrackMyOrder.aspx'), function (cb) {console.log('Page Loaded...'); cb();}, function (cb) {console.log('Adding Ref ID & Last Name'); cb();}, $('#ctl00_ContentPlaceHolder1_LocalRefID').go('val', '12345'), $('#ctl00_ContentPlaceHolder1_LastNameTB').go('val', 'mootzville'), function (cb) {console.log('Capturing \'before\' Screenshot'); cb();}, function (cb) {$.capture(dirname + '/before.png'); setTimeout(cb, 2000);}, function (cb) {console.log('before.png captured'); cb();}, function (cb) {console.log('Submitting Info'); cb();}, $('input[name="ctl00$ContentPlaceHolder1$CheckOrder"]').go('click'), $.go('waitForPage'), function (cb) {console.log('Capturing \'after\' Screenshot'); cb();}, function (cb) {$.capture(dirname + '/after.png'); setTimeout(cb, 2000);}, function (cb) {console.log('All done...'); cb();} ]

// Run the tasks... async.series(tasks, $.close);

julienmertens commented 10 years ago

Hi, I was very interrested in this system, to automate test of web site for my company. I spend one day to watch the video, read this forum and try to use the lib to make reports, but I always had a problem with click action on client side. Here Is the cleanest one of all tests I've done :

var $ = require('jquerygo'); var async = require('async'); $.config.addJQuery = true; var clickdwn = function(done) { async.series([ $.go('print', 'Access page'), $.go(false, 'visit', 'http://playvod.com/home.html#content.json?ref=1168479'), $.go(false, 'waitForElement', '#download'), $.go('print', 'Loaded...'), $.go('capture','before.png'), $(".billing_button").go('click'), $.go(false, 'waitForElement', '#billing_form'), $.go('capture', 'popup.png') ], done); }; clickdwn(function() { $.close(); });

The script stoped at 'loaded...'. I think it never found the "#billing_form' element. I try other site (http://www.zikiz.fr any link), and it doesn't work too, with or without addJQuery... adding a timeout, without 'false' first param in go method (I don't understand the difference between $.go(false, 'waitForElement', '#download'), and $.go('waitForElement', '#download')...)

ghost commented 10 years ago

Hi, Travis! Have similar issue. I'm clicking on Submit button on a login page (by design I do not provide username/password) , and waiting for the next page, but $.waitForPage method give me phantom stdout: ReferenceError: Can't find variable: jQuery

It looks like Query was not injected into this page, how can I handle it? Screenshot made from setTimeout function confirms, that page was loaded.

var $ =require('jquerygo');
$.config.addJQuery = true;
$.visit("http://www.e1.ru/talk/",  function() {
        $('input.button_orange[type="submit"]').click( function() {
                $.waitForPage(function(){             
                    console.log("Page is loaded");  // we never reach this place.
                    $.close();                                   
                })
        });
        setTimeout( function() {
                $.capture(__dirname + '/screenshot.png')
                console.log("Screenshot is made");  //We can see, that page was loaded.
                $.close();
        }, 7000);
});

I tried coding in async.series style, but result was the same: phantom stdout: ReferenceError: Can't find variable: jQuery

painkkiller commented 10 years ago

Having the same issue as hi-artem. Implementing automatic login function I trying to click on button with such html (dont know how to insert html like text in comment):

 

My code now looks like this:


$.login = function(user, path) {
    async.series([ $.go('visit', path),
                   $("input[name='email']").go('val', user.login),
                   $("input[name='pass']").go('val', user.password),
                   function (cb) {console.log('Adding username & password'); cb();},
                   $.go('capture', 'vk.png'),
                   $("input[class='button']").go('click'),
                   $.go('waitForPage'),
                   $.go('capture', 'vk2.png'),
                   function(done) {
                       console.log($('html'));
                       $.go('capture', 'vk3.png'),
                       done();
                   }

    ], function() {
          console.log('You are logged in!');
          $.close();});
}; 

On click action phantom gives error phantom stdout: ReferenceError: Can't find variable: jQuery and exeqution stops.

painkkiller commented 10 years ago

Tried another selector for button
$("input[value='Войти']").go('click'),

yura415 commented 9 years ago

I found a workaround on the "Can't find variable: jQuery" error. Here in my jquery.go fork (yura415/jquery.go.js-multipage-wo-phantomjs) I added "ensureJqueryIsLoaded" method, that checks jQuery availability and used it internally in waitForPage. See my examples/example6.js.