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.84k stars 1.33k forks source link

would like type (xpath vs. css) of selectors to be automatically detected #196

Open mam-p opened 10 years ago

mam-p commented 10 years ago

I have two "wishes" for Nightwatch locators:

  1. Support for all types of locators, not just xpath and css.
  2. Automatic detection of the type of locator, xpath vs. css.

Re: #2. We have only 17 test cases so far and we're already tripping up when a locator gets changed (at our request usually) to a reasonable CSS one. We make the change in the LOCATORS associative array of our PO but forget to change the "xpath" arg to "css" in the statement(s) that utilizes the locator. We're going to wind up prefixing every single locator with the proper type right in the LOCATORS associative array, which is going to make the accesses much uglier but at least less problematic. But if #2 were to get implemented in nightwatch, we wouldn't have to do this....

davidlinse commented 10 years ago

@beatfactor @mam-p I jumped into this this weekend, with partial success. I got it working for the waitForElementPresent command but there are a few things that makes me wonder about the reliability of the tests.

@beatfactor I really like the idea behind canned responses, but have the strange feeling that it is a hidden spot of issues. One can specify any (accidentally invalid) response, use it in your test and introduce a bug because there is (afaict) no other way than $ npm test to run some tests, right ?

For example i saw something like

.useXpath()
.waitForElementPresent('//weblogin', 50, ...)

which will work in the tests, (as the response is canned in mocks.json but cmiiw //webelement is neither a valid css selector nor a valid xpath selector.

In this contex i would really like to see:

I think it could serve as some security net as it will use real responses and will detect wrong defined mocked responses. What do you think ?

Also, would you mind sharing some details about your workflow defining the mocked responses ? How the are used (interally) in tests ? Is it c&p and adaption from a real session ?

best regards ~david

mam-p commented 10 years ago

David: Thanks so much for working on this one! The app I'm working on is very short on decent tags, leading to seriously brittle CSS selectors. So, I need to use text-based xpath ones quite a bit, but it is problematic to have to hard-code the locator type in the Nightwatch call.

One question: Does every Nightwatch command (including assertions) now support xpath? I bumped into a situation last week in which it appeared that assertions were not supporting the extra argument, and one of Andrei's comments in https://github.com/beatfactor/nightwatch/issues/33 indicated that assertions did not support xpath expressions. I cannot tell from the later comments whether support for xpath in assertions was added or not....

--Mary Ann  

On Monday, July 7, 2014 12:34 AM, David Linse notifications@github.com wrote:

@beatfactor @mam-p I jumped into this this weekend, with partial success. I got it working for the waitForElementPresent command but there are a few things that makes me wonder about the reliability of the tests. @beatfactor I really like the idea behind canned responses, but have the strange feeling that it is a hidden spot of issues. One can specify any (accidentally invalid) response, use it in your test and introduce a bug because there is (afaict) no other way than $ npm test to run some tests, right ? For example i saw something like .useXpath() .waitForElementPresent('//weblogin', 50, ...) which will work in the tests, (as the response is canned in mocks.json but cmiiw //webelement is neither a valid css selector nor a valid xpath selector. In this contex i would really like to see: * some kind of a real test-page.html (which could be served e.g. via express-plugin) to run a test-suite against. * an option to run all the tests against a real server/page combination. I think it could serve as some security net as it will use real responses and will detect wrong defined mocked responses. What do you think ? Also, would you mind sharing some details about your workflow defining the mocked responses ? Is it c&p and adaption from a real session ? best regards ~david — Reply to this email directly or view it on GitHub.

davidlinse commented 10 years ago

One question: Does every Nightwatch command (including assertions) now support xpath?

Sadly not at all.. As mentioned ..

.. got it working for the waitForElementPresent command

by implementing a method in the _waitForeElement "base-class". But i stopped b/c i have a bad pretty feeling about the mocked test responses. (s.o.)

I tried to update the tests for other commands/assertions as well but failed gracefully. It turns out that this is probably not an easy one b/c (i guess) almost every module/assertion would be affected.

Maybe @beatfactor can shed some light.. ;)

regards ~david

Update: Maybe the approach i proposed in #121 is an alternative (?)

beatfactor commented 10 years ago

@davidlinse a real test page would be nice to be able to test the commands/assertions against real data but that is more time consuming to set up. about the mocked responses, they attempt to just replicate a real response and it doesn't matter if the selector is right or wrong.

@davidlinse @mam-p xpath support is available for some time, since 0.4. you just need to "turn it on" by using either .useXpath() or by setting use_xpath in your nightwatch.json so it is always used. Just try it and let me know how it works. More details are available in the documentation: http://nightwatchjs.org/guide#usage.

Detecting the selector type dynamically is probably not very complicated. We'll just need to build something like this, from webdriver.io: https://github.com/camme/webdriverjs/blob/master/lib/helpers/find-element-strategy.js.

davidlinse commented 10 years ago

xpath support is available for some time, since 0.4.

As a relative close follower i'm aware of it, thanks.. ;)

@beatfactor as stated i've done some experimenting.. maybe you want to have a look

regards

beatfactor commented 10 years ago

@davidlinse looks good, although I would move the getLocatorStrategy somewhere else so it is accessible by other commands as well and make it so that it will detect the xpath first and otherwise assume css selector.

davidlinse commented 10 years ago

I would move the getLocatorStrategy somewhere else

Of course.. In case of a stategy-module that makes totally sense.. Was just tryin' .. ;)

mam-p commented 10 years ago

Re: my request for auto-detection. I was unaware that Selenium xpath locators could start with other than "//" but I would be perfectly happy if I just had to label my locators with the proper prefix. For example, if I could pass any Nightwatch command/assertion a locator with value of "xpath=//", that'd be super. This is how the framework I used at my previous job worked--see https://github.com/Element-34/py.saunter/blob/master/saunter/web_element.py

Sorry for making this wishlist item harder than I actually want/need!

@beatfactor: I know about the xpath support and have been using it. The two issues with it for me are: (1) having to include the type of locator as a separate parameter to the Nightwatch command (I want to just give Nightwatch a labeled locator, such as xpath= so that my PO strategy will be easy to maintain; and (2) the confusing inconsistency of not having assertions support xpath locators.

davidlinse commented 10 years ago

@beatfactor I've started a new attempt for a auto-detect-locator-type-via-strategy .. Was a pretty tough one but, (mocked) test's are passing so far for #id, xpath and css-selector.

Now i'd really like to see a test against a real-world example. /cc: @mam-p ?

There are obviously a lot of mocked responses missing to cover the rest but maybe it's a step in the right direction. Let me know what you think, feedback is welcome.

best regards ~david

related to #33

mam-p commented 10 years ago

I'll be happy to run our suite against it tomorrow if you send me instructions on how to install the new version.

Thanks for working on this, David!

--Mary Ann M-P

On Sunday, July 13, 2014 6:53 AM, David Linse notifications@github.com wrote:

@beatfactor I've started a new attempt for a auto-detect-locator-type-via-strategy .. Was a pretty tough one but, (mocked) test's are passing so far. Now i'd really like to see a test against a real-world example. /cc: @mam-p ? Let me know what you think, feedback is welcome. best regards ~david — Reply to this email directly or view it on GitHub.

davidlinse commented 10 years ago

@mam-p if iirc you can do something like this this in your package.json..

"nightwatch": "git+http://github.com/davidlinse/nightwatch.git#feat-auto-detect-locator-type-via-strategy

regards ~david

mam-p commented 10 years ago

@davidlinse : I reconfigured per your instructions above and re-ran our suite without seeing any failures. So, your change didn't break anything from my limited point of view.

But I really need a few lines to explain exactly how we can use this new functionality so I can properly test it out. Does it still work only for waitForElementPresent? Can I alternate between xpath and css selectors in my suite's waitForElementPresent calls without having to tell Nightwatch which type of selector I'm using? Or is your fix now supporting specifying an extra parameter to waitForElementPresent which specifies the type of locator (such as already works for commands like "click")?

Finally, //webelement is a valid xpath selector AFAIK. It refers to the first element of type "webelement" in the page. I verified that it still works with a random page within Sel-IDE, FWTW.

davidlinse commented 10 years ago

So, your change didn't break anything from my limited point of view.

@mam-p That's good news.. :+1:

Does it still work only for waitForElementPresent?

No.

Can I alternate between xpath and css selectors in my suite's waitForElementPresent calls without having to tell Nightwatch which type of selector I'm using?

In best case, yes. If this will work, it'll render the useCss() and useXpath() commands obsolete and you can pass any valid/supported selector and Nightwatch will do the rest for you.

@beatfactor I've implemented the find-element-strategy in _waitForElement.js, protocol.js and element-commands.js, in hope to cover all important (and hidden) places.

Let me know, what you (all) think.

best regards ~david

mam-p commented 10 years ago

@davidlinse: I don't think I'm testing your changes properly. I modified all 3 of my tests that specify "xpath" as the first argument (to delete that first argument). Then I added this line to my package.json:

"dependencies": { "nightwatch": "git+http://github.com/davidlinse/nightwatch.git#feat-auto-detect-locator-type-via-strategy" },

Then I executed "npm install nightwatch" followed by running my 3 tests individually. All 3 fail in the same fashion, which makes me think I'm not actually running your new code. Here's the relevant output from one of the failing tests:

ERROR: Unable to locate element: "//option[@value='12']" using: css selector There was an error while executing the Selenium command - enabling the --verbose option might offer more details. The given selector //select[@class='day']/option[@value='7'] is either invalid or does not result in a WebElement. The following error occurred: InvalidSelectorError: An invalid or illegal selector was specified Command duration or timeout: 8 milliseconds For documentation on this error, please visit: http://seleniumhq.org/exceptions/invalid_selector_exception.html Build info: version: '2.41.0', revision: '3192d8a', time: '2014-03-27 17:17:32' System info: host: 'MaryAnnMay-Pumphrey-MBP.local', ip: '10.20.23.58', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.9.3', java.version: '1.6.0_65' Session ID: 7bb975c8-8e96-2a45-95a7-f39b128a0ba4 Driver info: org.openqa.selenium.firefox.FirefoxDriver Capabilities [{platform=MAC, acceptSslCerts=true, javascriptEnabled=true, browserName=firefox, rotatable=false, locationContextEnabled=true, version=26.0, cssSelectorsEnabled=true, databaseEnabled=true, handlesAlerts=true, browserConnectionEnabled=true, nativeEvents=false, webStorageEnabled=true, applicationCacheEnabled=true, takesScreenshot=true}] ERROR: Unable to locate element: "//select[@class='day']/option[@value='7']" using: css selector There was an error while executing the Selenium command - enabling the --verbose option might offer more details. The given selector //option[@value='1941'] is either invalid or does not result in a WebElement. The following error occurred: InvalidSelectorError: An invalid or illegal selector was specified Command duration or timeout: 7 milliseconds For documentation on this error, please visit: http://seleniumhq.org/exceptions/invalid_selector_exception.html Build info: version: '2.41.0', revision: '3192d8a', time: '2014-03-27 17:17:32' System info: host: 'MaryAnnMay-Pumphrey-MBP.local', ip: '10.20.23.58', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.9.3', java.version: '1.6.0_65' Session ID: 7bb975c8-8e96-2a45-95a7-f39b128a0ba4 Driver info: org.openqa.selenium.firefox.FirefoxDriver Capabilities [{platform=MAC, acceptSslCerts=true, javascriptEnabled=true, browserName=firefox, rotatable=false, locationContextEnabled=true, version=26.0, cssSelectorsEnabled=true, databaseEnabled=true, handlesAlerts=true, browserConnectionEnabled=true, nativeEvents=false, webStorageEnabled=true, applicationCacheEnabled=true, takesScreenshot=true}] ERROR: Unable to locate element: "//option[@value='1941']" using: css selector

What am I doing wrong?

beatfactor commented 10 years ago

@davidlinse thanks for your efforts, it looks pretty good though some more polishing is going to be needed.

davidlinse commented 10 years ago

@mam-p i'll try to have a look.. do you find a find-element-strategy.js in "./node_modules/nightwatch/lib/selenium/" ?

@beatfactor great.. what do you have in mind ? let's talk ;)

davidlinse commented 10 years ago

@beatfactor i've done some more work on this.. Also included the strategy (for testing purposes) in attributeContains-command ..

Tests are passing .. Anyway i still feeling a bit uncomfortable with the test-setup. @mam-p Would you mind throwing your tests again against it.. ?

regards ~david

beatfactor commented 10 years ago

Cool, I'll have a look. What exactly makes you uncomfortable about the tests?

On Monday, July 21, 2014, David Linse notifications@github.com wrote:

@beatfactor https://github.com/beatfactor i've done some more work on this.. Also included the strategy (for testing purposes) in attributeContains-command ..

Tests are passing .. Anyway i still feeling a bit uncomfortable with the test-setup. regards ~

— Reply to this email directly or view it on GitHub https://github.com/beatfactor/nightwatch/issues/196#issuecomment-49646503 .

davidlinse commented 10 years ago

Cool, thanks..

What exactly makes you uncomfortable about the tests?

1.) That one can define (erroneous) mock-responses and introduce an unseen bug (as long as not tested real world) 2.) The way to setup a/the test(s). If you change/develop something you can't be sure what makes the test fail. Is it a failure in code or is it a missing/wrong mock-response ? If you have an error in code you "can" fix the mock-response to make a test pass or vice versa. Start from 1.) again..

Makes sense ? I hope that i expressed it appropriately .. (Kinda tricky for a non-native.. ;)

regards ~david

CASandmann commented 8 years ago

Whatever happened to this? It sounds like this was largely implemented... why wasn't it merged into the main project? This is a huge issue for me because I hate XPath and try to use CSS as much as possible, but sometimes I wind up needing XPath for one reason or another. We have utility functions that require one or the other and it becomes annoying if those functions have to change the client's exploration "mode."