pure-patchright 1.62.3__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.
Files changed (142) hide show
  1. patchright/__init__.py +5 -0
  2. patchright/__main__.py +18 -0
  3. patchright/_impl/__init__.py +0 -0
  4. patchright/_impl/__pyinstaller/__init__.py +20 -0
  5. patchright/_impl/__pyinstaller/hook-playwright.async_api.py +3 -0
  6. patchright/_impl/__pyinstaller/hook-playwright.sync_api.py +3 -0
  7. patchright/_impl/_api_structures.py +343 -0
  8. patchright/_impl/_artifact.py +46 -0
  9. patchright/_impl/_assertions.py +1014 -0
  10. patchright/_impl/_async_base.py +88 -0
  11. patchright/_impl/_browser.py +267 -0
  12. patchright/_impl/_browser_context.py +759 -0
  13. patchright/_impl/_browser_type.py +336 -0
  14. patchright/_impl/_cdp_session.py +25 -0
  15. patchright/_impl/_clock.py +62 -0
  16. patchright/_impl/_connection.py +686 -0
  17. patchright/_impl/_console_message.py +83 -0
  18. patchright/_impl/_credentials.py +38 -0
  19. patchright/_impl/_debugger.py +37 -0
  20. patchright/_impl/_dialog.py +45 -0
  21. patchright/_impl/_disposable.py +71 -0
  22. patchright/_impl/_download.py +49 -0
  23. patchright/_impl/_driver.py +24 -0
  24. patchright/_impl/_element_handle.py +446 -0
  25. patchright/_impl/_errors.py +46 -0
  26. patchright/_impl/_event_context_manager.py +19 -0
  27. patchright/_impl/_fetch.py +592 -0
  28. patchright/_impl/_file_chooser.py +42 -0
  29. patchright/_impl/_form_data.py +19 -0
  30. patchright/_impl/_frame.py +959 -0
  31. patchright/_impl/_glob.py +47 -0
  32. patchright/_impl/_greenlets.py +35 -0
  33. patchright/_impl/_har_router.py +98 -0
  34. patchright/_impl/_helper.py +551 -0
  35. patchright/_impl/_impl_to_api_mapping.py +141 -0
  36. patchright/_impl/_input.py +85 -0
  37. patchright/_impl/_js_handle.py +297 -0
  38. patchright/_impl/_json_pipe.py +55 -0
  39. patchright/_impl/_local_utils.py +73 -0
  40. patchright/_impl/_locator.py +894 -0
  41. patchright/_impl/_map.py +18 -0
  42. patchright/_impl/_network.py +953 -0
  43. patchright/_impl/_object_factory.py +93 -0
  44. patchright/_impl/_page.py +1601 -0
  45. patchright/_impl/_path_utils.py +13 -0
  46. patchright/_impl/_playwright.py +43 -0
  47. patchright/_impl/_screencast.py +149 -0
  48. patchright/_impl/_selectors.py +48 -0
  49. patchright/_impl/_set_input_files_helpers.py +134 -0
  50. patchright/_impl/_str_utils.py +59 -0
  51. patchright/_impl/_stream.py +31 -0
  52. patchright/_impl/_sync_base.py +130 -0
  53. patchright/_impl/_tracing.py +243 -0
  54. patchright/_impl/_transport.py +151 -0
  55. patchright/_impl/_video.py +41 -0
  56. patchright/_impl/_waiter.py +168 -0
  57. patchright/_impl/_web_error.py +33 -0
  58. patchright/_impl/_web_storage.py +41 -0
  59. patchright/_impl/_writable_stream.py +26 -0
  60. patchright/_repo_version.py +1 -0
  61. patchright/async_api/__init__.py +234 -0
  62. patchright/async_api/_context_manager.py +38 -0
  63. patchright/async_api/_generated.py +23396 -0
  64. patchright/driver/README.md +1 -0
  65. patchright/driver/package/README.md +3 -0
  66. patchright/driver/package/ThirdPartyNotices.txt +13 -0
  67. patchright/driver/package/bin/install_media_pack.ps1 +5 -0
  68. patchright/driver/package/bin/install_webkit_wsl.ps1 +33 -0
  69. patchright/driver/package/bin/reinstall_chrome_beta_linux.sh +42 -0
  70. patchright/driver/package/bin/reinstall_chrome_beta_mac.sh +13 -0
  71. patchright/driver/package/bin/reinstall_chrome_beta_win.ps1 +24 -0
  72. patchright/driver/package/bin/reinstall_chrome_stable_linux.sh +42 -0
  73. patchright/driver/package/bin/reinstall_chrome_stable_mac.sh +12 -0
  74. patchright/driver/package/bin/reinstall_chrome_stable_win.ps1 +24 -0
  75. patchright/driver/package/bin/reinstall_msedge_beta_linux.sh +48 -0
  76. patchright/driver/package/bin/reinstall_msedge_beta_mac.sh +11 -0
  77. patchright/driver/package/bin/reinstall_msedge_beta_win.ps1 +23 -0
  78. patchright/driver/package/bin/reinstall_msedge_dev_linux.sh +48 -0
  79. patchright/driver/package/bin/reinstall_msedge_dev_mac.sh +11 -0
  80. patchright/driver/package/bin/reinstall_msedge_dev_win.ps1 +23 -0
  81. patchright/driver/package/bin/reinstall_msedge_stable_linux.sh +48 -0
  82. patchright/driver/package/bin/reinstall_msedge_stable_mac.sh +11 -0
  83. patchright/driver/package/bin/reinstall_msedge_stable_win.ps1 +24 -0
  84. patchright/driver/package/browsers.json +75 -0
  85. patchright/driver/package/cli.js +21 -0
  86. patchright/driver/package/index.js +17 -0
  87. patchright/driver/package/index.mjs +28 -0
  88. patchright/driver/package/lib/bootstrap.js +88 -0
  89. patchright/driver/package/lib/coreBundle.js +77498 -0
  90. patchright/driver/package/lib/entry/cliDaemon.js +5 -0
  91. patchright/driver/package/lib/entry/dashboardApp.js +3 -0
  92. patchright/driver/package/lib/entry/mcp.js +10 -0
  93. patchright/driver/package/lib/entry/oopBrowserDownload.js +3 -0
  94. patchright/driver/package/lib/package.js +50 -0
  95. patchright/driver/package/lib/server/chromium/appIcon.png +0 -0
  96. patchright/driver/package/lib/server/electron/loader.js +107 -0
  97. patchright/driver/package/lib/serverRegistry.js +7347 -0
  98. patchright/driver/package/lib/serverRegistry.js.LICENSE +354 -0
  99. patchright/driver/package/lib/tools/cli-client/channelSessions.js +141 -0
  100. patchright/driver/package/lib/tools/cli-client/cli.js +6 -0
  101. patchright/driver/package/lib/tools/cli-client/help.json +708 -0
  102. patchright/driver/package/lib/tools/cli-client/minimist.js +128 -0
  103. patchright/driver/package/lib/tools/cli-client/output.js +343 -0
  104. patchright/driver/package/lib/tools/cli-client/program.js +404 -0
  105. patchright/driver/package/lib/tools/cli-client/registry.js +176 -0
  106. patchright/driver/package/lib/tools/cli-client/session.js +258 -0
  107. patchright/driver/package/lib/tools/dashboard/appIcon.png +0 -0
  108. patchright/driver/package/lib/tools/skills/playwright-cli/SKILL.md +420 -0
  109. patchright/driver/package/lib/tools/skills/playwright-cli/references/element-attributes.md +23 -0
  110. patchright/driver/package/lib/tools/skills/playwright-cli/references/playwright-tests.md +39 -0
  111. patchright/driver/package/lib/tools/skills/playwright-cli/references/request-mocking.md +87 -0
  112. patchright/driver/package/lib/tools/skills/playwright-cli/references/running-code.md +241 -0
  113. patchright/driver/package/lib/tools/skills/playwright-cli/references/session-management.md +225 -0
  114. patchright/driver/package/lib/tools/skills/playwright-cli/references/storage-state.md +275 -0
  115. patchright/driver/package/lib/tools/skills/playwright-cli/references/test-generation.md +433 -0
  116. patchright/driver/package/lib/tools/skills/playwright-cli/references/tracing.md +139 -0
  117. patchright/driver/package/lib/tools/skills/playwright-cli/references/video-recording.md +143 -0
  118. patchright/driver/package/lib/tools/skills/playwright-component-testing/SKILL.md +143 -0
  119. patchright/driver/package/lib/tools/skills/playwright-component-testing/references/gallery-spec.md +144 -0
  120. patchright/driver/package/lib/tools/skills/playwright-component-testing/references/migration.md +85 -0
  121. patchright/driver/package/lib/tools/skills/playwright-component-testing/references/react.md +67 -0
  122. patchright/driver/package/lib/tools/skills/playwright-component-testing/references/vue.md +75 -0
  123. patchright/driver/package/lib/tools/skills/playwright-trace/SKILL.md +171 -0
  124. patchright/driver/package/lib/tools/utils/extension.js +101 -0
  125. patchright/driver/package/lib/tools/utils/socketConnection.js +108 -0
  126. patchright/driver/package/lib/utilsBundle.js +90764 -0
  127. patchright/driver/package/lib/utilsBundle.js.LICENSE +2179 -0
  128. patchright/driver/package/lib/webp_codec.LICENSE +173 -0
  129. patchright/driver/package/lib/webp_codec.wasm +0 -0
  130. patchright/driver/package/lib/xdg-open +1267 -0
  131. patchright/driver/package/package.json +34 -0
  132. patchright/py.typed +0 -0
  133. patchright/sync_api/__init__.py +234 -0
  134. patchright/sync_api/_context_manager.py +73 -0
  135. patchright/sync_api/_generated.py +23590 -0
  136. pure_patchright-1.62.3.dist-info/LICENSE +201 -0
  137. pure_patchright-1.62.3.dist-info/METADATA +96 -0
  138. pure_patchright-1.62.3.dist-info/RECORD +142 -0
  139. pure_patchright-1.62.3.dist-info/WHEEL +4 -0
  140. pure_patchright-1.62.3.dist-info/entry_points.txt +5 -0
  141. pure_patchright-1.62.3.dist-info/licenses/LICENSE +202 -0
  142. pure_patchright-1.62.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1014 @@
