diff --git a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/AdditionalBrowserInteractions.java b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/AdditionalBrowserInteractions.java index 16476b103..1525e8ddf 100644 --- a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/AdditionalBrowserInteractions.java +++ b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/AdditionalBrowserInteractions.java @@ -32,5 +32,7 @@ public interface AdditionalBrowserInteractions { List filterByRegexp(List webElements, String regexp); + List filterByNearby(List webElements, WebElement target); + WebElement parentByCss(SearchContext element, String css); } diff --git a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/BrowserInjectedJavaScript.java b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/BrowserInjectedJavaScript.java index 267b07a96..22728be2a 100644 --- a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/BrowserInjectedJavaScript.java +++ b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/BrowserInjectedJavaScript.java @@ -77,6 +77,14 @@ public List filterByRegexp(List webElements, String rege webElements, regexp); } + @Override + @SuppressWarnings("unchecked") + public List filterByNearby(List webElements, WebElement target) { + injectScript(); + return (List) javascriptExecutor.executeScript(returnTwoArgFunc("filterByNearby"), + webElements, target); + } + @Override public WebElement parentByCss(SearchContext element, String css) { injectScript(); diff --git a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/PageElement.java b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/PageElement.java index db0e32d06..2a3bbd278 100644 --- a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/PageElement.java +++ b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/PageElement.java @@ -32,9 +32,8 @@ import org.testingisdocumenting.webtau.browser.page.path.filter.ByNumberPageElementsFilter; import org.testingisdocumenting.webtau.browser.page.path.filter.ByRegexpPageElementsFilter; import org.testingisdocumenting.webtau.browser.page.path.filter.ByTextPageElementsFilter; -import org.testingisdocumenting.webtau.browser.page.path.finder.ByCssPageElementFinder; -import org.testingisdocumenting.webtau.browser.page.path.finder.ParentByCssPageElementFinder; -import org.testingisdocumenting.webtau.browser.page.path.finder.ParentPageElementFinder; +import org.testingisdocumenting.webtau.browser.page.path.filter.NearbyPageElementFilter; +import org.testingisdocumenting.webtau.browser.page.path.finder.*; import org.testingisdocumenting.webtau.data.ValuePath; import org.testingisdocumenting.webtau.data.render.PrettyPrintable; import org.testingisdocumenting.webtau.data.render.PrettyPrinter; @@ -265,6 +264,10 @@ public PageElement parent(String css) { return withFinder(new ParentByCssPageElementFinder(additionalBrowserInteractions, css)); } + public PageElement nearby(PageElement target) { + return withFilter(new NearbyPageElementFilter(additionalBrowserInteractions, target)); + } + public PageElement get(String text) { return withFilter(new ByTextPageElementsFilter(additionalBrowserInteractions, text)); } diff --git a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementFinder.java b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementFinder.java index 81bcea430..a8f59887c 100644 --- a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementFinder.java +++ b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementFinder.java @@ -18,13 +18,12 @@ package org.testingisdocumenting.webtau.browser.page.path; import org.testingisdocumenting.webtau.reporter.TokenizedMessage; -import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebElement; import java.util.List; public interface PageElementFinder { - List find(SearchContext parent); + List find(PageElementPathSearchContext parent); /** * @param isFirst isFirst is this the first entry in the path diff --git a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementPath.java b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementPath.java index 9ff530e12..53da25dca 100644 --- a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementPath.java +++ b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementPath.java @@ -17,17 +17,16 @@ package org.testingisdocumenting.webtau.browser.page.path; -import org.testingisdocumenting.webtau.browser.page.path.finder.ByCssPageElementFinder; -import org.testingisdocumenting.webtau.reporter.TokenizedMessage; -import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; +import org.testingisdocumenting.webtau.browser.page.path.finder.ByCssPageElementFinder; +import org.testingisdocumenting.webtau.reporter.TokenizedMessage; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.*; public class PageElementPath { private List entries; @@ -64,16 +63,16 @@ public static PageElementPath css(String cssSelector) { } public List find(WebDriver driver) { - SearchContext root = driver; + var context = new PageElementPathSearchContext(driver, null); List webElements = Collections.emptyList(); for (PageElementPathEntry entry : entries) { - webElements = entry.find(root); + webElements = entry.find(context); if (webElements.isEmpty()) { return webElements; } - root = webElements.get(0); + context = PageElementPathSearchContext.fromElement(webElements.get(0)); } return webElements; diff --git a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementPathEntry.java b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementPathEntry.java index 9eac1f33c..1cde98a98 100644 --- a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementPathEntry.java +++ b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementPathEntry.java @@ -18,7 +18,6 @@ package org.testingisdocumenting.webtau.browser.page.path; import org.testingisdocumenting.webtau.reporter.TokenizedMessage; -import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebElement; import java.util.ArrayList; @@ -44,8 +43,8 @@ PageElementPathEntry copy() { return copy; } - List find(SearchContext parent) { - List elements = finder.find(parent); + List find(PageElementPathSearchContext searchContext) { + List elements = finder.find(searchContext); if (elements.isEmpty()) { return elements; } diff --git a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementPathSearchContext.java b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementPathSearchContext.java new file mode 100644 index 000000000..b1054c023 --- /dev/null +++ b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/PageElementPathSearchContext.java @@ -0,0 +1,30 @@ +/* + * Copyright 2023 webtau maintainers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.testingisdocumenting.webtau.browser.page.path; + +import org.openqa.selenium.SearchContext; +import org.openqa.selenium.WebElement; + +public record PageElementPathSearchContext(SearchContext searchContext, WebElement parent) { + static PageElementPathSearchContext fromElement(WebElement element) { + return new PageElementPathSearchContext(element, element); + } + + public boolean hasParent() { + return parent != null; + } +} diff --git a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/filter/NearbyPageElementFilter.java b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/filter/NearbyPageElementFilter.java new file mode 100644 index 000000000..77f4db8c4 --- /dev/null +++ b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/filter/NearbyPageElementFilter.java @@ -0,0 +1,54 @@ +/* + * Copyright 2023 webtau maintainers + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.testingisdocumenting.webtau.browser.page.path.filter; + +import org.openqa.selenium.WebElement; +import org.testingisdocumenting.webtau.browser.AdditionalBrowserInteractions; +import org.testingisdocumenting.webtau.browser.page.NullWebElement; +import org.testingisdocumenting.webtau.browser.page.PageElement; +import org.testingisdocumenting.webtau.browser.page.path.PageElementsFilter; +import org.testingisdocumenting.webtau.reporter.TokenizedMessage; + +import java.util.Collections; +import java.util.List; + +import static org.testingisdocumenting.webtau.WebTauCore.*; + +public class NearbyPageElementFilter implements PageElementsFilter { + private final AdditionalBrowserInteractions additionalBrowserInteractions; + private final PageElement target; + + public NearbyPageElementFilter(AdditionalBrowserInteractions additionalBrowserInteractions, PageElement target) { + this.additionalBrowserInteractions = additionalBrowserInteractions; + this.target = target; + } + + @Override + public List filter(List original) { + WebElement targetElement = target.findElement(); + if (targetElement instanceof NullWebElement) { + return Collections.emptyList(); + } + + return additionalBrowserInteractions.filterByNearby(original, targetElement); + } + + @Override + public TokenizedMessage description() { + return tokenizedMessage().classifier("nearby").add(target.describe()); + } +} diff --git a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ByCssPageElementFinder.java b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ByCssPageElementFinder.java index 72f826d4f..d0cf9067b 100644 --- a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ByCssPageElementFinder.java +++ b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ByCssPageElementFinder.java @@ -18,9 +18,9 @@ package org.testingisdocumenting.webtau.browser.page.path.finder; import org.testingisdocumenting.webtau.browser.page.path.PageElementFinder; +import org.testingisdocumenting.webtau.browser.page.path.PageElementPathSearchContext; import org.testingisdocumenting.webtau.reporter.TokenizedMessage; import org.openqa.selenium.By; -import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebElement; import java.util.List; @@ -35,8 +35,8 @@ public ByCssPageElementFinder(String css) { } @Override - public List find(SearchContext parent) { - return parent.findElements(By.cssSelector(css)); + public List find(PageElementPathSearchContext parent) { + return parent.searchContext().findElements(By.cssSelector(css)); } @Override diff --git a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ByRelativeAbovePageElementFinder.java b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ByRelativeAbovePageElementFinder.java new file mode 100644 index 000000000..01aebbf7c --- /dev/null +++ b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ByRelativeAbovePageElementFinder.java @@ -0,0 +1,34 @@ +/* + * Copyright 2021 webtau maintainers + * Copyright 2019 TWO SIGMA OPEN SOURCE, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.testingisdocumenting.webtau.browser.page.path.finder; + +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.locators.RelativeLocator; +import org.testingisdocumenting.webtau.browser.page.PageElement; + +import java.util.function.Function; + +public class ByRelativeAbovePageElementFinder extends ByRelativePageElementFinder { + public ByRelativeAbovePageElementFinder(PageElement target) { + super(target, "above"); + } + + protected Function direction(RelativeLocator.RelativeBy chainStart) { + return chainStart::above; + } +} diff --git a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ByRelativePageElementFinder.java b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ByRelativePageElementFinder.java new file mode 100644 index 000000000..64d34242d --- /dev/null +++ b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ByRelativePageElementFinder.java @@ -0,0 +1,69 @@ +/* + * Copyright 2021 webtau maintainers + * Copyright 2019 TWO SIGMA OPEN SOURCE, LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.testingisdocumenting.webtau.browser.page.path.finder; + +import org.openqa.selenium.By; +import org.openqa.selenium.SearchContext; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.locators.RelativeLocator; +import org.testingisdocumenting.webtau.browser.page.PageElement; +import org.testingisdocumenting.webtau.browser.page.path.PageElementFinder; +import org.testingisdocumenting.webtau.browser.page.path.PageElementPathSearchContext; +import org.testingisdocumenting.webtau.reporter.TokenizedMessage; + +import java.util.List; +import java.util.function.Function; + +import static org.testingisdocumenting.webtau.WebTauCore.*; + +abstract public class ByRelativePageElementFinder implements PageElementFinder { + private final PageElement target; + private final String classifier; + + public ByRelativePageElementFinder(PageElement target, String classifier) { + this.target = target; + this.classifier = classifier; + } + + abstract protected Function direction(RelativeLocator.RelativeBy chainStart); + + @Override + public List find(PageElementPathSearchContext parent) { + RelativeLocator.RelativeBy chainStart = RelativeLocator.with(new ByAdapter(parent.parent())); + RelativeLocator.RelativeBy relativeBy = direction(chainStart).apply(target.findElement()); + return parent.searchContext().findElements(relativeBy); + } + + @Override + public TokenizedMessage description(boolean isFirst) { + return tokenizedMessage().selectorType(classifier).add(target.describe()); + } + + static private class ByAdapter extends By { + private final WebElement parent; + + public ByAdapter(WebElement parent) { + this.parent = parent; + } + + @Override + public List findElements(SearchContext context) { + return List.of(parent); + } + } +} diff --git a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ByXPathPageElementFinder.java b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ByXPathPageElementFinder.java index 755a37b04..9df658663 100644 --- a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ByXPathPageElementFinder.java +++ b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ByXPathPageElementFinder.java @@ -17,9 +17,9 @@ package org.testingisdocumenting.webtau.browser.page.path.finder; import org.openqa.selenium.By; -import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebElement; import org.testingisdocumenting.webtau.browser.page.path.PageElementFinder; +import org.testingisdocumenting.webtau.browser.page.path.PageElementPathSearchContext; import org.testingisdocumenting.webtau.reporter.TokenizedMessage; import java.util.List; @@ -34,8 +34,8 @@ public ByXPathPageElementFinder(String xPath) { } @Override - public List find(SearchContext parent) { - return parent.findElements(By.xpath(xPath)); + public List find(PageElementPathSearchContext parent) { + return parent.searchContext().findElements(By.xpath(xPath)); } @Override diff --git a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ParentByCssPageElementFinder.java b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ParentByCssPageElementFinder.java index f37da2706..6b1693f4f 100644 --- a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ParentByCssPageElementFinder.java +++ b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ParentByCssPageElementFinder.java @@ -16,10 +16,10 @@ package org.testingisdocumenting.webtau.browser.page.path.finder; -import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebElement; import org.testingisdocumenting.webtau.browser.AdditionalBrowserInteractions; import org.testingisdocumenting.webtau.browser.page.path.PageElementFinder; +import org.testingisdocumenting.webtau.browser.page.path.PageElementPathSearchContext; import org.testingisdocumenting.webtau.reporter.TokenizedMessage; import java.util.Collections; @@ -37,8 +37,8 @@ public ParentByCssPageElementFinder(AdditionalBrowserInteractions additionalBrow } @Override - public List find(SearchContext parent) { - WebElement webElement = additionalBrowserInteractions.parentByCss(parent, css); + public List find(PageElementPathSearchContext parent) { + WebElement webElement = additionalBrowserInteractions.parentByCss(parent.searchContext(), css); return webElement == null ? Collections.emptyList() : Collections.singletonList(webElement); } diff --git a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ParentPageElementFinder.java b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ParentPageElementFinder.java index c9bc8d3c3..05351c961 100644 --- a/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ParentPageElementFinder.java +++ b/webtau-browser/src/main/java/org/testingisdocumenting/webtau/browser/page/path/finder/ParentPageElementFinder.java @@ -17,9 +17,9 @@ package org.testingisdocumenting.webtau.browser.page.path.finder; import org.openqa.selenium.By; -import org.openqa.selenium.SearchContext; import org.openqa.selenium.WebElement; import org.testingisdocumenting.webtau.browser.page.path.PageElementFinder; +import org.testingisdocumenting.webtau.browser.page.path.PageElementPathSearchContext; import org.testingisdocumenting.webtau.reporter.TokenizedMessage; import java.util.List; @@ -28,8 +28,8 @@ public class ParentPageElementFinder implements PageElementFinder { @Override - public List find(SearchContext parent) { - return parent.findElements(By.xpath("..")); + public List find(PageElementPathSearchContext parent) { + return parent.searchContext().findElements(By.xpath("..")); } @Override diff --git a/webtau-browser/src/main/resources/browser/injection.js b/webtau-browser/src/main/resources/browser/injection.js index 8f8038f30..6163b6961 100644 --- a/webtau-browser/src/main/resources/browser/injection.js +++ b/webtau-browser/src/main/resources/browser/injection.js @@ -56,20 +56,34 @@ window._webtau = } function filterByText(webElements, text) { - return filterBy(webElements, function (textValue) { + return filterByTextVaue(webElements, function (textValue) { return textValue === text; }); } + function filterByNearby(webElements, target) { + var result = []; + var idx = 0; + var len = webElements.length; + + for (; idx < len; idx++) { + if (isNearby(webElements[idx], target, 50)) { + result.push(webElements[idx]); + } + } + + return result; + } + function filterByRegexp(webElements, regexpText) { var regexp = new RegExp(regexpText); - return filterBy(webElements, function (textValue) { + return filterByTextVaue(webElements, function (textValue) { return regexp.test(textValue); }); } - function filterBy(webElements, predicate) { + function filterByTextVaue(webElements, predicate) { var metas = elementsDetails(webElements); var result = []; var idx = 0; @@ -97,13 +111,47 @@ window._webtau = } } + function isNearby(elA, elB, maxDistance) { + var a = elA.getBoundingClientRect(); + var b = elB.getBoundingClientRect(); + + var cornersA = [ + [a.x, a.y], + [a.x + a.width, a.y], + [a.x, a.y + a.height], + [a.x + a.width, a.y + a.height], + ]; + + var cornersB = [ + [b.x, b.y], + [b.x + b.width, b.y], + [b.x, b.y + b.height], + [b.x + b.width, b.y + b.height], + ]; + + var minDistance = 10000 + maxDistance; + for (var i = 0; i < cornersA.length; i++) + for (var j = 0; j < cornersB.length; j++) { + var cornerA = cornersA[i]; + var cornerB = cornersB[j]; + const distance = Math.sqrt( + Math.pow(cornerB[0] - cornerA[0], 2) + + Math.pow(cornerB[1] - cornerA[1], 2) + ); + + if (distance < minDistance) { + minDistance = distance; + } + } + + return minDistance <= maxDistance; + } + function findByParentCss(webElement, css) { if (!webElement || !webElement.parentElement) { - console.log("@@inside"); return undefined; } - console.log("@@outside"); return webElement.parentElement.closest(css); } @@ -184,5 +232,6 @@ window._webtau = filterByRegexp: filterByRegexp, findByParentCss: findByParentCss, flashElements: flashElements, + filterByNearby: filterByNearby, }; })(); diff --git a/webtau-browser/src/test/java/org/testingisdocumenting/webtau/FakeAdditionalBrowserInteractions.java b/webtau-browser/src/test/java/org/testingisdocumenting/webtau/FakeAdditionalBrowserInteractions.java index 135e8019d..dfbe1d77a 100644 --- a/webtau-browser/src/test/java/org/testingisdocumenting/webtau/FakeAdditionalBrowserInteractions.java +++ b/webtau-browser/src/test/java/org/testingisdocumenting/webtau/FakeAdditionalBrowserInteractions.java @@ -54,6 +54,11 @@ public List filterByRegexp(List webElements, String rege return Collections.emptyList(); } + @Override + public List filterByNearby(List webElements, WebElement target) { + return Collections.emptyList(); + } + @Override public WebElement parentByCss(SearchContext element, String css) { return null; diff --git a/webtau-docs/znai/browser/finders-and-filters.md b/webtau-docs/znai/browser/finders-and-filters.md index 683b4f79b..afcb1ba0d 100644 --- a/webtau-docs/znai/browser/finders-and-filters.md +++ b/webtau-docs/znai/browser/finders-and-filters.md @@ -32,26 +32,31 @@ Note: declaring element this way will not trigger element search right away. :include-xml: doc-artifacts/snippets/finders-filters/flat-menu.html {paths: ["ul.li[0].a", "ul.li[1].a", "ul.li[2].a"]} -# Filters +# Basic Filters You can use filters to narrow down elements selected by finders. -Filter comes in a way of `get` method. Parameter is one of the following +Use `get` method to filter found elements by * Element number * Element text * Element regexp -:include-file: doc-artifacts/snippets/finders-filters/byCssAndFilterByNumber.groovy { title: "Number" } -:include-file: doc-artifacts/snippets/finders-filters/byCssAndFilterByText.groovy { title: "Text" } -:include-file: doc-artifacts/snippets/finders-filters/byCssAndFilterByRegexp.groovy { title: "Regexp" } +:include-file: doc-artifacts/snippets/finders-filters/byCssAndFilterByNumber.groovy { title: "number" } +:include-file: doc-artifacts/snippets/finders-filters/byCssAndFilterByText.groovy { title: "text" } +:include-file: doc-artifacts/snippets/finders-filters/byCssAndFilterByRegexp.groovy { title: "regexp" } :include-xml: doc-artifacts/snippets/finders-filters/flat-menu.html {rightSide: true, paths: ["ul.li[1].a"]} +# Filter By Distance + +:include-file: doc-artifacts/snippets/finders-filters/byGeometry.groovy { title: "nearby filter", surroundedBy: "nearby-example" } +:include-xml: doc-artifacts/snippets/finders-filters/relative-selections.html {rightSide: true, paths: ["div.button[2]"]} + # Chaining After you filtered, you can use finders again to find nested elements. -:include-file: doc-artifacts/snippets/finders-filters/byCssAndFilterByNumberNestedFind.groovy { title: "Nested css selector" } +:include-file: doc-artifacts/snippets/finders-filters/byCssAndFilterByNumberNestedFind.groovy { title: "nested css selector" } :include-xml: doc-artifacts/snippets/finders-filters/flat-menu.html {rightSide: true, paths: ["ul.li[1].a"]} diff --git a/webtau-docs/znai/release-notes/2.3/add-2023-10-03-browser-nearby.md b/webtau-docs/znai/release-notes/2.3/add-2023-10-03-browser-nearby.md new file mode 100644 index 000000000..413a22e9c --- /dev/null +++ b/webtau-docs/znai/release-notes/2.3/add-2023-10-03-browser-nearby.md @@ -0,0 +1 @@ +* Add: [Nearby](browser/finders-and-filters#filter-by-distance) browser filter \ No newline at end of file diff --git a/webtau-feature-testing/examples/scenarios/ui/findersFilters.groovy b/webtau-feature-testing/examples/scenarios/ui/findersFilters.groovy index 3b3c6d5c4..143d3c42c 100644 --- a/webtau-feature-testing/examples/scenarios/ui/findersFilters.groovy +++ b/webtau-feature-testing/examples/scenarios/ui/findersFilters.groovy @@ -66,3 +66,15 @@ scenario("parent by css can't find") { mainWrapper.attribute("class").should == null } + +scenario("filter by geometry") { + // nearby-example + def button = $("button") + def helloMessage = $("#hello-message") + + button.nearby(helloMessage).should == "World2" + // nearby-example + // nearby-chain-example + button.get(~/World/).nearby(helloMessage).should == "World2" + // nearby-chain-example +} diff --git a/webtau-feature-testing/src/test/groovy/org/testingisdocumenting/webtau/featuretesting/WebTauBrowserFeaturesTestBase.groovy b/webtau-feature-testing/src/test/groovy/org/testingisdocumenting/webtau/featuretesting/WebTauBrowserFeaturesTestBase.groovy index 295def27f..d33552abb 100644 --- a/webtau-feature-testing/src/test/groovy/org/testingisdocumenting/webtau/featuretesting/WebTauBrowserFeaturesTestBase.groovy +++ b/webtau-feature-testing/src/test/groovy/org/testingisdocumenting/webtau/featuretesting/WebTauBrowserFeaturesTestBase.groovy @@ -147,6 +147,7 @@ class WebTauBrowserFeaturesTestBase { "byCssAndFilterByText.groovy": "by css and filter by text", "byCssAndFilterByRegexp.groovy": "by css and filter by regexp", "byCssAndFilterByNumberNestedFind.groovy": "by css and filter by number and nested css", + "byGeometry.groovy": "filter by geometry", "byParent.groovy": "immediate parent", "byParentCss.groovy": "parent by css", ]) @@ -154,6 +155,7 @@ class WebTauBrowserFeaturesTestBase { extractHtmlSnippets(root, "finders-and-filters.html", [ "welcome.html": "#welcome-wrapper", "welcome-wrapper.html": "#welcome-top-wrapper", + "relative-selections.html": "#relative-selections", "welcome-wrapper-wrapper.html": "#welcome-top-wrapper-wrapper", "flat-menu.html": "#menu" ]) diff --git a/webtau-feature-testing/src/test/resources/finders-and-filters.html b/webtau-feature-testing/src/test/resources/finders-and-filters.html index c8696c6ad..a4f5c487b 100644 --- a/webtau-feature-testing/src/test/resources/finders-and-filters.html +++ b/webtau-feature-testing/src/test/resources/finders-and-filters.html @@ -1,4 +1,5 @@ - +
@@ -59,5 +60,14 @@ of CSS
+
+
+ + +
block
+

hello message

+ +
+
\ No newline at end of file diff --git a/webtau-feature-testing/test-expectations/scenarios/ui/findersFilters/chrome-run-details.json b/webtau-feature-testing/test-expectations/scenarios/ui/findersFilters/chrome-run-details.json index bd6211206..310bc3967 100644 --- a/webtau-feature-testing/test-expectations/scenarios/ui/findersFilters/chrome-run-details.json +++ b/webtau-feature-testing/test-expectations/scenarios/ui/findersFilters/chrome-run-details.json @@ -77,6 +77,12 @@ "stepsSummary" : { "numberOfSuccessful" : 1 } + }, { + "scenario" : "filter by geometry", + "shortContainerId" : "findersFilters.groovy", + "stepsSummary" : { + "numberOfSuccessful" : 2 + } } ], "exitCode" : 0 } \ No newline at end of file diff --git a/webtau-feature-testing/test-expectations/scenarios/ui/findersFilters/firefox-run-details.json b/webtau-feature-testing/test-expectations/scenarios/ui/findersFilters/firefox-run-details.json index bd6211206..310bc3967 100644 --- a/webtau-feature-testing/test-expectations/scenarios/ui/findersFilters/firefox-run-details.json +++ b/webtau-feature-testing/test-expectations/scenarios/ui/findersFilters/firefox-run-details.json @@ -77,6 +77,12 @@ "stepsSummary" : { "numberOfSuccessful" : 1 } + }, { + "scenario" : "filter by geometry", + "shortContainerId" : "findersFilters.groovy", + "stepsSummary" : { + "numberOfSuccessful" : 2 + } } ], "exitCode" : 0 } \ No newline at end of file