Skip to content

Locators

Locators are special mechanisms used to find elements on a web page. They allow to locate specific elements such as buttons, input fields, or links to interact with them.

The Selenium webdriver methods use tuples (By, query) to find elements, where By is one of the supported locator strategies and query is the query for that strategy. Read about Selenium supported locator strategies.

Pomcorn implements its own classes for defining web page elements - Locators. XPath was chosen as the only strategy because it eliminated the need to specify the type of strategy and also made it easier to create relative locators.

Note

Others prefer NOT to use XPath because the DOM can change frequently and tests will crash. Therefore, to make the tests more stable, we have implemented a number of locators that follow the same logic as the other strategies (search by css, by tag name, by classes, by properties, etc.), but based on XPath.

Interfaces

classDiagram
  Locator <|-- XPathLocator
  XPathLocator <|-- TInitLocator
  XPathLocator <|-- TLocator
  XPathLocator <|-- ElementWithTextLocator
  XPathLocator <|-- InputByLabelLocator
  XPathLocator <|-- PropertyLocator
  XPathLocator <|-- TagNameLocator
  XPathLocator <|-- TextAreaByLabelLocator

  PropertyLocator <|-- ClassLocator
  PropertyLocator <|-- DataTestIdLocator
  PropertyLocator <|-- IdLocator
  PropertyLocator <|-- NameLocator
  ElementWithTextLocator <|-- ButtonWithTextLocator
  • you can zoom it

Base locator for looking for elements in page.

Source code in pomcorn/locators/base_locators.py
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
class Locator:
    """Base locator for looking for elements in page."""

    _ALLOWED_LOCATORS = (
        By.ID,
        By.XPATH,
        By.LINK_TEXT,
        By.PARTIAL_LINK_TEXT,
        By.NAME,
        By.TAG_NAME,
        By.CLASS_NAME,
        By.CSS_SELECTOR,
    )

    def __init__(self, by: str, query: str):
        """Init locator.

        Args:
            by: One of the supported selenium locator strategies.
            query: Query for the strategy.

        """
        if by not in self._ALLOWED_LOCATORS:
            raise ValueError(f"No valid `by` found -> `{by}`")
        self.by = by
        self.query: str = query

    def __iter__(self) -> Iterator[str]:
        """Unpack locator.

        This is necessary because selenium WebDriver methods use
        `By` and `value` tuples to find elements. Thanks to this we can use
        `*locator` for these methods.

        """
        return iter((self.by, self.query))

    def __repr__(self) -> str:
        return f"Locator<By `{self.by}`: Query `{self.query}`>"

    def __str__(self) -> str:
        return self.query

__init__(by, query)

Init locator.

Parameters:

Name Type Description Default
by str

One of the supported selenium locator strategies.

required
query str

Query for the strategy.

required
Source code in pomcorn/locators/base_locators.py
36
37
38
39
40
41
42
43
44
45
46
47
def __init__(self, by: str, query: str):
    """Init locator.

    Args:
        by: One of the supported selenium locator strategies.
        query: Query for the strategy.

    """
    if by not in self._ALLOWED_LOCATORS:
        raise ValueError(f"No valid `by` found -> `{by}`")
    self.by = by
    self.query: str = query

__iter__()

Unpack locator.

This is necessary because selenium WebDriver methods use By and value tuples to find elements. Thanks to this we can use *locator for these methods.

Source code in pomcorn/locators/base_locators.py
49
50
51
52
53
54
55
56
57
def __iter__(self) -> Iterator[str]:
    """Unpack locator.

    This is necessary because selenium WebDriver methods use
    `By` and `value` tuples to find elements. Thanks to this we can use
    `*locator` for these methods.

    """
    return iter((self.by, self.query))

Bases: Locator

Locator to looking for elements in page by XPath.

XPathLocator overrides methods for / and // operators to provide "path-like" syntax for locators.

So we can use / and // operators to concatenate locators query by / and // accordingly:

# //\*[@class="class"]

class_locator = ClassLocator("class")

# //container[@prop="value"]

property_locator = PropertyLocator(
    prop="prop",
    value="value",
    container="container",

)

# //\*[@class="class"]/container[@prop="value"]

class_locator / property_locator

# //\*[@class="class"]//container[@prop="value"]

class_locator // property_locator

To extend query of locator you can use extend_query method: new_locator = class_locator.extend_query("[@some_prop='value']")

new_locator.query   # //\*[@class="class"][@some_prop="value"]

All custom locators that inherit XPathLocator should be independent and start with //.

Source code in pomcorn/locators/base_locators.py
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
class XPathLocator(Locator):
    r"""Locator to looking for elements in page by XPath.

    XPathLocator overrides methods for `/` and `//` operators to provide
    "path-like" syntax for locators.

    So we can use `/` and `//` operators to concatenate locators query by `/`
    and `//` accordingly:

        # //\*[@class="class"]

        class_locator = ClassLocator("class")

        # //container[@prop="value"]

        property_locator = PropertyLocator(
            prop="prop",
            value="value",
            container="container",

        )

        # //\*[@class="class"]/container[@prop="value"]

        class_locator / property_locator

        # //\*[@class="class"]//container[@prop="value"]

        class_locator // property_locator

    To extend query of locator you can use `extend_query` method:
        new_locator = class_locator.extend_query("[@some_prop='value']")

        new_locator.query   # //\*[@class="class"][@some_prop="value"]

    All custom locators that inherit `XPathLocator` should be independent and
    start with `//`.

    """

    # We move it to constant to fix flake-8 warning B005:
    # https://pypi.org/project/flake8-bugbear/#:~:text=B005
    divider = "//"

    def __init__(self, query: str):
        """Set related query for locators concatenation.

        Args:
            query: Query for the XPath locator strategy.

        """
        self.related_query = query.lstrip(self.divider)
        super().__init__(by=By.XPATH, query=query)

    def __truediv__(self, other: XPathLocator | str) -> XPathLocator:
        """Override `/` operator to implement following XPath locators.

        "/" used to select the nearest children of the current node.

        """
        return self.prepare_relative_locator(other=other, separator="/")

    def __floordiv__(self, other: XPathLocator | str) -> XPathLocator:
        """Override `//` operator to implement nested XPath locators.

        "//" used to select all descendants (children, grandchildren,
        great-grandchildren, etc.) of current node, regardless of their level
        in hierarchy.

        """
        return self.prepare_relative_locator(other=other, separator="//")

    def __or__(self, other: XPathLocator) -> XPathLocator:
        r"""Override `|` operator to implement variant XPath locators.

        Example:
            span = XPathLocator("//span")
            div = XPathLocator("//div")
            img = XPathLocator("//img")

            (span | div) // img == XPathLocator("(//span | //div)//img")

            span | div // img == XPathLocator("(//span | //div//img)")

        """
        return XPathLocator(query=f"({self.query} | {other.query})")

    def __getitem__(self, value: int | str | XPathLocator) -> XPathLocator:
        """Allow to set xpath expressions or index into the locator query.

        Examples:
            div_locator = XPathLocator("//div") --> `//div`

            # Indexation
            div_locator[0]  --> `(//div)[1]`   # xpath numeration starts with 1
            div_locator[-1] --> `(//div)[last()]`

            # Attribute condition
            div_locator["@type='black'"] --> `//div[@type='black']

            # Checking if there are children
            child_locator = XPathLocator("//label").contains("Schedule")
                --> `//label[contains(., 'Star']`
            div_locator[child_locator] --> `//div[//label[contains(., 'Star']]`

        """
        query = f"({self.query})"

        if isinstance(value, XPathLocator):
            value = value.query

        if isinstance(value, str):
            return XPathLocator(f"{query}[{value}]")

        if value >= 0:
            # `+1` is used here because numeration in xpath starts with 1
            query += f"[{value + 1}]"
        elif value == -1:
            # To avoid ugly locators with `...)[last() - 0]`
            query += "[last()]"
        else:
            query += f"[last() - {abs(value + 1)}]"

        return XPathLocator(query)

    def __bool__(self) -> bool:
        """Return whether query of current locator is empty or not."""
        return bool(self.related_query)

    @classmethod
    def _escape_quotes(cls, text: str) -> str:
        """Escape single and double quotes in given text for use in locators.

        This method is useful when locating elements
        with text containing single or double quotes.

        For example, the text `He's 6'2"` will be transformed into:
        `concat("He", "'", "s 6", "'", "2", '"')`.

        The resulting string can be used in XPath expressions
        like `text()=...` or `contains(.,...)`.

        Returns:
            The escaped text wrapped in `concat()` for XPath compatibility,
            or the original text in double quotes if no escaping is needed.

        """
        if not text or ('"' not in text and "'" not in text):
            return f'"{text}"'

        escaped_parts = []
        buffer = ""  # Temporary storage for normal characters

        for char in text:
            if char not in ('"', "'"):
                buffer += char
                continue
            if buffer:
                escaped_parts.append(f'"{buffer}"')
                buffer = ""
            escaped_parts.append(
                "'" + char + "'" if char == '"' else '"' + char + '"',
            )

        if buffer:
            escaped_parts.append(f'"{buffer}"')

        return f"concat({', '.join(escaped_parts)})"

    def extend_query(self, extra_query: str) -> XPathLocator:
        """Return new XPathLocator with extended query."""
        return XPathLocator(query=self.query + extra_query)

    def contains(self, text: str, exact: bool = False) -> XPathLocator:
        """Return new XPathLocator with search on contained text.

        This is shortcut for the commonly used
        `.extend_query(f"[contains(., '{text}')])`.

        Args:
            text: The text that should be inside the tag.
            exact: Specify whether the text being searched must match exactly.
                By default, the search is based on a partial match.

        """
        partial_query = f"[contains(., {self._escape_quotes(text)})]"
        exact_query = f"[./text()={self._escape_quotes(text)}]"
        return self.extend_query(exact_query if exact else partial_query)

    def prepare_relative_locator(
        self,
        other: XPathLocator | str,
        separator: Literal["/", "//"] = "/",
    ) -> XPathLocator:
        """Prepare relative locator base on queries of two locators.

        If one of parent and other locator queries is empty, the method will
        return only the filled one.

        Args:
            other: Child locator object or str locator query.
            separator: Literal which will placed between locators queries - "/"
                used to select nearest children of current node and "//" used
                to select all descendants (children, grandchildren,
                great-grandchildren, etc.) of current node, regardless of their
                level in hierarchy.

        Raises:
            ValueError: If parent and child locators queries are empty.

        """
        related_query = self.related_query
        if not related_query.startswith("("):
            # Parent query can be bracketed, in which case we don't need to use
            # `//`
            # Example:
            #   (//li)[3] -> valid
            #   //(//li)[3] -> invalid
            related_query = f"//{self.related_query}"

        other = XPathLocator(other) if isinstance(other, str) else other

        locator = XPathLocator(
            query=f"{related_query}{separator}{other.related_query}",
        )

        if self and other:
            return locator

        if not (self or other):
            raise ValueError(
                f"Both of locators have empty query. The `{locator.query}` is "
                "not a valid locator.",
            )

        return self or other

__bool__()

Return whether query of current locator is empty or not.

Source code in pomcorn/locators/base_locators.py
198
199
200
def __bool__(self) -> bool:
    """Return whether query of current locator is empty or not."""
    return bool(self.related_query)

__floordiv__(other)

Override // operator to implement nested XPath locators.

"//" used to select all descendants (children, grandchildren, great-grandchildren, etc.) of current node, regardless of their level in hierarchy.

Source code in pomcorn/locators/base_locators.py
135
136
137
138
139
140
141
142
143
def __floordiv__(self, other: XPathLocator | str) -> XPathLocator:
    """Override `//` operator to implement nested XPath locators.

    "//" used to select all descendants (children, grandchildren,
    great-grandchildren, etc.) of current node, regardless of their level
    in hierarchy.

    """
    return self.prepare_relative_locator(other=other, separator="//")

__getitem__(value)

Allow to set xpath expressions or index into the locator query.

Examples:

div_locator = XPathLocator("//div") --> //div

Indexation

div_locator[0] --> (//div)[1] # xpath numeration starts with 1 div_locator[-1] --> (//div)[last()]

Attribute condition

div_locator["@type='black'"] --> `//div[@type='black']

Checking if there are children

child_locator = XPathLocator("//label").contains("Schedule") --> //label[contains(., 'Star'] div_locator[child_locator] --> //div[//label[contains(., 'Star']]

Source code in pomcorn/locators/base_locators.py
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
def __getitem__(self, value: int | str | XPathLocator) -> XPathLocator:
    """Allow to set xpath expressions or index into the locator query.

    Examples:
        div_locator = XPathLocator("//div") --> `//div`

        # Indexation
        div_locator[0]  --> `(//div)[1]`   # xpath numeration starts with 1
        div_locator[-1] --> `(//div)[last()]`

        # Attribute condition
        div_locator["@type='black'"] --> `//div[@type='black']

        # Checking if there are children
        child_locator = XPathLocator("//label").contains("Schedule")
            --> `//label[contains(., 'Star']`
        div_locator[child_locator] --> `//div[//label[contains(., 'Star']]`

    """
    query = f"({self.query})"

    if isinstance(value, XPathLocator):
        value = value.query

    if isinstance(value, str):
        return XPathLocator(f"{query}[{value}]")

    if value >= 0:
        # `+1` is used here because numeration in xpath starts with 1
        query += f"[{value + 1}]"
    elif value == -1:
        # To avoid ugly locators with `...)[last() - 0]`
        query += "[last()]"
    else:
        query += f"[last() - {abs(value + 1)}]"

    return XPathLocator(query)

__init__(query)

Set related query for locators concatenation.

Parameters:

Name Type Description Default
query str

Query for the XPath locator strategy.

required
Source code in pomcorn/locators/base_locators.py
117
118
119
120
121
122
123
124
125
def __init__(self, query: str):
    """Set related query for locators concatenation.

    Args:
        query: Query for the XPath locator strategy.

    """
    self.related_query = query.lstrip(self.divider)
    super().__init__(by=By.XPATH, query=query)

__or__(other)

Override | operator to implement variant XPath locators.

Example

span = XPathLocator("//span") div = XPathLocator("//div") img = XPathLocator("//img")

(span | div) // img == XPathLocator("(//span | //div)//img")

span | div // img == XPathLocator("(//span | //div//img)")

Source code in pomcorn/locators/base_locators.py
145
146
147
148
149
150
151
152
153
154
155
156
157
158
def __or__(self, other: XPathLocator) -> XPathLocator:
    r"""Override `|` operator to implement variant XPath locators.

    Example:
        span = XPathLocator("//span")
        div = XPathLocator("//div")
        img = XPathLocator("//img")

        (span | div) // img == XPathLocator("(//span | //div)//img")

        span | div // img == XPathLocator("(//span | //div//img)")

    """
    return XPathLocator(query=f"({self.query} | {other.query})")

__truediv__(other)

Override / operator to implement following XPath locators.

"/" used to select the nearest children of the current node.

Source code in pomcorn/locators/base_locators.py
127
128
129
130
131
132
133
def __truediv__(self, other: XPathLocator | str) -> XPathLocator:
    """Override `/` operator to implement following XPath locators.

    "/" used to select the nearest children of the current node.

    """
    return self.prepare_relative_locator(other=other, separator="/")

contains(text, exact=False)

Return new XPathLocator with search on contained text.

This is shortcut for the commonly used .extend_query(f"[contains(., '{text}')]).

Parameters:

Name Type Description Default
text str

The text that should be inside the tag.

required
exact bool

Specify whether the text being searched must match exactly. By default, the search is based on a partial match.

False
Source code in pomcorn/locators/base_locators.py
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
def contains(self, text: str, exact: bool = False) -> XPathLocator:
    """Return new XPathLocator with search on contained text.

    This is shortcut for the commonly used
    `.extend_query(f"[contains(., '{text}')])`.

    Args:
        text: The text that should be inside the tag.
        exact: Specify whether the text being searched must match exactly.
            By default, the search is based on a partial match.

    """
    partial_query = f"[contains(., {self._escape_quotes(text)})]"
    exact_query = f"[./text()={self._escape_quotes(text)}]"
    return self.extend_query(exact_query if exact else partial_query)

extend_query(extra_query)

Return new XPathLocator with extended query.

Source code in pomcorn/locators/base_locators.py
242
243
244
def extend_query(self, extra_query: str) -> XPathLocator:
    """Return new XPathLocator with extended query."""
    return XPathLocator(query=self.query + extra_query)

prepare_relative_locator(other, separator='/')

Prepare relative locator base on queries of two locators.

If one of parent and other locator queries is empty, the method will return only the filled one.

Parameters:

Name Type Description Default
other XPathLocator | str

Child locator object or str locator query.

required
separator Literal['/', '//']

Literal which will placed between locators queries - "/" used to select nearest children of current node and "//" used to select all descendants (children, grandchildren, great-grandchildren, etc.) of current node, regardless of their level in hierarchy.

'/'

Raises:

Type Description
ValueError

If parent and child locators queries are empty.

Source code in pomcorn/locators/base_locators.py
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
def prepare_relative_locator(
    self,
    other: XPathLocator | str,
    separator: Literal["/", "//"] = "/",
) -> XPathLocator:
    """Prepare relative locator base on queries of two locators.

    If one of parent and other locator queries is empty, the method will
    return only the filled one.

    Args:
        other: Child locator object or str locator query.
        separator: Literal which will placed between locators queries - "/"
            used to select nearest children of current node and "//" used
            to select all descendants (children, grandchildren,
            great-grandchildren, etc.) of current node, regardless of their
            level in hierarchy.

    Raises:
        ValueError: If parent and child locators queries are empty.

    """
    related_query = self.related_query
    if not related_query.startswith("("):
        # Parent query can be bracketed, in which case we don't need to use
        # `//`
        # Example:
        #   (//li)[3] -> valid
        #   //(//li)[3] -> invalid
        related_query = f"//{self.related_query}"

    other = XPathLocator(other) if isinstance(other, str) else other

    locator = XPathLocator(
        query=f"{related_query}{separator}{other.related_query}",
    )

    if self and other:
        return locator

    if not (self or other):
        raise ValueError(
            f"Both of locators have empty query. The `{locator.query}` is "
            "not a valid locator.",
        )

    return self or other

ButtonWithTextLocator

Bases: ElementWithTextLocator

Locator to looking for button with text by XPath.

Inherits from ElementWithTextLocator and sets the default value element="button".

Source code in pomcorn/locators/xpath_locators.py
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
class ButtonWithTextLocator(ElementWithTextLocator):
    """Locator to looking for button with text by XPath.

    Inherits from ``ElementWithTextLocator`` and sets the default value
    ``element="button"``.

    """

    def __init__(self, text: str, exact: bool = False):
        """Init XPathLocator.

        Args:
            text: The text that should be inside the button tag.
            exact: Specify whether the value of the property being searched
                must match exactly. By default, the search is based on a
                partial match of the value.

        """
        super().__init__(text=text, element="button", exact=exact)

__init__(text, exact=False)

Init XPathLocator.

Parameters:

Name Type Description Default
text str

The text that should be inside the button tag.

required
exact bool

Specify whether the value of the property being searched must match exactly. By default, the search is based on a partial match of the value.

False
Source code in pomcorn/locators/xpath_locators.py
194
195
196
197
198
199
200
201
202
203
204
def __init__(self, text: str, exact: bool = False):
    """Init XPathLocator.

    Args:
        text: The text that should be inside the button tag.
        exact: Specify whether the value of the property being searched
            must match exactly. By default, the search is based on a
            partial match of the value.

    """
    super().__init__(text=text, element="button", exact=exact)

ClassLocator

Bases: PropertyLocator

Locator to look for elements with partial class by XPath.

Inherits from PropertyLocator and sets the default value prop="class".

Source code in pomcorn/locators/xpath_locators.py
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
class ClassLocator(PropertyLocator):
    """Locator to look for elements with partial class by XPath.

    Inherits from ``PropertyLocator`` and sets the default value
    ``prop="class"``.

    """

    def __init__(
        self,
        class_name: str,
        container: str = "*",
        exact: bool = False,
    ):
        """Init XPathLocator.

        Args:
            class_name: The name of tag class.
            container: The tag in which the property should be. The default is
                ``*``, which means "any tag".
            exact: Specify whether the value of the property being searched
                must match exactly. By default, the search is based on a
                partial match of the value.

        """
        super().__init__(
            prop="class",
            value=class_name,
            container=container,
            exact=exact,
        )

__init__(class_name, container='*', exact=False)

Init XPathLocator.

Parameters:

Name Type Description Default
class_name str

The name of tag class.

required
container str

The tag in which the property should be. The default is *, which means "any tag".

'*'
exact bool

Specify whether the value of the property being searched must match exactly. By default, the search is based on a partial match of the value.

False
Source code in pomcorn/locators/xpath_locators.py
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
def __init__(
    self,
    class_name: str,
    container: str = "*",
    exact: bool = False,
):
    """Init XPathLocator.

    Args:
        class_name: The name of tag class.
        container: The tag in which the property should be. The default is
            ``*``, which means "any tag".
        exact: Specify whether the value of the property being searched
            must match exactly. By default, the search is based on a
            partial match of the value.

    """
    super().__init__(
        prop="class",
        value=class_name,
        container=container,
        exact=exact,
    )

DataTestIdLocator

Bases: PropertyLocator

Locator to look for elements with custom testid property.

Inherits from PropertyLocator and sets the default values prop="data-testid" and exact=True.

Source code in pomcorn/locators/xpath_locators.py
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
class DataTestIdLocator(PropertyLocator):
    """Locator to look for elements with custom `testid` property.

    Inherits from ``PropertyLocator`` and sets the default values
    ``prop="data-testid"`` and ``exact=True``.

    """

    def __init__(
        self,
        value: str,
        container: str = "*",
        exact: bool = True,
    ):
        """Init XPathLocator.

        Args:
            value: The value of ``testid`` property.
            container: The tag in which the property should be. The default is
                ``*``, which means "any tag".
            exact: Specify whether the value of the property being searched
                must match exactly. By default, the search is based on a
                partial match of the value.

        """
        super().__init__(
            prop="data-testid",
            value=value,
            container=container,
            exact=exact,
        )

__init__(value, container='*', exact=True)

Init XPathLocator.

Parameters:

Name Type Description Default
value str

The value of testid property.

required
container str

The tag in which the property should be. The default is *, which means "any tag".

'*'
exact bool

Specify whether the value of the property being searched must match exactly. By default, the search is based on a partial match of the value.

True
Source code in pomcorn/locators/xpath_locators.py
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
def __init__(
    self,
    value: str,
    container: str = "*",
    exact: bool = True,
):
    """Init XPathLocator.

    Args:
        value: The value of ``testid`` property.
        container: The tag in which the property should be. The default is
            ``*``, which means "any tag".
        exact: Specify whether the value of the property being searched
            must match exactly. By default, the search is based on a
            partial match of the value.

    """
    super().__init__(
        prop="data-testid",
        value=value,
        container=container,
        exact=exact,
    )

ElementWithTextLocator

Bases: XPathLocator

Locator to look for elements with text by XPath.

Source code in pomcorn/locators/xpath_locators.py
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
class ElementWithTextLocator(XPathLocator):
    """Locator to look for elements with text by XPath."""

    def __init__(self, text: str, element: str = "*", exact: bool = False):
        """Init XPathLocator.

        Args:
            text: The text that should be inside the tag.
            element: The tag in which the text should be. The default is
                ``*``, which means "any tag".
            exact: Specify whether the value of the property being searched
                must match exactly. By default, the search is based on a
                partial match of the value.

        """
        exact_query = f"//{element}[./text()={self._escape_quotes(text)}]"
        partial_query = f"//{element}[contains(.,{self._escape_quotes(text)})]"

        super().__init__(query=exact_query if exact else partial_query)

__init__(text, element='*', exact=False)

Init XPathLocator.

Parameters:

Name Type Description Default
text str

The text that should be inside the tag.

required
element str

The tag in which the text should be. The default is *, which means "any tag".

'*'
exact bool

Specify whether the value of the property being searched must match exactly. By default, the search is based on a partial match of the value.

False
Source code in pomcorn/locators/xpath_locators.py
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
def __init__(self, text: str, element: str = "*", exact: bool = False):
    """Init XPathLocator.

    Args:
        text: The text that should be inside the tag.
        element: The tag in which the text should be. The default is
            ``*``, which means "any tag".
        exact: Specify whether the value of the property being searched
            must match exactly. By default, the search is based on a
            partial match of the value.

    """
    exact_query = f"//{element}[./text()={self._escape_quotes(text)}]"
    partial_query = f"//{element}[contains(.,{self._escape_quotes(text)})]"

    super().__init__(query=exact_query if exact else partial_query)

IdLocator

Bases: PropertyLocator

Locator to look for elements with ID by Xpath.

Inherits from PropertyLocator and sets the default values prop="id" and exact=True.

Source code in pomcorn/locators/xpath_locators.py
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
class IdLocator(PropertyLocator):
    """Locator to look for elements with ID by Xpath.

    Inherits from ``PropertyLocator`` and sets the default values ``prop="id"``
    and ``exact=True``.

    """

    def __init__(
        self,
        value: str,
        container: str = "*",
    ):
        """Init XPathLocator.

        Args:
            value: The value of ``id`` property.
            container: The tag in which the property should be. The default is
                ``*``, which means "any tag".

        """
        super().__init__(
            prop="id",
            value=value,
            container=container,
            exact=True,
        )

__init__(value, container='*')

Init XPathLocator.

Parameters:

Name Type Description Default
value str

The value of id property.

required
container str

The tag in which the property should be. The default is *, which means "any tag".

'*'
Source code in pomcorn/locators/xpath_locators.py
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def __init__(
    self,
    value: str,
    container: str = "*",
):
    """Init XPathLocator.

    Args:
        value: The value of ``id`` property.
        container: The tag in which the property should be. The default is
            ``*``, which means "any tag".

    """
    super().__init__(
        prop="id",
        value=value,
        container=container,
        exact=True,
    )

InputByLabelLocator

Bases: XPathLocator

Locator to looking for input next to label by XPath.

Specify the query as the string //label[contains(., "label")]/following-sibling::input, where label is the text of the input label.

.. code-block:: html

# Example
<div>
    <label for="InputWithLabel">Title</label>
    <input id="InputWithLabel" value="Value">
</div>
Source code in pomcorn/locators/xpath_locators.py
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
class InputByLabelLocator(XPathLocator):
    """Locator to looking for input next to label by XPath.

    Specify the query as the string
    ``//label[contains(., "label")]/following-sibling::input``, where ``label``
    is the text of the input label.

    .. code-block:: html

        # Example
        <div>
            <label for="InputWithLabel">Title</label>
            <input id="InputWithLabel" value="Value">
        </div>

    """

    def __init__(self, label: str):
        """Init XPathLocator."""
        super().__init__(
            query=(
                f"//label[contains(., {self._escape_quotes(label)})]"
                "/following-sibling::input"
            ),
        )

__init__(label)

Init XPathLocator.

Source code in pomcorn/locators/xpath_locators.py
247
248
249
250
251
252
253
254
def __init__(self, label: str):
    """Init XPathLocator."""
    super().__init__(
        query=(
            f"//label[contains(., {self._escape_quotes(label)})]"
            "/following-sibling::input"
        ),
    )

InputInLabelLocator

Bases: XPathLocator

Locator to looking for input with label by XPath.

Specify the query as the string //label[contains(., "label")]//input, where label is the text of the input label.

.. code-block:: html

# Example
<label>Title</label>
    <input value="Value">
</label>
Source code in pomcorn/locators/xpath_locators.py
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
class InputInLabelLocator(XPathLocator):
    """Locator to looking for input with label by XPath.

    Specify the query as the string
    ``//label[contains(., "label")]//input``, where ``label`` is the text of
    the input label.

    .. code-block:: html

        # Example
        <label>Title</label>
            <input value="Value">
        </label>

    """

    def __init__(self, label: str):
        """Init XPathLocator."""
        super().__init__(
            query=f"//label[contains(., {self._escape_quotes(label)})]//input",
        )

__init__(label)

Init XPathLocator.

Source code in pomcorn/locators/xpath_locators.py
223
224
225
226
227
def __init__(self, label: str):
    """Init XPathLocator."""
    super().__init__(
        query=f"//label[contains(., {self._escape_quotes(label)})]//input",
    )

NameLocator

Bases: PropertyLocator

Locator to look for elements with name by Xpath.

Inherits from PropertyLocator and sets the default values prop="name" and exact=True.

Source code in pomcorn/locators/xpath_locators.py
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
class NameLocator(PropertyLocator):
    """Locator to look for elements with name by Xpath.

    Inherits from ``PropertyLocator`` and sets the default values
    ``prop="name"`` and ``exact=True``.

    """

    def __init__(self, value: str, container: str = "*"):
        """Init XPathLocator.

        Args:
            value: The value of ``name`` property.
            container: The tag in which the property should be. The default is
                ``*``, which means "any tag".

        """
        super().__init__(
            prop="name",
            value=value,
            container=container,
            exact=True,
        )

__init__(value, container='*')

Init XPathLocator.

Parameters:

Name Type Description Default
value str

The value of name property.

required
container str

The tag in which the property should be. The default is *, which means "any tag".

'*'
Source code in pomcorn/locators/xpath_locators.py
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
def __init__(self, value: str, container: str = "*"):
    """Init XPathLocator.

    Args:
        value: The value of ``name`` property.
        container: The tag in which the property should be. The default is
            ``*``, which means "any tag".

    """
    super().__init__(
        prop="name",
        value=value,
        container=container,
        exact=True,
    )

PropertyLocator

Bases: XPathLocator

Locator to look for elements with property by XPath.

Source code in pomcorn/locators/xpath_locators.py
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class PropertyLocator(XPathLocator):
    """Locator to look for elements with property by XPath."""

    def __init__(
        self,
        prop: str,
        value: str,
        container: str = "*",
        exact: bool = False,
    ):
        """Init XPathLocator.

        Args:
            prop: The name of the html tag property.
            value: The value of property.
            container: The tag in which the property should be. The default is
                ``*``, which means "any tag".
            exact: Specify whether the value of the property being searched
                must match exactly. By default, the search is based on a
                partial match of the value.

        """
        partial_query = f'//{container}[contains(@{prop}, "{value}")]'
        exact_query = f'//{container}[@{prop}="{value}"]'

        super().__init__(query=exact_query if exact else partial_query)

__init__(prop, value, container='*', exact=False)

Init XPathLocator.

Parameters:

Name Type Description Default
prop str

The name of the html tag property.

required
value str

The value of property.

required
container str

The tag in which the property should be. The default is *, which means "any tag".

'*'
exact bool

Specify whether the value of the property being searched must match exactly. By default, the search is based on a partial match of the value.

False
Source code in pomcorn/locators/xpath_locators.py
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
def __init__(
    self,
    prop: str,
    value: str,
    container: str = "*",
    exact: bool = False,
):
    """Init XPathLocator.

    Args:
        prop: The name of the html tag property.
        value: The value of property.
        container: The tag in which the property should be. The default is
            ``*``, which means "any tag".
        exact: Specify whether the value of the property being searched
            must match exactly. By default, the search is based on a
            partial match of the value.

    """
    partial_query = f'//{container}[contains(@{prop}, "{value}")]'
    exact_query = f'//{container}[@{prop}="{value}"]'

    super().__init__(query=exact_query if exact else partial_query)

TagNameLocator

Bases: XPathLocator

Locator to look for elements with tag by Xpath.

Source code in pomcorn/locators/xpath_locators.py
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class TagNameLocator(XPathLocator):
    """Locator to look for elements with tag by Xpath."""

    def __init__(self, tag: str):
        """Init XPathLocator.

        Specify the query as the string ``//tag``, where ``tag`` is the name of
        the html tag.

        """
        super().__init__(query=f"//{tag}")

__init__(tag)

Init XPathLocator.

Specify the query as the string //tag, where tag is the name of the html tag.

Source code in pomcorn/locators/xpath_locators.py
 7
 8
 9
10
11
12
13
14
def __init__(self, tag: str):
    """Init XPathLocator.

    Specify the query as the string ``//tag``, where ``tag`` is the name of
    the html tag.

    """
    super().__init__(query=f"//{tag}")

TextAreaByLabelLocator

Bases: XPathLocator

Locator to looking for textarea with label by XPath.

Specify the query as the string //*[label[contains(text(), "{label}")]]/textarea, where label is the text of the textarea label.

Source code in pomcorn/locators/xpath_locators.py
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
class TextAreaByLabelLocator(XPathLocator):
    """Locator to looking for textarea with label by XPath.

    Specify the query as the string
    ``//*[label[contains(text(), "{label}")]]/textarea``, where ``label``
    is the text of the textarea label.

    """

    def __init__(self, label: str):
        """Init XPathLocator."""
        super().__init__(
            query=(
                "//*[label[contains(text(), "
                f"{self._escape_quotes(label)})]]/textarea"
            ),
        )

__init__(label)

Init XPathLocator.

Source code in pomcorn/locators/xpath_locators.py
266
267
268
269
270
271
272
273
def __init__(self, label: str):
    """Init XPathLocator."""
    super().__init__(
        query=(
            "//*[label[contains(text(), "
            f"{self._escape_quotes(label)})]]/textarea"
        ),
    )