chai-webdriverio icon indicating copy to clipboard operation
chai-webdriverio copied to clipboard

Use already selected elements instead of string

Open cstro opened this issue 7 years ago • 15 comments

Is it possible to pass a selected element to expect, rather than a string selector?

Is there any way I could use it like this?

const element = $('.css-selector')
expect(element).to.be.there()

Thanks

cstro avatar Nov 07 '17 15:11 cstro

Currently, no. It would be possible to allow that (which would be awesome), but I think it would require work on every assertion to allow passing of either a selector or an element. Not hard... but tedious ;) Wanna work on it? :D

mltsy avatar Nov 07 '17 17:11 mltsy

Yeah definitely! :)

What would you suggest as the best way to do it?

Would it simply be a case of checking if the selector passed in is an object or a string?

cstro avatar Nov 07 '17 17:11 cstro

My idea to achieve it would be add a util function that does

function selectElement(client, selector) {
  if (typeof selector === 'object') return selector

  return client.element(selector)
}

Then in all the assertions functions where is does client.{function} we could replace it with selectElement(selector).{function}?

No idea if that is a good way to solve it though? :)

cstro avatar Nov 07 '17 17:11 cstro

That looks pretty good to me! I was going to suggest something similar. Might be nice to use something more specific than object to compare it to (I'm not sure what off the top of my head - maybe once you start running tests you can inspect one of the elements and find something appropriate)

We'll have to figure out how to deal with elementExists too, but that should be pretty simple - just check for the same condition at the top of that function :smile:

Also will have to decide if we're going to accept a collection of elements like $$('.css-selector') (seems like a good idea) or only single elements.

mltsy avatar Nov 07 '17 18:11 mltsy

Looking at the tests I think they may have to be reworked quite a lot as we wouldn't be using the client object to call any methods anymore? So they would need to be mocked/stubbed on the element returned from client.element() or $ (and possibly $$)

The other option is to go the other way, leave most of the code as it is and pull the selector string off the already selected element object. Kind of normalize this new input into the current expected input. The downside to this approach is that it would mean the element gets selected twice, which seems a bit nasty.

cstro avatar Nov 07 '17 21:11 cstro

Ahhh shoot - you're right!

Actually it shouldn't be too bad though - mostly we'd just have to replace fakeClient stubs in the beforeEach blocks with stubs of selectElement to setup/return whatever the context is describing... which should be analogous to the way elementExists is stubbed, although I'm not sure I really understand proxyquire, but... it seems to be a well-used testing module, and therefore probably not a terrible design pattern :) (I'm newish to Node programming)

So that's really only a couple places in each test - again, a bit tedious but hopefully not treacherous :wink:

mltsy avatar Nov 07 '17 21:11 mltsy

But just to validate your assessment - I agree! You're on the right track with what it should look like, and I think that plan is better than trying to shoehorn the implementation into the current testing setup! :+1:

mltsy avatar Nov 07 '17 21:11 mltsy

I'd love to see this feature; it's what chai-webdriverio needs to be able to work seamlessly with the Page Object model.

vincebowdrentribal avatar Jan 08 '18 12:01 vincebowdrentribal

I'd also love to have this feature. I did a small amount of research and discovered a few things.

  1. The selector is used in this library to log error messages. While the WebElement does have a "selector" property, it doesn't contain the full selector if it was "sub selected". For example browser.$('.hello').$('.hello-again'). In this case, the second element would only have the selector of ".hello-again". This is probably not desirable.
  2. Unless the client is configured to work with "async", their calls will be synchronous. This would be a bit of a problem when using the $$ since the only solution I can think of involves waiting for each and every element to see if (for example) they are visible. That could take a long time, and is probably not desirable. Of course you could put the wait time on the first element and then check if any of the other elements are visible. Still, it doesn't sound like the best solution.
  3. If there are ways to solve 1 and 2 I thought addCommand might be a nifty way to solve it. Call our custom commands and use the element itself if it is an element. Again this might be undesirable for the consumer of the library. Just thought I would throw it out there.

Please let me know if my research/assumptions are wrong. I would love to have this feature and I might spend time implementing it (as time allows).

kyle-long avatar Apr 12 '18 23:04 kyle-long

I'm afraid I'm not using Node in any of my current projects anymore, so I don't have the resources to collaborate on this much at this point 😞 But at a glance... no.1. seems unrelated to this issue, right? (You may be right, but I'd open a separate issue for that). I see your point with no.2. I was thinking we'd just pass it along to webdriverio as a single expectation (with a single timeout) but I don't see documentation showing whether you can say something like $$(.checkboxes).isVisible or check for text on a whole collection, etc... so maybe we leave that part out.

mltsy avatar Apr 13 '18 02:04 mltsy

Hey thanks for the quick response. 1. Is only an issue if elements are accepted. Currently there is no option other than to give the entire selector right away (that I am aware of). In that case, the selected element would have that entire selector. 2. Yeah I should have mentioned that. It appears just a vanilla array is returned from $$.

i'll give it some thought and submit a pull request if I find a way around these issues.

kyle-long avatar Apr 13 '18 22:04 kyle-long

Ooh, I see what you're saying about no.1 - yeah you'd just have to experiment with what useful info the error message has access to in that case... If nothing else, I feel like if there's a line number from the spec file, and the last selector in the error message, it's still not ideal, but that's enough information for the developer to determine where the problem is :)

mltsy avatar Apr 14 '18 13:04 mltsy

This would really be an awesome feature, especially when working with page objects!

Is someone working on an implementation of this at the moment?

AnnikaNissen avatar Jul 06 '18 10:07 AnnikaNissen

I'm curious where this request sits with wdio evolving to v5.

treyturner avatar Feb 20 '19 05:02 treyturner

@treyturner I think a first step would be to make the extension compatible with WebdriverIO v5. I created a separate issue for that today - see https://github.com/marcodejongh/chai-webdriverio/issues/48.

AnnikaNissen avatar Feb 26 '19 17:02 AnnikaNissen