yandex-qatools / htmlelements

Html Elements is a Java framework providing easy-to-use way of interaction with web-page elements in web-page tests.
Other
271 stars 116 forks source link

Expanding Table API to include Streams #128

Closed ham1 closed 3 years ago

ham1 commented 8 years ago

Now we are using Java 8, I wanted to extend the API of the Table by adding methods such as: public Stream<List<WebElement>> getRowStream()

As an example use case:

Table t ...
assert t.getRowStream()
        .anyMatch(row -> row.get(0).getText().equals("foo"))

This would be much faster in the best case i.e. it would only look at the first row, instead of always having to create a list of the entire table.

Before I create a PR I wanted people's opinion regarding if we should keep using xpath or change to CSS for the new stream methods?

I've tested on a few example tables and CSS seems to be ~2-4x faster than xpath, especially on large tables, which is exactly where this interface would be most useful.

Thanks

lanwen commented 8 years ago

I'm ok for the css selectors, but not ok with new stream methods. It looks very strange and similar to the quick workaround, but not the real api. If it should be lazy loaded, so it should return Iterable with corresponding iterator

ham1 commented 8 years ago

Just to clarify, you would be happy to change the current xpath to css, or only use css for new API methods?

I much prefer Streams over Iterators as an API, less client code and more functional in style. How would you achieve my example above with an iterator? What advantages are there to using Iterator instead of Stream?

lanwen commented 8 years ago

I'm for css selectors everywhere.

Stream provider should be able to provide lazily new elements. This is possible only with lazy evaluation of the selector. Lazy evaluation possible only with corresponding iterator. (Or it will be same as getList().stream()). As of Iterable much more simple interface - it should be used instead of stream. (It can be converted to stream easily). As a bonus - we can use lot of not java8 libs to handle items.

ham1 commented 8 years ago

Yes I see your point.

I had planned to do something like:

public Stream<List<WebElement>> getRowStream() {
    return getWrappedElement()
            .findElements(By.cssSelector("tr")).stream()
            .map(rowElement -> rowElement.findElements(By.cssSelector("td")))
            .filter(row -> row.size() > 0); // ignore rows with no <td> tags
}

Where it would still, as you say, have to get all the tr, but the mapping to td would be lazy.

I will submit PR and see what people think.