Red Cricket
Red Cricket

Reputation: 10470

How to call a button's onClick() method in PhantomJS?

This is NOT a duplicate. I have looked at the answers in PhantomJS; click an element and the OP said that the answer was to call the "onClick()" method assigned to element that needs to be clicked, but the OP does NOT say HOW they accomplished this. Also there are no accepted answers.

I am trying to automate the submission of Android apps to Amazon's App store with a PhantonJS script. I have these steps so far:

  1. Open the developer console URL: https://developer.amazon.com/login.html
  2. Login to my developer account
  3. Click on the add_new_app_link
  4. Populate the First App submission form and then call the onclick method defined on this element:

    < input id="submit_button" type="submit" class="button large primary one-click-submit" name="save" value="Save" onclick="sanitizeManifestURL()">

It is step 4 that is giving trouble. Here's the code:

    function(apptitle,category){
            page.evaluate(function(apptitle,category){
                    document.getElementById('title').value=apptitle;
                    var sel = document.querySelector('select');
                    sel.selectedIndex = 16;
                    sanitizeManifestURL();
            },apptitle,category);
            page.render('step4.png');
            console.log(page.content);
    },

I dump out the resulting HTML with console.log() and it is rather long so I created this pastebin: http://pastebin.com/kjg6XqSW

Here is the screen shot I generate.

enter image description here

Another thing I should note is that I can get the button to work via Chrome browser's developer console.

UPDATE 1:

Thanks Igor, but I am still not able to get the button to click. Here's the whole script:

//
//  Run this script like so:
//
//       phantomjs --cookies-file=cookys.txt example_amazon_login.js '[email protected]' 'mypasswordshhhh'
//
//       You may need to execute the script twice so that the cookys.txt file gets data written to it.
//       See https://stackoverflow.com/questions/41391254/not-able-to-get-phantomjs-example-to-work
//


var steps=[];
var testindex = 0;
var loadInProgress = false;//This is set to true when a page is still loading

/*********SETTINGS*********************/
var username = 'unknown';
var password = 'unknown';
var apptitle = 'unknown';
var category = 'Music & Audio';

var webPage = require('webpage');
var page = webPage.create();

/*
page.onResourceRequested = function(request) {
  console.log('Request ' + JSON.stringify(request, undefined, 4));
};
page.onResourceReceived = function(response) {
 console.log('Receive ' + JSON.stringify(response, undefined, 4));
};
*/

page.onError = function(msg, trace) {

  var msgStack = ['ERROR: ' + msg];

  if (trace && trace.length) {
    msgStack.push('TRACE:');
    trace.forEach(function(t) {
      msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
    });
  }

  console.error(msgStack.join('\n'));

};

page.settings.userAgent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36';
page.settings.javascriptEnabled = true;
page.settings.loadImages = false;//Script is much faster with this field set to false
phantom.cookiesEnabled = true;
phantom.javascriptEnabled = true;
/*********SETTINGS END*****************/


/* Get command line args user password*/
var system = require('system');
var args = system.args;
var initial_url = 'https://developer.amazon.com/login.html';

if (args.length === 1) {
  console.log('Try to pass some arguments when invoking this script!');
} else {
  args.forEach(function(arg, i) {
    console.log(i + ': ' + arg);
    if ( i === 1 ) { username = arg; }
    if ( i === 2 ) { password = arg; }
    if ( i === 3 ) { apptitle = arg; }
  });
}

if ( username == 'unknown' ) {
        console.log('Please specify username and password');
        phantom.exit();
}
if ( password == 'unknown' ) {
        console.log('Please specify username and password');
        phantom.exit();
}
if ( apptitle == 'unknown' ) {
        console.log('Please specify apptitle');
        phantom.exit();
}


