playwright-ruby-client 0.0.8 → 1.58.1.alpha1

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 (209) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +4 -0
  3. data/CLAUDE/api_generation.md +28 -0
  4. data/CLAUDE/ci_expectations.md +23 -0
  5. data/CLAUDE/gem_release_flow.md +39 -0
  6. data/CLAUDE/past_upgrade_pr_patterns.md +42 -0
  7. data/CLAUDE/playwright_upgrade_workflow.md +35 -0
  8. data/CLAUDE/rspec_debugging.md +30 -0
  9. data/CLAUDE/unimplemented_examples.md +18 -0
  10. data/CLAUDE.md +32 -0
  11. data/CONTRIBUTING.md +5 -0
  12. data/README.md +60 -16
  13. data/documentation/README.md +33 -0
  14. data/documentation/babel.config.js +3 -0
  15. data/documentation/docs/api/api_request.md +7 -0
  16. data/documentation/docs/api/api_request_context.md +298 -0
  17. data/documentation/docs/api/api_response.md +114 -0
  18. data/documentation/docs/api/browser.md +237 -0
  19. data/documentation/docs/api/browser_context.md +503 -0
  20. data/documentation/docs/api/browser_type.md +184 -0
  21. data/documentation/docs/api/cdp_session.md +44 -0
  22. data/documentation/docs/api/clock.md +154 -0
  23. data/documentation/docs/api/console_message.md +85 -0
  24. data/documentation/docs/api/dialog.md +84 -0
  25. data/documentation/docs/api/download.md +111 -0
  26. data/documentation/docs/api/element_handle.md +694 -0
  27. data/documentation/docs/api/experimental/_category_.yml +3 -0
  28. data/documentation/docs/api/experimental/android.md +42 -0
  29. data/documentation/docs/api/experimental/android_device.md +109 -0
  30. data/documentation/docs/api/experimental/android_input.md +43 -0
  31. data/documentation/docs/api/experimental/android_socket.md +7 -0
  32. data/documentation/docs/api/experimental/android_web_view.md +7 -0
  33. data/documentation/docs/api/file_chooser.md +53 -0
  34. data/documentation/docs/api/frame.md +1218 -0
  35. data/documentation/docs/api/frame_locator.md +348 -0
  36. data/documentation/docs/api/js_handle.md +121 -0
  37. data/documentation/docs/api/keyboard.md +170 -0
  38. data/documentation/docs/api/locator.md +1495 -0
  39. data/documentation/docs/api/locator_assertions.md +827 -0
  40. data/documentation/docs/api/mouse.md +86 -0
  41. data/documentation/docs/api/page.md +1946 -0
  42. data/documentation/docs/api/page_assertions.md +65 -0
  43. data/documentation/docs/api/playwright.md +66 -0
  44. data/documentation/docs/api/request.md +255 -0
  45. data/documentation/docs/api/response.md +176 -0
  46. data/documentation/docs/api/route.md +205 -0
  47. data/documentation/docs/api/selectors.md +63 -0
  48. data/documentation/docs/api/touchscreen.md +22 -0
  49. data/documentation/docs/api/tracing.md +129 -0
  50. data/documentation/docs/api/web_socket.md +51 -0
  51. data/documentation/docs/api/worker.md +83 -0
  52. data/documentation/docs/article/api_coverage.mdx +11 -0
  53. data/documentation/docs/article/getting_started.md +161 -0
  54. data/documentation/docs/article/guides/_category_.yml +3 -0
  55. data/documentation/docs/article/guides/download_playwright_driver.md +55 -0
  56. data/documentation/docs/article/guides/inspector.md +31 -0
  57. data/documentation/docs/article/guides/launch_browser.md +121 -0
  58. data/documentation/docs/article/guides/playwright_on_alpine_linux.md +112 -0
  59. data/documentation/docs/article/guides/rails_integration.md +278 -0
  60. data/documentation/docs/article/guides/rails_integration_with_null_driver.md +145 -0
  61. data/documentation/docs/article/guides/recording_video.md +79 -0
  62. data/documentation/docs/article/guides/rspec_integration.md +59 -0
  63. data/documentation/docs/article/guides/semi_automation.md +71 -0
  64. data/documentation/docs/article/guides/use_storage_state.md +78 -0
  65. data/documentation/docs/include/api_coverage.md +671 -0
  66. data/documentation/docusaurus.config.js +114 -0
  67. data/documentation/package.json +39 -0
  68. data/documentation/sidebars.js +15 -0
  69. data/documentation/src/components/HomepageFeatures.js +61 -0
  70. data/documentation/src/components/HomepageFeatures.module.css +13 -0
  71. data/documentation/src/css/custom.css +44 -0
  72. data/documentation/src/pages/index.js +49 -0
  73. data/documentation/src/pages/index.module.css +41 -0
  74. data/documentation/src/pages/markdown-page.md +7 -0
  75. data/documentation/static/.nojekyll +0 -0
  76. data/documentation/static/img/playwright-logo.svg +9 -0
  77. data/documentation/static/img/playwright-ruby-client.png +0 -0
  78. data/documentation/static/img/undraw_dropdown_menu.svg +1 -0
  79. data/documentation/static/img/undraw_web_development.svg +1 -0
  80. data/documentation/static/img/undraw_windows.svg +1 -0
  81. data/documentation/yarn.lock +9005 -0
  82. data/lib/playwright/{input_types/android_input.rb → android_input_impl.rb} +5 -1
  83. data/lib/playwright/api_implementation.rb +18 -0
  84. data/lib/playwright/api_response_impl.rb +77 -0
  85. data/lib/playwright/channel.rb +62 -1
  86. data/lib/playwright/channel_owner.rb +70 -7
  87. data/lib/playwright/channel_owners/android.rb +16 -3
  88. data/lib/playwright/channel_owners/android_device.rb +22 -66
  89. data/lib/playwright/channel_owners/api_request_context.rb +247 -0
  90. data/lib/playwright/channel_owners/artifact.rb +40 -0
  91. data/lib/playwright/channel_owners/binding_call.rb +70 -0
  92. data/lib/playwright/channel_owners/browser.rb +114 -22
  93. data/lib/playwright/channel_owners/browser_context.rb +589 -15
  94. data/lib/playwright/channel_owners/browser_type.rb +90 -1
  95. data/lib/playwright/channel_owners/cdp_session.rb +19 -0
  96. data/lib/playwright/channel_owners/dialog.rb +32 -0
  97. data/lib/playwright/channel_owners/element_handle.rb +107 -43
  98. data/lib/playwright/channel_owners/fetch_request.rb +8 -0
  99. data/lib/playwright/channel_owners/frame.rb +334 -104
  100. data/lib/playwright/channel_owners/js_handle.rb +9 -13
  101. data/lib/playwright/channel_owners/local_utils.rb +82 -0
  102. data/lib/playwright/channel_owners/page.rb +778 -95
  103. data/lib/playwright/channel_owners/playwright.rb +25 -30
  104. data/lib/playwright/channel_owners/request.rb +120 -18
  105. data/lib/playwright/channel_owners/response.rb +113 -0
  106. data/lib/playwright/channel_owners/route.rb +181 -0
  107. data/lib/playwright/channel_owners/stream.rb +30 -0
  108. data/lib/playwright/channel_owners/tracing.rb +117 -0
  109. data/lib/playwright/channel_owners/web_socket.rb +96 -0
  110. data/lib/playwright/channel_owners/worker.rb +46 -0
  111. data/lib/playwright/channel_owners/writable_stream.rb +14 -0
  112. data/lib/playwright/clock_impl.rb +67 -0
  113. data/lib/playwright/connection.rb +111 -63
  114. data/lib/playwright/console_message_impl.rb +29 -0
  115. data/lib/playwright/download_impl.rb +32 -0
  116. data/lib/playwright/errors.rb +42 -5
  117. data/lib/playwright/event_emitter.rb +17 -3
  118. data/lib/playwright/event_emitter_proxy.rb +49 -0
  119. data/lib/playwright/events.rb +10 -5
  120. data/lib/playwright/file_chooser_impl.rb +24 -0
  121. data/lib/playwright/frame_locator_impl.rb +66 -0
  122. data/lib/playwright/har_router.rb +89 -0
  123. data/lib/playwright/http_headers.rb +14 -0
  124. data/lib/playwright/input_files.rb +102 -15
  125. data/lib/playwright/javascript/expression.rb +7 -11
  126. data/lib/playwright/javascript/regex.rb +23 -0
  127. data/lib/playwright/javascript/source_url.rb +16 -0
  128. data/lib/playwright/javascript/value_parser.rb +108 -19
  129. data/lib/playwright/javascript/value_serializer.rb +47 -8
  130. data/lib/playwright/javascript/visitor_info.rb +26 -0
  131. data/lib/playwright/javascript.rb +2 -10
  132. data/lib/playwright/{input_types/keyboard.rb → keyboard_impl.rb} +6 -2
  133. data/lib/playwright/locator_assertions_impl.rb +571 -0
  134. data/lib/playwright/locator_impl.rb +544 -0
  135. data/lib/playwright/locator_utils.rb +136 -0
  136. data/lib/playwright/mouse_impl.rb +57 -0
  137. data/lib/playwright/page_assertions_impl.rb +154 -0
  138. data/lib/playwright/playwright_api.rb +102 -30
  139. data/lib/playwright/raw_headers.rb +61 -0
  140. data/lib/playwright/route_handler.rb +78 -0
  141. data/lib/playwright/select_option_values.rb +34 -13
  142. data/lib/playwright/selectors_impl.rb +45 -0
  143. data/lib/playwright/test.rb +102 -0
  144. data/lib/playwright/timeout_settings.rb +9 -4
  145. data/lib/playwright/touchscreen_impl.rb +14 -0
  146. data/lib/playwright/transport.rb +61 -10
  147. data/lib/playwright/url_matcher.rb +24 -2
  148. data/lib/playwright/utils.rb +48 -13
  149. data/lib/playwright/version.rb +2 -1
  150. data/lib/playwright/video.rb +54 -0
  151. data/lib/playwright/waiter.rb +166 -0
  152. data/lib/playwright/web_socket_client.rb +167 -0
  153. data/lib/playwright/web_socket_transport.rb +116 -0
  154. data/lib/playwright.rb +188 -11
  155. data/lib/playwright_api/android.rb +46 -11
  156. data/lib/playwright_api/android_device.rb +182 -31
  157. data/lib/playwright_api/android_input.rb +22 -13
  158. data/lib/playwright_api/android_socket.rb +18 -0
  159. data/lib/playwright_api/android_web_view.rb +24 -0
  160. data/lib/playwright_api/api_request.rb +26 -0
  161. data/lib/playwright_api/api_request_context.rb +311 -0
  162. data/lib/playwright_api/api_response.rb +92 -0
  163. data/lib/playwright_api/browser.rb +116 -103
  164. data/lib/playwright_api/browser_context.rb +290 -389
  165. data/lib/playwright_api/browser_type.rb +96 -118
  166. data/lib/playwright_api/cdp_session.rb +36 -39
  167. data/lib/playwright_api/clock.rb +121 -0
  168. data/lib/playwright_api/console_message.rb +35 -19
  169. data/lib/playwright_api/dialog.rb +53 -50
  170. data/lib/playwright_api/download.rb +49 -43
  171. data/lib/playwright_api/element_handle.rb +354 -402
  172. data/lib/playwright_api/file_chooser.rb +15 -18
  173. data/lib/playwright_api/frame.rb +703 -603
  174. data/lib/playwright_api/frame_locator.rb +285 -0
  175. data/lib/playwright_api/js_handle.rb +50 -76
  176. data/lib/playwright_api/keyboard.rb +67 -146
  177. data/lib/playwright_api/locator.rb +1304 -0
  178. data/lib/playwright_api/locator_assertions.rb +704 -0
  179. data/lib/playwright_api/mouse.rb +23 -29
  180. data/lib/playwright_api/page.rb +1196 -1176
  181. data/lib/playwright_api/page_assertions.rb +60 -0
  182. data/lib/playwright_api/playwright.rb +54 -122
  183. data/lib/playwright_api/request.rb +112 -74
  184. data/lib/playwright_api/response.rb +92 -20
  185. data/lib/playwright_api/route.rb +152 -62
  186. data/lib/playwright_api/selectors.rb +47 -61
  187. data/lib/playwright_api/touchscreen.rb +8 -2
  188. data/lib/playwright_api/tracing.rb +128 -0
  189. data/lib/playwright_api/web_socket.rb +43 -5
  190. data/lib/playwright_api/worker.rb +74 -34
  191. data/playwright.gemspec +14 -9
  192. data/sig/playwright.rbs +658 -0
  193. metadata +216 -50
  194. data/docs/api_coverage.md +0 -354
  195. data/lib/playwright/channel_owners/chromium_browser.rb +0 -8
  196. data/lib/playwright/channel_owners/chromium_browser_context.rb +0 -8
  197. data/lib/playwright/channel_owners/console_message.rb +0 -21
  198. data/lib/playwright/channel_owners/firefox_browser.rb +0 -8
  199. data/lib/playwright/channel_owners/selectors.rb +0 -4
  200. data/lib/playwright/channel_owners/webkit_browser.rb +0 -8
  201. data/lib/playwright/input_type.rb +0 -19
  202. data/lib/playwright/input_types/mouse.rb +0 -4
  203. data/lib/playwright/input_types/touchscreen.rb +0 -4
  204. data/lib/playwright/javascript/function.rb +0 -67
  205. data/lib/playwright/wait_helper.rb +0 -73
  206. data/lib/playwright_api/accessibility.rb +0 -93
  207. data/lib/playwright_api/binding_call.rb +0 -23
  208. data/lib/playwright_api/chromium_browser_context.rb +0 -57
  209. data/lib/playwright_api/video.rb +0 -24
@@ -1,49 +1,15 @@
1
1
  module Playwright
2
- # - extends: [EventEmitter]
3
- #
2
+ #
4
3
  # Page provides methods to interact with a single tab in a `Browser`, or an
5
- # [extension background page](https://developer.chrome.com/extensions/background_pages) in Chromium. One [Browser]
6
- # instance might have multiple [Page] instances.
7
- #
4
+ # [extension background page](https://developer.chrome.com/extensions/background_pages) in Chromium. One `Browser`
5
+ # instance might have multiple `Page` instances.
6
+ #
8
7
  # This example creates a page, navigates it to a URL, and then saves a screenshot:
9
- #
10
8
  #
11
- # ```js
12
- # const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'.
13
- #
14
- # (async () => {
15
- # const browser = await webkit.launch();
16
- # const context = await browser.newContext();
17
- # const page = await context.newPage();
18
- # await page.goto('https://example.com');
19
- # await page.screenshot({path: 'screenshot.png'});
20
- # await browser.close();
21
- # })();
22
- # ```
23
- #
24
- # ```python async
25
- # import asyncio
26
- # from playwright.async_api import async_playwright
27
- #
28
- # async def run(playwright):
29
- # webkit = playwright.webkit
30
- # browser = await webkit.launch()
31
- # context = await browser.new_context()
32
- # page = await context.new_page()
33
- # await page.goto("https://example.com")
34
- # await page.screenshot(path="screenshot.png")
35
- # await browser.close()
36
- #
37
- # async def main():
38
- # async with async_playwright() as playwright:
39
- # await run(playwright)
40
- # asyncio.run(main())
41
- # ```
42
- #
43
9
  # ```python sync
44
- # from playwright.sync_api import sync_playwright
45
- #
46
- # def run(playwright):
10
+ # from playwright.sync_api import sync_playwright, Playwright
11
+ #
12
+ # def run(playwright: Playwright):
47
13
  # webkit = playwright.webkit
48
14
  # browser = webkit.launch()
49
15
  # context = browser.new_context()
@@ -51,38 +17,23 @@ module Playwright
51
17
  # page.goto("https://example.com")
52
18
  # page.screenshot(path="screenshot.png")
53
19
  # browser.close()
54
- #
20
+ #
55
21
  # with sync_playwright() as playwright:
56
22
  # run(playwright)
57
23
  # ```
58
- #
24
+ #
59
25
  # The Page class emits various events (described below) which can be handled using any of Node's native
60
26
  # [`EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter) methods, such as `on`, `once` or
61
27
  # `removeListener`.
62
- #
28
+ #
63
29
  # This example logs a message for a single page `load` event:
64
- #
65
30
  #
66
- # ```js
67
- # page.once('load', () => console.log('Page loaded!'));
68
- # ```
69
- #
70
31
  # ```py
71
32
  # page.once("load", lambda: print("page loaded!"))
72
33
  # ```
73
- #
34
+ #
74
35
  # To unsubscribe from events use the `removeListener` method:
75
- #
76
36
  #
77
- # ```js
78
- # function logRequest(interceptedRequest) {
79
- # console.log('A request was made:', interceptedRequest.url());
80
- # }
81
- # page.on('request', logRequest);
82
- # // Sometime later...
83
- # page.removeListener('request', logRequest);
84
- # ```
85
- #
86
37
  # ```py
87
38
  # def log_request(intercepted_request):
88
39
  # print("a request was made:", intercepted_request.url)
@@ -92,14 +43,10 @@ module Playwright
92
43
  # ```
93
44
  class Page < PlaywrightApi
94
45
 
95
- def accessibility # property
96
- wrap_impl(@impl.accessibility)
97
- end
98
-
99
- # Browser-specific Coverage implementation, only available for Chromium atm. See
100
- # `ChromiumCoverage`(#class-chromiumcoverage) for more details.
101
- def coverage # property
102
- raise NotImplementedError.new('coverage is not implemented yet.')
46
+ #
47
+ # Playwright has ability to mock clock and passage of time.
48
+ def clock # property
49
+ wrap_impl(@impl.clock)
103
50
  end
104
51
 
105
52
  def keyboard # property
@@ -110,172 +57,92 @@ module Playwright
110
57
  wrap_impl(@impl.mouse)
111
58
  end
112
59
 
