-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: provide waitForInvisible etc. to make code clear #2307
Comments
Got to agree here, the current API is counter intuitive and requires comments for good code maintainability. Even worse you also need to also re-declare the timeout. |
I don't see why you have to redeclare the timeout. You can just do browser.waitUntil(() => $('elem').isVisible()) I am open for other opinions. |
OK, using null is a little better, but putting myself in the shoes of anyone who is going to look at the code in future - what exactly does it mean? I am sprinkling in comments like this at the moment.
I'm not sure how the example you have given improves readability unless there was an isInvisible method though? |
I personally have created a few helpers especially because of this https://github.com/ubccr/xdmod/tree/xdmod7.1/open_xdmod/modules/xdmod/automated_tests/webdriverHelpers I did this so interns and the like would easily be able to just know instead of having to pass a counter intuitive true to waitForVisible. If it was waitForVisible(, false) it would make a bit more sense But i prefer the waitForInvisible / waitUntilNotExist However, since we are debating this, I think we should choose one or the other of waitFor vs waitUntil these are the same but having both has always bothered me. I never know which one I am supposed to use In my opinion, waitUntil > waitFor |
Not sure what you mean by that but these are just different wait methods. With waitUntil you can wait on arbitrary things whereas waitForVisible obviously only checks for visibility. My example above was wrong it should be: browser.waitUntil(() => $('elem').isVisible() === false) to wait until an element is not visible. My issue with adding commands is that it blows up the API without adding any value. Anyone is free to create helper methods to increase readability. |
Thanks @christian-bromann that's a good solution. |
That makes sense, I was missing the reasoning. I just meant from a reading perspective waitUntil looks better than waitFor, though from a writing perspective waitFor is shorter :) |
I think it's pretty undeniably true that If you did go down the route of having separate methods for all of the reverse scenarios, you'd probably also need to include |
My personal preference would definitely be towards an API that would also add the option of passing in parameters along the lines of {reverse: True, timeout: 5000}. |
@christian-bromann the bottom line here is you have to admit that someone seeing the following code for the first time: await browser.waitForExist('#loginForm', 5000, true) Would be totally surprised to find out that means "wait for not exist". |
@MattyBalaam being able to pass |
I wrote some helpers functions for this purpose, I named it |
@christian-bromann If we aren't going to change the api in V5 - I say we close this issue. |
Having worked with many developers now on writing WebdriverIO tests, this always comes up, in a couple of ways:
The developers I've seen make these mistake range from totally new to seasoned experts, which is a clear sign to me that the API is broken, it is not an education issue. Good API is discoverable and clearly communicates the developer's intent when they wrote the code; I think the issues I've seen strongly suggest that is not the case here. The ancient software design maxim "code is written once and read many times" is very relevant here. I am extremely sympathetic to the argument of "don't explode the API", but a) the boolean argument IS part of the API – just a very confusing and poorly-discoverable way to do it, and b) the need to "reverse" these operations is so unbelievably common that having top-level methods for the behaviors is incredibly valuable API (and lacking it is very painful for real-world developers). I also disagree with @mmcculloch15's slippery-slope argument that adding top-level API to reverse the |
@chrishyle I just dealt with this EXACT question yesterday in a training session with my devs; and I think you are overthinking this. We offer addCommand as a feature, and its ridiculously easy to implement your own waitForInvisible(), waitForNotVisible(), or whatever you want to name it. browser.addCommand('waitForInvisible', function (timeout, message) { |
@abjerstedt thanks for the quick response! It would definitely not be the first time I over-thought something, but even so, I'm not sure that makes me wrong about this. =P Implicit in your response is: "you're right, this does come up all the time" – so I think we agree that it is very common, and maybe we even agree that the magic boolean is a bad solution. The real answer you have for this problem is not the boolean, but "write your own helper" – meaning that the "best practice" for every WebdriverIO user, across your entire ecosystem, is to write the code themselves… thus de-facto expanding the API, but in a boilerplate and fragmented way. You have punted the responsibility of solving this to your users =(. Further complicating it is @christian-bromann's fairly consistent messaging that we shouldn't use I'm not sure that "maximally minimal" API should be the goal for WebdriverIO (and it already isn't applied consistently – helpers DO exist, this is not a building blocks only framework); I deeply understand the dangers of expanding surface area, but I feel like it is being misapplied here over what I think should be a more important value for this framework: an incredible developer experience writing tests. Having "too much" API hurts that obviously, but so does having "too little" and "flat out bad" API. That you had to explain this in a training yesterday should suggest that you've floated too far in the "too little API" direction, and this feels like an easy fix. |
Even the word "reverse" in the API docs is not ideal... it should be "opposite" since "what is the opposite of visible" is more idiomatic than "what is the reverse of visible". |
I think addCommand() is considered an accepted feature of webdriverio at this point; and possibly even more accepted in v5 than v4 as the whole logic behind it was rebuilt. @jedwards1211 how would you feel about going with the chai terminology and call it negate? |
Ya, naming is maybe weird: waitForNotExist, waitForNotDisplayed, etc. would be more consistent, but less well-formed English. I think I'd slightly favor consistency over grammar. 🤷♂️ A functional approach might also be an option: negate($(selector).waitForExist)();
// or opposite / reverse ? I think this would still be slightly better than the magic boolean because the intent is more clear when reading it, but I think it would be an unfamiliar pattern in WebdriverIO and still way worse than just |
@abjerstedt I'm used to Chai looking like I'd prefer either @chrishyle's suggestion or getting rid of everything but Or maybe a chai-like API? |
|
What would you guys think of having a syntax being like: browser.not.waitForExist() ? |
.not stands for inverting waitFor* behavior? Will we wait for still work in old way? As a temporary solution users who need this function can just definite custom command |
Yes. As oppose to e.g.
What do you mean? |
I mean keep ability to pass true/false as a parameter |
Yeah, we would keep this. |
Grammar wise it doesn't work. We would need to break it up to be something like |
@jedwards1211 @chrishyle @MattyBalaam comments? |
are we still going to add command? |
In v6 we changed the structure of these commands to address this issue. Not the command can be called as follows: $('body').waitForDisplayed() // waits until it is displayed
$('body').waitForDisplayed({ reverse: true }) // waits until it disappears I hope this is a good compromise everyone can work with. |
still not as readable as if there were simply a |
@jedwards1211 you can always add a custom command that does add this command to the element context for better readability. |
oh okay |
No one seeing
waitForVisible(..., ..., true)
for the first time would think that thetrue
means to actually wait until the given element is invisible, and even I get confused reading or writing my tests sometimes ("why am I waiting for this thing to become visible and not invisible? oh right, the true flag means do the opposite...")It's a perfect example of unclear code (boolean arguments almost always are). I don't think anyone would prefer the
reverse
argument overwaitForInvisible(...)
orwaitFor('invisible', ...)
orwaitForVisibility(..., {visible: false})
.We can of course easily write our own
waitForInvisible
function, but please keep in mind that because such a function doesn't exist in the webdriver API, not everyone will be inclined to write their own, and a lot of code in the wild will be less readable as a result.Thoughts?
The text was updated successfully, but these errors were encountered: