pomcorn 0.8.3__py3-none-any.whl → 0.8.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pomcorn might be problematic. Click here for more details.
- pomcorn/component.py +3 -1
- pomcorn/locators/base_locators.py +43 -2
- pomcorn/locators/xpath_locators.py +11 -5
- {pomcorn-0.8.3.dist-info → pomcorn-0.8.4.dist-info}/METADATA +1 -1
- {pomcorn-0.8.3.dist-info → pomcorn-0.8.4.dist-info}/RECORD +7 -7
- {pomcorn-0.8.3.dist-info → pomcorn-0.8.4.dist-info}/LICENSE +0 -0
- {pomcorn-0.8.3.dist-info → pomcorn-0.8.4.dist-info}/WHEEL +0 -0
pomcorn/component.py
CHANGED
|
@@ -352,7 +352,9 @@ class ListComponent(Generic[ListItemType, TPage], Component[TPage]):
|
|
|
352
352
|
def get_item_by_text(self, text: str) -> ListItemType:
|
|
353
353
|
"""Get list item by text."""
|
|
354
354
|
locator = self.base_item_locator.extend_query(
|
|
355
|
-
extra_query=
|
|
355
|
+
extra_query=(
|
|
356
|
+
f"[contains(., {self.base_item_locator._escape_quotes(text)})]"
|
|
357
|
+
),
|
|
356
358
|
)
|
|
357
359
|
return self._item_class(page=self.page, base_locator=locator)
|
|
358
360
|
|
|
@@ -156,6 +156,47 @@ class XPathLocator(Locator):
|
|
|
156
156
|
"""Return whether query of current locator is empty or not."""
|
|
157
157
|
return bool(self.related_query)
|
|
158
158
|
|
|
159
|
+
@classmethod
|
|
160
|
+
def _escape_quotes(cls, text: str) -> str:
|
|
161
|
+
"""Escape single and double quotes in given text for use in locators. # noqa: D202, E501.
|
|
162
|
+
|
|
163
|
+
This method is useful when locating elements
|
|
164
|
+
with text containing single or double quotes.
|
|
165
|
+
|
|
166
|
+
For example, the text `He's 6'2"` will be transformed into:
|
|
167
|
+
`concat("He", "'", "s 6", "'", "2", '"')`.
|
|
168
|
+
|
|
169
|
+
The resulting string can be used in XPath expressions
|
|
170
|
+
like `text()=...` or `contains(.,...)`.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
The escaped text wrapped in `concat()` for XPath compatibility,
|
|
174
|
+
or the original text in double quotes if no escaping is needed.
|
|
175
|
+
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
if not text or ('"' not in text and "'" not in text):
|
|
179
|
+
return f'"{text}"'
|
|
180
|
+
|
|
181
|
+
escaped_parts = []
|
|
182
|
+
buffer = "" # Temporary storage for normal characters
|
|
183
|
+
|
|
184
|
+
for char in text:
|
|
185
|
+
if char not in ('"', "'"):
|
|
186
|
+
buffer += char
|
|
187
|
+
continue
|
|
188
|
+
if buffer:
|
|
189
|
+
escaped_parts.append(f'"{buffer}"')
|
|
190
|
+
buffer = ""
|
|
191
|
+
escaped_parts.append(
|
|
192
|
+
"'" + char + "'" if char == '"' else '"' + char + '"',
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
if buffer:
|
|
196
|
+
escaped_parts.append(f'"{buffer}"')
|
|
197
|
+
|
|
198
|
+
return f"concat({', '.join(escaped_parts)})"
|
|
199
|
+
|
|
159
200
|
def extend_query(self, extra_query: str) -> XPathLocator:
|
|
160
201
|
"""Return new XPathLocator with extended query."""
|
|
161
202
|
return XPathLocator(query=self.query + extra_query)
|
|
@@ -172,8 +213,8 @@ class XPathLocator(Locator):
|
|
|
172
213
|
By default, the search is based on a partial match.
|
|
173
214
|
|
|
174
215
|
"""
|
|
175
|
-
partial_query = f"[contains(.,
|
|
176
|
-
exact_query = f"[./text()=
|
|
216
|
+
partial_query = f"[contains(., {self._escape_quotes(text)})]"
|
|
217
|
+
exact_query = f"[./text()={self._escape_quotes(text)}]"
|
|
177
218
|
return self.extend_query(exact_query if exact else partial_query)
|
|
178
219
|
|
|
179
220
|
def prepare_relative_locator(
|
|
@@ -140,8 +140,8 @@ class ElementWithTextLocator(XPathLocator):
|
|
|
140
140
|
partial match of the value.
|
|
141
141
|
|
|
142
142
|
"""
|
|
143
|
-
exact_query = f
|
|
144
|
-
partial_query = f
|
|
143
|
+
exact_query = f"//{element}[./text()={self._escape_quotes(text)}]"
|
|
144
|
+
partial_query = f"//{element}[contains(.,{self._escape_quotes(text)})]"
|
|
145
145
|
|
|
146
146
|
super().__init__(query=exact_query if exact else partial_query)
|
|
147
147
|
|
|
@@ -219,7 +219,7 @@ class InputInLabelLocator(XPathLocator):
|
|
|
219
219
|
def __init__(self, label: str):
|
|
220
220
|
"""Init XPathLocator."""
|
|
221
221
|
super().__init__(
|
|
222
|
-
query=f
|
|
222
|
+
query=f"//label[contains(., {self._escape_quotes(label)})]//input",
|
|
223
223
|
)
|
|
224
224
|
|
|
225
225
|
|
|
@@ -243,7 +243,10 @@ class InputByLabelLocator(XPathLocator):
|
|
|
243
243
|
def __init__(self, label: str):
|
|
244
244
|
"""Init XPathLocator."""
|
|
245
245
|
super().__init__(
|
|
246
|
-
query=
|
|
246
|
+
query=(
|
|
247
|
+
f"//label[contains(., {self._escape_quotes(label)})]"
|
|
248
|
+
"/following-sibling::input"
|
|
249
|
+
),
|
|
247
250
|
)
|
|
248
251
|
|
|
249
252
|
|
|
@@ -259,5 +262,8 @@ class TextAreaByLabelLocator(XPathLocator):
|
|
|
259
262
|
def __init__(self, label: str):
|
|
260
263
|
"""Init XPathLocator."""
|
|
261
264
|
super().__init__(
|
|
262
|
-
query=
|
|
265
|
+
query=(
|
|
266
|
+
"//*[label[contains(text(), "
|
|
267
|
+
f"{self._escape_quotes(label)})]]/textarea"
|
|
268
|
+
),
|
|
263
269
|
)
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
pomcorn/__init__.py,sha256=V8v_V3wgKbao1KAQkcVTMnpGwyslw0nHfuTp-DwWTXg,318
|
|
2
|
-
pomcorn/component.py,sha256=
|
|
2
|
+
pomcorn/component.py,sha256=XdG6OJ_4dKXsDh4E_TJhbmcL3iXFOI8lvopCVjWpwXM,12164
|
|
3
3
|
pomcorn/descriptors/__init__.py,sha256=5q_d5GtcaFlIIyHdsUnE9UNbz3g40qJCHKNaWGvcC6s,72
|
|
4
4
|
pomcorn/descriptors/element.py,sha256=4g_4ay5f00AXzCT4xHN1i7mTrlsECoUHh1Ph_TFPBDs,4502
|
|
5
5
|
pomcorn/element.py,sha256=6VLLSPlc7961qa4rRXdno7cEAAeY8GEP2d4wtM5R9a0,12216
|
|
6
6
|
pomcorn/exceptions.py,sha256=8ZOmrybDwvEVZRLQzyozjRNhJvSLbablaFwGFUVMhrU,1131
|
|
7
7
|
pomcorn/locators/__init__.py,sha256=hNSlfmz3y-LI4PXF5VIwX8J5WSalyE2wmzuYc6kNxMA,708
|
|
8
|
-
pomcorn/locators/base_locators.py,sha256=
|
|
9
|
-
pomcorn/locators/xpath_locators.py,sha256=
|
|
8
|
+
pomcorn/locators/base_locators.py,sha256=nokiwxnIQh90bolOJcFJSQjuaX_0a4iB5aPhp_Vrbr8,8439
|
|
9
|
+
pomcorn/locators/xpath_locators.py,sha256=zcGNIk5HX36TTauCApgX0csdobWj8QFZ_td4-9qkTgU,7461
|
|
10
10
|
pomcorn/page.py,sha256=wuLoGUn1n0e7wSXLGYyUVnoPlz_gMfT8Jtg6yA09IeY,5755
|
|
11
11
|
pomcorn/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
pomcorn/waits_conditions.py,sha256=E8sLfBvIV2EO91Mm5KyKXB5IGEB9gUWza3XPE4_aCQE,3528
|
|
13
13
|
pomcorn/web_view.py,sha256=PlwEVgdOwFZXJY2WuUT2C2wyK1xOBJne5-A_FOuwsQI,14209
|
|
14
|
-
pomcorn-0.8.
|
|
15
|
-
pomcorn-0.8.
|
|
16
|
-
pomcorn-0.8.
|
|
17
|
-
pomcorn-0.8.
|
|
14
|
+
pomcorn-0.8.4.dist-info/LICENSE,sha256=1vmhQNp1dDH8ksJ199LuG4oKz5D4ZvNccPcFckiG2S4,1091
|
|
15
|
+
pomcorn-0.8.4.dist-info/METADATA,sha256=jPDp_4lyHdfibn0IqP1DNHb0ZP5QhG55dkA8aEWDZoE,5973
|
|
16
|
+
pomcorn-0.8.4.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
17
|
+
pomcorn-0.8.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|