Skip to content
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

Consider adding @property last to the Collection class #460

Open
roman-isakov opened this issue Nov 1, 2022 · 1 comment
Open

Consider adding @property last to the Collection class #460

roman-isakov opened this issue Nov 1, 2022 · 1 comment
Labels

Comments

@roman-isakov
Copy link

just like we've got this:

@property def first(self): """ A human-readable alias to .element(0) or [0] """ return self[0]

could you please consider implementing last ?

@yashaka
Copy link
Owner

yashaka commented Dec 6, 2022

from first point of view it may sound as a good idea... logic is kind of obvious: we have elements.first, we have elements.second, why not have elements.last?

But the problem lies when you start digging deeper. The reason why elements.last sounds a good way to go may be called as "consistency". But can we trully make the implementation of .last to be consistent in behavior with .first and .second?

.first and .second - will wait result in waiting for first and second elements to appear in the whole collection so we can use them. But how can we implement waiting "the last" element? We don't know exact index of "last" element. The selene tries to be "natural" and do exactly what a normal user would expect from its commands. Everybody got used to the fact that .first and .second will wait. Now, after inventing .last - they will expect that it will also wait, but in fact - it will not. (UPDATE: it will, but just for the size of collection = 1, that does not reflect all user cases)

Once more. With first and second you don't need to write:

browser.all('.list-item').should(have.size(1)).first.element('.remove-button').click()

browser.all('.list-item').should(have.size(2)).second.element('.remove-button').click()

selene will do all corresponding waiting on his own, just by using simpler code:

browser.all('.list-item').first.element('.remove-button').click()

browser.all('.list-item').second.element('.remove-button').click()

But if we implement .last, it will not remain the same, it will not remain consistent with .first and .last, you will have to use should(have.size(the_actual_collection_size)) to make it stable and work as expected in most cases:

# assuming there should be 10 items when everything is fully loaded
browser.all('.list-item').should(have.size(10)).last.element('.remove-button').click()

Now, taking this into account, the actual better and stable version for most cases would be:

# assuming there should be 10 items when everything is fully loaded
browser.all('.list-item')[9].element('.remove-button').click()

The main idea of Selene - is to help users write stable and efficient code, minimizing "shooting in theirs legs"... Of course we can't make Selene ideal in this context. You still can shoot into your leg with something like

# assuming there should be 10 items when everything is fully loaded
browser.all('.list-item')[-1].element('.remove-button').click()

But at least it looks like a "non readable low level way to achieve the goal", without pretending to be a nice-looking command named as .last :D

But maybe I am not right... maybe we could make an exception for .last and still add it... Let's see what others think...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants