selene icon indicating copy to clipboard operation
selene copied to clipboard

consider aliases for getting actual webelement from browser.element('#foo')

Open aleksandr-kotlyar opened this issue 4 years ago • 1 comments

In latest discussion @yashaka shared the following ideas regarding getting actual webelement from the lazy selene element...

Before (1.0)

browser.element().get_actual_webelement()

This style was deprecated in 2.0 because looks awkward in context of Appium for mobile automation (the method will return Mobile Element, not Web Element) and for more versatile and simple implementation of Waits.

Now (2.0)

In 2.0 Selene Element implements "callable API" via __call__ method implementation to allow smoother passing of element to selene's Wait that accepts any callable entity (like functions or object of classes that implements __call__) – this makes implementation simple and versatile. Yet... it might be not like that readable when someone decides to to get actual webelement from lazy selene Element to use more low level Selenium WebDriver API:

webelement = browser.element('#foo')()

By the way this becomes not like that awkward:

foo = browser.element('#foo')
webelement = foo()

Here come questions:

Q1: do we need to improve readability of such "access low level webelement API" cases by adding some aliases? Q2: do we need to solve it till stable release of 2.0?

Might be added

Option 1.1. More readable, pretty abstract and yet low level style of naming to emphasize the "Lower Level of WebElement API" (webelement for element is like webdriver for browser)

webelement = browser.element('#foo').handle

cons:

  • might be awkward in webelements = browser.all('.item').handle, because of plural context... If adding webelements = browser.all('.item').handles will be less KISS in implementation, less versatile
  • the name is less self-documented (this can be considered as a plus too – recall the idea to emphasize low level context)

Option 1.2. More readable, concise, high-level, more obvious/self-documented in context of what we do (yet hiding the revealing of low level context)

browser.element().get()

What do you think?

Don't hesitate to share your thoughts on Q1, Q2, Option 1.1 and 1.2!

aleksandr-kotlyar avatar Jan 16 '21 16:01 aleksandr-kotlyar

See also same ideas from NSelene at SeleneElement.cs:L117

Here is an excerpt:

        // TODO: consider renaming it to something more concise and handy in use...
        //       take into account that maybe it's good to just add an alias
        //       because in failures it looks pretty good now:
        //       > Timed out after 0.25s, while waiting for:
        //       > Browser.Element(a).ActualWebElement.Click()
        //       
        //       some alias candidates:
        //       * Browser.Element(...).Get()
        //         - kind of tells that we get Element, not raw WebElement
        //         + one of the concisest
        //       * Browser.Element(...).Find()
        //         - not consistent with Find(selector), 
        //         + but tells that we actually finding something
        //       * Browser.Element(...).Locate()
        //         + like above but does not interfere with other names
        //         + consistent with Element.locator
        //         - not the concisest
        //       * Browser.Element(...).Raw
        //         + !!! in fact it's "raw" in its nature, and the most concise
        //         - maybe a bit "too technical", but for tech-guys probably pretty obvious
        //           yeah, Selene is for users not for coders, 
        //           + but actual raw webelement is also not for users;)
        //       - Browser.Element(...).Invoke()
        //       - Browser.Element(...).Call()
        public IWebElement ActualWebElement {
            get {
                return locator.Find();
            }
        }

yashaka avatar Jun 18 '21 13:06 yashaka

Poll results: image

yashaka avatar Oct 02 '22 20:10 yashaka

locate() is exelent... works nice

  • with both...
    • element.locate()
  • and
    • collection.locate()

while raw or __raw__ would work with all three:

  • element.raw
  • collection.raw
  • browser.raw
    • here it will return raw driver

the latter might be usefull in some polimorphic functions that can accept element or browser for example (as search context), etc...

yashaka avatar Oct 03 '22 15:10 yashaka