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

Initial support for selectors via delegates #7

Closed
wants to merge 1 commit into from

Conversation

checketts
Copy link

@checketts checketts commented Dec 4, 2018

By using delegate properties, I would like to remove a lot of the noise when creating page objects.

This isn't complete, but it gives you an idea of how I would like to improve the syntax for creating page objects.

Compare the HelloWorld runButton and tryItButton syntax as an example.

The consoleOutput is the most complex example, since it changes what the waitFor from the default CLICKABLE to the IS_PRESENT condition and also does additional stuff with the element.

I don't love duplication in the so I'm considering alternative strategies. I look forward to your feedback.

@EPadronU
Copy link
Owner

EPadronU commented Dec 6, 2018

This is very interesting. I'll give a detailed look to it on the weekend (hopefully).

@EPadronU
Copy link
Owner

EPadronU commented Dec 9, 2018

I've been meditating about this and, to be totally honest, I'm not very convinced on the benefits.

The following two approaches are not radically different. So, one doesn't save a lot of typing nor time.

    private val tryItButton by lazy {
        waitFor { elementToBeClickable(By.xpath("//a[@class='nav-item' and contains(text(),'Try Online')]")) }
    }
    val tryItButton by xpath("//a[@class='nav-item' and contains(text(),'Try Online')]")

And it has to be mentioned that the flexibility the first approach gives plus the lack of more abstractions, makes such more convenient in my humble opinion.

We would have to introduce abstraction for each and every expected condition under ExpectedConditions. The way one can use a WebElement instead of a By would stop being so easy. And your proposed approach will limit the user to lazy evaluation only, versus having the choice of making the property contain the same value for the rest of the Page's life (by lazy) or being up-to-date with what the page contains (get).

private val foo by lazy {
    waitFor { presenceOfNestedElementLocatedBy(rootElement, By.className("child")) }
}
private val ads: List<WebElement>
    get() = waitFor { visibilityOfAllElementsLocatedBy(By.xpath(".ads")) }
}

In order to be less verbose, one could create a(n) (extension) function for custom expected conditions as follows:

    fun ExpectedConditions.isTextNotEmptyOfElementLocatedBy(by: By) = ExpectedCondition { webDriver ->
        webDriver?.findElement(by)?.let { webElement ->
             if (webElement.text.isEmpty()) null else webElement
         }
    }

So the usage will look like:

private val consoleOutput by lazy {
    waitFor { isTextNotEmptyOfElementLocatedBy(By.cssSelector(".code-output")) }
}

I look forward reading what you think about all of this.

@EPadronU EPadronU closed this Aug 31, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants