Skip to content

Commit 44aa819

Browse files
committed
Add docs
1 parent 6f503cc commit 44aa819

File tree

4 files changed

+136
-18
lines changed

4 files changed

+136
-18
lines changed

docs/modules/plugins/partials/plugin-web-app-locators.adoc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ This locator type is deprecated and will be removed in VIVIDUS 0.7.0. Use `name`
9393
|chain of css selectors, separated by `;`, where first value - selector for upper shadow host, last value - target element selector
9494
|shadowCssSelector(.upperHost; #innerHost1; #innerHost2; .targetValue)
9595

96+
|`relative`
97+
|https://www.selenium.dev/documentation/webdriver/elements/locators/#relative-locators[Selenium Relative Locators] allow to find web elements based on their position relative to other elements, making it easier to target elements in dynamic or complex layouts.
98+
99+
More detailed information with examples can be found in the xref:plugins:partial$plugin-web-app-relative-locators.adoc[Relative Locators] section.
100+
|relative(id(element)>>below(id(title))
101+
96102
|===
97103

98104
include::partial$visibility-types.adoc[]
@@ -182,3 +188,5 @@ This filter type is deprecated and will be removed in VIVIDUS 0.7.0.
182188
|id(v1)->filter.dropDownText(value)
183189

184190
|===
191+
192+
include::plugins:partial$plugin-web-app-relative-locators.adoc[]
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
=== Relative Locators
2+
3+
Relative locators enable finding elements based on their relationship to other elements on the page.
4+
This simplifies working with dynamic layouts by allowing flexible and context-aware element identification.
5+
6+
==== Relative locator format
7+
----
8+
By.relative([rootElementLocator]>>relativePosition([relativeElementLocator])):[visibility]->filter.[filterType]([filterValue])
9+
----
10+
11+
[IMPORTANT]
12+
By. prefix is optional.
13+
14+
[WARNING]
15+
====
16+
Root element locator type can be only: id, cssSelector, xPath, unnormalizedXPath, tagName, className, caseInsensitiveText, imageSrc, imageSrcPart, fieldName, radioButton, shadowCssSelector
17+
====
18+
19+
. `rootElementLocator` - *[mandatory]* common VIVIDUS locator for elements to find
20+
. `relativePosition` - *[mandatory]* how root elements placed against relative element. See the table below
21+
. `relativeElementLocator` - *[mandatory]* common VIVIDUS locator for elements to find. Supports all VIVIDUS locator types.
22+
. `visibility` - *[optional]* visibility of root elements (visible by default)
23+
. `filterType` - *[optional]* type of the filter for root elements
24+
. `filterValue` - *[required if filter type defined]* value of the filter
25+
26+
.Locate elements by xpath = '//div' placed below relative element with id = 'title'
27+
----
28+
relative(xpath(//div)>>below(id(title)))
29+
----
30+
31+
You can also chain locators if needed. Sometimes the element is most easily identified as being both above/below one element and right/left of another.
32+
33+
.Chaining relative locators
34+
----
35+
relative(xpath(//div)>>below(className(header))>>toRightOf(id(left_menu))>>above(xpath(//div[@testId='footer'])))
36+
----
37+
38+
[cols="2,3,3", options="header", title="Supported relative positions"]
39+
|===
40+
41+
|Relative position
42+
|Example
43+
|Description
44+
45+
|`above`
46+
|relative(xpath(//div)>>above(id(bottom_block)))
47+
|Locates elements matching xpath `//div` and placed *above* of relative element with id = bottom_block
48+
49+
|`below`
50+
|relative(xpath(//div)>>below(id(top_block)))
51+
|Locates elements matching xpath `//div` and placed *below* of relative element with id = top_block
52+
53+
|`toLeftOf`
54+
|relative(xpath(//div)>>toLeftOf(id(right_block)))
55+
|Locates elements matching xpath `//div` and placed *to the left of* relative element with id = right_block
56+
57+
|`toRightOf`
58+
|relative(xpath(//div)>>toRightOf(id(left_block)))
59+
|Locates elements matching xpath `//div` and placed *to the right of* relative element with id = left_block
60+
61+
|`near`
62+
|relative(xpath(//div)>>near(id(near_block)))
63+
|Locates elements matching xpath `//div` and placed at most *50px* away (in any direction) from the relative element with id = near_block
64+
65+
|`nearXpx`
66+
|relative(xpath(//div)>>near200px(id(distant_block)))
67+
|Provide possibility to configure max distance between near elements.
68+
69+
Locates elements matching xpath `//div` and placed at most *200px* away (in any direction) from the relative element with id = distant_block
70+
71+
|===
72+
73+
==== Examples
74+
75+
.Verify a number of elements with xpath = `//div` placed relative to other elements
76+
[source,gherkin]
77+
----
78+
Then number of elements found by `relative(xpath(//div)>>below(id(title)))` is = `1`
79+
Then number of elements found by `relative(xpath(//div)>>toLeftOf(id(right_image)))` is = `3`
80+
----
81+
82+
.Verify that two elements aren't placed in the specific relative position
83+
[source,gherkin]
84+
----
85+
Then number of elements found by `id(block1)` is = `1`
86+
Then number of elements found by `id(block2)` is = `1`
87+
Then number of elements found by `relative(id(block1)>>toRightOf(id(block2)))` is = `0`
88+
----
89+
90+
.Different locator types in the relative locators
91+
[source,gherkin]
92+
----
93+
Then number of elements found by `relative(id(block1)>>toLeftOf(className(item2)))` is = `1`
94+
Then number of elements found by `relative(className(item1)>>toLeftOf(cssSelector(.item2)))` is = `1`
95+
Then number of elements found by `relative(xpath(//div[@id='block1'])>>toLeftOf(name(item2)))` is = `1`
96+
----
97+
98+
.Verify number of invisible elements with xpath = '//div' and placed at the right of element with id = 'left-menu'
99+
[source,gherkin]
100+
----
101+
Then number of elements found by `relative(xpath(//div)>>toRightOf(id(left-menu))):i` is = `1`
102+
----
103+
104+
.Verify number of elements with xpath = '//div' and text part = 'some text' placed at the right of element with id = 'left-menu'
105+
[source,gherkin]
106+
----
107+
Then number of elements found by `relative(xpath(//div)>>toRightOf(id(left-menu)))->filter.textPart(some text)` is = `1``1`
108+
----
109+
110+
.Apply filter to the inner relative element locator
111+
[source,gherkin]
112+
----
113+
Then number of elements found by `relative(xpath(//div)>>above(xpath(//a)->filter.linkUrlPart(links)))` is = `1`
114+
----

vividus-plugin-web-app/src/main/java/org/vividus/ui/web/action/search/RelativeElementSearch.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,11 @@ public class RelativeElementSearch extends AbstractWebElementSearchAction implem
5555
private StringToLocatorConverter converter;
5656
private IBaseValidations baseValidations;
5757

58-
public RelativeElementSearch()
58+
public RelativeElementSearch(StringToLocatorConverter converter, IBaseValidations baseValidations)
5959
{
6060
super(WebLocatorType.RELATIVE);
61+
this.converter = converter;
62+
this.baseValidations = baseValidations;
6163
}
6264

6365
@Override
@@ -203,13 +205,13 @@ private RelativeLocator.RelativeBy applyRelativeNearPosition(RelativeLocator.Rel
203205
+ " Expected matches [%s]. Actual [%s]", NEAR_XPX_PATTERN, relativePositionString));
204206
}
205207

206-
public void setConverter(StringToLocatorConverter converter)
207-
{
208-
this.converter = converter;
209-
}
210-
211-
public void setBaseValidations(IBaseValidations baseValidations)
212-
{
213-
this.baseValidations = baseValidations;
214-
}
208+
// public void setConverter(StringToLocatorConverter converter)
209+
// {
210+
// this.converter = converter;
211+
// }
212+
//
213+
// public void setBaseValidations(IBaseValidations baseValidations)
214+
// {
215+
// this.baseValidations = baseValidations;
216+
// }
215217
}

vividus-plugin-web-app/src/main/resources/vividus-plugin/spring.xml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,8 @@
9393
<bean id="abstractStateFilter" class="org.vividus.ui.web.action.search.AbstractStateFilter"
9494
abstract="true" />
9595

96-
<bean class="org.vividus.ui.web.action.search.RelativeElementSearch" parent="abstractWebElementSearchAction" >
97-
<property name="converter" >
98-
<bean class="org.vividus.spring.StringToLocatorConverter" />
99-
</property>
100-
<property name="baseValidations">
101-
<bean class="org.vividus.steps.ui.validation.BaseValidations" />
102-
</property>
103-
</bean>
96+
<bean class="org.vividus.spring.StringToLocatorConverter" />
97+
<bean class="org.vividus.ui.web.action.search.RelativeElementSearch" parent="abstractWebElementSearchAction" />
10498

10599
<bean class="org.vividus.ui.web.action.search.LinkTextSearch" parent="abstractWebElementSearchAction" />
106100
<bean class="org.vividus.ui.web.action.search.LinkUrlPartSearch" parent="abstractWebElementSearchAction">

0 commit comments

Comments
 (0)