console.log('All settings loaded, start with execution');
page.onConsoleMessage = function(msg) {
    console.log(msg);
};
/**********DEFINE STEPS THAT FANTOM SHOULD DO***********************/
steps = [

        /*
         * Step 1 - Open Amazon home page
         */
        function(){
                console.log('Step 1 - Open Amazon home page ' + initial_url);
                // page.open("https://developer.amazon.com/home.html", function(status) {
                page.open( initial_url, function(status) {
                        console.log('status is '+ status );
                });
        },

        /*
         * Step 2 - Populate and submit the login form
         */
        function(username,password){
                console.log('Step 2 - Populate and submit the login form');
                // var appActionToken = page.evaluate(function() { return $('input[name="appActionToken"]').attr('value'); });
                // console.log( 'appActionToken is ' + appActionToken );
                console.log( 'username is ' + username );
                console.log( 'password is ' + password );
                page.evaluate(function(username,password){
                        console.log( '  username is ' + username );
                        console.log( '  password is ' + password );
                        document.getElementById("ap_email").value=username;
                        document.getElementById("ap_password").value=password;
                        document.getElementById("ap_signin_form").submit();
                },username, password);
        },
        /*
         * Step 3 Click the add_new_app button
         */
        function(){
                console.log('Step 3 - Click on the add_new_app button');
                page.evaluate(function(){
                        var evnt = document.createEvent("MouseEvents");
                        evnt.initEvent("click",true,true);
                        document.getElementById("add_new_app_link").dispatchEvent(evnt);

                });
                //page.render('step3.png');
        },

        /*
         * Step 4 - Populate and submit the First App submission vorm
         *
         * <input id="submit_button" type="submit" class="button large primary one-click-submit" name="save" value="Save" onclick="sanitizeManifestURL()">
         *
         * try looking here:
         * https://stackoverflow.com/questions/32771609/how-to-click-on-selectbox-options-using-phantomjs
         *
         */

        function(apptitle,category,click){
                console.log('Step 4 - save app ' + apptitle);
                page.evaluate(function(apptitle,category,click){
                        document.getElementById('title').value=apptitle;
                        var sel = document.querySelector('select');
                        sel.selectedIndex = 16;
                        // this works
                        var evt = document.createEvent("HTMLEvents");
                        evt.initEvent("change", false, true);
                        sel.dispatchEvent(evt);

                        //The form will be submitted, by click on the button:
                        click('#submit_button');
                },apptitle,category,click);

//              setTimeout(function(){
                        page.render('step4.png');
//                      console.log(page.content);
//              },200);
        }
];

/**********END STEPS THAT FANTOM SHOULD DO***********************/

//Execute steps one by one
interval = setInterval(executeRequestsStepByStep,50);
function click(sel){
        var event=document.createEvent('MouseEvents');
        event.initMouseEvent('click',1,1,window,1,0,0,0,0,0,0,0,0,0,null);
        document.querySelector(sel).dispatchEvent(event);
}

function executeRequestsStepByStep(){
    if (loadInProgress == false && typeof steps[testindex] == "function") {
        console.log("testindex is " + testindex );
        if ( testindex == 1 ) {
                console.log( "username is " + username );
                steps[testindex](username, password);
        } else if ( testindex == 3 ) {
                steps[testindex](apptitle, category, click);
        } else {
            steps[testindex]();
        }
        testindex++;
    }
    if (typeof steps[testindex] != "function") {
        console.log("test complete!");
        phantom.exit();
    }
}

/**
 * These listeners are very important in order to phantom work properly.
 * Using these listeners, we control loadInProgress marker which controls, weather a page is fully loaded.
 * Without this, we will get content of the page, even a page is not fully loaded.
 */
page.onLoadStarted = function() {
    loadInProgress = true;
    console.log('Loading started');
};
page.onLoadFinished = function() {
    loadInProgress = false;
    console.log('Loading finished');
};
page.onConsoleMessage = function(msg) {
    console.log(msg);
};

Upvotes: 0

Views: 2126

Answers (1)

user4535610
user4535610

Reputation:

PhantomJS exits before the work is done.
We need to wait, after the steps is complete.

//
//  Run this script like so:
//
//       phantomjs --cookies-file=cookys.txt example_amazon_login.js '[email protected]' 'mypasswordshhhh'
//
//       You may need to execute the script twice so that the cookys.txt file gets data written to it.
//       See http://stackoverflow.com/questions/41391254/not-able-to-get-phantomjs-example-to-work
//


var steps=[];
var testindex = 0;
var loadInProgress = false;//This is set to true when a page is still loading

/*********SETTINGS*********************/
var username = 'unknown';
var password = 'unknown';
var apptitle = 'unknown';
var category = 'Music & Audio';

var webPage = require('webpage');
var page = webPage.create();

/*
page.onResourceRequested = function(request) {
  console.log('Request ' + JSON.stringify(request, undefined, 4));
};
page.onResourceReceived = function(response) {
 console.log('Receive ' + JSON.stringify(response, undefined, 4));
};
*/

page.onError = function(msg, trace) {

  var msgStack = ['ERROR: ' + msg];

  if (trace && trace.length) {
    msgStack.push('TRACE:');
    trace.forEach(function(t) {
      msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
    });
  }

  console.error(msgStack.join('\n'));

};

page.settings.userAgent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 Safari/537.36';
page.settings.javascriptEnabled = true;
page.settings.loadImages = false;//Script is much faster with this field set to false
phantom.cookiesEnabled = true;
phantom.javascriptEnabled = true;
/*********SETTINGS END*****************/


/* Get command line args user password*/
var system = require('system');
var args = system.args;
var initial_url = 'https://developer.amazon.com/login.html';

if (args.length === 1) {
  console.log('Try to pass some arguments when invoking this script!');
} else {
  args.forEach(function(arg, i) {
    console.log(i + ': ' + arg);
    if ( i === 1 ) { username = arg; }
    if ( i === 2 ) { password = arg; }
    if ( i === 3 ) { apptitle = arg; }
  });
}

if ( username == 'unknown' ) {
        console.log('Please specify username and password');
        phantom.exit();
}
if ( password == 'unknown' ) {
        console.log('Please specify username and password');
        phantom.exit();
}
if ( apptitle == 'unknown' ) {
        console.log('Please specify apptitle');
        phantom.exit();
}


console.log('All settings loaded, start with execution');
page.onConsoleMessage = function(msg) {
    console.log(msg);
};
/**********DEFINE STEPS THAT FANTOM SHOULD DO***********************/
steps = [

        /*
         * Step 1 - Open Amazon home page
         */
        function(){
                console.log('Step 1 - Open Amazon home page ' + initial_url);
                // page.open("https://developer.amazon.com/home.html", function(status) {
                page.open( initial_url, function(status) {
                        console.log('status is '+ status );
                });
        },

        /*
         * Step 2 - Populate and submit the login form
         */
        function(username,password){
                console.log('Step 2 - Populate and submit the login form');
                // var appActionToken = page.evaluate(function() { return $('input[name="appActionToken"]').attr('value'); });
                // console.log( 'appActionToken is ' + appActionToken );
                console.log( 'username is ' + username );
                console.log( 'password is ' + password );
                page.evaluate(function(username,password){
                        console.log( '  username is ' + username );
                        console.log( '  password is ' + password );
                        document.getElementById("ap_email").value=username;
                        document.getElementById("ap_password").value=password;
                        document.getElementById("ap_signin_form").submit();
                },username, password);
        },
        /*
         * Step 3 Click the add_new_app button
         */
        function(){
                console.log('Step 3 - Click on the add_new_app button');
                page.evaluate(function(){
                        var evnt = document.createEvent("MouseEvents");
                        evnt.initEvent("click",true,true);
                        document.getElementById("add_new_app_link").dispatchEvent(evnt);

                });
                //page.render('step3.png');
        },

        /*
         * Step 4 - Populate and submit the First App submission vorm
         *
         * <input id="submit_button" type="submit" class="button large primary one-click-submit" name="save" value="Save" onclick="sanitizeManifestURL()">
         *
         * try looking here:
         * http://stackoverflow.com/questions/32771609/how-to-click-on-selectbox-options-using-phantomjs
         *
         */
        function(apptitle,category){
                console.log('Step 4 - save app ' + apptitle);
                page.evaluate(function(apptitle,category){
                        document.getElementById('title').value=apptitle;
                        // this works
                       document.querySelector('select').selectedIndex = 16;
                        $('select[lvl="1"]').change();
                        //document.querySelector('select[lvl="2"]').selectedIndex = 1;
                        //$('select[lvl="2"]').change();

                        //The form will be submitted, by click on the button:
                        $('#submit_button').click();
                   },apptitle,category);

                        page.render('step4.png');
//                      console.log(page.content);
        },
];

/**********END STEPS THAT FANTOM SHOULD DO***********************/

//Execute steps one by one
interval = setInterval(executeRequestsStepByStep,50);

function executeRequestsStepByStep(){
    if (loadInProgress == false && typeof steps[testindex] == "function") {
        console.log("testindex is " + testindex );
        if ( testindex == 1 ) {
                console.log( "username is " + username );
                steps[testindex](username, password);
        } else if ( testindex == 3 ) {
                steps[testindex](apptitle, category);
        } else {
            steps[testindex]();
        }
        testindex++;
    }
    if (typeof steps[testindex] != "function") {
  //We need to wait, after the steps is complete!
   clearInterval(interval);interval=0;
   setTimeout(function(){
   console.log("test complete!");
   page.render('complete.png');
   setTimeout(phantom.exit,2000)
   },3000);

    }
}

/**
 * These listeners are very important in order to phantom work properly.
 * Using these listeners, we control loadInProgress marker which controls, weather a page is fully loaded.
 * Without this, we will get content of the page, even a page is not fully loaded.
 */
page.onLoadStarted = function() {
    loadInProgress = true;
    console.log('Loading started');
};
page.onLoadFinished = function() {
    loadInProgress = false;
    console.log('Loading finished');
};
page.onConsoleMessage = function(msg) {
    console.log(msg);
};

Upvotes: 2

Related Questions