113
- def touchscreen # property
114
- wrap_impl(@impl.touchscreen)
115
- end
116
-
117
- # The method finds an element matching the specified selector within the page. If no elements match the selector, the
118
- # return value resolves to `null`.
119
- #
120
- # Shortcut for main frame's [`method: Frame.$`].
121
- def query_selector(selector)
122
- wrap_impl(@impl.query_selector(unwrap_impl(selector)))
123
- end
124
-
125
- # The method finds all elements matching the specified selector within the page. If no elements match the selector, the
126
- # return value resolves to `[]`.
127
- #
128
- # Shortcut for main frame's [`method: Frame.$$`].
129
- def query_selector_all(selector)
130
- wrap_impl(@impl.query_selector_all(unwrap_impl(selector)))
131
- end
132
-
133
- # The method finds an element matching the specified selector within the page and passes it as a first argument to
134
- # `pageFunction`. If no elements match the selector, the method throws an error. Returns the value of `pageFunction`.
135
- #
136
- # If `pageFunction` returns a [Promise], then [`method: Page.$eval`] would wait for the promise to resolve and return its
137
- # value.
138
- #
139
- # Examples:
140
- #
141
- #
142
- # ```js
143
- # const searchValue = await page.$eval('#search', el => el.value);
144
- # const preloadHref = await page.$eval('link[rel=preload]', el => el.href);
145
- # const html = await page.$eval('.main-container', (e, suffix) => e.outerHTML + suffix, 'hello');
146
- # ```
147
- #
148
- # ```python async
149
- # search_value = await page.eval_on_selector("#search", "el => el.value")
150
- # preload_href = await page.eval_on_selector("link[rel=preload]", "el => el.href")
151
- # html = await page.eval_on_selector(".main-container", "(e, suffix) => e.outer_html + suffix", "hello")
152
- # ```
153
- #
154
- # ```python sync
155
- # search_value = page.eval_on_selector("#search", "el => el.value")
156
- # preload_href = page.eval_on_selector("link[rel=preload]", "el => el.href")
157
- # html = page.eval_on_selector(".main-container", "(e, suffix) => e.outer_html + suffix", "hello")
158
- # ```
159
- #
160
- # Shortcut for main frame's [`method: Frame.$eval`].
161
- def eval_on_selector(selector, pageFunction, arg: nil)
162
- wrap_impl(@impl.eval_on_selector(unwrap_impl(selector), unwrap_impl(pageFunction), arg: unwrap_impl(arg)))
60
+ #
61
+ # API testing helper associated with this page. This method returns the same instance as
62
+ # [`property: BrowserContext.request`] on the page's context. See [`property: BrowserContext.request`] for more details.
63
+ def request # property
64
+ wrap_impl(@impl.request)
163
65
  end
164
66
 
165
- # The method finds all elements matching the specified selector within the page and passes an array of matched elements as
166
- # a first argument to `pageFunction`. Returns the result of `pageFunction` invocation.
167
- #
168
- # If `pageFunction` returns a [Promise], then [`method: Page.$$eval`] would wait for the promise to resolve and return its
169
- # value.
170
- #
171
- # Examples:
172
- #
173
- #
174
- # ```js
175
- # const divCounts = await page.$$eval('div', (divs, min) => divs.length >= min, 10);
176
- # ```
177
- #
178
- # ```python async
179
- # div_counts = await page.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10)
180
- # ```
181
- #
182
- # ```python sync
183
- # div_counts = page.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10)
184
- # ```
185
- def eval_on_selector_all(selector, pageFunction, arg: nil)
186
- wrap_impl(@impl.eval_on_selector_all(unwrap_impl(selector), unwrap_impl(pageFunction), arg: unwrap_impl(arg)))
67
+ def touchscreen # property
68
+ wrap_impl(@impl.touchscreen)
187
69
  end
188
70
 
71
+ #
189
72
  # Adds a script which would be evaluated in one of the following scenarios:
190
73
  # - Whenever the page is navigated.
191
- # - Whenever the child frame is attached or navigated. In this case, the script is evaluated in the context of the newly
192
- # attached frame.
193
- #
74
+ # - Whenever the child frame is attached or navigated. In this case, the script is evaluated in the context of the newly attached frame.
75
+ #
194
76
  # The script is evaluated after the document was created but before any of its scripts were run. This is useful to amend
195
77
  # the JavaScript environment, e.g. to seed `Math.random`.
196
- #
197
- # An example of overriding `Math.random` before the page loads:
198
- #
199
78
  #
200
- # ```js browser
201
- # // preload.js
202
- # Math.random = () => 42;
203
- # ```
204
- #
79
+ # **Usage**
80
+ #
81
+ # An example of overriding `Math.random` before the page loads:
205
82
  #
206
- # ```js
207
- # // In your playwright script, assuming the preload.js file is in same directory
208
- # await page.addInitScript({ path: './preload.js' });
209
- # ```
210
- #
211
- # ```python async
212
- # # in your playwright script, assuming the preload.js file is in same directory
213
- # await page.add_init_script(path="./preload.js")
214
- # ```
215
- #
216
83
  # ```python sync
217
84
  # # in your playwright script, assuming the preload.js file is in same directory
218
85
  # page.add_init_script(path="./preload.js")
219
86
  # ```
220
- #
221
- # > NOTE: The order of evaluation of multiple scripts installed via [`method: BrowserContext.addInitScript`] and
87
+ #
88
+ # **NOTE**: The order of evaluation of multiple scripts installed via [`method: BrowserContext.addInitScript`] and
222
89
  # [`method: Page.addInitScript`] is not defined.
223
- def add_init_script(script, arg: nil)
224
- raise NotImplementedError.new('add_init_script is not implemented yet.')
90
+ def add_init_script(path: nil, script: nil)
91
+ wrap_impl(@impl.add_init_script(path: unwrap_impl(path), script: unwrap_impl(script)))
225
92
  end
226
93
 
94
+ #
227
95
  # Adds a `<script>` tag into the page with the desired url or content. Returns the added tag when the script's onload
228
96
  # fires or when the script content was injected into frame.
229
- #
230
- # Shortcut for main frame's [`method: Frame.addScriptTag`].
231
97
  def add_script_tag(content: nil, path: nil, type: nil, url: nil)
232
98
  wrap_impl(@impl.add_script_tag(content: unwrap_impl(content), path: unwrap_impl(path), type: unwrap_impl(type), url: unwrap_impl(url)))
233
99
  end
234
100
 
101
+ #
235
102
  # Adds a `<link rel="stylesheet">` tag into the page with the desired url or a `<style type="text/css">` tag with the
236
103
  # content. Returns the added tag when the stylesheet's onload fires or when the CSS content was injected into frame.
237
- #
238
- # Shortcut for main frame's [`method: Frame.addStyleTag`].
239
104
  def add_style_tag(content: nil, path: nil, url: nil)
240
105
  wrap_impl(@impl.add_style_tag(content: unwrap_impl(content), path: unwrap_impl(path), url: unwrap_impl(url)))
241
106
  end
242
107
 
108
+ #
243
109
  # Brings page to front (activates tab).
244
110
  def bring_to_front
245
- raise NotImplementedError.new('bring_to_front is not implemented yet.')
111
+ wrap_impl(@impl.bring_to_front)
246
112
  end
247
113
 
114
+ #
248
115
  # This method checks an element matching `selector` by performing the following steps:
249
- # 1. Find an element match matching `selector`. If there is none, wait until a matching element is attached to the DOM.
250
- # 1. Ensure that matched element is a checkbox or a radio input. If not, this method rejects. If the element is already
251
- # checked, this method returns immediately.
252
- # 1. Wait for [actionability](./actionability.md) checks on the matched element, unless `force` option is set. If the
253
- # element is detached during the checks, the whole action is retried.
116
+ # 1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
117
+ # 1. Ensure that matched element is a checkbox or a radio input. If not, this method throws. If the element is already checked, this method returns immediately.
118
+ # 1. Wait for [actionability](../actionability.md) checks on the matched element, unless `force` option is set. If the element is detached during the checks, the whole action is retried.
254
119
  # 1. Scroll the element into view if needed.
255
120
  # 1. Use [`property: Page.mouse`] to click in the center of the element.
256
- # 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
257
- # 1. Ensure that the element is now checked. If not, this method rejects.
258
- #
259
- # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
260
- # Passing zero timeout disables this.
261
- #
262
- # Shortcut for main frame's [`method: Frame.check`].
263
- def check(selector, force: nil, noWaitAfter: nil, timeout: nil)
264
- raise NotImplementedError.new('check is not implemented yet.')
121
+ # 1. Ensure that the element is now checked. If not, this method throws.
122
+ #
123
+ # When all steps combined have not finished during the specified `timeout`, this method throws a
124
+ # `TimeoutError`. Passing zero timeout disables this.
125
+ def check(
126
+ selector,
127
+ force: nil,
128
+ noWaitAfter: nil,
129
+ position: nil,
130
+ strict: nil,
131
+ timeout: nil,
132
+ trial: nil)
133
+ wrap_impl(@impl.check(unwrap_impl(selector), force: unwrap_impl(force), noWaitAfter: unwrap_impl(noWaitAfter), position: unwrap_impl(position), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout), trial: unwrap_impl(trial)))
265
134
  end
266
135
 
136
+ #
267
137
  # This method clicks an element matching `selector` by performing the following steps:
268
- # 1. Find an element match matching `selector`. If there is none, wait until a matching element is attached to the DOM.
269
- # 1. Wait for [actionability](./actionability.md) checks on the matched element, unless `force` option is set. If the
270
- # element is detached during the checks, the whole action is retried.
138
+ # 1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
139
+ # 1. Wait for [actionability](../actionability.md) checks on the matched element, unless `force` option is set. If the element is detached during the checks, the whole action is retried.
271
140
  # 1. Scroll the element into view if needed.
272
141
  # 1. Use [`property: Page.mouse`] to click in the center of the element, or the specified `position`.
273
142
  # 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
274
- #
275
- # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
276
- # Passing zero timeout disables this.
277
- #
278
- # Shortcut for main frame's [`method: Frame.click`].
143
+ #
144
+ # When all steps combined have not finished during the specified `timeout`, this method throws a
145
+ # `TimeoutError`. Passing zero timeout disables this.
279
146
  def click(
280
147
  selector,
281
148
  button: nil,
@@ -285,46 +152,47 @@ module Playwright
285
152
  modifiers: nil,
286
153
  noWaitAfter: nil,
287
154
  position: nil,
288
- timeout: nil)
289
- wrap_impl(@impl.click(unwrap_impl(selector), button: unwrap_impl(button), clickCount: unwrap_impl(clickCount), delay: unwrap_impl(delay), force: unwrap_impl(force), modifiers: unwrap_impl(modifiers), noWaitAfter: unwrap_impl(noWaitAfter), position: unwrap_impl(position), timeout: unwrap_impl(timeout)))
155
+ strict: nil,
156
+ timeout: nil,
157
+ trial: nil)
158
+ wrap_impl(@impl.click(unwrap_impl(selector), button: unwrap_impl(button), clickCount: unwrap_impl(clickCount), delay: unwrap_impl(delay), force: unwrap_impl(force), modifiers: unwrap_impl(modifiers), noWaitAfter: unwrap_impl(noWaitAfter), position: unwrap_impl(position), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout), trial: unwrap_impl(trial)))
290
159
  end
291
160
 
161
+ #
292
162
  # If `runBeforeUnload` is `false`, does not run any unload handlers and waits for the page to be closed. If
293
163
  # `runBeforeUnload` is `true` the method will run unload handlers, but will **not** wait for the page to close.
294
- #
164
+ #
295
165
  # By default, `page.close()` **does not** run `beforeunload` handlers.
296
- #
297
- # > NOTE: if `runBeforeUnload` is passed as true, a `beforeunload` dialog might be summoned and should be handled manually
298
- # via [`event: Page.dialog`] event.
299
- def close(runBeforeUnload: nil)
300
- wrap_impl(@impl.close(runBeforeUnload: unwrap_impl(runBeforeUnload)))
166
+ #
167
+ # **NOTE**: if `runBeforeUnload` is passed as true, a `beforeunload` dialog might be summoned and should be handled
168
+ # manually via [`event: Page.dialog`] event.
169
+ def close(reason: nil, runBeforeUnload: nil)
170
+ wrap_impl(@impl.close(reason: unwrap_impl(reason), runBeforeUnload: unwrap_impl(runBeforeUnload)))
301
171
  end
302
172
 
173
+ #
303
174
  # Gets the full HTML contents of the page, including the doctype.
304
175
  def content
305
176
  wrap_impl(@impl.content)
306
177
  end
307
178
 
179
+ #
308
180
  # Get the browser context that the page belongs to.
309
181
  def context
310
182
  wrap_impl(@impl.context)
311
183
  end
312
184
 
185
+ #
313
186
  # This method double clicks an element matching `selector` by performing the following steps:
314
- # 1. Find an element match matching `selector`. If there is none, wait until a matching element is attached to the DOM.
315
- # 1. Wait for [actionability](./actionability.md) checks on the matched element, unless `force` option is set. If the
316
- # element is detached during the checks, the whole action is retried.
187
+ # 1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
188
+ # 1. Wait for [actionability](../actionability.md) checks on the matched element, unless `force` option is set. If the element is detached during the checks, the whole action is retried.
317
189
  # 1. Scroll the element into view if needed.
318
190
  # 1. Use [`property: Page.mouse`] to double click in the center of the element, or the specified `position`.
319
- # 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. Note that if the
320
- # first click of the `dblclick()` triggers a navigation event, this method will reject.
321
- #
322
- # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
323
- # Passing zero timeout disables this.
324
- #
325
- # > NOTE: `page.dblclick()` dispatches two `click` events and a single `dblclick` event.
326
- #
327
- # Shortcut for main frame's [`method: Frame.dblclick`].
191
+ #
192
+ # When all steps combined have not finished during the specified `timeout`, this method throws a
193
+ # `TimeoutError`. Passing zero timeout disables this.
194
+ #
195
+ # **NOTE**: `page.dblclick()` dispatches two `click` events and a single `dblclick` event.
328
196
  def dblclick(
329
197
  selector,
330
198
  button: nil,
@@ -333,366 +201,255 @@ module Playwright
333
201
  modifiers: nil,
334
202
  noWaitAfter: nil,
335
203
  position: nil,
336
- timeout: nil)
337
- wrap_impl(@impl.dblclick(unwrap_impl(selector), button: unwrap_impl(button), delay: unwrap_impl(delay), force: unwrap_impl(force), modifiers: unwrap_impl(modifiers), noWaitAfter: unwrap_impl(noWaitAfter), position: unwrap_impl(position), timeout: unwrap_impl(timeout)))
204
+ strict: nil,
205
+ timeout: nil,
206
+ trial: nil)
207
+ wrap_impl(@impl.dblclick(unwrap_impl(selector), button: unwrap_impl(button), delay: unwrap_impl(delay), force: unwrap_impl(force), modifiers: unwrap_impl(modifiers), noWaitAfter: unwrap_impl(noWaitAfter), position: unwrap_impl(position), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout), trial: unwrap_impl(trial)))
338
208
  end
339
209
 
340
- # The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the elment, `click`
341
- # is dispatched. This is equivalend to calling
210
+ #
211
+ # The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the element, `click`
212
+ # is dispatched. This is equivalent to calling
342
213
  # [element.click()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click).
343
- #
344
214
  #
345
- # ```js
346
- # await page.dispatchEvent('button#submit', 'click');
347
- # ```
348
- #
349
- # ```python async
350
- # await page.dispatch_event("button#submit", "click")
351
- # ```
352
- #
215
+ # **Usage**
216
+ #
353
217
  # ```python sync
354
218
  # page.dispatch_event("button#submit", "click")
355
219
  # ```
356
- #
357
- # Under the hood, it creates an instance of an event based on the given `type`, initializes it with `eventInit` properties
358
- # and dispatches it on the element. Events are `composed`, `cancelable` and bubble by default.
359
- #
360
- # Since `eventInit` is event-specific, please refer to the events documentation for the lists of initial properties:
220
+ #
221
+ # Under the hood, it creates an instance of an event based on the given `type`, initializes it with
222
+ # `eventInit` properties and dispatches it on the element. Events are `composed`, `cancelable` and bubble by
223
+ # default.
224
+ #
225
+ # Since `eventInit` is event-specific, please refer to the events documentation for the lists of initial
226
+ # properties:
227
+ # - [DeviceMotionEvent](https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent/DeviceMotionEvent)
228
+ # - [DeviceOrientationEvent](https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent/DeviceOrientationEvent)
361
229
  # - [DragEvent](https://developer.mozilla.org/en-US/docs/Web/API/DragEvent/DragEvent)
230
+ # - [Event](https://developer.mozilla.org/en-US/docs/Web/API/Event/Event)
362
231
  # - [FocusEvent](https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/FocusEvent)
363
232
  # - [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/KeyboardEvent)
364
233
  # - [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/MouseEvent)
365
234
  # - [PointerEvent](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/PointerEvent)
366
235
  # - [TouchEvent](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/TouchEvent)
367
- # - [Event](https://developer.mozilla.org/en-US/docs/Web/API/Event/Event)
368
- #
236
+ # - [WheelEvent](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/WheelEvent)
237
+ #
369
238
  # You can also specify `JSHandle` as the property value if you want live objects to be passed into the event:
370
- #
371
239
  #
372
- # ```js
373
- # // Note you can only create DataTransfer in Chromium and Firefox
374
- # const dataTransfer = await page.evaluateHandle(() => new DataTransfer());
375
- # await page.dispatchEvent('#source', 'dragstart', { dataTransfer });
376
- # ```
377
- #
378
- # ```python async
379
- # # note you can only create data_transfer in chromium and firefox
380
- # data_transfer = await page.evaluate_handle("new DataTransfer()")
381
- # await page.dispatch_event("#source", "dragstart", { "dataTransfer": data_transfer })
382
- # ```
383
- #
384
240
  # ```python sync
385
241
  # # note you can only create data_transfer in chromium and firefox
386
242
  # data_transfer = page.evaluate_handle("new DataTransfer()")
387
243
  # page.dispatch_event("#source", "dragstart", { "dataTransfer": data_transfer })
388
244
  # ```
