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,202 +1,89 @@
1
1
  module Playwright
2
+ #
2
3
  # At every point of time, page exposes its current frame tree via the [`method: Page.mainFrame`] and
3
4
  # [`method: Frame.childFrames`] methods.
4
- #
5
+ #
5
6
  # `Frame` object's lifecycle is controlled by three events, dispatched on the page object:
6
- # - [`event: Page.frameattached`] - fired when the frame gets attached to the page. A Frame can be attached to the page
7
- # only once.
8
- # - [`event: Page.framenavigated`] - fired when the frame commits navigation to a different URL.
9
- # - [`event: Page.framedetached`] - fired when the frame gets detached from the page. A Frame can be detached from the
10
- # page only once.
11
- #
7
+ # - [`event: Page.frameAttached`] - fired when the frame gets attached to the page. A Frame can be attached to the page only once.
8
+ # - [`event: Page.frameNavigated`] - fired when the frame commits navigation to a different URL.
9
+ # - [`event: Page.frameDetached`] - fired when the frame gets detached from the page. A Frame can be detached from the page only once.
10
+ #
12
11
  # An example of dumping frame tree:
13
- #
14
12
  #
15
- # ```js
16
- # const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'.
17
- #
18
- # (async () => {
19
- # const browser = await firefox.launch();
20
- # const page = await browser.newPage();
21
- # await page.goto('https://www.google.com/chrome/browser/canary.html');
22
- # dumpFrameTree(page.mainFrame(), '');
23
- # await browser.close();
24
- #
25
- # function dumpFrameTree(frame, indent) {
26
- # console.log(indent + frame.url());
27
- # for (const child of frame.childFrames()) {
28
- # dumpFrameTree(child, indent + ' ');
29
- # }
30
- # }
31
- # })();
32
- # ```
33
- #
34
- # ```python async
35
- # import asyncio
36
- # from playwright.async_api import async_playwright
37
- #
38
- # async def run(playwright):
39
- # firefox = playwright.firefox
40
- # browser = await firefox.launch()
41
- # page = await browser.new_page()
42
- # await page.goto("https://www.theverge.com")
43
- # dump_frame_tree(page.main_frame, "")
44
- # await browser.close()
45
- #
46
- # def dump_frame_tree(frame, indent):
47
- # print(indent + frame.name + '@' + frame.url)
48
- # for child in frame.child_frames:
49
- # dump_frame_tree(child, indent + " ")
50
- #
51
- # async def main():
52
- # async with async_playwright() as playwright:
53
- # await run(playwright)
54
- # asyncio.run(main())
55
- # ```
56
- #
57
13
  # ```python sync
58
- # from playwright.sync_api import sync_playwright
59
- #
60
- # def run(playwright):
14
+ # from playwright.sync_api import sync_playwright, Playwright
15
+ #
16
+ # def run(playwright: Playwright):
61
17
  # firefox = playwright.firefox
62
18
  # browser = firefox.launch()
63
19
  # page = browser.new_page()
64
20
  # page.goto("https://www.theverge.com")
65
21
  # dump_frame_tree(page.main_frame, "")
66
22
  # browser.close()
67
- #
23
+ #
68
24
  # def dump_frame_tree(frame, indent):
69
25
  # print(indent + frame.name + '@' + frame.url)
70
26
  # for child in frame.child_frames:
71
27
  # dump_frame_tree(child, indent + " ")
72
- #
28
+ #
73
29
  # with sync_playwright() as playwright:
74
30
  # run(playwright)
75
31
  # ```
76
32
  class Frame < PlaywrightApi
77
33
 
78
- # Returns the ElementHandle pointing to the frame element.
79
- #
80
- # The method finds an element matching the specified selector within the frame. See
81
- # [Working with selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector,
82
- # returns `null`.
83
- def query_selector(selector)
84
- wrap_impl(@impl.query_selector(unwrap_impl(selector)))
85
- end
86
-
87
- # Returns the ElementHandles pointing to the frame elements.
88
- #
89
- # The method finds all elements matching the specified selector within the frame. See
90
- # [Working with selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector,
91
- # returns empty array.
92
- def query_selector_all(selector)
93
- wrap_impl(@impl.query_selector_all(unwrap_impl(selector)))
94
- end
95
-
96
- # Returns the return value of `pageFunction`
97
- #
98
- # The method finds an element matching the specified selector within the frame and passes it as a first argument to
99
- # `pageFunction`. See [Working with selectors](./selectors.md#working-with-selectors) for more details. If no elements
100
- # match the selector, the method throws an error.
101
- #
102
- # If `pageFunction` returns a [Promise], then `frame.$eval` would wait for the promise to resolve and return its value.
103
- #
104
- # Examples:
105
- #
106
- #
107
- # ```js
108
- # const searchValue = await frame.$eval('#search', el => el.value);
109
- # const preloadHref = await frame.$eval('link[rel=preload]', el => el.href);
110
- # const html = await frame.$eval('.main-container', (e, suffix) => e.outerHTML + suffix, 'hello');
111
- # ```
112
- #
113
- # ```python async
114
- # search_value = await frame.eval_on_selector("#search", "el => el.value")
115
- # preload_href = await frame.eval_on_selector("link[rel=preload]", "el => el.href")
116
- # html = await frame.eval_on_selector(".main-container", "(e, suffix) => e.outerHTML + suffix", "hello")
117
- # ```
118
- #
119
- # ```python sync
120
- # search_value = frame.eval_on_selector("#search", "el => el.value")
121
- # preload_href = frame.eval_on_selector("link[rel=preload]", "el => el.href")
122
- # html = frame.eval_on_selector(".main-container", "(e, suffix) => e.outerHTML + suffix", "hello")
123
- # ```
124
- def eval_on_selector(selector, pageFunction, arg: nil)
125
- wrap_impl(@impl.eval_on_selector(unwrap_impl(selector), unwrap_impl(pageFunction), arg: unwrap_impl(arg)))
126
- end
127
-
128
- # Returns the return value of `pageFunction`
129
- #
130
- # The method finds all elements matching the specified selector within the frame and passes an array of matched elements
131
- # as a first argument to `pageFunction`. See [Working with selectors](./selectors.md#working-with-selectors) for more
132
- # details.
133
- #
134
- # If `pageFunction` returns a [Promise], then `frame.$$eval` would wait for the promise to resolve and return its value.
135
- #
136
- # Examples:
137
- #
138
- #
139
- # ```js
140
- # const divsCounts = await frame.$$eval('div', (divs, min) => divs.length >= min, 10);
141
- # ```
142
- #
143
- # ```python async
144
- # divs_counts = await frame.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10)
145
- # ```
146
- #
147
- # ```python sync
148
- # divs_counts = frame.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10)
149
- # ```
150
- def eval_on_selector_all(selector, pageFunction, arg: nil)
151
- wrap_impl(@impl.eval_on_selector_all(unwrap_impl(selector), unwrap_impl(pageFunction), arg: unwrap_impl(arg)))
152
- end
153
-
34
+ #
154
35
  # Returns the added tag when the script's onload fires or when the script content was injected into frame.
155
- #
36
+ #
156
37
  # Adds a `<script>` tag into the page with the desired url or content.
157
38
  def add_script_tag(content: nil, path: nil, type: nil, url: nil)
158
39
  wrap_impl(@impl.add_script_tag(content: unwrap_impl(content), path: unwrap_impl(path), type: unwrap_impl(type), url: unwrap_impl(url)))
159
40
  end
160
41
 
42
+ #
161
43
  # Returns the added tag when the stylesheet's onload fires or when the CSS content was injected into frame.
162
- #
44
+ #
163
45
  # Adds a `<link rel="stylesheet">` tag into the page with the desired url or a `<style type="text/css">` tag with the
164
46
  # content.
165
47
  def add_style_tag(content: nil, path: nil, url: nil)
166
48
  wrap_impl(@impl.add_style_tag(content: unwrap_impl(content), path: unwrap_impl(path), url: unwrap_impl(url)))
167
49
  end
168
50
 
51
+ #
169
52
  # This method checks an element matching `selector` by performing the following steps:
170
- # 1. Find an element match matching `selector`. If there is none, wait until a matching element is attached to the DOM.
171
- # 1. Ensure that matched element is a checkbox or a radio input. If not, this method rejects. If the element is already
172
- # checked, this method returns immediately.
173
- # 1. Wait for [actionability](./actionability.md) checks on the matched element, unless `force` option is set. If the
174
- # element is detached during the checks, the whole action is retried.
53
+ # 1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
54
+ # 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.
55
+ # 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.
175
56
  # 1. Scroll the element into view if needed.
176
57
  # 1. Use [`property: Page.mouse`] to click in the center of the element.
177
- # 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
178
- # 1. Ensure that the element is now checked. If not, this method rejects.
179
- #
180
- # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
181
- # Passing zero timeout disables this.
182
- def check(selector, force: nil, noWaitAfter: nil, timeout: nil)
183
- wrap_impl(@impl.check(unwrap_impl(selector), force: unwrap_impl(force), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
58
+ # 1. Ensure that the element is now checked. If not, this method throws.
59
+ #
60
+ # When all steps combined have not finished during the specified `timeout`, this method throws a
61
+ # `TimeoutError`. Passing zero timeout disables this.
62
+ def check(
63
+ selector,
64
+ force: nil,
65
+ noWaitAfter: nil,
66
+ position: nil,
67
+ strict: nil,
68
+ timeout: nil,
69
+ trial: nil)
70
+ 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)))
184
71
  end
185
72
 
186
73
  def child_frames
187
74
  wrap_impl(@impl.child_frames)
188
75
  end
189
76
 
77
+ #
190
78
  # This method clicks an element matching `selector` by performing the following steps:
191
- # 1. Find an element match matching `selector`. If there is none, wait until a matching element is attached to the DOM.
192
- # 1. Wait for [actionability](./actionability.md) checks on the matched element, unless `force` option is set. If the
193
- # element is detached during the checks, the whole action is retried.
79
+ # 1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
80
+ # 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.
194
81
  # 1. Scroll the element into view if needed.
195
82
  # 1. Use [`property: Page.mouse`] to click in the center of the element, or the specified `position`.
196
83
  # 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
197
- #
198
- # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
199
- # Passing zero timeout disables this.
84
+ #
85
+ # When all steps combined have not finished during the specified `timeout`, this method throws a
86
+ # `TimeoutError`. Passing zero timeout disables this.
200
87
  def click(
201
88
  selector,
202
89
  button: nil,
@@ -206,28 +93,29 @@ module Playwright
206
93
  modifiers: nil,
207
94
  noWaitAfter: nil,
208
95
  position: nil,
209
- timeout: nil)
210
- 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)))
96
+ strict: nil,
97
+ timeout: nil,
98
+ trial: nil)
99
+ 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)))
211
100
  end
212
101
 
102
+ #
213
103
  # Gets the full HTML contents of the frame, including the doctype.
214
104
  def content
215
105
  wrap_impl(@impl.content)
216
106
  end
217
107
 
108
+ #
218
109
  # This method double clicks an element matching `selector` by performing the following steps:
219
- # 1. Find an element match matching `selector`. If there is none, wait until a matching element is attached to the DOM.
220
- # 1. Wait for [actionability](./actionability.md) checks on the matched element, unless `force` option is set. If the
221
- # element is detached during the checks, the whole action is retried.
110
+ # 1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
111
+ # 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.
222
112
  # 1. Scroll the element into view if needed.
223
- # 1. Use [`property: Page.mouse`] to double click in the center of the element, or the specified `position`.
224
- # 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set. Note that if the
225
- # first click of the `dblclick()` triggers a navigation event, this method will reject.
226
- #
227
- # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
228
- # Passing zero timeout disables this.
229
- #
230
- # > NOTE: `frame.dblclick()` dispatches two `click` events and a single `dblclick` event.
113
+ # 1. Use [`property: Page.mouse`] to double click in the center of the element, or the specified `position`. if the first click of the `dblclick()` triggers a navigation event, this method will throw.
114
+ #
115
+ # When all steps combined have not finished during the specified `timeout`, this method throws a
116
+ # `TimeoutError`. Passing zero timeout disables this.
117
+ #
118
+ # **NOTE**: `frame.dblclick()` dispatches two `click` events and a single `dblclick` event.
231
119
  def dblclick(
232
120
  selector,
233
121
  button: nil,
@@ -236,605 +124,832 @@ module Playwright
236
124
  modifiers: nil,
237
125
  noWaitAfter: nil,
238
126
  position: nil,
239
- timeout: nil)
240
- 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)))
127
+ strict: nil,
128
+ timeout: nil,
129
+ trial: nil)
130
+ 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)))
241
131
  end
242
132
 
243
- # The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the elment, `click`
244
- # is dispatched. This is equivalend to calling
133
+ #
134
+ # The snippet below dispatches the `click` event on the element. Regardless of the visibility state of the element, `click`
135
+ # is dispatched. This is equivalent to calling
245
136
  # [element.click()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click).
246
- #
247
137
  #
248
- # ```js
249
- # await frame.dispatchEvent('button#submit', 'click');
250
- # ```
251
- #
252
- # ```python async
253
- # await frame.dispatch_event("button#submit", "click")
254
- # ```
255
- #
138
+ # **Usage**
139
+ #
256
140
  # ```python sync
257
141
  # frame.dispatch_event("button#submit", "click")
258
142
  # ```
259
- #
260
- # Under the hood, it creates an instance of an event based on the given `type`, initializes it with `eventInit` properties
261
- # and dispatches it on the element. Events are `composed`, `cancelable` and bubble by default.
262
- #
263
- # Since `eventInit` is event-specific, please refer to the events documentation for the lists of initial properties:
143
+ #
144
+ # Under the hood, it creates an instance of an event based on the given `type`, initializes it with
145
+ # `eventInit` properties and dispatches it on the element. Events are `composed`, `cancelable` and bubble by
146
+ # default.
147
+ #
148
+ # Since `eventInit` is event-specific, please refer to the events documentation for the lists of initial
149
+ # properties:
150
+ # - [DeviceMotionEvent](https://developer.mozilla.org/en-US/docs/Web/API/DeviceMotionEvent/DeviceMotionEvent)
151
+ # - [DeviceOrientationEvent](https://developer.mozilla.org/en-US/docs/Web/API/DeviceOrientationEvent/DeviceOrientationEvent)
264
152
  # - [DragEvent](https://developer.mozilla.org/en-US/docs/Web/API/DragEvent/DragEvent)
153
+ # - [Event](https://developer.mozilla.org/en-US/docs/Web/API/Event/Event)
265
154
  # - [FocusEvent](https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/FocusEvent)
266
155
  # - [KeyboardEvent](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/KeyboardEvent)
267
156
  # - [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/MouseEvent)
268
157
  # - [PointerEvent](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/PointerEvent)
269
158
  # - [TouchEvent](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/TouchEvent)
270
- # - [Event](https://developer.mozilla.org/en-US/docs/Web/API/Event/Event)
271
- #
159
+ # - [WheelEvent](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent/WheelEvent)
160
+ #
272
161
  # You can also specify `JSHandle` as the property value if you want live objects to be passed into the event:
273
- #
274
162
  #
275
- # ```js
276
- # // Note you can only create DataTransfer in Chromium and Firefox
277
- # const dataTransfer = await frame.evaluateHandle(() => new DataTransfer());
278
- # await frame.dispatchEvent('#source', 'dragstart', { dataTransfer });
279
- # ```
280
- #
281
- # ```python async
282
- # # note you can only create data_transfer in chromium and firefox
283
- # data_transfer = await frame.evaluate_handle("new DataTransfer()")
284
- # await frame.dispatch_event("#source", "dragstart", { "dataTransfer": data_transfer })
285
- # ```
286
- #
287
163
  # ```python sync
288
164
  # # note you can only create data_transfer in chromium and firefox
289
165
  # data_transfer = frame.evaluate_handle("new DataTransfer()")
290
166
  # frame.dispatch_event("#source", "dragstart", { "dataTransfer": data_transfer })
291
167
  # ```
292
- def dispatch_event(selector, type, eventInit: nil, timeout: nil)
293
- wrap_impl(@impl.dispatch_event(unwrap_impl(selector), unwrap_impl(type), eventInit: unwrap_impl(eventInit), timeout: unwrap_impl(timeout)))
294
- end
295
-
296
- # Returns the return value of `pageFunction`
297
- #
298
- # If the function passed to the [`method: Frame.evaluate`] returns a [Promise], then [`method: Frame.evaluate`] would wait
299
- # for the promise to resolve and return its value.
300
- #
301
- # If the function passed to the [`method: Frame.evaluate`] returns a non-[Serializable] value,
302
- # then[ method: `Frame.evaluate`] returns `undefined`. DevTools Protocol also supports transferring some additional values
303
- # that are not serializable by `JSON`: `-0`, `NaN`, `Infinity`, `-Infinity`, and bigint literals.
304
- #
305
- #
306
- # ```js
307
- # const result = await frame.evaluate(([x, y]) => {
308
- # return Promise.resolve(x * y);
309
- # }, [7, 8]);
310
- # console.log(result); // prints "56"
311
- # ```
312
- #
313
- # ```python async
314
- # result = await frame.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8])
315
- # print(result) # prints "56"
168
+ def dispatch_event(
169
+ selector,
170
+ type,
171
+ eventInit: nil,
172
+ strict: nil,
173
+ timeout: nil)
174
+ wrap_impl(@impl.dispatch_event(unwrap_impl(selector), unwrap_impl(type), eventInit: unwrap_impl(eventInit), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
175
+ end
176
+
177
+ def drag_and_drop(
178
+ source,
179
+ target,
180
+ force: nil,
181
+ noWaitAfter: nil,
182
+ sourcePosition: nil,
183
+ steps: nil,
184
+ strict: nil,
185
+ targetPosition: nil,
186
+ timeout: nil,
187
+ trial: nil)
188
+ 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)))
189
+ end
190
+
191
+ #
192
+ # Returns the return value of `expression`.
193
+ #
194
+ # The method finds an element matching the specified selector within the frame and passes it as a first argument to
195
+ # `expression`. If no
196
+ # elements match the selector, the method throws an error.
197
+ #
198
+ # If `expression` returns a [Promise], then [`method: Frame.evalOnSelector`] would wait for the promise to resolve and return its
199
+ # value.
200
+ #
201
+ # **Usage**
202
+ #
203
+ # ```python sync
204
+ # search_value = frame.eval_on_selector("#search", "el => el.value")
205
+ # preload_href = frame.eval_on_selector("link[rel=preload]", "el => el.href")
206
+ # html = frame.eval_on_selector(".main-container", "(e, suffix) => e.outerHTML + suffix", "hello")
316
207
  # ```
317
- #
208
+ def eval_on_selector(selector, expression, arg: nil, strict: nil)
209
+ wrap_impl(@impl.eval_on_selector(unwrap_impl(selector), unwrap_impl(expression), arg: unwrap_impl(arg), strict: unwrap_impl(strict)))
210
+ end
211
+
212
+ #
213
+ # Returns the return value of `expression`.
214
+ #
215
+ # The method finds all elements matching the specified selector within the frame and passes an array of matched elements
216
+ # as a first argument to `expression`.
217
+ #
218
+ # If `expression` returns a [Promise], then [`method: Frame.evalOnSelectorAll`] would wait for the promise to resolve and return its
219
+ # value.
220
+ #
221
+ # **Usage**
222
+ #
223
+ # ```python sync
224
+ # divs_counts = frame.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10)
225
+ # ```
226
+ def eval_on_selector_all(selector, expression, arg: nil)
227
+ wrap_impl(@impl.eval_on_selector_all(unwrap_impl(selector), unwrap_impl(expression), arg: unwrap_impl(arg)))
228
+ end
229
+
230
+ #
231
+ # Returns the return value of `expression`.
232
+ #
233
+ # If the function passed to the [`method: Frame.evaluate`] returns a [Promise], then [`method: Frame.evaluate`] would wait for the promise to
234
+ # resolve and return its value.
235
+ #
236
+ # If the function passed to the [`method: Frame.evaluate`] returns a non-[Serializable] value, then
237
+ # [`method: Frame.evaluate`] returns `undefined`. Playwright also supports transferring some
238
+ # additional values that are not serializable by `JSON`: `-0`, `NaN`, `Infinity`, `-Infinity`.
239
+ #
240
+ # **Usage**
241
+ #
318
242
  # ```python sync
319
243
  # result = frame.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8])
320
244
  # print(result) # prints "56"
321
245
  # ```
322
- #
246
+ #
323
247
  # A string can also be passed in instead of a function.
324
- #
325
248
  #
326
- # ```js
327
- # console.log(await frame.evaluate('1 + 2')); // prints "3"
328
- # ```
329
- #
330
- # ```python async
331
- # print(await frame.evaluate("1 + 2")) # prints "3"
332
- # x = 10
333
- # print(await frame.evaluate(f"1 + {x}")) # prints "11"
334
- # ```
335
- #
336
249
  # ```python sync
337
250
  # print(frame.evaluate("1 + 2")) # prints "3"
338
251
  # x = 10
339
252
  # print(frame.evaluate(f"1 + {x}")) # prints "11"
340
253
  # ```
341
- #
254
+ #
342
255
  # `ElementHandle` instances can be passed as an argument to the [`method: Frame.evaluate`]:
343
- #
344
256
  #
345
- # ```js
346
- # const bodyHandle = await frame.$('body');
347
- # const html = await frame.evaluate(([body, suffix]) => body.innerHTML + suffix, [bodyHandle, 'hello']);
348
- # await bodyHandle.dispose();
349
- # ```
350
- #
351
- # ```python async
352
- # body_handle = await frame.query_selector("body")
353
- # html = await frame.evaluate("([body, suffix]) => body.innerHTML + suffix", [body_handle, "hello"])
354
- # await body_handle.dispose()
355
- # ```
356
- #
357
257
  # ```python sync
358
- # body_handle = frame.query_selector("body")
258
+ # body_handle = frame.evaluate("document.body")
359
259
  # html = frame.evaluate("([body, suffix]) => body.innerHTML + suffix", [body_handle, "hello"])
360
260
  # body_handle.dispose()
361
261
  # ```
362
- def evaluate(pageFunction, arg: nil)
363
- wrap_impl(@impl.evaluate(unwrap_impl(pageFunction), arg: unwrap_impl(arg)))
262
+ def evaluate(expression, arg: nil)
263
+ wrap_impl(@impl.evaluate(unwrap_impl(expression), arg: unwrap_impl(arg)))
364
264
  end
365
265
 
366
- # Returns the return value of `pageFunction` as in-page object (JSHandle).
367
- #
368
- # The only difference between [`method: Frame.evaluate`] and [`method: Frame.evaluateHandle`] is
369
- # that[ method: Fframe.evaluateHandle`] returns in-page object (JSHandle).
370
- #
371
- # If the function, passed to the [`method: Frame.evaluateHandle`], returns a [Promise],
372
- # then[ method: Fframe.evaluateHandle`] would wait for the promise to resolve and return its value.
373
- #
374
266
  #
375
- # ```js
376
- # const aWindowHandle = await frame.evaluateHandle(() => Promise.resolve(window));
377
- # aWindowHandle; // Handle for the window object.
378
- # ```
379
- #
380
- # ```python async
381
- # # FIXME
382
- # a_window_handle = await frame.evaluate_handle("Promise.resolve(window)")
383
- # a_window_handle # handle for the window object.
384
- # ```
385
- #
267
+ # Returns the return value of `expression` as a `JSHandle`.
268
+ #
269
+ # The only difference between [`method: Frame.evaluate`] and [`method: Frame.evaluateHandle`] is that
270
+ # [`method: Frame.evaluateHandle`] returns `JSHandle`.
271
+ #
272
+ # If the function, passed to the [`method: Frame.evaluateHandle`], returns a [Promise], then
273
+ # [`method: Frame.evaluateHandle`] would wait for the promise to resolve and return its value.
274
+ #
275
+ # **Usage**
276
+ #
386
277
  # ```python sync
387
278
  # a_window_handle = frame.evaluate_handle("Promise.resolve(window)")
388
279
  # a_window_handle # handle for the window object.
389
280
  # ```
390
- #
281
+ #
391
282
  # A string can also be passed in instead of a function.
392
- #
393
283
  #
394
- # ```js
395
- # const aHandle = await frame.evaluateHandle('document'); // Handle for the 'document'.
396
- # ```
397
- #
398
- # ```python async
399
- # a_handle = await page.evaluate_handle("document") # handle for the "document"
400
- # ```
401
- #
402
284
  # ```python sync
403
285
  # a_handle = page.evaluate_handle("document") # handle for the "document"
404
286
  # ```
405
- #
287
+ #
406
288
  # `JSHandle` instances can be passed as an argument to the [`method: Frame.evaluateHandle`]:
407
- #
408
- #
409
- # ```js
410
- # const aHandle = await frame.evaluateHandle(() => document.body);
411
- # const resultHandle = await frame.evaluateHandle(([body, suffix]) => body.innerHTML + suffix, [aHandle, 'hello']);
412
- # console.log(await resultHandle.jsonValue());
413
- # await resultHandle.dispose();
414
- # ```
415
- #
416
- # ```python async
417
- # a_handle = await page.evaluate_handle("document.body")
418
- # result_handle = await page.evaluate_handle("body => body.innerHTML", a_handle)
419
- # print(await result_handle.json_value())
420
- # await result_handle.dispose()
421
- # ```
422
- #
289
+ #
423
290
  # ```python sync
424
291
  # a_handle = page.evaluate_handle("document.body")
425
292
  # result_handle = page.evaluate_handle("body => body.innerHTML", a_handle)
426
293
  # print(result_handle.json_value())
427
294
  # result_handle.dispose()
428
295
  # ```
429
- def evaluate_handle(pageFunction, arg: nil)
430
- wrap_impl(@impl.evaluate_handle(unwrap_impl(pageFunction), arg: unwrap_impl(arg)))
296
+ def evaluate_handle(expression, arg: nil)
297
+ wrap_impl(@impl.evaluate_handle(unwrap_impl(expression), arg: unwrap_impl(arg)))
431
298
  end
432
299
 
433
- # This method waits for an element matching `selector`, waits for [actionability](./actionability.md) checks, focuses the
434
- # element, fills it and triggers an `input` event after filling. If the element matching `selector` is not an `<input>`,
435
- # `<textarea>` or `[contenteditable]` element, this method throws an error. Note that you can pass an empty string to
436
- # clear the input field.
437
- #
438
- # To send fine-grained keyboard events, use [`method: Frame.type`].
439
- def fill(selector, value, noWaitAfter: nil, timeout: nil)
440
- wrap_impl(@impl.fill(unwrap_impl(selector), unwrap_impl(value), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
300
+ #
301
+ # 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.
302
+ #
303
+ # 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.
304
+ #
305
+ # To send fine-grained keyboard events, use [`method: Locator.pressSequentially`].
306
+ def fill(
307
+ selector,
308
+ value,
309
+ force: nil,
310
+ noWaitAfter: nil,
311
+ strict: nil,
312
+ timeout: nil)
313
+ 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)))
441
314
  end
442
315
 
443
- # This method fetches an element with `selector` and focuses it. If there's no element matching `selector`, the method
444
- # waits until a matching element appears in the DOM.
445
- def focus(selector, timeout: nil)
446
- wrap_impl(@impl.focus(unwrap_impl(selector), timeout: unwrap_impl(timeout)))
316
+ #
317
+ # This method fetches an element with `selector` and focuses it. If there's no element matching
318
+ # `selector`, the method waits until a matching element appears in the DOM.
319
+ def focus(selector, strict: nil, timeout: nil)
320
+ wrap_impl(@impl.focus(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
447
321
  end
448
322
 
323
+ #
449
324
  # Returns the `frame` or `iframe` element handle which corresponds to this frame.
450
- #
325
+ #
451
326
  # This is an inverse of [`method: ElementHandle.contentFrame`]. Note that returned handle actually belongs to the parent
452
327
  # frame.
453
- #
328
+ #
454
329
  # This method throws an error if the frame has been detached before `frameElement()` returns.
455
- #
456
330
  #
457
- # ```js
458
- # const frameElement = await frame.frameElement();
459
- # const contentFrame = await frameElement.contentFrame();
460
- # console.log(frame === contentFrame); // -> true
461
- # ```
462
- #
463
- # ```python async
464
- # frame_element = await frame.frame_element()
465
- # content_frame = await frame_element.content_frame()
466
- # assert frame == content_frame
467
- # ```
468
- #
331
+ # **Usage**
332
+ #
469
333
  # ```python sync
470
334
  # frame_element = frame.frame_element()
471
335
  # content_frame = frame_element.content_frame()
472
336
  # assert frame == content_frame
473
337
  # ```
474
338
  def frame_element
475
- raise NotImplementedError.new('frame_element is not implemented yet.')
339
+ wrap_impl(@impl.frame_element)
340
+ end
341
+
342
+ #
343
+ # When working with iframes, you can create a frame locator that will enter the iframe and allow selecting elements
344
+ # in that iframe.
345
+ #
346
+ # **Usage**
347
+ #
348
+ # Following snippet locates element with text "Submit" in the iframe with id `my-frame`, like `<iframe id="my-frame">`:
349
+ #
350
+ # ```python sync
351
+ # locator = frame.frame_locator("#my-iframe").get_by_text("Submit")
352
+ # locator.click()
353
+ # ```
354
+ def frame_locator(selector)
355
+ wrap_impl(@impl.frame_locator(unwrap_impl(selector)))
476
356
  end
477
357
 
358
+ #
478
359
  # Returns element attribute value.
479
- def get_attribute(selector, name, timeout: nil)
480
- wrap_impl(@impl.get_attribute(unwrap_impl(selector), unwrap_impl(name), timeout: unwrap_impl(timeout)))
360
+ def get_attribute(selector, name, strict: nil, timeout: nil)
361
+ wrap_impl(@impl.get_attribute(unwrap_impl(selector), unwrap_impl(name), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
362
+ end
363
+
364
+ #
365
+ # Allows locating elements by their alt text.
366
+ #
367
+ # **Usage**
368
+ #
369
+ # For example, this method will find the image by alt text "Playwright logo":
370
+ #
371
+ # ```html
372
+ # <img alt='Playwright logo'>
373
+ # ```
374
+ #
375
+ # ```python sync
376
+ # page.get_by_alt_text("Playwright logo").click()
377
+ # ```
378
+ def get_by_alt_text(text, exact: nil)
379
+ wrap_impl(@impl.get_by_alt_text(unwrap_impl(text), exact: unwrap_impl(exact)))
380
+ end
381
+
382
+ #
383
+ # Allows locating input elements by the text of the associated `<label>` or `aria-labelledby` element, or by the `aria-label` attribute.
384
+ #
385
+ # **Usage**
386
+ #
387
+ # For example, this method will find inputs by label "Username" and "Password" in the following DOM:
388
+ #
389
+ # ```html
390
+ # <input aria-label="Username">
391
+ # <label for="password-input">Password:</label>
392
+ # <input id="password-input">
393
+ # ```
394
+ #
395
+ # ```python sync
396
+ # page.get_by_label("Username").fill("john")
397
+ # page.get_by_label("Password").fill("secret")
398
+ # ```
399
+ def get_by_label(text, exact: nil)
400
+ wrap_impl(@impl.get_by_label(unwrap_impl(text), exact: unwrap_impl(exact)))
401
+ end
402
+
403
+ #
404
+ # Allows locating input elements by the placeholder text.
405
+ #
406
+ # **Usage**
407
+ #
408
+ # For example, consider the following DOM structure.
409
+ #
410
+ # ```html
411
+ # <input type="email" placeholder="name@example.com" />
412
+ # ```
413
+ #
414
+ # You can fill the input after locating it by the placeholder text:
415
+ #
416
+ # ```python sync
417
+ # page.get_by_placeholder("name@example.com").fill("playwright@microsoft.com")
418
+ # ```
419
+ def get_by_placeholder(text, exact: nil)
420
+ wrap_impl(@impl.get_by_placeholder(unwrap_impl(text), exact: unwrap_impl(exact)))
421
+ end
422
+
423
+ #
424
+ # 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).
425
+ #
426
+ # **Usage**
427
+ #
428
+ # Consider the following DOM structure.
429
+ #
430
+ # ```html
431
+ # <h3>Sign up</h3>
432
+ # <label>
433
+ # <input type="checkbox" /> Subscribe
434
+ # </label>
435
+ # <br/>
436
+ # <button>Submit</button>
437
+ # ```
438
+ #
439
+ # You can locate each element by it's implicit role:
440
+ #
441
+ # ```python sync
442
+ # expect(page.get_by_role("heading", name="Sign up")).to_be_visible()
443
+ #
444
+ # page.get_by_role("checkbox", name="Subscribe").check()
445
+ #
446
+ # page.get_by_role("button", name=re.compile("submit", re.IGNORECASE)).click()
447
+ # ```
448
+ #
449
+ # **Details**
450
+ #
451
+ # Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback about the ARIA guidelines.
452
+ #
453
+ # 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.
454
+ def get_by_role(
455
+ role,
456
+ checked: nil,
457
+ disabled: nil,
458
+ exact: nil,
459
+ expanded: nil,
460
+ includeHidden: nil,
461
+ level: nil,
462
+ name: nil,
463
+ pressed: nil,
464
+ selected: nil)
465
+ 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)))
466
+ end
467
+
468
+ #
469
+ # Locate element by the test id.
470
+ #
471
+ # **Usage**
472
+ #
473
+ # Consider the following DOM structure.
474
+ #
475
+ # ```html
476
+ # <button data-testid="directions">Itinéraire</button>
477
+ # ```
478
+ #
479
+ # You can locate the element by it's test id:
480
+ #
481
+ # ```python sync
482
+ # page.get_by_test_id("directions").click()
483
+ # ```
484
+ #
485
+ # **Details**
486
+ #
487
+ # 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.
488
+ def get_by_test_id(testId)
489
+ wrap_impl(@impl.get_by_test_id(unwrap_impl(testId)))
481
490
  end
491
+ alias_method :get_by_testid, :get_by_test_id
482
492
 
493
+ #
494
+ # Allows locating elements that contain given text.
495
+ #
496
+ # See also [`method: Locator.filter`] that allows to match by another criteria, like an accessible role, and then filter by the text content.
497
+ #
498
+ # **Usage**
499
+ #
500
+ # Consider the following DOM structure:
501
+ #
502
+ # ```html
503
+ # <div>Hello <span>world</span></div>
504
+ # <div>Hello</div>
505
+ # ```
506
+ #
507
+ # You can locate by text substring, exact string, or a regular expression:
508
+ #
509
+ # ```python sync
510
+ # # Matches <span>
511
+ # page.get_by_text("world")
512
+ #
513
+ # # Matches first <div>
514
+ # page.get_by_text("Hello world")
515
+ #
516
+ # # Matches second <div>
517
+ # page.get_by_text("Hello", exact=True)
518
+ #
519
+ # # Matches both <div>s
520
+ # page.get_by_text(re.compile("Hello"))
521
+ #
522
+ # # Matches second <div>
523
+ # page.get_by_text(re.compile("^hello$", re.IGNORECASE))
524
+ # ```
525
+ #
526
+ # **Details**
527
+ #
528
+ # 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.
529
+ #
530
+ # 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">`.
531
+ def get_by_text(text, exact: nil)
532
+ wrap_impl(@impl.get_by_text(unwrap_impl(text), exact: unwrap_impl(exact)))
533
+ end
534
+
535
+ #
536
+ # Allows locating elements by their title attribute.
537
+ #
538
+ # **Usage**
539
+ #
540
+ # Consider the following DOM structure.
541
+ #
542
+ # ```html
543
+ # <span title='Issues count'>25 issues</span>
544
+ # ```
545
+ #
546
+ # You can check the issues count after locating it by the title text:
547
+ #
548
+ # ```python sync
549
+ # expect(page.get_by_title("Issues count")).to_have_text("25 issues")
550
+ # ```
551
+ def get_by_title(text, exact: nil)
552
+ wrap_impl(@impl.get_by_title(unwrap_impl(text), exact: unwrap_impl(exact)))
553
+ end
554
+
555
+ #
483
556
  # Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
484
557
  # last redirect.
485
- #
486
- # `frame.goto` will throw an error if:
558
+ #
559
+ # The method will throw an error if:
487
560
  # - there's an SSL error (e.g. in case of self-signed certificates).
488
561
  # - target URL is invalid.
489
562
  # - the `timeout` is exceeded during navigation.
490
563
  # - the remote server does not respond or is unreachable.
491
564
  # - the main resource failed to load.
492
- #
493
- # `frame.goto` will not throw an error when any valid HTTP status code is returned by the remote server, including 404
565
+ #
566
+ # The method will not throw an error when any valid HTTP status code is returned by the remote server, including 404
494
567
  # "Not Found" and 500 "Internal Server Error". The status code for such responses can be retrieved by calling
495
568
  # [`method: Response.status`].
496
- #
497
- # > NOTE: `frame.goto` either throws an error or returns a main resource response. The only exceptions are navigation to
569
+ #
570
+ # **NOTE**: The method either throws an error or returns a main resource response. The only exceptions are navigation to
498
571
  # `about:blank` or navigation to the same URL with a different hash, which would succeed and return `null`.
499
- # > NOTE: Headless mode doesn't support navigation to a PDF document. See the
572
+ #
573
+ # **NOTE**: Headless mode doesn't support navigation to a PDF document. See the
500
574
  # [upstream issue](https://bugs.chromium.org/p/chromium/issues/detail?id=761295).
501
575
  def goto(url, referer: nil, timeout: nil, waitUntil: nil)
502
576
  wrap_impl(@impl.goto(unwrap_impl(url), referer: unwrap_impl(referer), timeout: unwrap_impl(timeout), waitUntil: unwrap_impl(waitUntil)))
503
577
  end
504
578
 
579
+ #
505
580
  # This method hovers over an element matching `selector` by performing the following steps:
506
- # 1. Find an element match matching `selector`. If there is none, wait until a matching element is attached to the DOM.
507
- # 1. Wait for [actionability](./actionability.md) checks on the matched element, unless `force` option is set. If the
508
- # element is detached during the checks, the whole action is retried.
581
+ # 1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
582
+ # 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.
509
583
  # 1. Scroll the element into view if needed.
510
584
  # 1. Use [`property: Page.mouse`] to hover over the center of the element, or the specified `position`.
511
- # 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
512
- #
513
- # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
514
- # Passing zero timeout disables this.
585
+ #
586
+ # When all steps combined have not finished during the specified `timeout`, this method throws a
587
+ # `TimeoutError`. Passing zero timeout disables this.
515
588
  def hover(
516
589
  selector,
517
590
  force: nil,
518
591
  modifiers: nil,
592
+ noWaitAfter: nil,
519
593
  position: nil,
520
- timeout: nil)
521
- wrap_impl(@impl.hover(unwrap_impl(selector), force: unwrap_impl(force), modifiers: unwrap_impl(modifiers), position: unwrap_impl(position), timeout: unwrap_impl(timeout)))
594
+ strict: nil,
595
+ timeout: nil,
596
+ trial: nil)
597
+ 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)))
522
598
  end
523
599
 
600
+ #
524
601
  # Returns `element.innerHTML`.
525
- def inner_html(selector, timeout: nil)
526
- wrap_impl(@impl.inner_html(unwrap_impl(selector), timeout: unwrap_impl(timeout)))
602
+ def inner_html(selector, strict: nil, timeout: nil)
603
+ wrap_impl(@impl.inner_html(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
527
604
  end
528
605
 
606
+ #
529
607
  # Returns `element.innerText`.
530
- def inner_text(selector, timeout: nil)
531
- wrap_impl(@impl.inner_text(unwrap_impl(selector), timeout: unwrap_impl(timeout)))
608
+ def inner_text(selector, strict: nil, timeout: nil)
609
+ wrap_impl(@impl.inner_text(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
532
610
  end
533
611
 
612
+ #
613
+ # Returns `input.value` for the selected `<input>` or `<textarea>` or `<select>` element.
614
+ #
615
+ # 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.
616
+ def input_value(selector, strict: nil, timeout: nil)
617
+ wrap_impl(@impl.input_value(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
618
+ end
619
+
620
+ #
534
621
  # Returns whether the element is checked. Throws if the element is not a checkbox or radio input.
535
- def checked?(selector, timeout: nil)
536
- wrap_impl(@impl.checked?(unwrap_impl(selector), timeout: unwrap_impl(timeout)))
622
+ def checked?(selector, strict: nil, timeout: nil)
623
+ wrap_impl(@impl.checked?(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
537
624
  end
538
625
 
626
+ #
539
627
  # Returns `true` if the frame has been detached, or `false` otherwise.
540
628
  def detached?
541
629
  wrap_impl(@impl.detached?)
542
630
  end
543
631
 
544
- # Returns whether the element is disabled, the opposite of [enabled](./actionability.md#enabled).
545
- def disabled?(selector, timeout: nil)
546
- wrap_impl(@impl.disabled?(unwrap_impl(selector), timeout: unwrap_impl(timeout)))
632
+ #
633
+ # Returns whether the element is disabled, the opposite of [enabled](../actionability.md#enabled).
634
+ def disabled?(selector, strict: nil, timeout: nil)
635
+ wrap_impl(@impl.disabled?(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
547
636
  end
548
637
 
549
- # Returns whether the element is [editable](./actionability.md#editable).
550
- def editable?(selector, timeout: nil)
551
- wrap_impl(@impl.editable?(unwrap_impl(selector), timeout: unwrap_impl(timeout)))
638
+ #
639
+ # Returns whether the element is [editable](../actionability.md#editable).
640
+ def editable?(selector, strict: nil, timeout: nil)
641
+ wrap_impl(@impl.editable?(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
552
642
  end
553
643
 
554
- # Returns whether the element is [enabled](./actionability.md#enabled).
555
- def enabled?(selector, timeout: nil)
556
- wrap_impl(@impl.enabled?(unwrap_impl(selector), timeout: unwrap_impl(timeout)))
644
+ #
645
+ # Returns whether the element is [enabled](../actionability.md#enabled).
646
+ def enabled?(selector, strict: nil, timeout: nil)
647
+ wrap_impl(@impl.enabled?(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
557
648
  end
558
649
 
559
- # Returns whether the element is hidden, the opposite of [visible](./actionability.md#visible).
560
- def hidden?(selector, timeout: nil)
561
- wrap_impl(@impl.hidden?(unwrap_impl(selector), timeout: unwrap_impl(timeout)))
650
+ #
651
+ # Returns whether the element is hidden, the opposite of [visible](../actionability.md#visible). `selector` that does not match any elements is considered hidden.
652
+ def hidden?(selector, strict: nil, timeout: nil)
653
+ wrap_impl(@impl.hidden?(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
562
654
  end
563
655
 
564
- # Returns whether the element is [visible](./actionability.md#visible).
565
- def visible?(selector, timeout: nil)
566
- wrap_impl(@impl.visible?(unwrap_impl(selector), timeout: unwrap_impl(timeout)))
656
+ #
657
+ # Returns whether the element is [visible](../actionability.md#visible). `selector` that does not match any elements is considered not visible.
658
+ def visible?(selector, strict: nil, timeout: nil)
659
+ wrap_impl(@impl.visible?(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
567
660
  end
568
661
 
662
+ #
663
+ # The method returns an element locator that can be used to perform actions on this page / frame.
664
+ # 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.
665
+ #
666
+ # [Learn more about locators](../locators.md).
667
+ #
668
+ # [Learn more about locators](../locators.md).
669
+ def locator(
670
+ selector,
671
+ has: nil,
672
+ hasNot: nil,
673
+ hasNotText: nil,
674
+ hasText: nil)
675
+ wrap_impl(@impl.locator(unwrap_impl(selector), has: unwrap_impl(has), hasNot: unwrap_impl(hasNot), hasNotText: unwrap_impl(hasNotText), hasText: unwrap_impl(hasText)))
676
+ end
677
+
678
+ #
569
679
  # Returns frame's name attribute as specified in the tag.
570
- #
680
+ #
571
681
  # If the name is empty, returns the id attribute instead.
572
- #
573
- # > NOTE: This value is calculated once when the frame is created, and will not update if the attribute is changed later.
682
+ #
683
+ # **NOTE**: This value is calculated once when the frame is created, and will not update if the attribute is changed later.
574
684
  def name
575
685
  wrap_impl(@impl.name)
576
686
  end
577
687
 
688
+ #
578
689
  # Returns the page containing this frame.
579
690
  def page
580
691
  wrap_impl(@impl.page)
581
692
  end
582
693
 
694
+ #
583
695
  # Parent frame, if any. Detached frames and main frames return `null`.
584
696
  def parent_frame
585
697
  wrap_impl(@impl.parent_frame)
586
698
  end
587
699
 
588
- # `key` can specify the intended [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key)
589
- # value or a single character to generate the text for. A superset of the `key` values can be found
700
+ #
701
+ # `key` can specify the intended
702
+ # [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character to
703
+ # generate the text for. A superset of the `key` values can be found
590
704
  # [here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Examples of the keys are:
591
- #
705
+ #
592
706
  # `F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
593
707
  # `Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
594
- #
595
- # Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`.
596
- #
708
+ #
709
+ # Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
710
+ # `ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
711
+ #
597
712
  # Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
598
- #
599
- # If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different respective
600
- # texts.
601
- #
602
- # Shortcuts such as `key: "Control+o"` or `key: "Control+Shift+T"` are supported as well. When speficied with the
713
+ #
714
+ # If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different
715
+ # respective texts.
716
+ #
717
+ # Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+T"` are supported as well. When specified with the
603
718
  # modifier, modifier is pressed and being held while the subsequent key is being pressed.
604
719
  def press(
605
720
  selector,
606
721
  key,
607
722
  delay: nil,
608
723
  noWaitAfter: nil,
724
+ strict: nil,
609
725
  timeout: nil)
610
- wrap_impl(@impl.press(unwrap_impl(selector), unwrap_impl(key), delay: unwrap_impl(delay), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
726
+ 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)))
611
727
  end
612
728
 
729
+ #
730
+ # Returns the ElementHandle pointing to the frame element.
731
+ #
732
+ # **NOTE**: The use of `ElementHandle` is discouraged, use `Locator` objects and web-first assertions instead.
733
+ #
734
+ # The method finds an element matching the specified selector within the frame. If no elements match the selector,
735
+ # returns `null`.
736
+ def query_selector(selector, strict: nil)
737
+ wrap_impl(@impl.query_selector(unwrap_impl(selector), strict: unwrap_impl(strict)))
738
+ end
739
+
740
+ #
741
+ # Returns the ElementHandles pointing to the frame elements.
742
+ #
743
+ # **NOTE**: The use of `ElementHandle` is discouraged, use `Locator` objects instead.
744
+ #
745
+ # The method finds all elements matching the specified selector within the frame. If no elements match the selector,
746
+ # returns empty array.
747
+ def query_selector_all(selector)
748
+ wrap_impl(@impl.query_selector_all(unwrap_impl(selector)))
749
+ end
750
+
751
+ #
752
+ # 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.
753
+ #
754
+ # 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.
755
+ #
613
756
  # Returns the array of option values that have been successfully selected.
614
- #
615
- # Triggers a `change` and `input` event once all the provided options have been selected. If there's no `<select>` element
616
- # matching `selector`, the method throws an error.
617
- #
618
- # Will wait until all specified options are present in the `<select>` element.
619
- #
620
- #
621
- # ```js
622
- # // single selection matching the value
623
- # frame.selectOption('select#colors', 'blue');
624
- #
625
- # // single selection matching both the value and the label
626
- # frame.selectOption('select#colors', { label: 'Blue' });
627
- #
628
- # // multiple selection
629
- # frame.selectOption('select#colors', 'red', 'green', 'blue');
630
- # ```
631
- #
632
- # ```python async
633
- # # single selection matching the value
634
- # await frame.select_option("select#colors", "blue")
635
- # # single selection matching the label
636
- # await frame.select_option("select#colors", label="blue")
637
- # # multiple selection
638
- # await frame.select_option("select#colors", value=["red", "green", "blue"])
639
- # ```
640
- #
757
+ #
758
+ # Triggers a `change` and `input` event once all the provided options have been selected.
759
+ #
760
+ # **Usage**
761
+ #
641
762
  # ```python sync
642
- # # single selection matching the value
763
+ # # Single selection matching the value or label
643
764
  # frame.select_option("select#colors", "blue")
644
765
  # # single selection matching both the label
645
766
  # frame.select_option("select#colors", label="blue")
646
767
  # # multiple selection
647
768
  # frame.select_option("select#colors", value=["red", "green", "blue"])
648
769
  # ```
649
- def select_option(selector, values, noWaitAfter: nil, timeout: nil)
650
- wrap_impl(@impl.select_option(unwrap_impl(selector), unwrap_impl(values), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
770
+ def select_option(
771
+ selector,
772
+ element: nil,
773
+ index: nil,
774
+ value: nil,
775
+ label: nil,
776
+ force: nil,
777
+ noWaitAfter: nil,
778
+ strict: nil,
779
+ timeout: nil)
780
+ 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)))
651
781
  end
652
782
 
783
+ #
784
+ # This method checks or unchecks an element matching `selector` by performing the following steps:
785
+ # 1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
786
+ # 1. Ensure that matched element is a checkbox or a radio input. If not, this method throws.
787
+ # 1. If the element already has the right checked state, this method returns immediately.
788
+ # 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.
789
+ # 1. Scroll the element into view if needed.
790
+ # 1. Use [`property: Page.mouse`] to click in the center of the element.
791
+ # 1. Ensure that the element is now checked or unchecked. If not, this method throws.
792
+ #
793
+ # When all steps combined have not finished during the specified `timeout`, this method throws a
794
+ # `TimeoutError`. Passing zero timeout disables this.
795
+ def set_checked(
796
+ selector,
797
+ checked,
798
+ force: nil,
799
+ noWaitAfter: nil,
800
+ position: nil,
801
+ strict: nil,
802
+ timeout: nil,
803
+ trial: nil)
804
+ 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)))
805
+ end
806
+
807
+ #
808
+ # This method internally calls [document.write()](https://developer.mozilla.org/en-US/docs/Web/API/Document/write), inheriting all its specific characteristics and behaviors.
653
809
  def set_content(html, timeout: nil, waitUntil: nil)
654
810
  wrap_impl(@impl.set_content(unwrap_impl(html), timeout: unwrap_impl(timeout), waitUntil: unwrap_impl(waitUntil)))
655
811
  end
656
812
  alias_method :content=, :set_content
657
813
 
658
- # This method expects `selector` to point to an
659
- # [input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input).
660
- #
814
+ #
661
815
  # Sets the value of the file input to these file paths or files. If some of the `filePaths` are relative paths, then they
662
- # are resolved relative to the the current working directory. For empty array, clears the selected files.
663
- def set_input_files(selector, files, noWaitAfter: nil, timeout: nil)
664
- wrap_impl(@impl.set_input_files(unwrap_impl(selector), unwrap_impl(files), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
816
+ # are resolved relative to the current working directory. For empty array, clears the selected files.
817
+ #
818
+ # This method expects `selector` to point to an
819
+ # [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.
820
+ def set_input_files(
821
+ selector,
822
+ files,
823
+ noWaitAfter: nil,
824
+ strict: nil,
825
+ timeout: nil)
826
+ wrap_impl(@impl.set_input_files(unwrap_impl(selector), unwrap_impl(files), noWaitAfter: unwrap_impl(noWaitAfter), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
665
827
  end
666
828
 
829
+ #
667
830
  # This method taps an element matching `selector` by performing the following steps:
668
- # 1. Find an element match matching `selector`. If there is none, wait until a matching element is attached to the DOM.
669
- # 1. Wait for [actionability](./actionability.md) checks on the matched element, unless `force` option is set. If the
670
- # element is detached during the checks, the whole action is retried.
831
+ # 1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
832
+ # 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.
671
833
  # 1. Scroll the element into view if needed.
672
834
  # 1. Use [`property: Page.touchscreen`] to tap the center of the element, or the specified `position`.
673
- # 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
674
- #
675
- # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
676
- # Passing zero timeout disables this.
677
- #
678
- # > NOTE: `frame.tap()` requires that the `hasTouch` option of the browser context be set to true.
835
+ #
836
+ # When all steps combined have not finished during the specified `timeout`, this method throws a
837
+ # `TimeoutError`. Passing zero timeout disables this.
838
+ #
839
+ # **NOTE**: `frame.tap()` requires that the `hasTouch` option of the browser context be set to true.
679
840
  def tap_point(
680
841
  selector,
681
842
  force: nil,
682
843
  modifiers: nil,
683
844
  noWaitAfter: nil,
684
845
  position: nil,
685
- timeout: nil)
686
- wrap_impl(@impl.tap_point(unwrap_impl(selector), force: unwrap_impl(force), modifiers: unwrap_impl(modifiers), noWaitAfter: unwrap_impl(noWaitAfter), position: unwrap_impl(position), timeout: unwrap_impl(timeout)))
846
+ strict: nil,
847
+ timeout: nil,
848
+ trial: nil)
849
+ 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)))
687
850
  end
688
851
 
852
+ #
689
853
  # Returns `element.textContent`.
690
- def text_content(selector, timeout: nil)
691
- wrap_impl(@impl.text_content(unwrap_impl(selector), timeout: unwrap_impl(timeout)))
854
+ def text_content(selector, strict: nil, timeout: nil)
855
+ wrap_impl(@impl.text_content(unwrap_impl(selector), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
692
856
  end
693
857
 
858
+ #
694
859
  # Returns the page title.
695
860
  def title
696
861
  wrap_impl(@impl.title)
697
862
  end
698
863
 
864
+ #
699
865
  # Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text. `frame.type` can be used to
700
866
  # send fine-grained keyboard events. To fill values in form fields, use [`method: Frame.fill`].
701
- #
867
+ #
702
868
  # To press a special key, like `Control` or `ArrowDown`, use [`method: Keyboard.press`].
703
- #
704
869
  #
705
- # ```js
706
- # await frame.type('#mytextarea', 'Hello'); // Types instantly
707
- # await frame.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user
708
- # ```
709
- #
710
- # ```python async
711
- # await frame.type("#mytextarea", "hello") # types instantly
712
- # await frame.type("#mytextarea", "world", delay=100) # types slower, like a user
713
- # ```
714
- #
715
- # ```python sync
716
- # frame.type("#mytextarea", "hello") # types instantly
717
- # frame.type("#mytextarea", "world", delay=100) # types slower, like a user
718
- # ```
870
+ # **Usage**
871
+ #
872
+ # @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`].
719
873
  def type(
720
874
  selector,
721
875
  text,
722
876
  delay: nil,
723
877
  noWaitAfter: nil,
878
+ strict: nil,
724
879
  timeout: nil)
725
- wrap_impl(@impl.type(unwrap_impl(selector), unwrap_impl(text), delay: unwrap_impl(delay), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
880
+ 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)))
726
881
  end
727
882
 
883
+ #
728
884
  # This method checks an element matching `selector` by performing the following steps:
729
- # 1. Find an element match matching `selector`. If there is none, wait until a matching element is attached to the DOM.
730
- # 1. Ensure that matched element is a checkbox or a radio input. If not, this method rejects. If the element is already
731
- # unchecked, this method returns immediately.
732
- # 1. Wait for [actionability](./actionability.md) checks on the matched element, unless `force` option is set. If the
733
- # element is detached during the checks, the whole action is retried.
885
+ # 1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
886
+ # 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.
887
+ # 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.
734
888
  # 1. Scroll the element into view if needed.
735
889
  # 1. Use [`property: Page.mouse`] to click in the center of the element.
736
- # 1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
737
- # 1. Ensure that the element is now unchecked. If not, this method rejects.
738
- #
739
- # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
740
- # Passing zero timeout disables this.
741
- def uncheck(selector, force: nil, noWaitAfter: nil, timeout: nil)
742
- wrap_impl(@impl.uncheck(unwrap_impl(selector), force: unwrap_impl(force), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
890
+ # 1. Ensure that the element is now unchecked. If not, this method throws.
891
+ #
892
+ # When all steps combined have not finished during the specified `timeout`, this method throws a
893
+ # `TimeoutError`. Passing zero timeout disables this.
894
+ def uncheck(
895
+ selector,
896
+ force: nil,
897
+ noWaitAfter: nil,
898
+ position: nil,
899
+ strict: nil,
900
+ timeout: nil,
901
+ trial: nil)
902
+ 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)))
743
903
  end
744
904
 
905
+ #
745
906
  # Returns frame's url.
746
907
  def url
747
908
  wrap_impl(@impl.url)
748
909
  end
749
910
 
750
- # Returns when the `pageFunction` returns a truthy value, returns that value.
751
- #
752
- # The `waitForFunction` can be used to observe viewport size change:
753
- #
754
- #
755
- # ```js
756
- # const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'.
757
- #
758
- # (async () => {
759
- # const browser = await firefox.launch();
760
- # const page = await browser.newPage();
761
- # const watchDog = page.mainFrame().waitForFunction('window.innerWidth < 100');
762
- # page.setViewportSize({width: 50, height: 50});
763
- # await watchDog;
764
- # await browser.close();
765
- # })();
766
- # ```
767
- #
768
- # ```python async
769
- # import asyncio
770
- # from playwright.async_api import async_playwright
771
- #
772
- # async def run(playwright):
773
- # webkit = playwright.webkit
774
- # browser = await webkit.launch()
775
- # page = await browser.new_page()
776
- # await page.evaluate("window.x = 0; setTimeout(() => { window.x = 100 }, 1000);", force_expr=True)
777
- # await page.main_frame.wait_for_function("() => window.x > 0")
778
- # await browser.close()
779
- #
780
- # async def main():
781
- # async with async_playwright() as playwright:
782
- # await run(playwright)
783
- # asyncio.run(main())
784
- # ```
785
- #
911
+ #
912
+ # Returns when the `expression` returns a truthy value, returns that value.
913
+ #
914
+ # **Usage**
915
+ #
916
+ # The [`method: Frame.waitForFunction`] can be used to observe viewport size change:
917
+ #
786
918
  # ```python sync
787
- # from playwright.sync_api import sync_playwright
788
- #
789
- # def run(playwright):
919
+ # from playwright.sync_api import sync_playwright, Playwright
920
+ #
921
+ # def run(playwright: Playwright):
790
922
  # webkit = playwright.webkit
791
923
  # browser = webkit.launch()
792
924
  # page = browser.new_page()
793
- # page.evaluate("window.x = 0; setTimeout(() => { window.x = 100 }, 1000);", force_expr=True)
925
+ # page.evaluate("window.x = 0; setTimeout(() => { window.x = 100 }, 1000);")
794
926
  # page.main_frame.wait_for_function("() => window.x > 0")
795
927
  # browser.close()
796
- #
928
+ #
797
929
  # with sync_playwright() as playwright:
798
930
  # run(playwright)
799
931
  # ```
800
- #
932
+ #
801
933
  # To pass an argument to the predicate of `frame.waitForFunction` function:
802
- #
803
934
  #
804
- # ```js
805
- # const selector = '.foo';
806
- # await frame.waitForFunction(selector => !!document.querySelector(selector), selector);
807
- # ```
808
- #
809
- # ```python async
810
- # selector = ".foo"
811
- # await frame.wait_for_function("selector => !!document.querySelector(selector)", selector)
812
- # ```
813
- #
814
935
  # ```python sync
815
936
  # selector = ".foo"
816
937
  # frame.wait_for_function("selector => !!document.querySelector(selector)", selector)
817
938
  # ```
818
- def wait_for_function(pageFunction, arg: nil, polling: nil, timeout: nil)
819
- wrap_impl(@impl.wait_for_function(unwrap_impl(pageFunction), arg: unwrap_impl(arg), polling: unwrap_impl(polling), timeout: unwrap_impl(timeout)))
939
+ def wait_for_function(expression, arg: nil, polling: nil, timeout: nil)
940
+ wrap_impl(@impl.wait_for_function(unwrap_impl(expression), arg: unwrap_impl(arg), polling: unwrap_impl(polling), timeout: unwrap_impl(timeout)))
820
941
  end
821
942
 
943
+ #
822
944
  # Waits for the required load state to be reached.
823
- #
945
+ #
824
946
  # This returns when the frame reaches a required load state, `load` by default. The navigation must have been committed
825
947
  # when this method is called. If current document has already reached the required state, resolves immediately.
826
- #
827
948
  #
828
- # ```js
829
- # await frame.click('button'); // Click triggers navigation.
830
- # await frame.waitForLoadState(); // Waits for 'load' state by default.
831
- # ```
832
- #
833
- # ```python async
834
- # await frame.click("button") # click triggers navigation.
835
- # await frame.wait_for_load_state() # the promise resolves after "load" event.
836
- # ```
837
- #
949
+ # **NOTE**: Most of the time, this method is not needed because Playwright [auto-waits before every action](../actionability.md).
950
+ #
951
+ # **Usage**
952
+ #
838
953
  # ```python sync
839
954
  # frame.click("button") # click triggers navigation.
840
955
  # frame.wait_for_load_state() # the promise resolves after "load" event.
@@ -843,88 +958,50 @@ module Playwright
843
958
  wrap_impl(@impl.wait_for_load_state(state: unwrap_impl(state), timeout: unwrap_impl(timeout)))
844
959
  end
845
960
 
961
+ #
846
962
  # Waits for the frame navigation and returns the main resource response. In case of multiple redirects, the navigation
847
963
  # will resolve with the response of the last redirect. In case of navigation to a different anchor or navigation due to
848
964
  # History API usage, the navigation will resolve with `null`.
849
- #
965
+ #
966
+ # **Usage**
967
+ #
850
968
  # This method waits for the frame to navigate to a new URL. It is useful for when you run code which will indirectly cause
851
969
  # the frame to navigate. Consider this example:
852
- #
853
- #
854
- # ```js
855
- # const [response] = await Promise.all([
856
- # frame.waitForNavigation(), // The promise resolves after navigation has finished
857
- # frame.click('a.delayed-navigation'), // Clicking the link will indirectly cause a navigation
858
- # ]);
859
- # ```
860
- #
861
- # ```python async
862
- # async with frame.expect_navigation():
863
- # await frame.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
864
- # # Resolves after navigation has finished
865
- # ```
866
- #
970
+ #
867
971
  # ```python sync
868
972
  # with frame.expect_navigation():
869
973
  # frame.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
870
974
  # # Resolves after navigation has finished
871
975
  # ```
872
- #
873
- # > NOTE: Usage of the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) to change the URL is
874
- # considered a navigation.
976
+ #
977
+ # **NOTE**: Usage of the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) to change the URL is considered
978
+ # a navigation.
979
+ #
980
+ # @deprecated This method is inherently racy, please use [`method: Frame.waitForURL`] instead.
875
981
  def expect_navigation(timeout: nil, url: nil, waitUntil: nil, &block)
876
982
  wrap_impl(@impl.expect_navigation(timeout: unwrap_impl(timeout), url: unwrap_impl(url), waitUntil: unwrap_impl(waitUntil), &wrap_block_call(block)))
877
983
  end
878
984
 
985
+ #
879
986
  # Returns when element specified by selector satisfies `state` option. Returns `null` if waiting for `hidden` or
880
987
  # `detached`.
881
- #
882
- # Wait for the `selector` to satisfy `state` option (either appear/disappear from dom, or become visible/hidden). If at
883
- # the moment of calling the method `selector` already satisfies the condition, the method will return immediately. If the
884
- # selector doesn't satisfy the condition for the `timeout` milliseconds, the function will throw.
885
- #
988
+ #
989
+ # **NOTE**: Playwright automatically waits for element to be ready before performing an action. Using
990
+ # `Locator` objects and web-first assertions make the code wait-for-selector-free.
991
+ #
992
+ # Wait for the `selector` to satisfy `state` option (either appear/disappear from dom, or become
993
+ # visible/hidden). If at the moment of calling the method `selector` already satisfies the condition, the method
994
+ # will return immediately. If the selector doesn't satisfy the condition for the `timeout` milliseconds, the
995
+ # function will throw.
996
+ #
997
+ # **Usage**
998
+ #
886
999
  # This method works across navigations:
887
- #
888
- #
889
- # ```js
890
- # const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'.
891
- #
892
- # (async () => {
893
- # const browser = await chromium.launch();
894
- # const page = await browser.newPage();
895
- # for (let currentURL of ['https://google.com', 'https://bbc.com']) {
896
- # await page.goto(currentURL);
897
- # const element = await page.mainFrame().waitForSelector('img');
898
- # console.log('Loaded image: ' + await element.getAttribute('src'));
899
- # }
900
- # await browser.close();
901
- # })();
902
- # ```
903
- #
904
- # ```python async
905
- # import asyncio
906
- # from playwright.async_api import async_playwright
907
- #
908
- # async def run(playwright):
909
- # chromium = playwright.chromium
910
- # browser = await chromium.launch()
911
- # page = await browser.new_page()
912
- # for current_url in ["https://google.com", "https://bbc.com"]:
913
- # await page.goto(current_url, wait_until="domcontentloaded")
914
- # element = await page.main_frame.wait_for_selector("img")
915
- # print("Loaded image: " + str(await element.get_attribute("src")))
916
- # await browser.close()
917
- #
918
- # async def main():
919
- # async with async_playwright() as playwright:
920
- # await run(playwright)
921
- # asyncio.run(main())
922
- # ```
923
- #
1000
+ #
924
1001
  # ```python sync
925
- # from playwright.sync_api import sync_playwright
926
- #
927
- # def run(playwright):
1002
+ # from playwright.sync_api import sync_playwright, Playwright
1003
+ #
1004
+ # def run(playwright: Playwright):
928
1005
  # chromium = playwright.chromium
929
1006
  # browser = chromium.launch()
930
1007
  # page = browser.new_page()
@@ -933,20 +1010,44 @@ module Playwright
933
1010
  # element = page.main_frame.wait_for_selector("img")
934
1011
  # print("Loaded image: " + str(element.get_attribute("src")))
935
1012
  # browser.close()
936
- #
1013
+ #
937
1014
  # with sync_playwright() as playwright:
938
1015
  # run(playwright)
939
1016
  # ```
940
- def wait_for_selector(selector, state: nil, timeout: nil)
941
- raise NotImplementedError.new('wait_for_selector is not implemented yet.')
1017
+ def wait_for_selector(selector, state: nil, strict: nil, timeout: nil)
1018
+ wrap_impl(@impl.wait_for_selector(unwrap_impl(selector), state: unwrap_impl(state), strict: unwrap_impl(strict), timeout: unwrap_impl(timeout)))
942
1019
  end
943
1020
 
1021
+ #
944
1022
  # Waits for the given `timeout` in milliseconds.
945
- #
1023
+ #
946
1024
  # Note that `frame.waitForTimeout()` should only be used for debugging. Tests using the timer in production are going to
947
1025
  # be flaky. Use signals such as network events, selectors becoming visible and others instead.
948
1026
  def wait_for_timeout(timeout)
949
- raise NotImplementedError.new('wait_for_timeout is not implemented yet.')
1027
+ wrap_impl(@impl.wait_for_timeout(unwrap_impl(timeout)))
1028
+ end
1029
+
1030
+ #
1031
+ # Waits for the frame to navigate to the given URL.
1032
+ #
1033
+ # **Usage**
1034
+ #
1035
+ # ```python sync
1036
+ # frame.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
1037
+ # frame.wait_for_url("**/target.html")
1038
+ # ```
1039
+ def wait_for_url(url, timeout: nil, waitUntil: nil)
1040
+ wrap_impl(@impl.wait_for_url(unwrap_impl(url), timeout: unwrap_impl(timeout), waitUntil: unwrap_impl(waitUntil)))
1041
+ end
1042
+
1043
+ # @nodoc
1044
+ def highlight(selector)
1045
+ wrap_impl(@impl.highlight(unwrap_impl(selector)))
1046
+ end
1047
+
1048
+ # @nodoc
1049
+ def expect(selector, expression, options, title)
1050
+ wrap_impl(@impl.expect(unwrap_impl(selector), unwrap_impl(expression), unwrap_impl(options), unwrap_impl(title)))
950
1051
  end
951
1052
 
952
1053
  # @nodoc
@@ -954,27 +1055,26 @@ module Playwright
954
1055
  wrap_impl(@impl.detached=(unwrap_impl(req)))
955
1056
  end
956
1057
 
1058
+ # -- inherited from EventEmitter --
957
1059
  # @nodoc
958
- def after_initialize
959
- wrap_impl(@impl.after_initialize)
1060
+ def once(event, callback)
1061
+ event_emitter_proxy.once(event, callback)
960
1062
  end
961
1063
 
962
1064
  # -- inherited from EventEmitter --
963
1065
  # @nodoc
964
1066
  def on(event, callback)
965
- wrap_impl(@impl.on(unwrap_impl(event), unwrap_impl(callback)))
1067
+ event_emitter_proxy.on(event, callback)
966
1068
  end
967
1069
 
968
1070
  # -- inherited from EventEmitter --
969
1071
  # @nodoc
970
1072
  def off(event, callback)
971
- wrap_impl(@impl.off(unwrap_impl(event), unwrap_impl(callback)))
1073
+ event_emitter_proxy.off(event, callback)
972
1074
  end
973
1075
 
974
- # -- inherited from EventEmitter --
975
- # @nodoc
976
- def once(event, callback)
977
- wrap_impl(@impl.once(unwrap_impl(event), unwrap_impl(callback)))
1076
+ private def event_emitter_proxy
1077
+ @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
978
1078
  end
979
1079
  end
980
1080
  end