1
+ import collections.abc
2
+ from contextlib import contextmanager
3
+ from typing import Any, Iterator, List, Literal, Optional, Pattern, Sequence, Union
4
+ from urllib.parse import urljoin
5
+ from patchright._impl._api_structures import (
6
+ AriaRole,
7
+ ExpectedTextValue,
8
+ FrameExpectOptions,
9
+ FrameExpectResult,
10
+ )
11
+ from patchright._impl._connection import format_call_log
12
+ from patchright._impl._errors import Error
13
+ from patchright._impl._fetch import APIResponse
14
+ from patchright._impl._helper import is_textual_mime_type
15
+ from patchright._impl._js_handle import parse_value
16
+ from patchright._impl._locator import Locator
17
+ from patchright._impl._page import Page
18
+ from patchright._impl._str_utils import escape_regex_flags
19
+
20
+ _soft_errors: Optional[List[AssertionError]] = None
21
+
22
+
23
+ @contextmanager
24
+ def _soft_scope() -> Iterator[List[AssertionError]]:
25
+ global _soft_errors
26
+ assert _soft_errors is None, "nested soft assertion scopes are not supported"
27
+ _soft_errors = []
28
+ try:
29
+ yield _soft_errors
30
+ finally:
31
+ _soft_errors = None
32
+
33
+
34
+ def _record_soft_or_raise(error: AssertionError, is_soft: bool) -> None:
35
+ __tracebackhide__ = True
36
+ if is_soft:
37
+ if _soft_errors is None:
38
+ raise RuntimeError(
39
+ "expect.soft(...) requires pytest-playwright>=0.7.3 (or pytest-playwright-asyncio>=0.7.3). Upgrade the plugin, or use a regular expect(...) assertion."
40
+ )
41
+ _soft_errors.append(error)
42
+ return
43
+ raise error
44
+
45
+
46
+ class AssertionsBase:
47
+ def __init__(
48
+ self,
49
+ locator: Locator,
50
+ timeout: float = None,
51
+ is_not: bool = False,
52
+ message: Optional[str] = None,
53
+ is_soft: bool = False,
54
+ ) -> None:
55
+ self._actual_locator = locator
56
+ self._loop = locator._loop
57
+ self._dispatcher_fiber = locator._dispatcher_fiber
58
+ self._timeout = timeout
59
+ self._is_not = is_not
60
+ self._custom_message = message
61
+ self._is_soft = is_soft
62
+
63
+ async def _call_expect(
64
+ self, expression: str, expect_options: FrameExpectOptions, title: Optional[str]
65
+ ) -> FrameExpectResult:
66
+ raise NotImplementedError(
67
+ "_call_expect must be implemented in a derived class."
68
+ )
69
+
70
+ async def _expect_impl(
71
+ self,
72
+ expression: str,
73
+ expect_options: FrameExpectOptions,
74
+ expected: Any,
75
+ message: str,
76
+ title: str = None,
77
+ ) -> None:
78
+ __tracebackhide__ = True
79
+ expect_options["isNot"] = self._is_not
80
+ if expect_options.get("timeout") is None:
81
+ expect_options["timeout"] = self._timeout or 5000
82
+ if expect_options["isNot"]:
83
+ message = message.replace("expected to", "expected not to")
84
+ if title:
85
+ title = title.replace('"to_', '"not_to_')
86
+ if "useInnerText" in expect_options and expect_options["useInnerText"] is None:
87
+ del expect_options["useInnerText"]
88
+ result = await self._call_expect(expression, expect_options, title)
89
+ if result["matches"] == self._is_not:
90
+ received = result.get("received") or {}
91
+ aria_snapshot = None
92
+ if isinstance(received, dict):
93
+ aria_snapshot = received.get("ariaSnapshot")
94
+ value = received.get("value")
95
+ actual = parse_value(value) if value is not None else None
96
+ else:
97
+ actual = received
98
+ if self._custom_message:
99
+ out_message = self._custom_message
100
+ if expected is not None:
101
+ out_message += f"\nExpected value: '{expected or '<None>'}'"
102
+ else:
103
+ out_message = (
104
+ f"{message} '{expected}'" if expected is not None else f"{message}"
105
+ )
106
+ error_message = result.get("errorMessage")
107
+ error_message = f"\n{error_message}" if error_message else ""
108
+ aria_snapshot_message = (
109
+ f"\nAria snapshot:\n{aria_snapshot}" if aria_snapshot else ""
110
+ )
111
+ _record_soft_or_raise(
112
+ AssertionError(
113
+ f"{out_message}\nActual value: {actual}{error_message} {format_call_log(result.get('log'))}{aria_snapshot_message}"
114
+ ),
115
+ self._is_soft,
116
+ )
117
+
118
+
119
+ class PageAssertions(AssertionsBase):
120
+ def __init__(
121
+ self,
122
+ page: Page,
123
+ timeout: float = None,
124
+ is_not: bool = False,
125
+ message: Optional[str] = None,
126
+ is_soft: bool = False,
127
+ ) -> None:
128
+ super().__init__(page.locator(":root"), timeout, is_not, message, is_soft)
129
+ self._actual_page = page
130
+
131
+ async def _call_expect(
132
+ self, expression: str, expect_options: FrameExpectOptions, title: Optional[str]
133
+ ) -> FrameExpectResult:
134
+ __tracebackhide__ = True
135
+ return await self._actual_page.main_frame._expect(
136
+ None, expression, expect_options, title
137
+ )
138
+
139
+ @property
140
+ def _not(self) -> "PageAssertions":
141
+ return PageAssertions(
142
+ self._actual_page,
143
+ self._timeout,
144
+ not self._is_not,
145
+ self._custom_message,
146
+ self._is_soft,
147
+ )
148
+
149
+ async def to_have_title(
150
+ self, titleOrRegExp: Union[Pattern[str], str], timeout: float = None
151
+ ) -> None:
152
+ __tracebackhide__ = True
153
+ expected_values = to_expected_text_values(
154
+ [titleOrRegExp], normalize_white_space=True
155
+ )
156
+ await self._expect_impl(
157
+ "to.have.title",
158
+ FrameExpectOptions(expectedText=expected_values, timeout=timeout),
159
+ titleOrRegExp,
160
+ "Page title expected to be",
161
+ 'Expect "to_have_title"',
162
+ )
163
+
164
+ async def not_to_have_title(
165
+ self, titleOrRegExp: Union[Pattern[str], str], timeout: float = None
166
+ ) -> None:
167
+ __tracebackhide__ = True
168
+ await self._not.to_have_title(titleOrRegExp, timeout)
169
+
170
+ async def to_have_url(
171
+ self,
172
+ urlOrRegExp: Union[str, Pattern[str]],
173
+ timeout: float = None,
174
+ ignoreCase: bool = None,
175
+ ) -> None:
176
+ __tracebackhide__ = True
177
+ base_url = self._actual_page.context._base_url
178
+ if isinstance(urlOrRegExp, str) and base_url:
179
+ urlOrRegExp = urljoin(base_url, urlOrRegExp)
180
+ expected_text = to_expected_text_values([urlOrRegExp], ignoreCase=ignoreCase)
181
+ await self._expect_impl(
182
+ "to.have.url",
183
+ FrameExpectOptions(expectedText=expected_text, timeout=timeout),
184
+ urlOrRegExp,
185
+ "Page URL expected to be",
186
+ 'Expect "to_have_url"',
187
+ )
188
+
189
+ async def not_to_have_url(
190
+ self,
191
+ urlOrRegExp: Union[Pattern[str], str],
192
+ timeout: float = None,
193
+ ignoreCase: bool = None,
194
+ ) -> None:
195
+ __tracebackhide__ = True
196
+ await self._not.to_have_url(urlOrRegExp, timeout, ignoreCase)
197
+
198
+ async def to_match_aria_snapshot(
199
+ self, expected: str, timeout: float = None
200
+ ) -> None:
201
+ __tracebackhide__ = True
202
+ await self._expect_impl(
203
+ "to.match.aria",
204
+ FrameExpectOptions(expectedValue=expected, timeout=timeout),
205
+ expected,
206
+ "Page expected to match Aria snapshot",
207
+ 'Expect "to_match_aria_snapshot"',
208
+ )
209
+
210
+ async def not_to_match_aria_snapshot(
211
+ self, expected: str, timeout: float = None
212
+ ) -> None:
213
+ __tracebackhide__ = True
214
+ await self._not.to_match_aria_snapshot(expected, timeout)
215
+
216
+
217
+ class LocatorAssertions(AssertionsBase):
218
+ def __init__(
219
+ self,
220
+ locator: Locator,
221
+ timeout: float = None,
222
+ is_not: bool = False,
223
+ message: Optional[str] = None,
224
+ is_soft: bool = False,
225
+ ) -> None:
226
+ super().__init__(locator, timeout, is_not, message, is_soft)
227
+ self._actual_locator = locator
228
+
229
+ async def _call_expect(
230
+ self, expression: str, expect_options: FrameExpectOptions, title: Optional[str]
231
+ ) -> FrameExpectResult:
232
+ __tracebackhide__ = True
233
+ return await self._actual_locator._expect(expression, expect_options, title)
234
+
235
+ @property
236
+ def _not(self) -> "LocatorAssertions":
237
+ return LocatorAssertions(
238
+ self._actual_locator,
239
+ self._timeout,
240
+ not self._is_not,
241
+ self._custom_message,
242
+ self._is_soft,
243
+ )
244
+
245
+ async def to_contain_text(
246
+ self,
247
+ expected: Union[
248
+ Sequence[str],
249
+ Sequence[Pattern[str]],
250
+ Sequence[Union[Pattern[str], str]],
251
+ Pattern[str],
252
+ str,
253
+ ],
254
+ useInnerText: bool = None,
255
+ timeout: float = None,
256
+ ignoreCase: bool = None,
257
+ ) -> None:
258
+ __tracebackhide__ = True
259
+ if isinstance(expected, collections.abc.Sequence) and (
260
+ not isinstance(expected, str)
261
+ ):
262
+ expected_text = to_expected_text_values(
263
+ expected,
264
+ match_substring=True,
265
+ normalize_white_space=True,
266
+ ignoreCase=ignoreCase,
267
+ )
268
+ await self._expect_impl(
269
+ "to.contain.text.array",
270
+ FrameExpectOptions(
271
+ expectedText=expected_text,
272
+ useInnerText=useInnerText,
273
+ timeout=timeout,
274
+ ),
275
+ expected,
276
+ "Locator expected to contain text",
277
+ 'Expect "to_contain_text"',
278
+ )
279
+ else:
280
+ expected_text = to_expected_text_values(
281
+ [expected],
282
+ match_substring=True,
283
+ normalize_white_space=True,
284
+ ignoreCase=ignoreCase,
285
+ )
286
+ await self._expect_impl(
287
+ "to.have.text",
288
+ FrameExpectOptions(
289
+ expectedText=expected_text,
290
+ useInnerText=useInnerText,
291
+ timeout=timeout,
292
+ ),
293
+ expected,
294
+ "Locator expected to contain text",
295
+ 'Expect "to_contain_text"',
296
+ )
297
+
298
+ async def not_to_contain_text(
299
+ self,
300
+ expected: Union[
301
+ Sequence[str],
302
+ Sequence[Pattern[str]],
303
+ Sequence[Union[Pattern[str], str]],
304
+ Pattern[str],
305
+ str,
306
+ ],
307
+ useInnerText: bool = None,
308
+ timeout: float = None,
309
+ ignoreCase: bool = None,
310
+ ) -> None:
311
+ __tracebackhide__ = True
312
+ await self._not.to_contain_text(expected, useInnerText, timeout, ignoreCase)
313
+
314
+ async def to_have_attribute(
315
+ self,
316
+ name: str,
317
+ value: Union[Pattern[str], str] = None,
318
+ ignoreCase: bool = None,
319
+ timeout: float = None,
320
+ ) -> None:
321
+ __tracebackhide__ = True
322
+ if value is None:
323
+ await self._expect_impl(
324
+ "to.have.attribute",
325
+ FrameExpectOptions(expressionArg=name, timeout=timeout),
326
+ None,
327
+ "Locator expected to have attribute",
328
+ 'Expect "to_have_attribute"',
329
+ )
330
+ return
331
+ expected_text = to_expected_text_values([value], ignoreCase=ignoreCase)
332
+ await self._expect_impl(
333
+ "to.have.attribute.value",
334
+ FrameExpectOptions(
335
+ expressionArg=name, expectedText=expected_text, timeout=timeout
336
+ ),
337
+ value,
338
+ "Locator expected to have attribute",
339
+ 'Expect "to_have_attribute"',
340
+ )
341
+
342
+ async def not_to_have_attribute(
343
+ self,
344
+ name: str,
345
+ value: Union[Pattern[str], str] = None,
346
+ ignoreCase: bool = None,
347
+ timeout: float = None,
348
+ ) -> None:
349
+ __tracebackhide__ = True
350
+ await self._not.to_have_attribute(
351
+ name, value, ignoreCase=ignoreCase, timeout=timeout
352
+ )
353
+
354
+ async def to_have_class(
355
+ self,
356
+ expected: Union[
357
+ Sequence[str],
358
+ Sequence[Pattern[str]],
359
+ Sequence[Union[Pattern[str], str]],
360
+ Pattern[str],
361
+ str,
362
+ ],
363
+ timeout: float = None,
364
+ ) -> None:
365
+ __tracebackhide__ = True
366
+ if isinstance(expected, collections.abc.Sequence) and (
367
+ not isinstance(expected, str)
368
+ ):
369
+ expected_text = to_expected_text_values(expected)
370
+ await self._expect_impl(
371
+ "to.have.class.array",
372
+ FrameExpectOptions(expectedText=expected_text, timeout=timeout),
373
+ expected,
374
+ "Locator expected to have class",
375
+ 'Expect "to_have_class"',
376
+ )
377
+ else:
378
+ expected_text = to_expected_text_values([expected])
379
+ await self._expect_impl(
380
+ "to.have.class",
381
+ FrameExpectOptions(expectedText=expected_text, timeout=timeout),
382
+ expected,
383
+ "Locator expected to have class",
384
+ 'Expect "to_have_class"',
385
+ )
386
+
387
+ async def not_to_have_class(
388
+ self,
389
+ expected: Union[
390
+ Sequence[str],
391
+ Sequence[Pattern[str]],
392
+ Sequence[Union[Pattern[str], str]],
393
+ Pattern[str],
394
+ str,
395
+ ],
396
+ timeout: float = None,
397
+ ) -> None:
398
+ __tracebackhide__ = True
399
+ await self._not.to_have_class(expected, timeout)
400
+
401
+ async def to_contain_class(
402
+ self, expected: Union[Sequence[str], str], timeout: float = None
403
+ ) -> None:
404
+ __tracebackhide__ = True
405
+ if isinstance(expected, collections.abc.Sequence) and (
406
+ not isinstance(expected, str)
407
+ ):
408
+ expected_text = to_expected_text_values(expected)
409
+ await self._expect_impl(
410
+ "to.contain.class.array",
411
+ FrameExpectOptions(expectedText=expected_text, timeout=timeout),
412
+ expected,
413
+ "Locator expected to contain class names",
414
+ 'Expect "to_contain_class"',
415
+ )
416
+ else:
417
+ expected_text = to_expected_text_values([expected])
418
+ await self._expect_impl(
419
+ "to.contain.class",
420
+ FrameExpectOptions(expectedText=expected_text, timeout=timeout),
421
+ expected,
422
+ "Locator expected to contain class",
423
+ 'Expect "to_contain_class"',
424
+ )
425
+
426
+ async def not_to_contain_class(
427
+ self, expected: Union[Sequence[str], str], timeout: float = None
428
+ ) -> None:
429
+ __tracebackhide__ = True
430
+ await self._not.to_contain_class(expected, timeout)
431
+
432
+ async def to_have_count(self, count: int, timeout: float = None) -> None:
433
+ __tracebackhide__ = True
434
+ await self._expect_impl(
435
+ "to.have.count",
436
+ FrameExpectOptions(expectedNumber=count, timeout=timeout),
437
+ count,
438
+ "Locator expected to have count",
439
+ 'Expect "to_have_count"',
440
+ )
441
+
442
+ async def not_to_have_count(self, count: int, timeout: float = None) -> None:
443
+ __tracebackhide__ = True
444
+ await self._not.to_have_count(count, timeout)
445
+
446
+ async def to_have_css(
447
+ self,
448
+ name: str,
449
+ value: Union[str, Pattern[str]],
450
+ timeout: float = None,
451
+ pseudo: Literal["after", "before"] = None,
452
+ ) -> None:
453
+ __tracebackhide__ = True
454
+ expected_text = to_expected_text_values([value])
455
+ await self._expect_impl(
456
+ "to.have.css",
457
+ FrameExpectOptions(
458
+ expressionArg=name,
459
+ expectedText=expected_text,
460
+ timeout=timeout,
461
+ pseudo=pseudo,
462
+ ),
463
+ value,
464
+ "Locator expected to have CSS",
465
+ 'Expect "to_have_css"',
466
+ )
467
+
468
+ async def not_to_have_css(
469
+ self, name: str, value: Union[str, Pattern[str]], timeout: float = None
470
+ ) -> None:
471
+ __tracebackhide__ = True
472
+ await self._not.to_have_css(name, value, timeout)
473
+
474
+ async def to_have_id(
475
+ self, id: Union[str, Pattern[str]], timeout: float = None
476
+ ) -> None:
477
+ __tracebackhide__ = True
478
+ expected_text = to_expected_text_values([id])
479
+ await self._expect_impl(
480
+ "to.have.id",
481
+ FrameExpectOptions(expectedText=expected_text, timeout=timeout),
482
+ id,
483
+ "Locator expected to have ID",
484
+ 'Expect "to_have_id"',
485
+ )
486
+
487
+ async def not_to_have_id(
488
+ self, id: Union[str, Pattern[str]], timeout: float = None
489
+ ) -> None:
490
+ __tracebackhide__ = True
491
+ await self._not.to_have_id(id, timeout)
492
+
493
+ async def to_have_js_property(
494
+ self, name: str, value: Any, timeout: float = None
495
+ ) -> None:
496
+ __tracebackhide__ = True
497
+ await self._expect_impl(
498
+ "to.have.property",
499
+ FrameExpectOptions(
500
+ expressionArg=name, expectedValue=value, timeout=timeout
501
+ ),
502
+ value,
503
+ "Locator expected to have JS Property",
504
+ 'Expect "to_have_property"',
505
+ )
506
+
507
+ async def not_to_have_js_property(
508
+ self, name: str, value: Any, timeout: float = None
509
+ ) -> None:
510
+ __tracebackhide__ = True
511
+ await self._not.to_have_js_property(name, value, timeout)
512
+
513
+ async def to_have_value(
514
+ self, value: Union[str, Pattern[str]], timeout: float = None
515
+ ) -> None:
516
+ __tracebackhide__ = True
517
+ expected_text = to_expected_text_values([value])
518
+ await self._expect_impl(
519
+ "to.have.value",
520
+ FrameExpectOptions(expectedText=expected_text, timeout=timeout),
521
+ value,
522
+ "Locator expected to have Value",
523
+ 'Expect "to_have_value"',
524
+ )
525
+
526
+ async def not_to_have_value(
527
+ self, value: Union[str, Pattern[str]], timeout: float = None
528
+ ) -> None:
529
+ __tracebackhide__ = True
530
+ await self._not.to_have_value(value, timeout)
531
+
532
+ async def to_have_values(
533
+ self,
534
+ values: Union[
535
+ Sequence[str], Sequence[Pattern[str]], Sequence[Union[Pattern[str], str]]
536
+ ],
537
+ timeout: float = None,
538
+ ) -> None:
539
+ __tracebackhide__ = True
540
+ expected_text = to_expected_text_values(values)
541
+ await self._expect_impl(
542
+ "to.have.values",
543
+ FrameExpectOptions(expectedText=expected_text, timeout=timeout),
544
+ values,
545
+ "Locator expected to have Values",
546
+ 'Expect "to_have_values"',
547
+ )
548
+
549
+ async def not_to_have_values(
550
+ self,
551
+ values: Union[
552
+ Sequence[str], Sequence[Pattern[str]], Sequence[Union[Pattern[str], str]]
553
+ ],
554
+ timeout: float = None,
555
+ ) -> None:
556
+ __tracebackhide__ = True
557
+ await self._not.to_have_values(values, timeout)
558
+
559
+ async def to_have_text(
560
+ self,
561
+ expected: Union[
562
+ Sequence[str],
563
+ Sequence[Pattern[str]],
564
+ Sequence[Union[Pattern[str], str]],
565
+ Pattern[str],
566
+ str,
567
+ ],
568
+ useInnerText: bool = None,
569
+ timeout: float = None,
570
+ ignoreCase: bool = None,
571
+ ) -> None:
572
+ __tracebackhide__ = True
573
+ if isinstance(expected, collections.abc.Sequence) and (
574
+ not isinstance(expected, str)
575
+ ):
576
+ expected_text = to_expected_text_values(
577
+ expected, normalize_white_space=True, ignoreCase=ignoreCase
578
+ )
579
+ await self._expect_impl(
580
+ "to.have.text.array",
581
+ FrameExpectOptions(
582
+ expectedText=expected_text,
583
+ useInnerText=useInnerText,
584
+ timeout=timeout,
585
+ ),
586
+ expected,
587
+ "Locator expected to have text",
588
+ 'Expect "to_have_text"',
589
+ )
590
+ else:
591
+ expected_text = to_expected_text_values(
592
+ [expected], normalize_white_space=True, ignoreCase=ignoreCase
593
+ )
594
+ await self._expect_impl(
595
+ "to.have.text",
596
+ FrameExpectOptions(
597
+ expectedText=expected_text,
598
+ useInnerText=useInnerText,
599
+ timeout=timeout,
600
+ ),
601
+ expected,
602
+ "Locator expected to have text",
603
+ 'Expect "to_have_text"',
604
+ )
605
+
606
+ async def not_to_have_text(
607
+ self,
608
+ expected: Union[
609
+ Sequence[str],
610
+ Sequence[Pattern[str]],
611
+ Sequence[Union[Pattern[str], str]],
612
+ Pattern[str],
613
+ str,
614
+ ],
615
+ useInnerText: bool = None,
616
+ timeout: float = None,
617
+ ignoreCase: bool = None,
618
+ ) -> None:
619
+ __tracebackhide__ = True
620
+ await self._not.to_have_text(expected, useInnerText, timeout, ignoreCase)
621
+
622
+ async def to_be_attached(
623
+ self, attached: bool = None, timeout: float = None
624
+ ) -> None:
625
+ __tracebackhide__ = True
626
+ if attached is None:
627
+ attached = True
628
+ attached_string = "attached" if attached else "detached"
629
+ await self._expect_impl(
630
+ "to.be.attached" if attached else "to.be.detached",
631
+ FrameExpectOptions(timeout=timeout),
632
+ None,
633
+ f"Locator expected to be {attached_string}",
634
+ 'Expect "to_be_attached"',
635
+ )
636
+
637
+ async def to_be_checked(
638
+ self, timeout: float = None, checked: bool = None, indeterminate: bool = None
639
+ ) -> None:
640
+ __tracebackhide__ = True
641
+ expected_value = {}
642
+ if indeterminate is not None:
643
+ expected_value["indeterminate"] = indeterminate
644
+ if checked is not None:
645
+ expected_value["checked"] = checked
646
+ checked_string: str
647
+ if indeterminate:
648
+ checked_string = "indeterminate"
649
+ else:
650
+ checked_string = "unchecked" if checked is False else "checked"
651
+ await self._expect_impl(
652
+ "to.be.checked",
653
+ FrameExpectOptions(timeout=timeout, expectedValue=expected_value),
654
+ None,
655
+ f"Locator expected to be {checked_string}",
656
+ 'Expect "to_be_checked"',
657
+ )
658
+
659
+ async def not_to_be_attached(
660
+ self, attached: bool = None, timeout: float = None
661
+ ) -> None:
662
+ __tracebackhide__ = True
663
+ await self._not.to_be_attached(attached=attached, timeout=timeout)
664
+
665
+ async def not_to_be_checked(self, timeout: float = None) -> None:
666
+ __tracebackhide__ = True
667
+ await self._not.to_be_checked(timeout)
668
+
669
+ async def to_be_disabled(self, timeout: float = None) -> None:
670
+ __tracebackhide__ = True
671
+ await self._expect_impl(
672
+ "to.be.disabled",
673
+ FrameExpectOptions(timeout=timeout),
674
+ None,
675
+ "Locator expected to be disabled",
676
+ 'Expect "to_be_disabled"',
677
+ )
678
+
679
+ async def not_to_be_disabled(self, timeout: float = None) -> None:
680
+ __tracebackhide__ = True
681
+ await self._not.to_be_disabled(timeout)
682
+
683
+ async def to_be_editable(
684
+ self, editable: bool = None, timeout: float = None
685
+ ) -> None:
686
+ __tracebackhide__ = True
687
+ if editable is None:
688
+ editable = True
689
+ editable_string = "editable" if editable else "readonly"
690
+ await self._expect_impl(
691
+ "to.be.editable" if editable else "to.be.readonly",
692
+ FrameExpectOptions(timeout=timeout),
693
+ None,
694
+ f"Locator expected to be {editable_string}",
695
+ 'Expect "to_be_editable"',
696
+ )
697
+
698
+ async def not_to_be_editable(
699
+ self, editable: bool = None, timeout: float = None
700
+ ) -> None:
701
+ __tracebackhide__ = True
702
+ await self._not.to_be_editable(editable, timeout)
703
+
704
+ async def to_be_empty(self, timeout: float = None) -> None:
705
+ __tracebackhide__ = True
706
+ await self._expect_impl(
707
+ "to.be.empty",
708
+ FrameExpectOptions(timeout=timeout),
709
+ None,
710
+ "Locator expected to be empty",
711
+ 'Expect "to_be_empty"',
712
+ )
713
+
714
+ async def not_to_be_empty(self, timeout: float = None) -> None:
715
+ __tracebackhide__ = True
716
+ await self._not.to_be_empty(timeout)
717
+
718
+ async def to_be_enabled(self, enabled: bool = None, timeout: float = None) -> None:
719
+ __tracebackhide__ = True
720
+ if enabled is None:
721
+ enabled = True
722
+ enabled_string = "enabled" if enabled else "disabled"
723
+ await self._expect_impl(
724
+ "to.be.enabled" if enabled else "to.be.disabled",
725
+ FrameExpectOptions(timeout=timeout),
726
+ None,
727
+ f"Locator expected to be {enabled_string}",
728
+ 'Expect "to_be_enabled"',
729
+ )
730
+
731
+ async def not_to_be_enabled(
732
+ self, enabled: bool = None, timeout: float = None
733
+ ) -> None:
734
+ __tracebackhide__ = True
735
+ await self._not.to_be_enabled(enabled, timeout)
736
+
737
+ async def to_be_hidden(self, timeout: float = None) -> None:
738
+ __tracebackhide__ = True
739
+ await self._expect_impl(
740
+ "to.be.hidden",
741
+ FrameExpectOptions(timeout=timeout),
742
+ None,
743
+ "Locator expected to be hidden",
744
+ 'Expect "to_be_hidden"',
745
+ )
746
+
747
+ async def not_to_be_hidden(self, timeout: float = None) -> None:
748
+ __tracebackhide__ = True
749
+ await self._not.to_be_hidden(timeout)
750
+
751
+ async def to_be_visible(self, visible: bool = None, timeout: float = None) -> None:
752
+ __tracebackhide__ = True
753
+ if visible is None:
754
+ visible = True
755
+ visible_string = "visible" if visible else "hidden"
756
+ await self._expect_impl(
757
+ "to.be.visible" if visible else "to.be.hidden",
758
+ FrameExpectOptions(timeout=timeout),
759
+ None,
760
+ f"Locator expected to be {visible_string}",
761
+ 'Expect "to_be_visible"',
762
+ )
763
+
764
+ async def not_to_be_visible(
765
+ self, visible: bool = None, timeout: float = None
766
+ ) -> None:
767
+ __tracebackhide__ = True
768
+ await self._not.to_be_visible(visible, timeout)
769
+
770
+ async def to_be_focused(self, timeout: float = None) -> None:
771
+ __tracebackhide__ = True
772
+ await self._expect_impl(
773
+ "to.be.focused",
774
+ FrameExpectOptions(timeout=timeout),
775
+ None,
776
+ "Locator expected to be focused",
777
+ 'Expect "to_be_focused"',
778
+ )
779
+
780
+ async def not_to_be_focused(self, timeout: float = None) -> None:
781
+ __tracebackhide__ = True
782
+ await self._not.to_be_focused(timeout)
783
+
784
+ async def to_be_in_viewport(
785
+ self, ratio: float = None, timeout: float = None
786
+ ) -> None:
787
+ __tracebackhide__ = True
788
+ await self._expect_impl(
789
+ "to.be.in.viewport",
790
+ FrameExpectOptions(timeout=timeout, expectedNumber=ratio),
791
+ None,
792
+ "Locator expected to be in viewport",
793
+ 'Expect "to_be_in_viewport"',
794
+ )
795
+
796
+ async def not_to_be_in_viewport(
797
+ self, ratio: float = None, timeout: float = None
798
+ ) -> None:
799
+ __tracebackhide__ = True
800
+ await self._not.to_be_in_viewport(ratio=ratio, timeout=timeout)
801
+
802
+ async def to_have_accessible_description(
803
+ self,
804
+ description: Union[str, Pattern[str]],
805
+ ignoreCase: bool = None,
806
+ timeout: float = None,
807
+ ) -> None:
808
+ __tracebackhide__ = True
809
+ expected_values = to_expected_text_values(
810
+ [description], ignoreCase=ignoreCase, normalize_white_space=True
811
+ )
812
+ await self._expect_impl(
813
+ "to.have.accessible.description",
814
+ FrameExpectOptions(expectedText=expected_values, timeout=timeout),
815
+ None,
816
+ "Locator expected to have accessible description",
817
+ 'Expect "to_have_accessible_description"',
818
+ )
819
+
820
+ async def not_to_have_accessible_description(
821
+ self,
822
+ name: Union[str, Pattern[str]],
823
+ ignoreCase: bool = None,
824
+ timeout: float = None,
825
+ ) -> None:
826
+ __tracebackhide__ = True
827
+ await self._not.to_have_accessible_description(name, ignoreCase, timeout)
828
+
829
+ async def to_have_accessible_name(
830
+ self,
831
+ name: Union[str, Pattern[str]],
832
+ ignoreCase: bool = None,
833
+ timeout: float = None,
834
+ ) -> None:
835
+ __tracebackhide__ = True
836
+ expected_values = to_expected_text_values(
837
+ [name], ignoreCase=ignoreCase, normalize_white_space=True
838
+ )
839
+ await self._expect_impl(
840
+ "to.have.accessible.name",
841
+ FrameExpectOptions(expectedText=expected_values, timeout=timeout),
842
+ None,
843
+ "Locator expected to have accessible name",
844
+ 'Expect "to_have_accessible_name"',
845
+ )
846
+
847
+ async def not_to_have_accessible_name(
848
+ self,
849
+ name: Union[str, Pattern[str]],
850
+ ignoreCase: bool = None,
851
+ timeout: float = None,
852
+ ) -> None:
853
+ __tracebackhide__ = True
854
+ await self._not.to_have_accessible_name(name, ignoreCase, timeout)
855
+
856
+ async def to_have_role(self, role: AriaRole, timeout: float = None) -> None:
857
+ __tracebackhide__ = True
858
+ if isinstance(role, Pattern):
859
+ raise Error('"role" argument in to_have_role must be a string')
860
+ expected_values = to_expected_text_values([role])
861
+ await self._expect_impl(
862
+ "to.have.role",
863
+ FrameExpectOptions(expectedText=expected_values, timeout=timeout),
864
+ None,
865
+ "Locator expected to have accessible role",
866
+ 'Expect "to_have_role"',
867
+ )
868
+
869
+ async def to_have_accessible_error_message(
870
+ self,
871
+ errorMessage: Union[str, Pattern[str]],
872
+ ignoreCase: bool = None,
873
+ timeout: float = None,
874
+ ) -> None:
875
+ __tracebackhide__ = True
876
+ expected_values = to_expected_text_values(
877
+ [errorMessage], ignoreCase=ignoreCase, normalize_white_space=True
878
+ )
879
+ await self._expect_impl(
880
+ "to.have.accessible.error.message",
881
+ FrameExpectOptions(expectedText=expected_values, timeout=timeout),
882
+ None,
883
+ "Locator expected to have accessible error message",
884
+ 'Expect "to_have_accessible_error_message"',
885
+ )
886
+
887
+ async def not_to_have_accessible_error_message(
888
+ self,
889
+ errorMessage: Union[str, Pattern[str]],
890
+ ignoreCase: bool = None,
891
+ timeout: float = None,
892
+ ) -> None:
893
+ __tracebackhide__ = True
894
+ await self._not.to_have_accessible_error_message(
895
+ errorMessage=errorMessage, ignoreCase=ignoreCase, timeout=timeout
896
+ )
897
+
898
+ async def not_to_have_role(self, role: AriaRole, timeout: float = None) -> None:
899
+ __tracebackhide__ = True
900
+ await self._not.to_have_role(role, timeout)
901
+
902
+ async def to_match_aria_snapshot(
903
+ self, expected: str, timeout: float = None
904
+ ) -> None:
905
+ __tracebackhide__ = True
906
+ await self._expect_impl(
907
+ "to.match.aria",
908
+ FrameExpectOptions(expectedValue=expected, timeout=timeout),
909
+ expected,
910
+ "Locator expected to match Aria snapshot",
911
+ 'Expect "to_match_aria_snapshot"',
912
+ )
913
+
914
+ async def not_to_match_aria_snapshot(
915
+ self, expected: str, timeout: float = None
916
+ ) -> None:
917
+ __tracebackhide__ = True
918
+ await self._not.to_match_aria_snapshot(expected, timeout)
919
+
920
+
921
+ class APIResponseAssertions:
922
+ def __init__(
923
+ self,
924
+ response: APIResponse,
925
+ timeout: float = None,
926
+ is_not: bool = False,
927
+ message: Optional[str] = None,
928
+ is_soft: bool = False,
929
+ ) -> None:
930
+ self._loop = response._loop
931
+ self._dispatcher_fiber = response._dispatcher_fiber
932
+ self._timeout = timeout
933
+ self._is_not = is_not
934
+ self._actual = response
935
+ self._custom_message = message
936
+ self._is_soft = is_soft
937
+
938
+ @property
939
+ def _not(self) -> "APIResponseAssertions":
940
+ return APIResponseAssertions(
941
+ self._actual,
942
+ self._timeout,
943
+ not self._is_not,
944
+ self._custom_message,
945
+ self._is_soft,
946
+ )
947
+
948
+ async def to_be_ok(self) -> None:
949
+ __tracebackhide__ = True
950
+ if self._is_not is not self._actual.ok:
951
+ return
952
+ message = f"Response status expected to be within [200..299] range, was '{self._actual.status}'"
953
+ if self._is_not:
954
+ message = message.replace("expected to", "expected not to")
955
+ out_message = self._custom_message or message
956
+ out_message += format_call_log(await self._actual._fetch_log())
957
+ content_type = self._actual.headers.get("content-type")
958
+ is_text_encoding = content_type and is_textual_mime_type(content_type)
959
+ text = await self._actual.text() if is_text_encoding else None
960
+ if text is not None:
961
+ out_message += f"\n Response Text:\n{text[:1000]}"
962
+ _record_soft_or_raise(AssertionError(out_message), self._is_soft)
963
+
964
+ async def not_to_be_ok(self) -> None:
965
+ __tracebackhide__ = True
966
+ await self._not.to_be_ok()
967
+
968
+
969
+ def expected_regex(
970
+ pattern: Pattern[str],
971
+ match_substring: bool,
972
+ normalize_white_space: bool,
973
+ ignoreCase: Optional[bool] = None,
974
+ ) -> ExpectedTextValue:
975
+ expected = ExpectedTextValue(
976
+ regexSource=pattern.pattern,
977
+ regexFlags=escape_regex_flags(pattern),
978
+ matchSubstring=match_substring,
979
+ normalizeWhiteSpace=normalize_white_space,
980
+ ignoreCase=ignoreCase,
981
+ )
982
+ if expected["ignoreCase"] is None:
983
+ del expected["ignoreCase"]
984
+ return expected
985
+
986
+
987
+ def to_expected_text_values(
988
+ items: Union[
989
+ Sequence[Pattern[str]], Sequence[str], Sequence[Union[str, Pattern[str]]]
990
+ ],
991
+ match_substring: bool = False,
992
+ normalize_white_space: bool = False,
993
+ ignoreCase: Optional[bool] = None,
994
+ ) -> Sequence[ExpectedTextValue]:
995
+ out: List[ExpectedTextValue] = []
996
+ assert isinstance(items, (list, tuple))
997
+ for item in items:
998
+ if isinstance(item, str):
999
+ o = ExpectedTextValue(
1000
+ string=item,
1001
+ matchSubstring=match_substring,
1002
+ normalizeWhiteSpace=normalize_white_space,
1003
+ ignoreCase=ignoreCase,
1004
+ )
1005
+ if o["ignoreCase"] is None:
1006
+ del o["ignoreCase"]
1007
+ out.append(o)
1008
+ elif isinstance(item, Pattern):
1009
+ out.append(
1010
+ expected_regex(item, match_substring, normalize_white_space, ignoreCase)
1011
+ )
1012
+ else:
1013
+ raise Error("value must be a string or regular expression")
1014
+ return out