Skip to content

Commit

Permalink
[ui] implemented locateAll() with filter #1123
Browse files Browse the repository at this point in the history
  • Loading branch information
ptrthomas committed May 3, 2020
1 parent 6f79483 commit dcd0c4a
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 9 deletions.
23 changes: 20 additions & 3 deletions karate-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1243,7 +1243,9 @@ See [Function Composition](#function-composition) for another good example. Also
* match list == ['data1', 'data2']
```

> Note that the JS in this case is run by Karate not the browser, so you use the Java `String.contains()` API not the JavaScript `String.includes()` one.
> Note that the JS in this case is run by *Karate* not the browser, so you use the Java `String.contains()` API not the JavaScript `String.includes()` one.
See also [`locateAll()` with filter](#locateall-with-filter).

## `locate()`
Rarely used, but when you want to just instantiate an [`Element`](src/main/java/com/intuit/karate/driver/Element.java) instance, typically when you are writing custom re-usable functions. See also [`locateAll()`](#locateall)
Expand All @@ -1267,12 +1269,27 @@ This will return *all* elements that match the [locator](#locator) as a list of
# find all elements with the text-content "Click Me"
* def elements = locateAll('{}Click Me')
* match karate.sizeOf(elements) == 7
* elements.get(6).click()
* match elements.get(3).script('_.tagName') == 'BUTTON'
* elements[6].click()
* match elements[3].script('_.tagName') == 'BUTTON'
```

Take a look at how to [loop and transform](https://github.com/intuit/karate#json-transforms) data for more ideas.

### `locateAll()` with filter
`locateAll()` can take a second argument which has to be a JavaScript "predicate" function, that returns a boolean `true` or `false`. This is very useful to "filter" the results that match a desired condition - typically a text comparison.

Imagine a situation where you want to get only the element where a certain attribute value *starts with* some text - and then click on it. A plain CSS selector won't work - but you can do this:

```cucumber
* def filter = function(x){ return x.attribute('data-label').startsWith('myQues1_1') }
* def list = locateAll('div[data-label]', filter)
* list[0].click()
```

The `filter` function above, will be called for each [`Element`](src/main/java/com/intuit/karate/driver/Element.java) - which means that you can call methods on it such as [`Element.attribute(name)`](#chaining) in this case. Note that the JS function in this case is run by *Karate* not the browser, so you use the Java `String.startsWith()` API.

See also [`scriptAll()` with filter](#scriptall-with-filter).

## `refresh()`
Normal page reload, does *not* clear cache.

Expand Down
13 changes: 12 additions & 1 deletion karate-core/src/main/java/com/intuit/karate/driver/Driver.java
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,18 @@ default Element locate(String locator) {
default List<Element> locateAll(String locator) {
return getOptions().findAll(this, locator);
}


default List<Element> locateAll(String locator, Predicate predicate) {
List before = locateAll(locator);
List after = new ArrayList(before.size());
for (Object o : before) {
if (predicate.test(o)) {
after.add(o);
}
}
return after;
}

default Element scroll(String locator) {
script(locator, DriverOptions.SCROLL_JS_FUNCTION);
return DriverElement.locatorExists(this, locator);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,16 @@ public List<Element> locateAll(String locator) {
return elements;
}

@Override
public String attribute(String name) {
return driver.attribute(locator, name);
}

@Override
public String property(String name) {
return driver.property(locator, name);
}

//java bean naming conventions =============================================
//
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ public interface Element {

void setValue(String value); // setter

String attribute(String name);

String property(String name);

Finder rightOf();

Finder leftOf();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,16 @@ public List<Element> locateAll(String locator) {
return null;
}

@Override
public String attribute(String name) {
return null;
}

@Override
public String property(String name) {
return null;
}

@Override
public String getHtml() {
return null;
Expand Down
12 changes: 7 additions & 5 deletions karate-demo/src/test/java/driver/core/test-04.feature
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@ Scenario Outline: <type>
* def webUrlBase = karate.properties['web.url.base']
* configure driver = { type: '#(type)', showDriverLog: true }

* driver webUrlBase + '/page-01'
* driver webUrlBase + '/page-02'

* driver.http.path('url').post({ url: 'https://github.com' })
* delay(3000)
* def elements = locateAll('{}Click Me')
* match karate.sizeOf(elements) == 7
* elements[6].click()
* match elements[3].script('_.tagName') == 'BUTTON'


Examples:
| type |
#| chrome |
| chromedriver |
| chrome |
#| chromedriver |
#| geckodriver |
#| safaridriver |

0 comments on commit dcd0c4a

Please sign in to comment.