389
- def dispatch_event(selector, type, eventInit: nil, timeout: nil)
390
- raise NotImplementedError.new('dispatch_event is not implemented yet.')
391
- end
392
-
393
- #
394
- #
395
- # ```js
396
- # await page.evaluate(() => matchMedia('screen').matches);
397
- # // → true
398
- # await page.evaluate(() => matchMedia('print').matches);
399
- # // false
400
- #
401
- # await page.emulateMedia({ media: 'print' });
402
- # await page.evaluate(() => matchMedia('screen').matches);
403
- # // → false
404
- # await page.evaluate(() => matchMedia('print').matches);
405
- # // → true
406
- #
407
- # await page.emulateMedia({});
408
- # await page.evaluate(() => matchMedia('screen').matches);
409
- # // → true
410
- # await page.evaluate(() => matchMedia('print').matches);
411
- # // false
412
- # ```
413
- #
414
- # ```python async
415
- # await page.evaluate("matchMedia('screen').matches")
416
- # # → True
417
- # await page.evaluate("matchMedia('print').matches")
418
- # # → False
419
- #
420
- # await page.emulate_media(media="print")
421
- # await page.evaluate("matchMedia('screen').matches")
422
- # # → False
423
- # await page.evaluate("matchMedia('print').matches")
424
- # # → True
425
- #
426
- # await page.emulate_media()
427
- # await page.evaluate("matchMedia('screen').matches")
428
- # # → True
429
- # await page.evaluate("matchMedia('print').matches")
430
- # # False
431
- # ```
432
- #
245
+ def dispatch_event(
246
+ selector,
247
+ type,
248
+ eventInit: nil,
249
+ strict: nil,
250
+ timeout: nil)
251
+ wrap_impl(@impl.dispatch_event(unwrap_impl(selector), unwrap_impl(type), eventInit: unwrap_impl(eventInit), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
252
+ end
253
+
254
+ #
255
+ # This method drags the source element to the target element.
256
+ # It will first move to the source element, perform a `mousedown`,
257
+ # then move to the target element and perform a `mouseup`.
258
+ #
259
+ # **Usage**
260
+ #
261
+ # ```python sync
262
+ # page.drag_and_drop("#source", "#target")
263
+ # # or specify exact positions relative to the top-left corners of the elements:
264
+ # page.drag_and_drop(
265
+ # "#source",
266
+ # "#target",
267
+ # source_position={"x": 34, "y": 7},
268
+ # target_position={"x": 10, "y": 20}
269
+ # )
270
+ # ```
271
+ def drag_and_drop(
272
+ source,
273
+ target,
274
+ force: nil,
275
+ noWaitAfter: nil,
276
+ sourcePosition: nil,
277
+ steps: nil,
278
+ strict: nil,
279
+ targetPosition: nil,
280
+ timeout: nil,
281
+ trial: nil)
282
+ wrap_impl(@impl.drag_and_drop(unwrap_impl(source), unwrap_impl(target), force: unwrap_impl(force), noWaitAfter: unwrap_impl(noWaitAfter), sourcePosition: unwrap_impl(sourcePosition), steps: unwrap_impl(steps), strict: unwrap_impl(strict), targetPosition: unwrap_impl(targetPosition), timeout: unwrap_impl(timeout), trial: unwrap_impl(trial)))
283
+ end
284
+
285
+ #
286
+ # This method changes the `CSS media type` through the `media` argument, and/or the `'prefers-colors-scheme'` media feature, using the `colorScheme` argument.
287
+ #
288
+ # **Usage**
289
+ #
433
290
  # ```python sync
434
291
  # page.evaluate("matchMedia('screen').matches")
435
292
  # # → True
436
293
  # page.evaluate("matchMedia('print').matches")
437
294
  # # → False
438
- #
295
+ #
439
296
  # page.emulate_media(media="print")
440
297
  # page.evaluate("matchMedia('screen').matches")
441
298
  # # → False
442
299
  # page.evaluate("matchMedia('print').matches")
443
300
  # # → True
444
- #
301
+ #
445
302
  # page.emulate_media()
446
303
  # page.evaluate("matchMedia('screen').matches")
447
304
  # # → True
448
305
  # page.evaluate("matchMedia('print').matches")
449
306
  # # → False
450
307
  # ```
451
- #
452
- #
453
- # ```js
454
- # await page.emulateMedia({ colorScheme: 'dark' });
455
- # await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches);
456
- # // → true
457
- # await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches);
458
- # // → false
459
- # await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches);
460
- # // → false
461
- # ```
462
- #
463
- # ```python async
464
- # await page.emulate_media(color_scheme="dark")
465
- # await page.evaluate("matchMedia('(prefers-color-scheme: dark)').matches")
466
- # # → True
467
- # await page.evaluate("matchMedia('(prefers-color-scheme: light)').matches")
468
- # # → False
469
- # await page.evaluate("matchMedia('(prefers-color-scheme: no-preference)').matches")
470
- # # → False
471
- # ```
472
- #
308
+ #
473
309
  # ```python sync
474
310
  # page.emulate_media(color_scheme="dark")
475
311
  # page.evaluate("matchMedia('(prefers-color-scheme: dark)').matches")
476
312
  # # → True
477
313
  # page.evaluate("matchMedia('(prefers-color-scheme: light)').matches")
478
314
  # # → False
479
- # page.evaluate("matchMedia('(prefers-color-scheme: no-preference)').matches")
480
315
  # ```
481
- def emulate_media(params)
482
- raise NotImplementedError.new('emulate_media is not implemented yet.')
316
+ def emulate_media(
317
+ colorScheme: nil,
318
+ contrast: nil,
319
+ forcedColors: nil,
320
+ media: nil,
321
+ reducedMotion: nil)
322
+ wrap_impl(@impl.emulate_media(colorScheme: unwrap_impl(colorScheme), contrast: unwrap_impl(contrast), forcedColors: unwrap_impl(forcedColors), media: unwrap_impl(media), reducedMotion: unwrap_impl(reducedMotion)))
483
323
  end
484
324
 
485
- # Returns the value of the `pageFunction` invocation.
486
- #
487
- # If the function passed to the [`method: Page.evaluate`] returns a [Promise], then [`method: Page.evaluate`] would wait
488
- # for the promise to resolve and return its value.
489
- #
490
- # If the function passed to the [`method: Page.evaluate`] returns a non-[Serializable] value,
491
- # then[ method: `Page.evaluate`] resolves to `undefined`. DevTools Protocol also supports transferring some additional
492
- # values that are not serializable by `JSON`: `-0`, `NaN`, `Infinity`, `-Infinity`, and bigint literals.
493
- #
494
- # Passing argument to `pageFunction`:
495
- #
496
- #
497
- # ```js
498
- # const result = await page.evaluate(([x, y]) => {
499
- # return Promise.resolve(x * y);
500
- # }, [7, 8]);
501
- # console.log(result); // prints "56"
325
+ #
326
+ # The method finds an element matching the specified selector within the page and passes it as a first argument to
327
+ # `expression`. If no elements match the selector, the method throws an error. Returns the value of
328
+ # `expression`.
329
+ #
330
+ # If `expression` returns a [Promise], then [`method: Page.evalOnSelector`] would wait for the promise to resolve and
331
+ # return its value.
332
+ #
333
+ # **Usage**
334
+ #
335
+ # ```python sync
336
+ # search_value = page.eval_on_selector("#search", "el => el.value")
337
+ # preload_href = page.eval_on_selector("link[rel=preload]", "el => el.href")
338
+ # html = page.eval_on_selector(".main-container", "(e, suffix) => e.outer_html + suffix", "hello")
502
339
  # ```
503
- #
504
- # ```python async
505
- # result = await page.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8])
506
- # print(result) # prints "56"
340
+ def eval_on_selector(selector, expression, arg: nil, strict: nil)
341
+ wrap_impl(@impl.eval_on_selector(unwrap_impl(selector), unwrap_impl(expression), arg: unwrap_impl(arg), strict: unwrap_impl(strict)))
342
+ end
343
+
344
+ #
345
+ # The method finds all elements matching the specified selector within the page and passes an array of matched elements as
346
+ # a first argument to `expression`. Returns the result of `expression` invocation.
347
+ #
348
+ # If `expression` returns a [Promise], then [`method: Page.evalOnSelectorAll`] would wait for the promise to resolve and
349
+ # return its value.
350
+ #
351
+ # **Usage**
352
+ #
353
+ # ```python sync
354
+ # div_counts = page.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10)
507
355
  # ```
508
- #
356
+ def eval_on_selector_all(selector, expression, arg: nil)
357
+ wrap_impl(@impl.eval_on_selector_all(unwrap_impl(selector), unwrap_impl(expression), arg: unwrap_impl(arg)))
358
+ end
359
+
360
+ #
361
+ # Returns the value of the `expression` invocation.
362
+ #
363
+ # If the function passed to the [`method: Page.evaluate`] returns a [Promise], then [`method: Page.evaluate`] would wait
364
+ # for the promise to resolve and return its value.
365
+ #
366
+ # If the function passed to the [`method: Page.evaluate`] returns a non-[Serializable] value, then
367
+ # [`method: Page.evaluate`] resolves to `undefined`. Playwright also supports transferring some
368
+ # additional values that are not serializable by `JSON`: `-0`, `NaN`, `Infinity`, `-Infinity`.
369
+ #
370
+ # **Usage**
371
+ #
372
+ # Passing argument to `expression`:
373
+ #
509
374
  # ```python sync
510
375
  # result = page.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8])
511
376
  # print(result) # prints "56"
512
377
  # ```
513
- #
378
+ #
514
379
  # A string can also be passed in instead of a function:
515
- #
516
380
  #
517
- # ```js
518
- # console.log(await page.evaluate('1 + 2')); // prints "3"
519
- # const x = 10;
520
- # console.log(await page.evaluate(`1 + ${x}`)); // prints "11"
521
- # ```
522
- #
523
- # ```python async
524
- # print(await page.evaluate("1 + 2")) # prints "3"
525
- # x = 10
526
- # print(await page.evaluate(f"1 + {x}")) # prints "11"
527
- # ```
528
- #
529
381
  # ```python sync
530
382
  # print(page.evaluate("1 + 2")) # prints "3"
531
383
  # x = 10
532
384
  # print(page.evaluate(f"1 + {x}")) # prints "11"
533
385
  # ```
534
- #
386
+ #
535
387
  # `ElementHandle` instances can be passed as an argument to the [`method: Page.evaluate`]:
536
- #
537
388
  #
538
- # ```js
539
- # const bodyHandle = await page.$('body');
540
- # const html = await page.evaluate(([body, suffix]) => body.innerHTML + suffix, [bodyHandle, 'hello']);
541
- # await bodyHandle.dispose();
542
- # ```
543
- #
544
- # ```python async
545
- # body_handle = await page.query_selector("body")
546
- # html = await page.evaluate("([body, suffix]) => body.innerHTML + suffix", [body_handle, "hello"])
547
- # await body_handle.dispose()
548
- # ```
549
- #
550
389
  # ```python sync
551
- # body_handle = page.query_selector("body")
390
+ # body_handle = page.evaluate("document.body")
552
391
  # html = page.evaluate("([body, suffix]) => body.innerHTML + suffix", [body_handle, "hello"])
553
392
  # body_handle.dispose()
554
393
  # ```
555
- #
556
- # Shortcut for main frame's [`method: Frame.evaluate`].
557
- def evaluate(pageFunction, arg: nil)
558
- wrap_impl(@impl.evaluate(unwrap_impl(pageFunction), arg: unwrap_impl(arg)))
559
- end
560
-
561
- # Returns the value of the `pageFunction` invocation as in-page object (JSHandle).
562
- #
563
- # The only difference between [`method: Page.evaluate`] and [`method: Page.evaluateHandle`] is that
564
- # [`method: Page.evaluateHandle`] returns in-page object (JSHandle).
565
- #
566
- # If the function passed to the [`method: Page.evaluateHandle`] returns a [Promise], then [`method: Page.evaluateHandle`]
567
- # would wait for the promise to resolve and return its value.
568
- #
569
- #
570
- # ```js
571
- # const aWindowHandle = await page.evaluateHandle(() => Promise.resolve(window));
572
- # aWindowHandle; // Handle for the window object.
573
- # ```
574
- #
575
- # ```python async
576
- # # FIXME
577
- # a_window_handle = await page.evaluate_handle("Promise.resolve(window)")
578
- # a_window_handle # handle for the window object.
579
- # ```
580
- #
394
+ def evaluate(expression, arg: nil)
395
+ wrap_impl(@impl.evaluate(unwrap_impl(expression), arg: unwrap_impl(arg)))
396
+ end
397
+
398
+ #
399
+ # Returns the value of the `expression` invocation as a `JSHandle`.
400
+ #
401
+ # The only difference between [`method: Page.evaluate`] and [`method: Page.evaluateHandle`] is that [`method: Page.evaluateHandle`] returns `JSHandle`.
402
+ #
403
+ # If the function passed to the [`method: Page.evaluateHandle`] returns a [Promise], then [`method: Page.evaluateHandle`] would wait for the
404
+ # promise to resolve and return its value.
405
+ #
406
+ # **Usage**
407
+ #
581
408
  # ```python sync
582
409
  # a_window_handle = page.evaluate_handle("Promise.resolve(window)")
583
410
  # a_window_handle # handle for the window object.
584
411
  # ```
585
- #
412
+ #
586
413
  # A string can also be passed in instead of a function:
587
- #
588
414
  #
589
- # ```js
590
- # const aHandle = await page.evaluateHandle('document'); // Handle for the 'document'
591
- # ```
592
- #
593
- # ```python async
594
- # a_handle = await page.evaluate_handle("document") # handle for the "document"
595
- # ```
596
- #
597
415
  # ```python sync
598
416
  # a_handle = page.evaluate_handle("document") # handle for the "document"
599
417
  # ```
600
- #
418
+ #
601
419
  # `JSHandle` instances can be passed as an argument to the [`method: Page.evaluateHandle`]:
602
- #
603
420
  #
604
- # ```js
605
- # const aHandle = await page.evaluateHandle(() => document.body);
606
- # const resultHandle = await page.evaluateHandle(body => body.innerHTML, aHandle);
607
- # console.log(await resultHandle.jsonValue());
608
- # await resultHandle.dispose();
609
- # ```
610
- #
611
- # ```python async
612
- # a_handle = await page.evaluate_handle("document.body")
613
- # result_handle = await page.evaluate_handle("body => body.innerHTML", a_handle)
614
- # print(await result_handle.json_value())
615
- # await result_handle.dispose()
616
- # ```
617
- #
618
421
  # ```python sync
619
422
  # a_handle = page.evaluate_handle("document.body")
620
423
  # result_handle = page.evaluate_handle("body => body.innerHTML", a_handle)
621
424
  # print(result_handle.json_value())
622
425
  # result_handle.dispose()
623
426
  # ```
624
- def evaluate_handle(pageFunction, arg: nil)
625
- wrap_impl(@impl.evaluate_handle(unwrap_impl(pageFunction), arg: unwrap_impl(arg)))
427
+ def evaluate_handle(expression, arg: nil)
428
+ wrap_impl(@impl.evaluate_handle(unwrap_impl(expression), arg: unwrap_impl(arg)))
626
429
  end
627
430
 
628
- # The method adds a function called `name` on the `window` object of every frame in this page. When called, the function
629
- # executes `callback` and returns a [Promise] which resolves to the return value of `callback`. If the `callback` returns
630
- # a [Promise], it will be awaited.
631
- #
632
- # The first argument of the `callback` function contains information about the caller: `{ browserContext: BrowserContext,
633
- # page: Page, frame: Frame }`.
634
- #
431
+ #
432
+ # The method adds a function called `name` on the `window` object of every frame in this page. When called, the
433
+ # function executes `callback` and returns a [Promise] which resolves to the return value of `callback`.
434
+ # If the `callback` returns a [Promise], it will be awaited.
435
+ #
436
+ # The first argument of the `callback` function contains information about the caller: `{ browserContext:
437
+ # BrowserContext, page: Page, frame: Frame }`.
438
+ #
635
439
  # See [`method: BrowserContext.exposeBinding`] for the context-wide version.
636
- #
637
- # > NOTE: Functions installed via [`method: Page.exposeBinding`] survive navigations.
638
- #
440
+ #
441
+ # **NOTE**: Functions installed via [`method: Page.exposeBinding`] survive navigations.
442
+ #
443
+ # **Usage**
444
+ #
639
445
  # An example of exposing page URL to all frames in a page:
640
- #
641
- #
642
- # ```js
643
- # const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'.
644
- #
645
- # (async () => {
646
- # const browser = await webkit.launch({ headless: false });
647
- # const context = await browser.newContext();
648
- # const page = await context.newPage();
649
- # await page.exposeBinding('pageURL', ({ page }) => page.url());
650
- # await page.setContent(`
651
- # <script>
652
- # async function onClick() {
653
- # document.querySelector('div').textContent = await window.pageURL();
654
- # }
655
- # </script>
656
- # <button onclick="onClick()">Click me</button>
657
- # <div></div>
658
- # `);
659
- # await page.click('button');
660
- # })();
661
- # ```
662
- #
663
- # ```python async
664
- # import asyncio
665
- # from playwright.async_api import async_playwright
666
- #
667
- # async def run(playwright):
668
- # webkit = playwright.webkit
669
- # browser = await webkit.launch(headless=false)
670
- # context = await browser.new_context()
671
- # page = await context.new_page()
672
- # await page.expose_binding("pageURL", lambda source: source["page"].url)
673
- # await page.set_content("""
674
- # <script>
675
- # async function onClick() {
676
- # document.querySelector('div').textContent = await window.pageURL();
677
- # }
678
- # </script>
679
- # <button onclick="onClick()">Click me</button>
680
- # <div></div>
681
- # """)
682
- # await page.click("button")
683
- #
684
- # async def main():
685
- # async with async_playwright() as playwright:
686
- # await run(playwright)
687
- # asyncio.run(main())
688
- # ```
689
- #
446
+ #
690
447
  # ```python sync
691
- # from playwright.sync_api import sync_playwright
692
- #
693
- # def run(playwright):
448
+ # from playwright.sync_api import sync_playwright, Playwright
449
+ #
450
+ # def run(playwright: Playwright):
694
451
  # webkit = playwright.webkit
695
- # browser = webkit.launch(headless=false)
452
+ # browser = webkit.launch(headless=False)
696
453
  # context = browser.new_context()
697
454
  # page = context.new_page()
698
455
  # page.expose_binding("pageURL", lambda source: source["page"].url)
@@ -706,369 +463,544 @@ module Playwright
706
463
  # <div></div>
707
464
  # """)
708
465
  # page.click("button")
709
- #
466
+ #
710
467
  # with sync_playwright() as playwright:
711
468
  # run(playwright)
712
469
  # ```
713
- #
714
- # An example of passing an element handle:
715
- #
716
- #
717
- # ```js
718
- # await page.exposeBinding('clicked', async (source, element) => {
719
- # console.log(await element.textContent());
720
- # }, { handle: true });
721
- # await page.setContent(`
722
- # <script>
723
- # document.addEventListener('click', event => window.clicked(event.target));
724
- # </script>
725
- # <div>Click me</div>
726
- # <div>Or click me</div>
727
- # `);
728
- # ```
729
- #
730
- # ```python async
731
- # async def print(source, element):
732
- # print(await element.text_content())
733
- #
734
- # await page.expose_binding("clicked", print, handle=true)
735
- # await page.set_content("""
736
- # <script>
737
- # document.addEventListener('click', event => window.clicked(event.target));
738
- # </script>
739
- # <div>Click me</div>
740
- # <div>Or click me</div>
741
- # """)
742
- # ```
743
- #
744
- # ```python sync
745
- # def print(source, element):
746
- # print(element.text_content())
747
- #
748
- # page.expose_binding("clicked", print, handle=true)
749
- # page.set_content("""
750
- # <script>
751
- # document.addEventListener('click', event => window.clicked(event.target));
752
- # </script>
753
- # <div>Click me</div>
754
- # <div>Or click me</div>
755
- # """)
756
- # ```
757
470
  def expose_binding(name, callback, handle: nil)
758
- raise NotImplementedError.new('expose_binding is not implemented yet.')
471
+ wrap_impl(@impl.expose_binding(unwrap_impl(name), unwrap_impl(callback), handle: unwrap_impl(handle)))
759
472
  end
760
473
 
761
- # The method adds a function called `name` on the `window` object of every frame in the page. When called, the function
762
- # executes `callback` and returns a [Promise] which resolves to the return value of `callback`.
763
- #
474
+ #
475
+ # The method adds a function called `name` on the `window` object of every frame in the page. When called, the
476
+ # function executes `callback` and returns a [Promise] which resolves to the return value of `callback`.
477
+ #
764
478
  # If the `callback` returns a [Promise], it will be awaited.
765
- #
479
+ #
766
480
  # See [`method: BrowserContext.exposeFunction`] for context-wide exposed function.
767
- #
768
- # > NOTE: Functions installed via [`method: Page.exposeFunction`] survive navigations.
769
- #
770
- # An example of adding an `sha1` function to the page:
771
- #
772
- #
773
- # ```js
774
- # const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'.
775
- # const crypto = require('crypto');
776
- #
777
- # (async () => {
778
- # const browser = await webkit.launch({ headless: false });
779
- # const page = await browser.newPage();
780
- # await page.exposeFunction('sha1', text => crypto.createHash('sha1').update(text).digest('hex'));
781
- # await page.setContent(`
782
- # <script>
783
- # async function onClick() {
784
- # document.querySelector('div').textContent = await window.sha1('PLAYWRIGHT');
785
- # }
786
- # </script>
787
- # <button onclick="onClick()">Click me</button>
788
- # <div></div>
789
- # `);
790
- # await page.click('button');
791
- # })();
792
- # ```
793
- #
794
- # ```python async
795
- # import asyncio
796
- # import hashlib
797
- # from playwright.async_api import async_playwright
798
- #
799
- # async def sha1(text):
800
- # m = hashlib.sha1()
801
- # m.update(bytes(text, "utf8"))
802
- # return m.hexdigest()
803
- #
804
- #
805
- # async def run(playwright):
806
- # webkit = playwright.webkit
807
- # browser = await webkit.launch(headless=False)
808
- # page = await browser.new_page()
809
- # await page.expose_function("sha1", sha1)
810
- # await page.set_content("""
811
- # <script>
812
- # async function onClick() {
813
- # document.querySelector('div').textContent = await window.sha1('PLAYWRIGHT');
814
- # }
815
- # </script>
816
- # <button onclick="onClick()">Click me</button>
817
- # <div></div>
818
- # """)
819
- # await page.click("button")
820
- #
821
- # async def main():
822
- # async with async_playwright() as playwright:
823
- # await run(playwright)
824
- # asyncio.run(main())
825
- # ```
826
- #
481
+ #
482
+ # **NOTE**: Functions installed via [`method: Page.exposeFunction`] survive navigations.
483
+ #
484
+ # **Usage**
485
+ #
486
+ # An example of adding a `sha256` function to the page:
487
+ #
827
488
  # ```python sync
828
489
  # import hashlib
829
- # from playwright.sync_api import sync_playwright
830
- #
831
- # def sha1(text):
832
- # m = hashlib.sha1()
490
+ # from playwright.sync_api import sync_playwright, Playwright
491
+ #
492
+ # def sha256(text):
493
+ # m = hashlib.sha256()
833
494
  # m.update(bytes(text, "utf8"))
834
495
  # return m.hexdigest()
835
- #
836
- #
837
- # def run(playwright):
496
+ #
497
+ #
498
+ # def run(playwright: Playwright):
838
499
  # webkit = playwright.webkit
839
500
  # browser = webkit.launch(headless=False)
840
501
  # page = browser.new_page()
841
- # page.expose_function("sha1", sha1)
502
+ # page.expose_function("sha256", sha256)
842
503
  # page.set_content("""
843
504
  # <script>
844
505
  # async function onClick() {
845
- # document.querySelector('div').textContent = await window.sha1('PLAYWRIGHT');
506
+ # document.querySelector('div').textContent = await window.sha256('PLAYWRIGHT');
846
507
  # }
847
508
  # </script>
848
509
  # <button onclick="onClick()">Click me</button>
849
510
  # <div></div>
850
511
  # """)
851
512
  # page.click("button")
852
- #
513
+ #
853
514
  # with sync_playwright() as playwright:
854
515
  # run(playwright)
855
516
  # ```
856
517
  def expose_function(name, callback)
857
- raise NotImplementedError.new('expose_function is not implemented yet.')
518
+ wrap_impl(@impl.expose_function(unwrap_impl(name), unwrap_impl(callback)))
858
519
  end
859
520
 
860
- # This method waits for an element matching `selector`, waits for [actionability](./actionability.md) checks, focuses the
861
- # element, fills it and triggers an `input` event after filling. If the element matching `selector` is not an `<input>`,
862
- # `<textarea>` or `[contenteditable]` element, this method throws an error. Note that you can pass an empty string to
863
- # clear the input field.
864
- #
865
- # To send fine-grained keyboard events, use [`method: Page.type`].
866
- #
867
- # Shortcut for main frame's [`method: Frame.fill`]
868
- def fill(selector, value, noWaitAfter: nil, timeout: nil)
869
- wrap_impl(@impl.fill(unwrap_impl(selector), unwrap_impl(value), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
521
+ #
522
+ # This method waits for an element matching `selector`, waits for [actionability](../actionability.md) checks, focuses the element, fills it and triggers an `input` event after filling. Note that you can pass an empty string to clear the input field.
523
+ #
524
+ # If the target element is not an `<input>`, `<textarea>` or `[contenteditable]` element, this method throws an error. However, if the element is inside the `<label>` element that has an associated [control](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control), the control will be filled instead.
525
+ #
526
+ # To send fine-grained keyboard events, use [`method: Locator.pressSequentially`].
527
+ def fill(
528
+ selector,
529
+ value,
530
+ force: nil,
531
+ noWaitAfter: nil,
532
+ strict: nil,
533
+ timeout: nil)
534
+ wrap_impl(@impl.fill(unwrap_impl(selector), unwrap_impl(value), force: unwrap_impl(force), noWaitAfter: unwrap_impl(noWaitAfter), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
870
535
  end
871
536
 
872
- # This method fetches an element with `selector` and focuses it. If there's no element matching `selector`, the method
873
- # waits until a matching element appears in the DOM.
874
- #
875
- # Shortcut for main frame's [`method: Frame.focus`].
876
- def focus(selector, timeout: nil)
877
- wrap_impl(@impl.focus(unwrap_impl(selector), timeout: unwrap_impl(timeout)))
537
+ #
538
+ # This method fetches an element with `selector` and focuses it. If there's no element matching
539
+ # `selector`, the method waits until a matching element appears in the DOM.
540
+ def focus(selector, strict: nil, timeout: nil)
541
+ wrap_impl(@impl.focus(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
878
542
  end
879
543
 
544
+ #
880
545
  # Returns frame matching the specified criteria. Either `name` or `url` must be specified.
881
- #
882
546
  #
883
- # ```js
884
- # const frame = page.frame('frame-name');
885
- # ```
886
- #
547
+ # **Usage**
548
+ #
887
549
  # ```py
888
550
  # frame = page.frame(name="frame-name")
889
551
  # ```
890
- #
891
552
  #
892
- # ```js
893
- # const frame = page.frame({ url: /.*domain.*/ });
894
- # ```
895
- #
896
553
  # ```py
897
554
  # frame = page.frame(url=r".*domain.*")
898
555
  # ```
899
- def frame(frameSelector)
900
- wrap_impl(@impl.frame(unwrap_impl(frameSelector)))
556
+ def frame(name: nil, url: nil)
557
+ wrap_impl(@impl.frame(name: unwrap_impl(name), url: unwrap_impl(url)))
901
558
  end
902
559
 
903
- # An array of all frames attached to the page.
904
- def frames
905
- wrap_impl(@impl.frames)
560
+ #
561
+ # When working with iframes, you can create a frame locator that will enter the iframe and allow selecting elements
562
+ # in that iframe.
563
+ #
564
+ # **Usage**
565
+ #
566
+ # Following snippet locates element with text "Submit" in the iframe with id `my-frame`,
567
+ # like `<iframe id="my-frame">`:
568
+ #
569
+ # ```python sync
570
+ # locator = page.frame_locator("#my-iframe").get_by_text("Submit")
571
+ # locator.click()
572
+ # ```
573
+ def frame_locator(selector)
574
+ wrap_impl(@impl.frame_locator(unwrap_impl(selector)))
906
575
  end
907
576
 
577
+ #
578
+ # An array of all frames attached to the page.
579
+ def frames
580
+ wrap_impl(@impl.frames)
581
+ end
582
+
583
+ #
908
584
  # Returns element attribute value.
909
- def get_attribute(selector, name, timeout: nil)
910
- raise NotImplementedError.new('get_attribute is not implemented yet.')
585
+ def get_attribute(selector, name, strict: nil, timeout: nil)
586
+ wrap_impl(@impl.get_attribute(unwrap_impl(selector), unwrap_impl(name), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
587
+ end
588
+
589
+ #
590
+ # Allows locating elements by their alt text.
591
+ #
592
+ # **Usage**
593
+ #
594
+ # For example, this method will find the image by alt text "Playwright logo":
595
+ #
596
+ # ```html
597
+ # <img alt='Playwright logo'>
598
+ # ```
599
+ #
600
+ # ```python sync
601
+ # page.get_by_alt_text("Playwright logo").click()
602
+ # ```
603
+ def get_by_alt_text(text, exact: nil)
604
+ wrap_impl(@impl.get_by_alt_text(unwrap_impl(text), exact: unwrap_impl(exact)))
605
+ end
606
+
607
+ #
608
+ # Allows locating input elements by the text of the associated `<label>` or `aria-labelledby` element, or by the `aria-label` attribute.
609
+ #
610
+ # **Usage**
611
+ #
612
+ # For example, this method will find inputs by label "Username" and "Password" in the following DOM:
613
+ #
614
+ # ```html
615
+ # <input aria-label="Username">
616
+ # <label for="password-input">Password:</label>
617
+ # <input id="password-input">
618
+ # ```
619
+ #
620
+ # ```python sync
621
+ # page.get_by_label("Username").fill("john")
622
+ # page.get_by_label("Password").fill("secret")
623
+ # ```
624
+ def get_by_label(text, exact: nil)
625
+ wrap_impl(@impl.get_by_label(unwrap_impl(text), exact: unwrap_impl(exact)))
626
+ end
627
+
628
+ #
629
+ # Allows locating input elements by the placeholder text.
630
+ #
631
+ # **Usage**
632
+ #
633
+ # For example, consider the following DOM structure.
634
+ #
635
+ # ```html
636
+ # <input type="email" placeholder="name@example.com" />
637
+ # ```
638
+ #
639
+ # You can fill the input after locating it by the placeholder text:
640
+ #
641
+ # ```python sync
642
+ # page.get_by_placeholder("name@example.com").fill("playwright@microsoft.com")
643
+ # ```
644
+ def get_by_placeholder(text, exact: nil)
645
+ wrap_impl(@impl.get_by_placeholder(unwrap_impl(text), exact: unwrap_impl(exact)))
646
+ end
647
+
648
+ #
649
+ # Allows locating elements by their [ARIA role](https://www.w3.org/TR/wai-aria-1.2/#roles), [ARIA attributes](https://www.w3.org/TR/wai-aria-1.2/#aria-attributes) and [accessible name](https://w3c.github.io/accname/#dfn-accessible-name).
650
+ #
651
+ # **Usage**
652
+ #
653
+ # Consider the following DOM structure.
654
+ #
655
+ # ```html
656
+ # <h3>Sign up</h3>
657
+ # <label>
658
+ # <input type="checkbox" /> Subscribe
659
+ # </label>
660
+ # <br/>
661
+ # <button>Submit</button>
662
+ # ```
663
+ #
664
+ # You can locate each element by it's implicit role:
665
+ #
666
+ # ```python sync
667
+ # expect(page.get_by_role("heading", name="Sign up")).to_be_visible()
668
+ #
669
+ # page.get_by_role("checkbox", name="Subscribe").check()
670
+ #
671
+ # page.get_by_role("button", name=re.compile("submit", re.IGNORECASE)).click()
672
+ # ```
673
+ #
674
+ # **Details**
675
+ #
676
+ # Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback about the ARIA guidelines.
677
+ #
678
+ # Many html elements have an implicitly [defined role](https://w3c.github.io/html-aam/#html-element-role-mappings) that is recognized by the role selector. You can find all the [supported roles here](https://www.w3.org/TR/wai-aria-1.2/#role_definitions). ARIA guidelines **do not recommend** duplicating implicit roles and attributes by setting `role` and/or `aria-*` attributes to default values.
679
+ def get_by_role(
680
+ role,
681
+ checked: nil,
682
+ disabled: nil,
683
+ exact: nil,
684
+ expanded: nil,
685
+ includeHidden: nil,
686
+ level: nil,
687
+ name: nil,
688
+ pressed: nil,
689
+ selected: nil)
690
+ wrap_impl(@impl.get_by_role(unwrap_impl(role), checked: unwrap_impl(checked), disabled: unwrap_impl(disabled), exact: unwrap_impl(exact), expanded: unwrap_impl(expanded), includeHidden: unwrap_impl(includeHidden), level: unwrap_impl(level), name: unwrap_impl(name), pressed: unwrap_impl(pressed), selected: unwrap_impl(selected)))
691
+ end
692
+
693
+ #
694
+ # Locate element by the test id.
695
+ #
696
+ # **Usage**
697
+ #
698
+ # Consider the following DOM structure.
699
+ #
700
+ # ```html
701
+ # <button data-testid="directions">Itinéraire</button>
702
+ # ```
703
+ #
704
+ # You can locate the element by it's test id:
705
+ #
706
+ # ```python sync
707
+ # page.get_by_test_id("directions").click()
708
+ # ```
709
+ #
710
+ # **Details**
711
+ #
712
+ # By default, the `data-testid` attribute is used as a test id. Use [`method: Selectors.setTestIdAttribute`] to configure a different test id attribute if necessary.
713
+ def get_by_test_id(testId)
714
+ wrap_impl(@impl.get_by_test_id(unwrap_impl(testId)))
715
+ end
716
+ alias_method :get_by_testid, :get_by_test_id
717
+
718
+ #
719
+ # Allows locating elements that contain given text.
720
+ #
721
+ # See also [`method: Locator.filter`] that allows to match by another criteria, like an accessible role, and then filter by the text content.
722
+ #
723
+ # **Usage**
724
+ #
725
+ # Consider the following DOM structure:
726
+ #
727
+ # ```html
728
+ # <div>Hello <span>world</span></div>
729
+ # <div>Hello</div>
730
+ # ```
731
+ #
732
+ # You can locate by text substring, exact string, or a regular expression:
733
+ #
734
+ # ```python sync
735
+ # # Matches <span>
736
+ # page.get_by_text("world")
737
+ #
738
+ # # Matches first <div>
739
+ # page.get_by_text("Hello world")
740
+ #
741
+ # # Matches second <div>
742
+ # page.get_by_text("Hello", exact=True)
743
+ #
744
+ # # Matches both <div>s
745
+ # page.get_by_text(re.compile("Hello"))
746
+ #
747
+ # # Matches second <div>
748
+ # page.get_by_text(re.compile("^hello$", re.IGNORECASE))
749
+ # ```
750
+ #
751
+ # **Details**
752
+ #
753
+ # Matching by text always normalizes whitespace, even with exact match. For example, it turns multiple spaces into one, turns line breaks into spaces and ignores leading and trailing whitespace.
754
+ #
755
+ # Input elements of the type `button` and `submit` are matched by their `value` instead of the text content. For example, locating by text `"Log in"` matches `<input type=button value="Log in">`.
756
+ def get_by_text(text, exact: nil)
757
+ wrap_impl(@impl.get_by_text(unwrap_impl(text), exact: unwrap_impl(exact)))
911
758
  end
912
759
 
760
+ #
761
+ # Allows locating elements by their title attribute.
762
+ #
763
+ # **Usage**
764
+ #
765
+ # Consider the following DOM structure.
766
+ #
767
+ # ```html
768
+ # <span title='Issues count'>25 issues</span>
769
+ # ```
770
+ #
771
+ # You can check the issues count after locating it by the title text:
772
+ #
773
+ # ```python sync
774
+ # expect(page.get_by_title("Issues count")).to_have_text("25 issues")
775
+ # ```
776
+ def get_by_title(text, exact: nil)
777
+ wrap_impl(@impl.get_by_title(unwrap_impl(text), exact: unwrap_impl(exact)))
778
+ end
779
+
780
+ #
913
781
  # Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
914
- # last redirect. If can not go back, returns `null`.
915
- #
782
+ # last redirect. If cannot go back, returns `null`.
783
+ #
916
784
  # Navigate to the previous page in history.
917
785
  def go_back(timeout: nil, waitUntil: nil)
918
- raise NotImplementedError.new('go_back is not implemented yet.')
786
+ wrap_impl(@impl.go_back(timeout: unwrap_impl(timeout), waitUntil: unwrap_impl(waitUntil)))
919
787
  end
920
788
 
789
+ #
921
790
  # Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
922
- # last redirect. If can not go forward, returns `null`.
923
- #
791
+ # last redirect. If cannot go forward, returns `null`.
792
+ #
924
793
  # Navigate to the next page in history.
925
794
  def go_forward(timeout: nil, waitUntil: nil)
926
- raise NotImplementedError.new('go_forward is not implemented yet.')
795
+ wrap_impl(@impl.go_forward(timeout: unwrap_impl(timeout), waitUntil: unwrap_impl(waitUntil)))
927
796
  end
928
797
 
929
- # Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
930
- # last redirect.
931
- #
932
- # `page.goto` will throw an error if:
798
+ #
799
+ # Request the page to perform garbage collection. Note that there is no guarantee that all unreachable objects will be collected.
800
+ #
801
+ # This is useful to help detect memory leaks. For example, if your page has a large object `'suspect'` that might be leaked, you can check that it does not leak by using a [`WeakRef`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef).
802
+ #
803
+ # ```python sync
804
+ # # 1. In your page, save a WeakRef for the "suspect".
805
+ # page.evaluate("globalThis.suspectWeakRef = new WeakRef(suspect)")
806
+ # # 2. Request garbage collection.
807
+ # page.request_gc()
808
+ # # 3. Check that weak ref does not deref to the original object.
809
+ # assert page.evaluate("!globalThis.suspectWeakRef.deref()")
810
+ # ```
811
+ def request_gc
812
+ raise NotImplementedError.new('request_gc is not implemented yet.')
813
+ end
814
+
815
+ #
816
+ # Returns the main resource response. In case of multiple redirects, the navigation will resolve with the first
817
+ # non-redirect response.
818
+ #
819
+ # The method will throw an error if:
933
820
  # - there's an SSL error (e.g. in case of self-signed certificates).
934
821
  # - target URL is invalid.
935
822
  # - the `timeout` is exceeded during navigation.
936
823
  # - the remote server does not respond or is unreachable.
937
824
  # - the main resource failed to load.
938
- #
939
- # `page.goto` will not throw an error when any valid HTTP status code is returned by the remote server, including 404 "Not
825
+ #
826
+ # The method will not throw an error when any valid HTTP status code is returned by the remote server, including 404 "Not
940
827
  # Found" and 500 "Internal Server Error". The status code for such responses can be retrieved by calling
941
828
  # [`method: Response.status`].
942
- #
943
- # > NOTE: `page.goto` either throws an error or returns a main resource response. The only exceptions are navigation to
829
+ #
830
+ # **NOTE**: The method either throws an error or returns a main resource response. The only exceptions are navigation to
944
831
  # `about:blank` or navigation to the same URL with a different hash, which would succeed and return `null`.
945
- # > NOTE: Headless mode doesn't support navigation to a PDF document. See the
832
+ #
833
+ # **NOTE**: Headless mode doesn't support navigation to a PDF document. See the
946
834
  # [upstream issue](https://bugs.chromium.org/p/chromium/issues/detail?id=761295).
947
- #
948
- # Shortcut for main frame's [`method: Frame.goto`]
949
835
  def goto(url, referer: nil, timeout: nil, waitUntil: nil)
950
836
  wrap_impl(@impl.goto(unwrap_impl(url), referer: unwrap_impl(referer), timeout: unwrap_impl(timeout), waitUntil: unwrap_impl(waitUntil)))
951
837
  end
952
838
 
839
+ #
953
840
  # This method hovers over an element matching `selector` by performing the following steps:
954
- # 1. Find an element match matching `selector`. If there is none, wait until a matching element is attached to the DOM.
955
- # 1. Wait for [actionability](./actionability.md) checks on the matched element, unless `force` option is set. If the
956
- # element is detached during the checks, the whole action is retried.
841
+ # 1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
842
+ # 1. Wait for [actionability](../actionability.md) checks on the matched element, unless `force` option is set. If the element is detached during the checks, the whole action is retried.
957
843
  # 1. Scroll the element into view if needed.
958
844
  # 1. Use [`property: Page.mouse`] to hover over the center of the element, or the specified `position`.
959
- # 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
960
- #
961
- # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
962
- # Passing zero timeout disables this.
963
- #
964
- # Shortcut for main frame's [`method: Frame.hover`].
845
+ #
846
+ # When all steps combined have not finished during the specified `timeout`, this method throws a
847
+ # `TimeoutError`. Passing zero timeout disables this.
965
848
  def hover(
966
849
  selector,
967
850
  force: nil,
968
851
  modifiers: nil,
852
+ noWaitAfter: nil,
969
853
  position: nil,
970
- timeout: nil)
971
- raise NotImplementedError.new('hover is not implemented yet.')
854
+ strict: nil,
855
+ timeout: nil,
856
+ trial: nil)
857
+ wrap_impl(@impl.hover(unwrap_impl(selector), force: unwrap_impl(force), modifiers: unwrap_impl(modifiers), noWaitAfter: unwrap_impl(noWaitAfter), position: unwrap_impl(position), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout), trial: unwrap_impl(trial)))
972
858
  end
973
859
 
860
+ #
974
861
  # Returns `element.innerHTML`.
975
- def inner_html(selector, timeout: nil)
976
- raise NotImplementedError.new('inner_html is not implemented yet.')
862
+ def inner_html(selector, strict: nil, timeout: nil)
863
+ wrap_impl(@impl.inner_html(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
977
864
  end
978
865
 
866
+ #
979
867
  # Returns `element.innerText`.
980
- def inner_text(selector, timeout: nil)
981
- raise NotImplementedError.new('inner_text is not implemented yet.')
868
+ def inner_text(selector, strict: nil, timeout: nil)
869
+ wrap_impl(@impl.inner_text(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
982
870
  end
983
871
 
872
+ #
873
+ # Returns `input.value` for the selected `<input>` or `<textarea>` or `<select>` element.
874
+ #
875
+ # Throws for non-input elements. However, if the element is inside the `<label>` element that has an associated [control](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control), returns the value of the control.
876
+ def input_value(selector, strict: nil, timeout: nil)
877
+ wrap_impl(@impl.input_value(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
878
+ end
879
+
880
+ #
984
881
  # Returns whether the element is checked. Throws if the element is not a checkbox or radio input.
985
- def checked?(selector, timeout: nil)
986
- raise NotImplementedError.new('checked? is not implemented yet.')
882
+ def checked?(selector, strict: nil, timeout: nil)
883
+ wrap_impl(@impl.checked?(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
987
884
  end
988
885
 
886
+ #
989
887
  # Indicates that the page has been closed.
990
888
  def closed?
991
889
  wrap_impl(@impl.closed?)
992
890
  end
993
891
 
994
- # Returns whether the element is disabled, the opposite of [enabled](./actionability.md#enabled).
995
- def disabled?(selector, timeout: nil)
996
- raise NotImplementedError.new('disabled? is not implemented yet.')
892
+ #
893
+ # Returns whether the element is disabled, the opposite of [enabled](../actionability.md#enabled).
894
+ def disabled?(selector, strict: nil, timeout: nil)
895
+ wrap_impl(@impl.disabled?(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
896
+ end
897
+
898
+ #
899
+ # Returns whether the element is [editable](../actionability.md#editable).
900
+ def editable?(selector, strict: nil, timeout: nil)
901
+ wrap_impl(@impl.editable?(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
902
+ end
903
+
904
+ #
905
+ # Returns whether the element is [enabled](../actionability.md#enabled).
906
+ def enabled?(selector, strict: nil, timeout: nil)
907
+ wrap_impl(@impl.enabled?(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
908
+ end
909
+
910
+ #
911
+ # Returns whether the element is hidden, the opposite of [visible](../actionability.md#visible). `selector` that does not match any elements is considered hidden.
912
+ def hidden?(selector, strict: nil, timeout: nil)
913
+ wrap_impl(@impl.hidden?(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
997
914
  end
998
915
 
999
- # Returns whether the element is [editable](./actionability.md#editable).
1000
- def editable?(selector, timeout: nil)
1001
- raise NotImplementedError.new('editable? is not implemented yet.')
916
+ #
917
+ # Returns whether the element is [visible](../actionability.md#visible). `selector` that does not match any elements is considered not visible.
918
+ def visible?(selector, strict: nil, timeout: nil)
919
+ wrap_impl(@impl.visible?(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
1002
920
  end
1003
921
 
1004
- # Returns whether the element is [enabled](./actionability.md#enabled).
1005
- def enabled?(selector, timeout: nil)
1006
- raise NotImplementedError.new('enabled? is not implemented yet.')
922
+ #
923
+ # Returns up to (currently) 200 last console messages from this page. See [`event: Page.console`] for more details.
924
+ def console_messages
925
+ wrap_impl(@impl.console_messages)
1007
926
  end
1008
927
 
1009
- # Returns whether the element is hidden, the opposite of [visible](./actionability.md#visible).
1010
- def hidden?(selector, timeout: nil)
1011
- raise NotImplementedError.new('hidden? is not implemented yet.')
928
+ #
929
+ # Returns up to (currently) 200 last page errors from this page. See [`event: Page.pageError`] for more details.
930
+ def page_errors
931
+ wrap_impl(@impl.page_errors)
1012
932
  end
1013
933
 
1014
- # Returns whether the element is [visible](./actionability.md#visible).
1015
- def visible?(selector, timeout: nil)
1016
- raise NotImplementedError.new('visible? is not implemented yet.')
934
+ #
935
+ # The method returns an element locator that can be used to perform actions on this page / frame.
936
+ # Locator is resolved to the element immediately before performing an action, so a series of actions on the same locator can in fact be performed on different DOM elements. That would happen if the DOM structure between those actions has changed.
937
+ #
938
+ # [Learn more about locators](../locators.md).
939
+ def locator(
940
+ selector,
941
+ has: nil,
942
+ hasNot: nil,
943
+ hasNotText: nil,
944
+ hasText: nil)
945
+ wrap_impl(@impl.locator(unwrap_impl(selector), has: unwrap_impl(has), hasNot: unwrap_impl(hasNot), hasNotText: unwrap_impl(hasNotText), hasText: unwrap_impl(hasText)))
1017
946
  end
1018
947
 
948
+ #
1019
949
  # The page's main frame. Page is guaranteed to have a main frame which persists during navigations.
1020
950
  def main_frame
1021
951
  wrap_impl(@impl.main_frame)
1022
952
  end
1023
953
 
954
+ #
1024
955
  # Returns the opener for popup pages and `null` for others. If the opener has been closed already the returns `null`.
1025
956
  def opener
1026
957
  wrap_impl(@impl.opener)
1027
958
  end
1028
959
 
960
+ #
961
+ # Pauses script execution. Playwright will stop executing the script and wait for the user to either press the 'Resume'
962
+ # button in the page overlay or to call `playwright.resume()` in the DevTools console.
963
+ #
964
+ # User can inspect selectors or perform manual steps while paused. Resume will continue running the original script from
965
+ # the place it was paused.
966
+ #
967
+ # **NOTE**: This method requires Playwright to be started in a headed mode, with a falsy `headless` option.
968
+ def pause
969
+ wrap_impl(@impl.pause)
970
+ end
971
+
972
+ #
1029
973
  # Returns the PDF buffer.
1030
- #
1031
- # > NOTE: Generating a pdf is currently only supported in Chromium headless.
1032
- #
974
+ #
1033
975
  # `page.pdf()` generates a pdf of the page with `print` css media. To generate a pdf with `screen` media, call
1034
976
  # [`method: Page.emulateMedia`] before calling `page.pdf()`:
1035
- #
1036
- # > NOTE: By default, `page.pdf()` generates a pdf with modified colors for printing. Use the
977
+ #
978
+ # **NOTE**: By default, `page.pdf()` generates a pdf with modified colors for printing. Use the
1037
979
  # [`-webkit-print-color-adjust`](https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-print-color-adjust) property to
1038
980
  # force rendering of exact colors.
1039
- #
1040
981
  #
1041
- # ```js
1042
- # // Generates a PDF with 'screen' media type.
1043
- # await page.emulateMedia({media: 'screen'});
1044
- # await page.pdf({path: 'page.pdf'});
1045
- # ```
1046
- #
1047
- # ```python async
1048
- # # generates a pdf with "screen" media type.
1049
- # await page.emulate_media(media="screen")
1050
- # await page.pdf(path="page.pdf")
1051
- # ```
1052
- #
982
+ # **Usage**
983
+ #
1053
984
  # ```python sync
1054
985
  # # generates a pdf with "screen" media type.
1055
986
  # page.emulate_media(media="screen")
1056
987
  # page.pdf(path="page.pdf")
1057
988
  # ```
1058
- #
1059
- # The `width`, `height`, and `margin` options accept values labeled with units. Unlabeled values are treated as pixels.
1060
- #
989
+ #
990
+ # The `width`, `height`, and `margin` options accept values labeled with units. Unlabeled
991
+ # values are treated as pixels.
992
+ #
1061
993
  # A few examples:
1062
994
  # - `page.pdf({width: 100})` - prints with width set to 100 pixels
1063
995
  # - `page.pdf({width: '100px'})` - prints with width set to 100 pixels
1064
996
  # - `page.pdf({width: '10cm'})` - prints with width set to 10 centimeters.
1065
- #
997
+ #
1066
998
  # All possible units are:
1067
999
  # - `px` - pixel
1068
1000
  # - `in` - inch
1069
1001
  # - `cm` - centimeter
1070
1002
  # - `mm` - millimeter
1071
- #
1003
+ #
1072
1004
  # The `format` options are:
1073
1005
  # - `Letter`: 8.5in x 11in
1074
1006
  # - `Legal`: 8.5in x 14in
@@ -1081,9 +1013,9 @@ module Playwright
1081
1013
  # - `A4`: 8.27in x 11.7in
1082
1014
  # - `A5`: 5.83in x 8.27in
1083
1015
  # - `A6`: 4.13in x 5.83in
1084
- #
1085
- # > NOTE: `headerTemplate` and `footerTemplate` markup have the following limitations: > 1. Script tags inside templates
1086
- # are not evaluated. > 2. Page styles are not visible inside templates.
1016
+ #
1017
+ # **NOTE**: `headerTemplate` and `footerTemplate` markup have the following limitations: > 1. Script tags inside
1018
+ # templates are not evaluated. > 2. Page styles are not visible inside templates.
1087
1019
  def pdf(
1088
1020
  displayHeaderFooter: nil,
1089
1021
  footerTemplate: nil,
@@ -1092,59 +1024,41 @@ module Playwright
1092
1024
  height: nil,
1093
1025
  landscape: nil,
1094
1026
  margin: nil,
1027
+ outline: nil,
1095
1028
  pageRanges: nil,
1096
1029
  path: nil,
1097
1030
  preferCSSPageSize: nil,
1098
1031
  printBackground: nil,
1099
1032
  scale: nil,
1033
+ tagged: nil,
1100
1034
  width: nil)
1101
- raise NotImplementedError.new('pdf is not implemented yet.')
1035
+ wrap_impl(@impl.pdf(displayHeaderFooter: unwrap_impl(displayHeaderFooter), footerTemplate: unwrap_impl(footerTemplate), format: unwrap_impl(format), headerTemplate: unwrap_impl(headerTemplate), height: unwrap_impl(height), landscape: unwrap_impl(landscape), margin: unwrap_impl(margin), outline: unwrap_impl(outline), pageRanges: unwrap_impl(pageRanges), path: unwrap_impl(path), preferCSSPageSize: unwrap_impl(preferCSSPageSize), printBackground: unwrap_impl(printBackground), scale: unwrap_impl(scale), tagged: unwrap_impl(tagged), width: unwrap_impl(width)))
1102
1036
  end
1103
1037
 
1038
+ #
1104
1039
  # Focuses the element, and then uses [`method: Keyboard.down`] and [`method: Keyboard.up`].
1105
- #
1106
- # `key` can specify the intended [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key)
1107
- # value or a single character to generate the text for. A superset of the `key` values can be found
1040
+ #
1041
+ # `key` can specify the intended
1042
+ # [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character to
1043
+ # generate the text for. A superset of the `key` values can be found
1108
1044
  # [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Examples of the keys are:
1109
- #
1045
+ #
1110
1046
  # `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
1111
1047
  # `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
1112
- #
1113
- # Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
1114
- #
1048
+ #
1049
+ # Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
1050
+ # `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
1051
+ #
1115
1052
  # Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
1116
- #
1117
- # If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective
1118
- # texts.
1119
- #
1120
- # Shortcuts such as `key: "Control+o"` or `key: "Control+Shift+T"` are supported as well. When speficied with the
1053
+ #
1054
+ # If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different
1055
+ # respective texts.
1056
+ #
1057
+ # Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+T"` are supported as well. When specified with the
1121
1058
  # modifier, modifier is pressed and being held while the subsequent key is being pressed.
1122
- #
1123
- #
1124
- # ```js
1125
- # const page = await browser.newPage();
1126
- # await page.goto('https://keycode.info');
1127
- # await page.press('body', 'A');
1128
- # await page.screenshot({ path: 'A.png' });
1129
- # await page.press('body', 'ArrowLeft');
1130
- # await page.screenshot({ path: 'ArrowLeft.png' });
1131
- # await page.press('body', 'Shift+O');
1132
- # await page.screenshot({ path: 'O.png' });
1133
- # await browser.close();
1134
- # ```
1135
- #
1136
- # ```python async
1137
- # page = await browser.new_page()
1138
- # await page.goto("https://keycode.info")
1139
- # await page.press("body", "A")
1140
- # await page.screenshot(path="a.png")
1141
- # await page.press("body", "ArrowLeft")
1142
- # await page.screenshot(path="arrow_left.png")
1143
- # await page.press("body", "Shift+O")
1144
- # await page.screenshot(path="o.png")
1145
- # await browser.close()
1146
- # ```
1147
- #
1059
+ #
1060
+ # **Usage**
1061
+ #
1148
1062
  # ```python sync
1149
1063
  # page = browser.new_page()
1150
1064
  # page.goto("https://keycode.info")
@@ -1161,141 +1075,291 @@ module Playwright
1161
1075
  key,
1162
1076
  delay: nil,
1163
1077
  noWaitAfter: nil,
1078
+ strict: nil,
1164
1079
  timeout: nil)
1165
- wrap_impl(@impl.press(unwrap_impl(selector), unwrap_impl(key), delay: unwrap_impl(delay), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
1080
+ wrap_impl(@impl.press(unwrap_impl(selector), unwrap_impl(key), delay: unwrap_impl(delay), noWaitAfter: unwrap_impl(noWaitAfter), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
1081
+ end
1082
+
1083
+ #
1084
+ # The method finds an element matching the specified selector within the page. If no elements match the selector, the
1085
+ # return value resolves to `null`. To wait for an element on the page, use [`method: Locator.waitFor`].
1086
+ def query_selector(selector, strict: nil)
1087
+ wrap_impl(@impl.query_selector(unwrap_impl(selector), strict: unwrap_impl(strict)))
1088
+ end
1089
+
1090
+ #
1091
+ # The method finds all elements matching the specified selector within the page. If no elements match the selector, the
1092
+ # return value resolves to `[]`.
1093
+ def query_selector_all(selector)
1094
+ wrap_impl(@impl.query_selector_all(unwrap_impl(selector)))
1095
+ end
1096
+
1097
+ #
1098
+ # Returns up to (currently) 100 last network request from this page. See [`event: Page.request`] for more details.
1099
+ #
1100
+ # Returned requests should be accessed immediately, otherwise they might be collected to prevent unbounded memory growth as new requests come in. Once collected, retrieving most information about the request is impossible.
1101
+ #
1102
+ # Note that requests reported through the [`event: Page.request`] request are not collected, so there is a trade off between efficient memory usage with [`method: Page.requests`] and the amount of available information reported through [`event: Page.request`].
1103
+ def requests
1104
+ wrap_impl(@impl.requests)
1105
+ end
1106
+
1107
+ #
1108
+ # When testing a web page, sometimes unexpected overlays like a "Sign up" dialog appear and block actions you want to automate, e.g. clicking a button. These overlays don't always show up in the same way or at the same time, making them tricky to handle in automated tests.
1109
+ #
1110
+ # This method lets you set up a special function, called a handler, that activates when it detects that overlay is visible. The handler's job is to remove the overlay, allowing your test to continue as if the overlay wasn't there.
1111
+ #
1112
+ # Things to keep in mind:
1113
+ # - When an overlay is shown predictably, we recommend explicitly waiting for it in your test and dismissing it as a part of your normal test flow, instead of using [`method: Page.addLocatorHandler`].
1114
+ # - Playwright checks for the overlay every time before executing or retrying an action that requires an [actionability check](../actionability.md), or before performing an auto-waiting assertion check. When overlay is visible, Playwright calls the handler first, and then proceeds with the action/assertion. Note that the handler is only called when you perform an action/assertion - if the overlay becomes visible but you don't perform any actions, the handler will not be triggered.
1115
+ # - After executing the handler, Playwright will ensure that overlay that triggered the handler is not visible anymore. You can opt-out of this behavior with `noWaitAfter`.
1116
+ # - The execution time of the handler counts towards the timeout of the action/assertion that executed the handler. If your handler takes too long, it might cause timeouts.
1117
+ # - You can register multiple handlers. However, only a single handler will be running at a time. Make sure the actions within a handler don't depend on another handler.
1118
+ #
1119
+ # **NOTE**: Running the handler will alter your page state mid-test. For example it will change the currently focused element and move the mouse. Make sure that actions that run after the handler are self-contained and do not rely on the focus and mouse state being unchanged.
1120
+ #
1121
+ # For example, consider a test that calls [`method: Locator.focus`] followed by [`method: Keyboard.press`]. If your handler clicks a button between these two actions, the focused element most likely will be wrong, and key press will happen on the unexpected element. Use [`method: Locator.press`] instead to avoid this problem.
1122
+ #
1123
+ # Another example is a series of mouse actions, where [`method: Mouse.move`] is followed by [`method: Mouse.down`]. Again, when the handler runs between these two actions, the mouse position will be wrong during the mouse down. Prefer self-contained actions like [`method: Locator.click`] that do not rely on the state being unchanged by a handler.
1124
+ #
1125
+ # **Usage**
1126
+ #
1127
+ # An example that closes a "Sign up to the newsletter" dialog when it appears:
1128
+ #
1129
+ # ```python sync
1130
+ # # Setup the handler.
1131
+ # def handler():
1132
+ # page.get_by_role("button", name="No thanks").click()
1133
+ # page.add_locator_handler(page.get_by_text("Sign up to the newsletter"), handler)
1134
+ #
1135
+ # # Write the test as usual.
1136
+ # page.goto("https://example.com")
1137
+ # page.get_by_role("button", name="Start here").click()
1138
+ # ```
1139
+ #
1140
+ # An example that skips the "Confirm your security details" page when it is shown:
1141
+ #
1142
+ # ```python sync
1143
+ # # Setup the handler.
1144
+ # def handler():
1145
+ # page.get_by_role("button", name="Remind me later").click()
1146
+ # page.add_locator_handler(page.get_by_text("Confirm your security details"), handler)
1147
+ #
1148
+ # # Write the test as usual.
1149
+ # page.goto("https://example.com")
1150
+ # page.get_by_role("button", name="Start here").click()
1151
+ # ```
1152
+ #
1153
+ # An example with a custom callback on every actionability check. It uses a `<body>` locator that is always visible, so the handler is called before every actionability check. It is important to specify `noWaitAfter`, because the handler does not hide the `<body>` element.
1154
+ #
1155
+ # ```python sync
1156
+ # # Setup the handler.
1157
+ # def handler():
1158
+ # page.evaluate("window.removeObstructionsForTestIfNeeded()")
1159
+ # page.add_locator_handler(page.locator("body"), handler, no_wait_after=True)
1160
+ #
1161
+ # # Write the test as usual.
1162
+ # page.goto("https://example.com")
1163
+ # page.get_by_role("button", name="Start here").click()
1164
+ # ```
1165
+ #
1166
+ # Handler takes the original locator as an argument. You can also automatically remove the handler after a number of invocations by setting `times`:
1167
+ #
1168
+ # ```python sync
1169
+ # def handler(locator):
1170
+ # locator.click()
1171
+ # page.add_locator_handler(page.get_by_label("Close"), handler, times=1)
1172
+ # ```
1173
+ def add_locator_handler(locator, handler, noWaitAfter: nil, times: nil)
1174
+ raise NotImplementedError.new('add_locator_handler is not implemented yet.')
1166
1175
  end
1167
1176
 
1177
+ #
1178
+ # Removes all locator handlers added by [`method: Page.addLocatorHandler`] for a specific locator.
1179
+ def remove_locator_handler(locator)
1180
+ raise NotImplementedError.new('remove_locator_handler is not implemented yet.')
1181
+ end
1182
+
1183
+ #
1184
+ # This method reloads the current page, in the same way as if the user had triggered a browser refresh.
1168
1185
  # Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
1169
1186
  # last redirect.
1170
1187
  def reload(timeout: nil, waitUntil: nil)
1171
1188
  wrap_impl(@impl.reload(timeout: unwrap_impl(timeout), waitUntil: unwrap_impl(waitUntil)))
1172
1189
  end
1173
1190
 
1191
+ #
1174
1192
  # Routing provides the capability to modify network requests that are made by a page.
1175
- #
1193
+ #
1176
1194
  # Once routing is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted.
1177
- #
1178
- # > NOTE: The handler will only be called for the first url if the response is a redirect.
1179
- #
1180
- # An example of a naïve handler that aborts all image requests:
1181
- #
1182
- #
1183
- # ```js
1184
- # const page = await browser.newPage();
1185
- # await page.route('**/*.{png,jpg,jpeg}', route => route.abort());
1186
- # await page.goto('https://example.com');
1187
- # await browser.close();
1188
- # ```
1189
- #
1190
- # ```python async
1191
- # page = await browser.new_page()
1192
- # await page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())
1193
- # await page.goto("https://example.com")
1194
- # await browser.close()
1195
- # ```
1196
- #
1195
+ #
1196
+ # **NOTE**: The handler will only be called for the first url if the response is a redirect.
1197
+ #
1198
+ # **NOTE**: [`method: Page.route`] will not intercept requests intercepted by Service Worker. See [this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using request interception by setting `serviceWorkers` to `'block'`.
1199
+ #
1200
+ # **NOTE**: [`method: Page.route`] will not intercept the first request of a popup page. Use [`method: BrowserContext.route`] instead.
1201
+ #
1202
+ # **Usage**
1203
+ #
1204
+ # An example of a naive handler that aborts all image requests:
1205
+ #
1197
1206
  # ```python sync
1198
1207
  # page = browser.new_page()
1199
1208
  # page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())
1200
1209
  # page.goto("https://example.com")
1201
1210
  # browser.close()
1202
1211
  # ```
1203
- #
1212
+ #
1204
1213
  # or the same snippet using a regex pattern instead:
1205
- #
1206
1214
  #
1207
- # ```js
1208
- # const page = await browser.newPage();
1209
- # await page.route(/(\.png$)|(\.jpg$)/, route => route.abort());
1210
- # await page.goto('https://example.com');
1211
- # await browser.close();
1212
- # ```
1213
- #
1214
- # ```python async
1215
- # page = await browser.new_page()
1216
- # await page.route(re.compile(r"(\.png$)|(\.jpg$)"), lambda route: route.abort())
1217
- # await page.goto("https://example.com")
1218
- # await browser.close()
1219
- # ```
1220
- #
1221
1215
  # ```python sync
1222
1216
  # page = browser.new_page()
1223
1217
  # page.route(re.compile(r"(\.png$)|(\.jpg$)"), lambda route: route.abort())
1224
1218
  # page.goto("https://example.com")
1225
1219
  # browser.close()
1226
1220
  # ```
1227
- #
1221
+ #
1222
+ # It is possible to examine the request to decide the route action. For example, mocking all requests that contain some post data, and leaving all other requests as is:
1223
+ #
1224
+ # ```python sync
1225
+ # def handle_route(route: Route):
1226
+ # if ("my-string" in route.request.post_data):
1227
+ # route.fulfill(body="mocked-data")
1228
+ # else:
1229
+ # route.continue_()
1230
+ # page.route("/api/**", handle_route)
1231
+ # ```
1232
+ #
1228
1233
  # Page routes take precedence over browser context routes (set up with [`method: BrowserContext.route`]) when request
1229
1234
  # matches both handlers.
1230
- #
1231
- # > NOTE: Enabling routing disables http cache.
1232
- def route(url, handler)
1233
- raise NotImplementedError.new('route is not implemented yet.')
1235
+ #
1236
+ # To remove a route with its handler you can use [`method: Page.unroute`].
1237
+ #
1238
+ # **NOTE**: Enabling routing disables http cache.
1239
+ def route(url, handler, times: nil)
1240
+ wrap_impl(@impl.route(unwrap_impl(url), unwrap_impl(handler), times: unwrap_impl(times)))
1241
+ end
1242
+
1243
+ #
1244
+ # If specified the network requests that are made in the page will be served from the HAR file. Read more about [Replaying from HAR](../mock.md#replaying-from-har).
1245
+ #
1246
+ # Playwright will not serve requests intercepted by Service Worker from the HAR file. See [this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using request interception by setting `serviceWorkers` to `'block'`.
1247
+ def route_from_har(
1248
+ har,
1249
+ notFound: nil,
1250
+ update: nil,
1251
+ updateContent: nil,
1252
+ updateMode: nil,
1253
+ url: nil)
1254
+ wrap_impl(@impl.route_from_har(unwrap_impl(har), notFound: unwrap_impl(notFound), update: unwrap_impl(update), updateContent: unwrap_impl(updateContent), updateMode: unwrap_impl(updateMode), url: unwrap_impl(url)))
1255
+ end
1256
+
1257
+ #
1258
+ # This method allows to modify websocket connections that are made by the page.
1259
+ #
1260
+ # Note that only `WebSocket`s created after this method was called will be routed. It is recommended to call this method before navigating the page.
1261
+ #
1262
+ # **Usage**
1263
+ #
1264
+ # Below is an example of a simple mock that responds to a single message. See `WebSocketRoute` for more details and examples.
1265
+ #
1266
+ # ```python sync
1267
+ # def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
1268
+ # if message == "request":
1269
+ # ws.send("response")
1270
+ #
1271
+ # def handler(ws: WebSocketRoute):
1272
+ # ws.on_message(lambda message: message_handler(ws, message))
1273
+ #
1274
+ # page.route_web_socket("/ws", handler)
1275
+ # ```
1276
+ def route_web_socket(url, handler)
1277
+ raise NotImplementedError.new('route_web_socket is not implemented yet.')
1234
1278
  end
1235
1279
 
1280
+ #
1236
1281
  # Returns the buffer with the captured screenshot.
1237
- #
1238
- # > NOTE: Screenshots take at least 1/6 second on Chromium OS X and Chromium Windows. See https://crbug.com/741689 for
1239
- # discussion.
1240
1282
  def screenshot(
1283
+ animations: nil,
1284
+ caret: nil,
1241
1285
  clip: nil,
1242
1286
  fullPage: nil,
1287
+ mask: nil,
1288
+ maskColor: nil,
1243
1289
  omitBackground: nil,
1244
1290
  path: nil,
1245
1291
  quality: nil,
1292
+ scale: nil,
1293
+ style: nil,
1246
1294
  timeout: nil,
1247
1295
  type: nil)
1248
- wrap_impl(@impl.screenshot(clip: unwrap_impl(clip), fullPage: unwrap_impl(fullPage), omitBackground: unwrap_impl(omitBackground), path: unwrap_impl(path), quality: unwrap_impl(quality), timeout: unwrap_impl(timeout), type: unwrap_impl(type)))
1296
+ wrap_impl(@impl.screenshot(animations: unwrap_impl(animations), caret: unwrap_impl(caret), clip: unwrap_impl(clip), fullPage: unwrap_impl(fullPage), mask: unwrap_impl(mask), maskColor: unwrap_impl(maskColor), omitBackground: unwrap_impl(omitBackground), path: unwrap_impl(path), quality: unwrap_impl(quality), scale: unwrap_impl(scale), style: unwrap_impl(style), timeout: unwrap_impl(timeout), type: unwrap_impl(type)))
1249
1297
  end
1250
1298
 
1299
+ #
1300
+ # This method waits for an element matching `selector`, waits for [actionability](../actionability.md) checks, waits until all specified options are present in the `<select>` element and selects these options.
1301
+ #
1302
+ # If the target element is not a `<select>` element, this method throws an error. However, if the element is inside the `<label>` element that has an associated [control](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control), the control will be used instead.
1303
+ #
1251
1304
  # Returns the array of option values that have been successfully selected.
1252
- #
1253
- # Triggers a `change` and `input` event once all the provided options have been selected. If there's no `<select>` element
1254
- # matching `selector`, the method throws an error.
1255
- #
1256
- # Will wait until all specified options are present in the `<select>` element.
1257
- #
1258
- #
1259
- # ```js
1260
- # // single selection matching the value
1261
- # page.selectOption('select#colors', 'blue');
1262
- #
1263
- # // single selection matching the label
1264
- # page.selectOption('select#colors', { label: 'Blue' });
1265
- #
1266
- # // multiple selection
1267
- # page.selectOption('select#colors', ['red', 'green', 'blue']);
1268
- #
1269
- # ```
1270
- #
1271
- # ```python async
1272
- # # single selection matching the value
1273
- # await page.select_option("select#colors", "blue")
1274
- # # single selection matching the label
1275
- # await page.select_option("select#colors", label="blue")
1276
- # # multiple selection
1277
- # await page.select_option("select#colors", value=["red", "green", "blue"])
1278
- # ```
1279
- #
1305
+ #
1306
+ # Triggers a `change` and `input` event once all the provided options have been selected.
1307
+ #
1308
+ # **Usage**
1309
+ #
1280
1310
  # ```python sync
1281
- # # single selection matching the value
1311
+ # # Single selection matching the value or label
1282
1312
  # page.select_option("select#colors", "blue")
1283
1313
  # # single selection matching both the label
1284
1314
  # page.select_option("select#colors", label="blue")
1285
1315
  # # multiple selection
1286
1316
  # page.select_option("select#colors", value=["red", "green", "blue"])
1287
1317
  # ```
1288
- #
1289
- # Shortcut for main frame's [`method: Frame.selectOption`]
1290
- def select_option(selector, values, noWaitAfter: nil, timeout: nil)
1291
- raise NotImplementedError.new('select_option is not implemented yet.')
1318
+ def select_option(
1319
+ selector,
1320
+ element: nil,
1321
+ index: nil,
1322
+ value: nil,
1323
+ label: nil,
1324
+ force: nil,
1325
+ noWaitAfter: nil,
1326
+ strict: nil,
1327
+ timeout: nil)
1328
+ wrap_impl(@impl.select_option(unwrap_impl(selector), element: unwrap_impl(element), index: unwrap_impl(index), value: unwrap_impl(value), label: unwrap_impl(label), force: unwrap_impl(force), noWaitAfter: unwrap_impl(noWaitAfter), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
1329
+ end
1330
+
1331
+ #
1332
+ # This method checks or unchecks an element matching `selector` by performing the following steps:
1333
+ # 1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
1334
+ # 1. Ensure that matched element is a checkbox or a radio input. If not, this method throws.
1335
+ # 1. If the element already has the right checked state, this method returns immediately.
1336
+ # 1. Wait for [actionability](../actionability.md) checks on the matched element, unless `force` option is set. If the element is detached during the checks, the whole action is retried.
1337
+ # 1. Scroll the element into view if needed.
1338
+ # 1. Use [`property: Page.mouse`] to click in the center of the element.
1339
+ # 1. Ensure that the element is now checked or unchecked. If not, this method throws.
1340
+ #
1341
+ # When all steps combined have not finished during the specified `timeout`, this method throws a
1342
+ # `TimeoutError`. Passing zero timeout disables this.
1343
+ def set_checked(
1344
+ selector,
1345
+ checked,
1346
+ force: nil,
1347
+ noWaitAfter: nil,
1348
+ position: nil,
1349
+ strict: nil,
1350
+ timeout: nil,
1351
+ trial: nil)
1352
+ wrap_impl(@impl.set_checked(unwrap_impl(selector), unwrap_impl(checked), force: unwrap_impl(force), noWaitAfter: unwrap_impl(noWaitAfter), position: unwrap_impl(position), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout), trial: unwrap_impl(trial)))
1292
1353
  end
1293
1354
 
1355
+ #
1356
+ # This method internally calls [document.write()](https://developer.mozilla.org/en-US/docs/Web/API/Document/write), inheriting all its specific characteristics and behaviors.
1294
1357
  def set_content(html, timeout: nil, waitUntil: nil)
1295
1358
  wrap_impl(@impl.set_content(unwrap_impl(html), timeout: unwrap_impl(timeout), waitUntil: unwrap_impl(waitUntil)))
1296
1359
  end
1297
1360
  alias_method :content=, :set_content
1298
1361
 
1362
+ #
1299
1363
  # This setting will change the default maximum navigation time for the following methods and related shortcuts:
1300
1364
  # - [`method: Page.goBack`]
1301
1365
  # - [`method: Page.goForward`]
@@ -1303,61 +1367,58 @@ module Playwright
1303
1367
  # - [`method: Page.reload`]
1304
1368
  # - [`method: Page.setContent`]
1305
1369
  # - [`method: Page.waitForNavigation`]
1306
- #
1307
- # > NOTE: [`method: Page.setDefaultNavigationTimeout`] takes priority over [`method: Page.setDefaultTimeout`],
1370
+ # - [`method: Page.waitForURL`]
1371
+ #
1372
+ # **NOTE**: [`method: Page.setDefaultNavigationTimeout`] takes priority over [`method: Page.setDefaultTimeout`],
1308
1373
  # [`method: BrowserContext.setDefaultTimeout`] and [`method: BrowserContext.setDefaultNavigationTimeout`].
1309
1374
  def set_default_navigation_timeout(timeout)
1310
1375
  wrap_impl(@impl.set_default_navigation_timeout(unwrap_impl(timeout)))
1311
1376
  end
1312
1377
  alias_method :default_navigation_timeout=, :set_default_navigation_timeout
1313
1378
 
1379
+ #
1314
1380
  # This setting will change the default maximum time for all the methods accepting `timeout` option.
1315
- #
1316
- # > NOTE: [`method: Page.setDefaultNavigationTimeout`] takes priority over [`method: Page.setDefaultTimeout`].
1381
+ #
1382
+ # **NOTE**: [`method: Page.setDefaultNavigationTimeout`] takes priority over [`method: Page.setDefaultTimeout`].
1317
1383
  def set_default_timeout(timeout)
1318
1384
  wrap_impl(@impl.set_default_timeout(unwrap_impl(timeout)))
1319
1385
  end
1320
1386
  alias_method :default_timeout=, :set_default_timeout
1321
1387
 
1388
+ #
1322
1389
  # The extra HTTP headers will be sent with every request the page initiates.
1323
- #
1324
- # > NOTE: [`method: Page.setExtraHTTPHeaders`] does not guarantee the order of headers in the outgoing requests.
1390
+ #
1391
+ # **NOTE**: [`method: Page.setExtraHTTPHeaders`] does not guarantee the order of headers in the outgoing requests.
1325
1392
  def set_extra_http_headers(headers)
1326
- raise NotImplementedError.new('set_extra_http_headers is not implemented yet.')
1393
+ wrap_impl(@impl.set_extra_http_headers(unwrap_impl(headers)))
1327
1394
  end
1328
1395
  alias_method :extra_http_headers=, :set_extra_http_headers
1329
1396
 
1330
- # This method expects `selector` to point to an
1331
- # [input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input).
1332
- #
1397
+ #
1333
1398
  # Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then they
1334
- # are resolved relative to the the current working directory. For empty array, clears the selected files.
1335
- def set_input_files(selector, files, noWaitAfter: nil, timeout: nil)
1336
- raise NotImplementedError.new('set_input_files is not implemented yet.')
1399
+ # are resolved relative to the current working directory. For empty array, clears the selected files.
1400
+ # For inputs with a `[webkitdirectory]` attribute, only a single directory path is supported.
1401
+ #
1402
+ # This method expects `selector` to point to an
1403
+ # [input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). However, if the element is inside the `<label>` element that has an associated [control](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control), targets the control instead.
1404
+ def set_input_files(
1405
+ selector,
1406
+ files,
1407
+ noWaitAfter: nil,
1408
+ strict: nil,
1409
+ timeout: nil)
1410
+ wrap_impl(@impl.set_input_files(unwrap_impl(selector), unwrap_impl(files), noWaitAfter: unwrap_impl(noWaitAfter), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
1337
1411
  end
1338
1412
 
1413
+ #
1339
1414
  # In the case of multiple pages in a single browser, each page can have its own viewport size. However,
1340
1415
  # [`method: Browser.newContext`] allows to set viewport size (and more) for all pages in the context at once.
1341
- #
1342
- # `page.setViewportSize` will resize the page. A lot of websites don't expect phones to change size, so you should set the
1343
- # viewport size before navigating to the page.
1344
- #
1345
- #
1346
- # ```js
1347
- # const page = await browser.newPage();
1348
- # await page.setViewportSize({
1349
- # width: 640,
1350
- # height: 480,
1351
- # });
1352
- # await page.goto('https://example.com');
1353
- # ```
1354
- #
1355
- # ```python async
1356
- # page = await browser.new_page()
1357
- # await page.set_viewport_size({"width": 640, "height": 480})
1358
- # await page.goto("https://example.com")
1359
- # ```
1360
- #
1416
+ #
1417
+ # [`method: Page.setViewportSize`] will resize the page. A lot of websites don't expect phones to change size, so you should set the
1418
+ # viewport size before navigating to the page. [`method: Page.setViewportSize`] will also reset `screen` size, use [`method: Browser.newContext`] with `screen` and `viewport` parameters if you need better control of these properties.
1419
+ #
1420
+ # **Usage**
1421
+ #
1361
1422
  # ```python sync
1362
1423
  # page = browser.new_page()
1363
1424
  # page.set_viewport_size({"width": 640, "height": 480})
@@ -1368,409 +1429,309 @@ module Playwright
1368
1429
  end
1369
1430
  alias_method :viewport_size=, :set_viewport_size
1370
1431
 
1432
+ #
1371
1433
  # This method taps an element matching `selector` by performing the following steps:
1372
- # 1. Find an element match matching `selector`. If there is none, wait until a matching element is attached to the DOM.
1373
- # 1. Wait for [actionability](./actionability.md) checks on the matched element, unless `force` option is set. If the
1374
- # element is detached during the checks, the whole action is retried.
1434
+ # 1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
1435
+ # 1. Wait for [actionability](../actionability.md) checks on the matched element, unless `force` option is set. If the element is detached during the checks, the whole action is retried.
1375
1436
  # 1. Scroll the element into view if needed.
1376
1437
  # 1. Use [`property: Page.touchscreen`] to tap the center of the element, or the specified `position`.
1377
- # 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
1378
- #
1379
- # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
1380
- # Passing zero timeout disables this.
1381
- #
1382
- # > NOTE: [`method: Page.tap`] requires that the `hasTouch` option of the browser context be set to true.
1383
- #
1384
- # Shortcut for main frame's [`method: Frame.tap`].
1438
+ #
1439
+ # When all steps combined have not finished during the specified `timeout`, this method throws a
1440
+ # `TimeoutError`. Passing zero timeout disables this.
1441
+ #
1442
+ # **NOTE**: [`method: Page.tap`] the method will throw if `hasTouch` option of the browser context is false.
1385
1443
  def tap_point(
1386
1444
  selector,
1387
1445
  force: nil,
1388
1446
  modifiers: nil,
1389
1447
  noWaitAfter: nil,
1390
1448
  position: nil,
1391
- timeout: nil)
1392
- raise NotImplementedError.new('tap_point is not implemented yet.')
1449
+ strict: nil,
1450
+ timeout: nil,
1451
+ trial: nil)
1452
+ wrap_impl(@impl.tap_point(unwrap_impl(selector), force: unwrap_impl(force), modifiers: unwrap_impl(modifiers), noWaitAfter: unwrap_impl(noWaitAfter), position: unwrap_impl(position), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout), trial: unwrap_impl(trial)))
1393
1453
  end
1394
1454
 
1455
+ #
1395
1456
  # Returns `element.textContent`.
1396
- def text_content(selector, timeout: nil)
1397
- raise NotImplementedError.new('text_content is not implemented yet.')
1457
+ def text_content(selector, strict: nil, timeout: nil)
1458
+ wrap_impl(@impl.text_content(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
1398
1459
  end
1399
1460
 
1400
- # Returns the page's title. Shortcut for main frame's [`method: Frame.title`].
1461
+ #
1462
+ # Returns the page's title.
1401
1463
  def title
1402
1464
  wrap_impl(@impl.title)
1403
1465
  end
1404
1466
 
1467
+ #
1405
1468
  # Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text. `page.type` can be used to send
1406
1469
  # fine-grained keyboard events. To fill values in form fields, use [`method: Page.fill`].
1407
- #
1470
+ #
1408
1471
  # To press a special key, like `Control` or `ArrowDown`, use [`method: Keyboard.press`].
1409
- #
1410
1472
  #
1411
- # ```js
1412
- # await page.type('#mytextarea', 'Hello'); // Types instantly
1413
- # await page.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user
1414
- # ```
1415
- #
1416
- # ```python async
1417
- # await page.type("#mytextarea", "hello") # types instantly
1418
- # await page.type("#mytextarea", "world", delay=100) # types slower, like a user
1419
- # ```
1420
- #
1421
- # ```python sync
1422
- # page.type("#mytextarea", "hello") # types instantly
1423
- # page.type("#mytextarea", "world", delay=100) # types slower, like a user
1424
- # ```
1425
- #
1426
- # Shortcut for main frame's [`method: Frame.type`].
1473
+ # **Usage**
1474
+ #
1475
+ # @deprecated In most cases, you should use [`method: Locator.fill`] instead. You only need to press keys one by one if there is special keyboard handling on the page - in this case use [`method: Locator.pressSequentially`].
1427
1476
  def type(
1428
1477
  selector,
1429
1478
  text,
1430
1479
  delay: nil,
1431
1480
  noWaitAfter: nil,
1481
+ strict: nil,
1432
1482
  timeout: nil)
1433
- wrap_impl(@impl.type(unwrap_impl(selector), unwrap_impl(text), delay: unwrap_impl(delay), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
1483
+ wrap_impl(@impl.type(unwrap_impl(selector), unwrap_impl(text), delay: unwrap_impl(delay), noWaitAfter: unwrap_impl(noWaitAfter), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
1434
1484
  end
1435
1485
 
1486
+ #
1436
1487
  # This method unchecks an element matching `selector` by performing the following steps:
1437
- # 1. Find an element match matching `selector`. If there is none, wait until a matching element is attached to the DOM.
1438
- # 1. Ensure that matched element is a checkbox or a radio input. If not, this method rejects. If the element is already
1439
- # unchecked, this method returns immediately.
1440
- # 1. Wait for [actionability](./actionability.md) checks on the matched element, unless `force` option is set. If the
1441
- # element is detached during the checks, the whole action is retried.
1488
+ # 1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
1489
+ # 1. Ensure that matched element is a checkbox or a radio input. If not, this method throws. If the element is already unchecked, this method returns immediately.
1490
+ # 1. Wait for [actionability](../actionability.md) checks on the matched element, unless `force` option is set. If the element is detached during the checks, the whole action is retried.
1442
1491
  # 1. Scroll the element into view if needed.
1443
1492
  # 1. Use [`property: Page.mouse`] to click in the center of the element.
1444
- # 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
1445
- # 1. Ensure that the element is now unchecked. If not, this method rejects.
1446
- #
1447
- # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
1448
- # Passing zero timeout disables this.
1449
- #
1450
- # Shortcut for main frame's [`method: Frame.uncheck`].
1451
- def uncheck(selector, force: nil, noWaitAfter: nil, timeout: nil)
1452
- raise NotImplementedError.new('uncheck is not implemented yet.')
1493
+ # 1. Ensure that the element is now unchecked. If not, this method throws.
1494
+ #
1495
+ # When all steps combined have not finished during the specified `timeout`, this method throws a
1496
+ # `TimeoutError`. Passing zero timeout disables this.
1497
+ def uncheck(
1498
+ selector,
1499
+ force: nil,
1500
+ noWaitAfter: nil,
1501
+ position: nil,
1502
+ strict: nil,
1503
+ timeout: nil,
1504
+ trial: nil)
1505
+ wrap_impl(@impl.uncheck(unwrap_impl(selector), force: unwrap_impl(force), noWaitAfter: unwrap_impl(noWaitAfter), position: unwrap_impl(position), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout), trial: unwrap_impl(trial)))
1453
1506
  end
1454
1507
 
1455
- # Removes a route created with [`method: Page.route`]. When `handler` is not specified, removes all routes for the `url`.
1508
+ #
1509
+ # Removes all routes created with [`method: Page.route`] and [`method: Page.routeFromHAR`].
1510
+ def unroute_all(behavior: nil)
1511
+ wrap_impl(@impl.unroute_all(behavior: unwrap_impl(behavior)))
1512
+ end
1513
+
1514
+ #
1515
+ # Removes a route created with [`method: Page.route`]. When `handler` is not specified, removes all routes for
1516
+ # the `url`.
1456
1517
  def unroute(url, handler: nil)
1457
- raise NotImplementedError.new('unroute is not implemented yet.')
1518
+ wrap_impl(@impl.unroute(unwrap_impl(url), handler: unwrap_impl(handler)))
1458
1519
  end
1459
1520
 
1460
- # Shortcut for main frame's [`method: Frame.url`].
1461
1521
  def url
1462
1522
  wrap_impl(@impl.url)
1463
1523
  end
1464
1524
 
1525
+ #
1465
1526
  # Video object associated with this page.
1466
1527
  def video
1467
- raise NotImplementedError.new('video is not implemented yet.')
1528
+ wrap_impl(@impl.video)
1468
1529
  end
1469
1530
 
1470
1531
  def viewport_size
1471
1532
  wrap_impl(@impl.viewport_size)
1472
1533
  end
1473
1534
 
1535
+ #
1536
+ # Performs action and waits for a `ConsoleMessage` to be logged by in the page. If predicate is provided, it passes
1537
+ # `ConsoleMessage` value into the `predicate` function and waits for `predicate(message)` to return a truthy value.
1538
+ # Will throw an error if the page is closed before the [`event: Page.console`] event is fired.
1539
+ def expect_console_message(predicate: nil, timeout: nil, &block)
1540
+ wrap_impl(@impl.expect_console_message(predicate: unwrap_impl(predicate), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
1541
+ end
1542
+
1543
+ #
1544
+ # Performs action and waits for a new `Download`. If predicate is provided, it passes
1545
+ # `Download` value into the `predicate` function and waits for `predicate(download)` to return a truthy value.
1546
+ # Will throw an error if the page is closed before the download event is fired.
1547
+ def expect_download(predicate: nil, timeout: nil, &block)
1548
+ wrap_impl(@impl.expect_download(predicate: unwrap_impl(predicate), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
1549
+ end
1550
+
1551
+ #
1474
1552
  # Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy
1475
1553
  # value. Will throw an error if the page is closed before the event is fired. Returns the event data value.
1476
- #
1477
1554
  #
1478
- # ```js
1479
- # const [frame, _] = await Promise.all([
1480
- # page.waitForEvent('framenavigated'),
1481
- # page.click('button')
1482
- # ]);
1483
- # ```
1484
- #
1485
- # ```python async
1486
- # async with page.expect_event("framenavigated") as event_info:
1487
- # await page.click("button")
1488
- # frame = await event_info.value
1489
- # ```
1490
- #
1555
+ # **Usage**
1556
+ #
1491
1557
  # ```python sync
1492
1558
  # with page.expect_event("framenavigated") as event_info:
1493
- # page.click("button")
1559
+ # page.get_by_role("button")
1494
1560
  # frame = event_info.value
1495
1561
  # ```
1496
- def expect_event(event, optionsOrPredicate: nil, &block)
1497
- wrap_impl(@impl.expect_event(unwrap_impl(event), optionsOrPredicate: unwrap_impl(optionsOrPredicate), &wrap_block_call(block)))
1498
- end
1499
-
1500
- # Returns when the `pageFunction` returns a truthy value. It resolves to a JSHandle of the truthy value.
1501
- #
1502
- # The `waitForFunction` can be used to observe viewport size change:
1503
- #
1504
- #
1505
- # ```js
1506
- # const { webkit } = require('playwright'); // Or 'chromium' or 'firefox'.
1507
- #
1508
- # (async () => {
1509
- # const browser = await webkit.launch();
1510
- # const page = await browser.newPage();
1511
- # const watchDog = page.waitForFunction(() => window.innerWidth < 100);
1512
- # await page.setViewportSize({width: 50, height: 50});
1513
- # await watchDog;
1514
- # await browser.close();
1515
- # })();
1516
- # ```
1517
- #
1518
- # ```python async
1519
- # import asyncio
1520
- # from playwright.async_api import async_playwright
1521
- #
1522
- # async def run(playwright):
1523
- # webkit = playwright.webkit
1524
- # browser = await webkit.launch()
1525
- # page = await browser.new_page()
1526
- # await page.evaluate("window.x = 0; setTimeout(() => { window.x = 100 }, 1000);", force_expr=True)
1527
- # await page.wait_for_function("() => window.x > 0")
1528
- # await browser.close()
1529
- #
1530
- # async def main():
1531
- # async with async_playwright() as playwright:
1532
- # await run(playwright)
1533
- # asyncio.run(main())
1534
- # ```
1535
- #
1562
+ def expect_event(event, predicate: nil, timeout: nil, &block)
1563
+ wrap_impl(@impl.expect_event(unwrap_impl(event), predicate: unwrap_impl(predicate), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
1564
+ end
1565
+
1566
+ #
1567
+ # Performs action and waits for a new `FileChooser` to be created. If predicate is provided, it passes
1568
+ # `FileChooser` value into the `predicate` function and waits for `predicate(fileChooser)` to return a truthy value.
1569
+ # Will throw an error if the page is closed before the file chooser is opened.
1570
+ def expect_file_chooser(predicate: nil, timeout: nil, &block)
1571
+ wrap_impl(@impl.expect_file_chooser(predicate: unwrap_impl(predicate), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
1572
+ end
1573
+
1574
+ #
1575
+ # Returns when the `expression` returns a truthy value. It resolves to a JSHandle of the truthy value.
1576
+ #
1577
+ # **Usage**
1578
+ #
1579
+ # The [`method: Page.waitForFunction`] can be used to observe viewport size change:
1580
+ #
1536
1581
  # ```python sync
1537
- # from playwright.sync_api import sync_playwright
1538
- #
1539
- # def run(playwright):
1582
+ # from playwright.sync_api import sync_playwright, Playwright
1583
+ #
1584
+ # def run(playwright: Playwright):
1540
1585
  # webkit = playwright.webkit
1541
1586
  # browser = webkit.launch()
1542
1587
  # page = browser.new_page()
1543
- # page.evaluate("window.x = 0; setTimeout(() => { window.x = 100 }, 1000);", force_expr=True)
1588
+ # page.evaluate("window.x = 0; setTimeout(() => { window.x = 100 }, 1000);")
1544
1589
  # page.wait_for_function("() => window.x > 0")
1545
1590
  # browser.close()
1546
- #
1591
+ #
1547
1592
  # with sync_playwright() as playwright:
1548
1593
  # run(playwright)
1549
1594
  # ```
1550
- #
1595
+ #
1551
1596
  # To pass an argument to the predicate of [`method: Page.waitForFunction`] function:
1552
- #
1553
1597
  #
1554
- # ```js
1555
- # const selector = '.foo';
1556
- # await page.waitForFunction(selector => !!document.querySelector(selector), selector);
1557
- # ```
1558
- #
1559
- # ```python async
1560
- # selector = ".foo"
1561
- # await page.wait_for_function("selector => !!document.querySelector(selector)", selector)
1562
- # ```
1563
- #
1564
1598
  # ```python sync
1565
1599
  # selector = ".foo"
1566
1600
  # page.wait_for_function("selector => !!document.querySelector(selector)", selector)
1567
1601
  # ```
1568
- #
1569
- # Shortcut for main frame's [`method: Frame.waitForFunction`].
1570
- def wait_for_function(pageFunction, arg: nil, polling: nil, timeout: nil)
1571
- wrap_impl(@impl.wait_for_function(unwrap_impl(pageFunction), arg: unwrap_impl(arg), polling: unwrap_impl(polling), timeout: unwrap_impl(timeout)))
1602
+ def wait_for_function(expression, arg: nil, polling: nil, timeout: nil)
1603
+ wrap_impl(@impl.wait_for_function(unwrap_impl(expression), arg: unwrap_impl(arg), polling: unwrap_impl(polling), timeout: unwrap_impl(timeout)))
1572
1604
  end
1573
1605
 
1606
+ #
1574
1607
  # Returns when the required load state has been reached.
1575
- #
1608
+ #
1576
1609
  # This resolves when the page reaches a required load state, `load` by default. The navigation must have been committed
1577
1610
  # when this method is called. If current document has already reached the required state, resolves immediately.
1578
- #
1579
1611
  #
1580
- # ```js
1581
- # await page.click('button'); // Click triggers navigation.
1582
- # await page.waitForLoadState(); // The promise resolves after 'load' event.
1583
- # ```
1584
- #
1585
- # ```python async
1586
- # await page.click("button") # click triggers navigation.
1587
- # await page.wait_for_load_state() # the promise resolves after "load" event.
1588
- # ```
1589
- #
1612
+ # **NOTE**: Most of the time, this method is not needed because Playwright [auto-waits before every action](../actionability.md).
1613
+ #
1614
+ # **Usage**
1615
+ #
1590
1616
  # ```python sync
1591
- # page.click("button") # click triggers navigation.
1617
+ # page.get_by_role("button").click() # click triggers navigation.
1592
1618
  # page.wait_for_load_state() # the promise resolves after "load" event.
1593
1619
  # ```
1594
- #
1595
- #
1596
- # ```js
1597
- # const [popup] = await Promise.all([
1598
- # page.waitForEvent('popup'),
1599
- # page.click('button'), // Click triggers a popup.
1600
- # ])
1601
- # await popup.waitForLoadState('domcontentloaded'); // The promise resolves after 'domcontentloaded' event.
1602
- # console.log(await popup.title()); // Popup is ready to use.
1603
- # ```
1604
- #
1605
- # ```python async
1606
- # async with page.expect_popup() as page_info:
1607
- # await page.click("button") # click triggers a popup.
1608
- # popup = await page_info.value
1609
- # # Following resolves after "domcontentloaded" event.
1610
- # await popup.wait_for_load_state("domcontentloaded")
1611
- # print(await popup.title()) # popup is ready to use.
1612
- # ```
1613
- #
1620
+ #
1614
1621
  # ```python sync
1615
1622
  # with page.expect_popup() as page_info:
1616
- # page.click("button") # click triggers a popup.
1623
+ # page.get_by_role("button").click() # click triggers a popup.
1617
1624
  # popup = page_info.value
1618
- # # Following resolves after "domcontentloaded" event.
1625
+ # # Wait for the "DOMContentLoaded" event.
1619
1626
  # popup.wait_for_load_state("domcontentloaded")
1620
1627
  # print(popup.title()) # popup is ready to use.
1621
1628
  # ```
1622
- #
1623
- # Shortcut for main frame's [`method: Frame.waitForLoadState`].
1624
1629
  def wait_for_load_state(state: nil, timeout: nil)
1625
1630
  wrap_impl(@impl.wait_for_load_state(state: unwrap_impl(state), timeout: unwrap_impl(timeout)))
1626
1631
  end
1627
1632
 
1628
- # Waits for the main frame navigation and returns the main resource response. In case of multiple redirects, the
1629
- # navigation will resolve with the response of the last redirect. In case of navigation to a different anchor or
1630
- # navigation due to History API usage, the navigation will resolve with `null`.
1631
- #
1633
+ #
1634
+ # Waits for the main frame navigation and returns the main resource response. In case of multiple redirects, the navigation
1635
+ # will resolve with the response of the last redirect. In case of navigation to a different anchor or navigation due to
1636
+ # History API usage, the navigation will resolve with `null`.
1637
+ #
1638
+ # **Usage**
1639
+ #
1632
1640
  # This resolves when the page navigates to a new URL or reloads. It is useful for when you run code which will indirectly
1633
1641
  # cause the page to navigate. e.g. The click target has an `onclick` handler that triggers navigation from a `setTimeout`.
1634
1642
  # Consider this example:
1635
- #
1636
1643
  #
1637
- # ```js
1638
- # const [response] = await Promise.all([
1639
- # page.waitForNavigation(), // The promise resolves after navigation has finished
1640
- # page.click('a.delayed-navigation'), // Clicking the link will indirectly cause a navigation
1641
- # ]);
1642
- # ```
1643
- #
1644
- # ```python async
1645
- # async with page.expect_navigation():
1646
- # await page.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
1647
- # # Resolves after navigation has finished
1648
- # ```
1649
- #
1650
1644
  # ```python sync
1651
1645
  # with page.expect_navigation():
1652
- # page.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
1646
+ # # This action triggers the navigation after a timeout.
1647
+ # page.get_by_text("Navigate after timeout").click()
1653
1648
  # # Resolves after navigation has finished
1654
1649
  # ```
1655
- #
1656
- # > NOTE: Usage of the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) to change the URL is
1657
- # considered a navigation.
1658
- #
1659
- # Shortcut for main frame's [`method: Frame.waitForNavigation`].
1650
+ #
1651
+ # **NOTE**: Usage of the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) to change the URL is considered
1652
+ # a navigation.
1653
+ #
1654
+ # @deprecated This method is inherently racy, please use [`method: Page.waitForURL`] instead.
1660
1655
  def expect_navigation(timeout: nil, url: nil, waitUntil: nil, &block)
1661
1656
  wrap_impl(@impl.expect_navigation(timeout: unwrap_impl(timeout), url: unwrap_impl(url), waitUntil: unwrap_impl(waitUntil), &wrap_block_call(block)))
1662
1657
  end
1663
1658
 
1664
- # Waits for the matching request and returns it.
1665
- #
1666
1659
  #
1667
- # ```js
1668
- # const firstRequest = await page.waitForRequest('http://example.com/resource');
1669
- # const finalRequest = await page.waitForRequest(request => request.url() === 'http://example.com' && request.method() === 'GET');
1670
- # return firstRequest.url();
1671
- # ```
1672
- #
1673
- # ```python async
1674
- # async with page.expect_request("http://example.com/resource") as first:
1675
- # await page.click('button')
1676
- # first_request = await first.value
1677
- #
1678
- # async with page.expect_request(lambda request: request.url == "http://example.com" and request.method == "get") as second:
1679
- # await page.click('img')
1680
- # second_request = await second.value
1681
- # ```
1682
- #
1660
+ # Performs action and waits for a popup `Page`. If predicate is provided, it passes
1661
+ # [Popup] value into the `predicate` function and waits for `predicate(page)` to return a truthy value.
1662
+ # Will throw an error if the page is closed before the popup event is fired.
1663
+ def expect_popup(predicate: nil, timeout: nil, &block)
1664
+ wrap_impl(@impl.expect_popup(predicate: unwrap_impl(predicate), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
1665
+ end
1666
+
1667
+ #
1668
+ # Waits for the matching request and returns it. See [waiting for event](../events.md#waiting-for-event) for more details about events.
1669
+ #
1670
+ # **Usage**
1671
+ #
1683
1672
  # ```python sync
1684
1673
  # with page.expect_request("http://example.com/resource") as first:
1685
- # page.click('button')
1674
+ # page.get_by_text("trigger request").click()
1686
1675
  # first_request = first.value
1687
- #
1676
+ #
1677
+ # # or with a lambda
1688
1678
  # with page.expect_request(lambda request: request.url == "http://example.com" and request.method == "get") as second:
1689
- # page.click('img')
1679
+ # page.get_by_text("trigger request").click()
1690
1680
  # second_request = second.value
1691
1681
  # ```
1692
- #
1682
+ def expect_request(urlOrPredicate, timeout: nil, &block)
1683
+ wrap_impl(@impl.expect_request(unwrap_impl(urlOrPredicate), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
1684
+ end
1685
+
1693
1686
  #
1694
- # ```js
1695
- # await page.waitForRequest(request => request.url().searchParams.get('foo') === 'bar' && request.url().searchParams.get('foo2') === 'bar2');
1696
- # ```
1697
- def expect_request(urlOrPredicate, timeout: nil)
1698
- wrap_impl(@impl.expect_request(unwrap_impl(urlOrPredicate), timeout: unwrap_impl(timeout)))
1687
+ # Performs action and waits for a `Request` to finish loading. If predicate is provided, it passes
1688
+ # `Request` value into the `predicate` function and waits for `predicate(request)` to return a truthy value.
1689
+ # Will throw an error if the page is closed before the [`event: Page.requestFinished`] event is fired.
1690
+ def expect_request_finished(predicate: nil, timeout: nil, &block)
1691
+ wrap_impl(@impl.expect_request_finished(predicate: unwrap_impl(predicate), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
1699
1692
  end
1700
1693
 
1701
- # Returns the matched response.
1702
- #
1703
1694
  #
1704
- # ```js
1705
- # const firstResponse = await page.waitForResponse('https://example.com/resource');
1706
- # const finalResponse = await page.waitForResponse(response => response.url() === 'https://example.com' && response.status() === 200);
1707
- # return finalResponse.ok();
1708
- # ```
1709
- #
1710
- # ```python async
1711
- # first_response = await page.wait_for_response("https://example.com/resource")
1712
- # final_response = await page.wait_for_response(lambda response: response.url == "https://example.com" and response.status === 200)
1713
- # return final_response.ok
1714
- # ```
1715
- #
1695
+ # Returns the matched response. See [waiting for event](../events.md#waiting-for-event) for more details about events.
1696
+ #
1697
+ # **Usage**
1698
+ #
1716
1699
  # ```python sync
1717
- # first_response = page.wait_for_response("https://example.com/resource")
1718
- # final_response = page.wait_for_response(lambda response: response.url == "https://example.com" and response.status === 200)
1719
- # return final_response.ok
1700
+ # with page.expect_response("https://example.com/resource") as response_info:
1701
+ # page.get_by_text("trigger response").click()
1702
+ # response = response_info.value
1703
+ # return response.ok
1704
+ #
1705
+ # # or with a lambda
1706
+ # with page.expect_response(lambda response: response.url == "https://example.com" and response.status == 200 and response.request.method == "get") as response_info:
1707
+ # page.get_by_text("trigger response").click()
1708
+ # response = response_info.value
1709
+ # return response.ok
1720
1710
  # ```
1721
- def expect_response(urlOrPredicate, timeout: nil)
1722
- wrap_impl(@impl.expect_response(unwrap_impl(urlOrPredicate), timeout: unwrap_impl(timeout)))
1711
+ def expect_response(urlOrPredicate, timeout: nil, &block)
1712
+ wrap_impl(@impl.expect_response(unwrap_impl(urlOrPredicate), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
1723
1713
  end
1724
1714
 
1715
+ #
1725
1716
  # Returns when element specified by selector satisfies `state` option. Returns `null` if waiting for `hidden` or
1726
1717
  # `detached`.
1727
- #
1728
- # Wait for the `selector` to satisfy `state` option (either appear/disappear from dom, or become visible/hidden). If at
1729
- # the moment of calling the method `selector` already satisfies the condition, the method will return immediately. If the
1730
- # selector doesn't satisfy the condition for the `timeout` milliseconds, the function will throw.
1731
- #
1718
+ #
1719
+ # **NOTE**: Playwright automatically waits for element to be ready before performing an action. Using
1720
+ # `Locator` objects and web-first assertions makes the code wait-for-selector-free.
1721
+ #
1722
+ # Wait for the `selector` to satisfy `state` option (either appear/disappear from dom, or become
1723
+ # visible/hidden). If at the moment of calling the method `selector` already satisfies the condition, the method
1724
+ # will return immediately. If the selector doesn't satisfy the condition for the `timeout` milliseconds, the
1725
+ # function will throw.
1726
+ #
1727
+ # **Usage**
1728
+ #
1732
1729
  # This method works across navigations:
1733
- #
1734
- #
1735
- # ```js
1736
- # const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'.
1737
- #
1738
- # (async () => {
1739
- # const browser = await chromium.launch();
1740
- # const page = await browser.newPage();
1741
- # for (let currentURL of ['https://google.com', 'https://bbc.com']) {
1742
- # await page.goto(currentURL);
1743
- # const element = await page.waitForSelector('img');
1744
- # console.log('Loaded image: ' + await element.getAttribute('src'));
1745
- # }
1746
- # await browser.close();
1747
- # })();
1748
- # ```
1749
- #
1750
- # ```python async
1751
- # import asyncio
1752
- # from playwright.async_api import async_playwright
1753
- #
1754
- # async def run(playwright):
1755
- # chromium = playwright.chromium
1756
- # browser = await chromium.launch()
1757
- # page = await browser.new_page()
1758
- # for current_url in ["https://google.com", "https://bbc.com"]:
1759
- # await page.goto(current_url, wait_until="domcontentloaded")
1760
- # element = await page.wait_for_selector("img")
1761
- # print("Loaded image: " + str(await element.get_attribute("src")))
1762
- # await browser.close()
1763
- #
1764
- # async def main():
1765
- # async with async_playwright() as playwright:
1766
- # await run(playwright)
1767
- # asyncio.run(main())
1768
- # ```
1769
- #
1730
+ #
1770
1731
  # ```python sync
1771
- # from playwright.sync_api import sync_playwright
1772
- #
1773
- # def run(playwright):
1732
+ # from playwright.sync_api import sync_playwright, Playwright
1733
+ #
1734
+ # def run(playwright: Playwright):
1774
1735
  # chromium = playwright.chromium
1775
1736
  # browser = chromium.launch()
1776
1737
  # page = browser.new_page()
@@ -1779,51 +1740,101 @@ module Playwright
1779
1740
  # element = page.wait_for_selector("img")
1780
1741
  # print("Loaded image: " + str(element.get_attribute("src")))
1781
1742
  # browser.close()
1782
- #
1743
+ #
1783
1744
  # with sync_playwright() as playwright:
1784
1745
  # run(playwright)
1785
1746
  # ```
1786
- def wait_for_selector(selector, state: nil, timeout: nil)
1787
- raise NotImplementedError.new('wait_for_selector is not implemented yet.')
1747
+ def wait_for_selector(selector, state: nil, strict: nil, timeout: nil)
1748
+ wrap_impl(@impl.wait_for_selector(unwrap_impl(selector), state: unwrap_impl(state), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
1788
1749
  end
1789
1750
 
1751
+ #
1790
1752
  # Waits for the given `timeout` in milliseconds.
1791
- #
1753
+ #
1792
1754
  # Note that `page.waitForTimeout()` should only be used for debugging. Tests using the timer in production are going to be
1793
1755
  # flaky. Use signals such as network events, selectors becoming visible and others instead.
1794
- #
1795
1756
  #
1796
- # ```js
1797
- # // wait for 1 second
1798
- # await page.waitForTimeout(1000);
1799
- # ```
1800
- #
1801
- # ```python async
1802
- # # wait for 1 second
1803
- # await page.wait_for_timeout(1000)
1804
- # ```
1805
- #
1757
+ # **Usage**
1758
+ #
1806
1759
  # ```python sync
1807
1760
  # # wait for 1 second
1808
1761
  # page.wait_for_timeout(1000)
1809
1762
  # ```
1810
- #
1811
- # Shortcut for main frame's [`method: Frame.waitForTimeout`].
1812
1763
  def wait_for_timeout(timeout)
1813
- raise NotImplementedError.new('wait_for_timeout is not implemented yet.')
1764
+ wrap_impl(@impl.wait_for_timeout(unwrap_impl(timeout)))
1814
1765
  end
1815
1766
 
1767
+ #
1768
+ # Waits for the main frame to navigate to the given URL.
1769
+ #
1770
+ # **Usage**
1771
+ #
1772
+ # ```python sync
1773
+ # page.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
1774
+ # page.wait_for_url("**/target.html")
1775
+ # ```
1776
+ def wait_for_url(url, timeout: nil, waitUntil: nil)
1777
+ wrap_impl(@impl.wait_for_url(unwrap_impl(url), timeout: unwrap_impl(timeout), waitUntil: unwrap_impl(waitUntil)))
1778
+ end
1779
+
1780
+ #
1781
+ # Performs action and waits for a new `WebSocket`. If predicate is provided, it passes
1782
+ # `WebSocket` value into the `predicate` function and waits for `predicate(webSocket)` to return a truthy value.
1783
+ # Will throw an error if the page is closed before the WebSocket event is fired.
1784
+ def expect_websocket(predicate: nil, timeout: nil, &block)
1785
+ wrap_impl(@impl.expect_websocket(predicate: unwrap_impl(predicate), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
1786
+ end
1787
+
1788
+ #
1789
+ # Performs action and waits for a new `Worker`. If predicate is provided, it passes
1790
+ # `Worker` value into the `predicate` function and waits for `predicate(worker)` to return a truthy value.
1791
+ # Will throw an error if the page is closed before the worker event is fired.
1792
+ def expect_worker(predicate: nil, timeout: nil, &block)
1793
+ wrap_impl(@impl.expect_worker(predicate: unwrap_impl(predicate), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
1794
+ end
1795
+
1796
+ #
1816
1797
  # This method returns all of the dedicated [WebWorkers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API)
1817
1798
  # associated with the page.
1818
- #
1819
- # > NOTE: This does not contain ServiceWorkers
1799
+ #
1800
+ # **NOTE**: This does not contain ServiceWorkers
1820
1801
  def workers
1821
- raise NotImplementedError.new('workers is not implemented yet.')
1802
+ wrap_impl(@impl.workers)
1803
+ end
1804
+
1805
+ #
1806
+ # **NOTE**: In most cases, you should use [`method: Page.waitForEvent`].
1807
+ #
1808
+ # Waits for given `event` to fire. If predicate is provided, it passes
1809
+ # event's value into the `predicate` function and waits for `predicate(event)` to return a truthy value.
1810
+ # Will throw an error if the page is closed before the `event` is fired.
1811
+ def wait_for_event(event, predicate: nil, timeout: nil)
1812
+ raise NotImplementedError.new('wait_for_event is not implemented yet.')
1813
+ end
1814
+
1815
+ # @nodoc
1816
+ def guid
1817
+ wrap_impl(@impl.guid)
1818
+ end
1819
+
1820
+ # @nodoc
1821
+ def snapshot_for_ai(timeout: nil, mode: nil, track: nil)
1822
+ wrap_impl(@impl.snapshot_for_ai(timeout: unwrap_impl(timeout), mode: unwrap_impl(mode), track: unwrap_impl(track)))
1823
+ end
1824
+
1825
+ # @nodoc
1826
+ def start_js_coverage(resetOnNavigation: nil, reportAnonymousScripts: nil)
1827
+ wrap_impl(@impl.start_js_coverage(resetOnNavigation: unwrap_impl(resetOnNavigation), reportAnonymousScripts: unwrap_impl(reportAnonymousScripts)))
1822
1828
  end
1823
1829
 
1824
1830
  # @nodoc
1825
- def after_initialize
1826
- wrap_impl(@impl.after_initialize)
1831
+ def stop_js_coverage
1832
+ wrap_impl(@impl.stop_js_coverage)
1833
+ end
1834
+
1835
+ # @nodoc
1836
+ def start_css_coverage(resetOnNavigation: nil, reportAnonymousScripts: nil)
1837
+ wrap_impl(@impl.start_css_coverage(resetOnNavigation: unwrap_impl(resetOnNavigation), reportAnonymousScripts: unwrap_impl(reportAnonymousScripts)))
1827
1838
  end
1828
1839
 
1829
1840
  # @nodoc
@@ -1831,22 +1842,31 @@ module Playwright
1831
1842
  wrap_impl(@impl.owned_context=(unwrap_impl(req)))
1832
1843
  end
1833
1844
 
1845
+ # @nodoc
1846
+ def stop_css_coverage
1847
+ wrap_impl(@impl.stop_css_coverage)
1848
+ end
1849
+
1834
1850
  # -- inherited from EventEmitter --
1835
1851
  # @nodoc
1836
- def on(event, callback)
1837
- wrap_impl(@impl.on(unwrap_impl(event), unwrap_impl(callback)))
1852
+ def once(event, callback)
1853
+ event_emitter_proxy.once(event, callback)
1838
1854
  end
1839
1855
 
1840
1856
  # -- inherited from EventEmitter --
1841
1857
  # @nodoc
1842
- def off(event, callback)
1843
- wrap_impl(@impl.off(unwrap_impl(event), unwrap_impl(callback)))
1858
+ def on(event, callback)
1859
+ event_emitter_proxy.on(event, callback)
1844
1860
  end
1845
1861
 
1846
1862
  # -- inherited from EventEmitter --
1847
1863
  # @nodoc
1848
- def once(event, callback)
1849
- wrap_impl(@impl.once(unwrap_impl(event), unwrap_impl(callback)))
1864
+ def off(event, callback)
1865
+ event_emitter_proxy.off(event, callback)
1866
+ end
1867
+
1868
+ private def event_emitter_proxy
1869
+ @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
1850
1870
  end
1851
1871
  end
1852
1872
  end