I am new to Selenium and StackOverflow.
I apologize in advance if there is any mistake.
My question is:
How @FindBy()
annotation works internally and why initElemets()
method is needed?
The method initElements()
initializes all of WebElement
and List<WebElement>
fields with Java Reflection API. It basically changes the default null
values to implementations of the interface using Proxy
. It also provides sort of Lazy instantiation of the WebElement
which means - WebElements are found (looked for?) only when needed - when you invoke operations on them.
In more depth:
initElements
accepts Object
or Class<?>
as an argument and creates an object from it. Having that, PageFactory
gets all fields in the class, verifies if any of them is a type of WebElement
or List and initializes them.
If WebElement
is NOT annotated with @FindBy
then PageFactory
tries to create selector by the variable name. Something like this WebElement username
might actually work without annotation.
If WebElement
is annotated with @FindBy
then By
object is created and connected to the WebElement
for later use. This part is just an assumption.
Then, the instance of WebElement
is created. Since it's an interface, it cannot be instantiated directly with Reflection API. Proxy is used to handle the creation of a WebElement
. PageFactory
initializes elements in provided Page Object with newly created instances of WebElements using Reflection.
Both, WebDriver
and WebElement
implements interface SearchContext
which also tells the WebDriver
how to look for the element. Is it in the whole page source or scope is reduced to the particular WebElement
. That's why we can search elements through other elements like this: element.findElement(By.id("username"))
.
Hope I explained it a little bit!