nightwatchjs / nightwatch

Integrated end-to-end testing framework written in Node.js and using W3C Webdriver API. Developed at @browserstack
https://nightwatchjs.org
MIT License
11.8k stars 1.31k forks source link

cannot pass arguments to execute() #353

Closed paulbrie closed 9 years ago

paulbrie commented 9 years ago

Hi, it seems that I cannot pass arguments to execute() command. result.value in the callback function displays []. Am I missing something in the syntax?

.execute(function(data){
    console.log("data?", arguments);
                return arguments;
            }, ['a value'], function (result){
                console.log(result.value)
    })

Thanks, Paul

SoYoureAWaffleMan commented 9 years ago

Same Issue here

browser.execute(
    function(data) {
        alert(data); // = undefined
        alert(arguments.length); // = 0
    },
    ['one','two','three'],
    function(outcome) {
        console.log(outcome); 
    }
);
paulbrie commented 9 years ago

Hi, the interesting fact is that it seems to work on my colleague's PC. I am on Mac, nightwatch v0.5.34. Hope it helps.

SoYoureAWaffleMan commented 9 years ago

That is interesting. I'm on Linux Mint, Nightwatch v0.5.36 Selenium 2.44.0

As the chain goes NW -> Selenium -> Browser, I wonder if the failure to pass params could be in Selenium. What version are you using @paulbrie?

paulbrie commented 9 years ago

Here is my Selenium info, hope it helps.

18:25:46.558 INFO - Launching a standalone server
18:25:46.624 INFO - Java: Apple Inc. 20.65-b04-466.1
18:25:46.624 INFO - OS: Mac OS X 10.10.2 x86_64
18:25:46.645 INFO - v2.44.0, with Core v2.44.0. Built from revision 76d78cf
18:25:46.770 INFO - Default driver org.openqa.selenium.ie.InternetExplorerDriver registration is skipped: registration capabilities Capabilities [{platform=WINDOWS, ensureCleanSession=true, browserName=internet explorer, version=}] does not match with current platform: MAC
18:25:46.846 INFO - RemoteWebDriver instances should connect to: http://127.0.0.1:4444/wd/hub
18:25:46.847 INFO - Version Jetty/5.1.x
18:25:46.847 INFO - Started HttpContext[/selenium-server/driver,/selenium-server/driver]
18:25:46.848 INFO - Started HttpContext[/selenium-server,/selenium-server]
18:25:46.848 INFO - Started HttpContext[/,/]
18:25:46.915 INFO - Started org.openqa.jetty.jetty.servlet.ServletHandler@3b6f0be8
18:25:46.915 INFO - Started HttpContext[/wd,/wd]
18:25:46.924 INFO - Started SocketListener on 0.0.0.0:4444
18:25:46.924 INFO - Started org.openqa.jetty.jetty.Server@7a3570b0
tortila commented 9 years ago

I have the same problem, I wrote about it here: https://groups.google.com/forum/#!topic/nightwatchjs/31GaFh1cRN4

When I alerted the values of argument and its length I got undefined and 0 respectively. My command works when I hard-code the argument.

Any idea what is the cause of this problem?

nightwatch v0.5.36 Selenium v2.44.0 Firefox v35.0.1

davidlinse commented 9 years ago

I think you don't understand the concept behind .execute() .. It works with returned values from within the document scope and as alert and console.log do not return anything there won't be any result.value in it's callback.

Hope the sample below illustrates it.

/* global document */

module.exports = {
  'Demo passing arguments to .execute()' : function (client) {

    client
      .url('https://github.com/beatfactor/nightwatch')
      .waitForElementVisible('body', 1000)
      .execute(function(selector){
        return document.querySelector(selector).innerHTML;
      }, ['title'], function(result){

        // work w/ returned value from .execute()
        client.assert.equal(result.value, 'beatfactor/nightwatch · GitHub');

        // double check title w/ implementation
        client.assert.title('beatfactor/nightwatch · GitHub');
      });
  },

  after : function(client) {
    client.end();
  }
};

regards ~david

tortila commented 9 years ago

I think you misunderstood my point. In my previous comment I meant that I alerted the arguments and their length not instead of, but in addition to the document.evaluate() (which, by the way, returns an object). I did it just to check if the arguments are actually passed successfully to .execute() and got the same result as @SoYoureAWaffleMan did.

Now, to be precise, .execute() does not work with values returned from the document scope, but its callback does, when I return them explicitly in .execute().

My point is that no values are passed as arguments to .execute() command, which can be easily checked by loggin/alerting them or their length.

davidlinse commented 9 years ago

Yes, thanks for correcting the part with the 'returned value' .. Beside that your sample works fine for me..

  'Demo passing arguments to .execute()' : function (client) {

    client
      .url('https://github.com/beatfactor/nightwatch')
      .execute(function(data){
        console.log('passed args: ', arguments);
        return arguments;
      }, ['a value'], function (result){
        console.log(result.value);
        client.assert.deepEqual(['a value'], result.value, 'Result matches');
      })
      .end();
  }

produces the following output:

nightwatch: $ bin/nightwatch -c bin/nightwatch.json --test examples/demo-execute.js

[Demo Execute] Test Suite
=========================

Running:  Demo passing arguments to .execute()

[ 'a value' ]
✔  Assertion passed: Result matches

OK. 1 total assertions passed. (3.679s)

Here is the selenium-server log for reference..

13:41:58.465 INFO - Executing: [new session: Capabilities [{javascriptEnabled=true, name=Demo Execute, acceptSslCerts=true, platform=ANY, browserName=firefox}]])
13:41:58.466 INFO - Creating a new session for Capabilities [{javascriptEnabled=true, name=Demo Execute, acceptSslCerts=true, platform=ANY, browserName=firefox}]
13:42:00.099 INFO - Done: [new session: Capabilities [{javascriptEnabled=true, name=Demo Execute, acceptSslCerts=true, platform=ANY, browserName=firefox}]]
13:42:00.117 INFO - Executing: [get: https://github.com/beatfactor/nightwatch])
13:42:02.016 INFO - Done: [get: https://github.com/beatfactor/nightwatch]
13:42:02.019 INFO - Executing: [execute script: var passedArgs = Array.prototype.slice.call(arguments,0); return function (data){
        console.log('passed args: ', arguments);
        return arguments;
      }.apply(window, passedArgs);, [a value]])
13:42:02.030 INFO - Done: [execute script: var passedArgs = Array.prototype.slice.call(arguments,0); return function (data){
        console.log('passed args: ', arguments);
        return arguments;
      }.apply(window, passedArgs);, [a value]]
13:42:02.037 INFO - Executing: [delete session: ae5aa525-2af0-486a-b8d8-66ee62e32226])
13:42:02.108 INFO - Done: [delete session: ae5aa525-2af0-486a-b8d8-66ee62e32226]
tortila commented 9 years ago

Well, that's interesting - I ran the same exact test you posted and the selenium output is the same (obviously except session details), but nightwatch output is as follows:

[Demo] Test Suite
=================

Running:  Demo passing arguments to .execute() 

[]
✖  Assertion failed: Result matches  - expected "" but got: a value

TEST FAILURE: 1 assertions failed, 0 passed and 1 skipped.. (8.771s)

What nightwatch version are you using?

davidlinse commented 9 years ago

I'm running this against latest HEAD (v0.5.36)

tortila commented 9 years ago

Could it be the fault of Selenium firefoxDriver, which is by default in the selenium jar? I'm using selenium 2.44.0 and I just checked chromeDriver (v2.14 downloaded from official website) instead of default firefoxDriver, and there is no such problem with .execute() in Chrome. If this is true, then - as I assume - there is no way to specify a path to custom firefox driver and this bug can only be patched with new selenium standalone version?

SoYoureAWaffleMan commented 9 years ago

I can confirm this: using Chrome the params are sent successfully, using Firefox they are not.

Thank you @tortila - I believe your assertion re: Selenium is correct.

davidlinse commented 9 years ago

Just for reference.. I can run my sample from above with the following setup:

regards ~david

Pigmalion commented 4 years ago

I think you don't understand the concept behind .execute() .. It works with returned values from within the document scope and as alert and console.log do not return anything there won't be any result.value in it's callback.

Hope the sample below illustrates it.

/* global document */

module.exports = {
  'Demo passing arguments to .execute()' : function (client) {

    client
      .url('https://github.com/beatfactor/nightwatch')
      .waitForElementVisible('body', 1000)
      .execute(function(selector){
        return document.querySelector(selector).innerHTML;
      }, ['title'], function(result){

        // work w/ returned value from .execute()
        client.assert.equal(result.value, 'beatfactor/nightwatch · GitHub');

        // double check title w/ implementation
        client.assert.title('beatfactor/nightwatch · GitHub');
      });
  },

  after : function(client) {
    client.end();
  }
};

regards ~david

I think you didnt understand the problem. We need to pass parameters from outside the scope , in example to pass for assertion a string from array of options