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
@@ -0,0 +1,285 @@
1
+ module Playwright
2
+ #
3
+ # FrameLocator represents a view to the `iframe` on the page. It captures the logic sufficient to retrieve the `iframe` and locate elements in that iframe. FrameLocator can be created with either [`method: Locator.contentFrame`], [`method: Page.frameLocator`] or [`method: Locator.frameLocator`] method.
4
+ #
5
+ # ```python sync
6
+ # locator = page.locator("my-frame").content_frame.get_by_text("Submit")
7
+ # locator.click()
8
+ # ```
9
+ #
10
+ # **Strictness**
11
+ #
12
+ # Frame locators are strict. This means that all operations on frame locators will throw if more than one element matches a given selector.
13
+ #
14
+ # ```python sync
15
+ # # Throws if there are several frames in DOM:
16
+ # page.locator('.result-frame').content_frame.get_by_role('button').click()
17
+ #
18
+ # # Works because we explicitly tell locator to pick the first frame:
19
+ # page.locator('.result-frame').first.content_frame.get_by_role('button').click()
20
+ # ```
21
+ #
22
+ # **Converting Locator to FrameLocator**
23
+ #
24
+ # If you have a `Locator` object pointing to an `iframe` it can be converted to `FrameLocator` using [`method: Locator.contentFrame`].
25
+ #
26
+ # **Converting FrameLocator to Locator**
27
+ #
28
+ # If you have a `FrameLocator` object it can be converted to `Locator` pointing to the same `iframe` using [`method: FrameLocator.owner`].
29
+ class FrameLocator < PlaywrightApi
30
+
31
+ #
32
+ # Returns locator to the first matching frame.
33
+ #
34
+ # @deprecated Use [`method: Locator.first`] followed by [`method: Locator.contentFrame`] instead.
35
+ def first
36
+ wrap_impl(@impl.first)
37
+ end
38
+
39
+ #
40
+ # When working with iframes, you can create a frame locator that will enter the iframe and allow selecting elements
41
+ # in that iframe.
42
+ def frame_locator(selector)
43
+ wrap_impl(@impl.frame_locator(unwrap_impl(selector)))
44
+ end
45
+
46
+ #
47
+ # Allows locating elements by their alt text.
48
+ #
49
+ # **Usage**
50
+ #
51
+ # For example, this method will find the image by alt text "Playwright logo":
52
+ #
53
+ # ```html
54
+ # <img alt='Playwright logo'>
55
+ # ```
56
+ #
57
+ # ```python sync
58
+ # page.get_by_alt_text("Playwright logo").click()
59
+ # ```
60
+ def get_by_alt_text(text, exact: nil)
61
+ wrap_impl(@impl.get_by_alt_text(unwrap_impl(text), exact: unwrap_impl(exact)))
62
+ end
63
+
64
+ #
65
+ # Allows locating input elements by the text of the associated `<label>` or `aria-labelledby` element, or by the `aria-label` attribute.
66
+ #
67
+ # **Usage**
68
+ #
69
+ # For example, this method will find inputs by label "Username" and "Password" in the following DOM:
70
+ #
71
+ # ```html
72
+ # <input aria-label="Username">
73
+ # <label for="password-input">Password:</label>
74
+ # <input id="password-input">
75
+ # ```
76
+ #
77
+ # ```python sync
78
+ # page.get_by_label("Username").fill("john")
79
+ # page.get_by_label("Password").fill("secret")
80
+ # ```
81
+ def get_by_label(text, exact: nil)
82
+ wrap_impl(@impl.get_by_label(unwrap_impl(text), exact: unwrap_impl(exact)))
83
+ end
84
+
85
+ #
86
+ # Allows locating input elements by the placeholder text.
87
+ #
88
+ # **Usage**
89
+ #
90
+ # For example, consider the following DOM structure.
91
+ #
92
+ # ```html
93
+ # <input type="email" placeholder="name@example.com" />
94
+ # ```
95
+ #
96
+ # You can fill the input after locating it by the placeholder text:
97
+ #
98
+ # ```python sync
99
+ # page.get_by_placeholder("name@example.com").fill("playwright@microsoft.com")
100
+ # ```
101
+ def get_by_placeholder(text, exact: nil)
102
+ wrap_impl(@impl.get_by_placeholder(unwrap_impl(text), exact: unwrap_impl(exact)))
103
+ end
104
+
105
+ #
106
+ # 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).
107
+ #
108
+ # **Usage**
109
+ #
110
+ # Consider the following DOM structure.
111
+ #
112
+ # ```html
113
+ # <h3>Sign up</h3>
114
+ # <label>
115
+ # <input type="checkbox" /> Subscribe
116
+ # </label>
117
+ # <br/>
118
+ # <button>Submit</button>
119
+ # ```
120
+ #
121
+ # You can locate each element by it's implicit role:
122
+ #
123
+ # ```python sync
124
+ # expect(page.get_by_role("heading", name="Sign up")).to_be_visible()
125
+ #
126
+ # page.get_by_role("checkbox", name="Subscribe").check()
127
+ #
128
+ # page.get_by_role("button", name=re.compile("submit", re.IGNORECASE)).click()
129
+ # ```
130
+ #
131
+ # **Details**
132
+ #
133
+ # Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback about the ARIA guidelines.
134
+ #
135
+ # 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.
136
+ def get_by_role(
137
+ role,
138
+ checked: nil,
139
+ disabled: nil,
140
+ exact: nil,
141
+ expanded: nil,
142
+ includeHidden: nil,
143
+ level: nil,
144
+ name: nil,
145
+ pressed: nil,
146
+ selected: nil)
147
+ 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)))
148
+ end
149
+
150
+ #
151
+ # Locate element by the test id.
152
+ #
153
+ # **Usage**
154
+ #
155
+ # Consider the following DOM structure.
156
+ #
157
+ # ```html
158
+ # <button data-testid="directions">Itinéraire</button>
159
+ # ```
160
+ #
161
+ # You can locate the element by it's test id:
162
+ #
163
+ # ```python sync
164
+ # page.get_by_test_id("directions").click()
165
+ # ```
166
+ #
167
+ # **Details**
168
+ #
169
+ # 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.
170
+ def get_by_test_id(testId)
171
+ wrap_impl(@impl.get_by_test_id(unwrap_impl(testId)))
172
+ end
173
+ alias_method :get_by_testid, :get_by_test_id
174
+
175
+ #
176
+ # Allows locating elements that contain given text.
177
+ #
178
+ # See also [`method: Locator.filter`] that allows to match by another criteria, like an accessible role, and then filter by the text content.
179
+ #
180
+ # **Usage**
181
+ #
182
+ # Consider the following DOM structure:
183
+ #
184
+ # ```html
185
+ # <div>Hello <span>world</span></div>
186
+ # <div>Hello</div>
187
+ # ```
188
+ #
189
+ # You can locate by text substring, exact string, or a regular expression:
190
+ #
191
+ # ```python sync
192
+ # # Matches <span>
193
+ # page.get_by_text("world")
194
+ #
195
+ # # Matches first <div>
196
+ # page.get_by_text("Hello world")
197
+ #
198
+ # # Matches second <div>
199
+ # page.get_by_text("Hello", exact=True)
200
+ #
201
+ # # Matches both <div>s
202
+ # page.get_by_text(re.compile("Hello"))
203
+ #
204
+ # # Matches second <div>
205
+ # page.get_by_text(re.compile("^hello$", re.IGNORECASE))
206
+ # ```
207
+ #
208
+ # **Details**
209
+ #
210
+ # 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.
211
+ #
212
+ # 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">`.
213
+ def get_by_text(text, exact: nil)
214
+ wrap_impl(@impl.get_by_text(unwrap_impl(text), exact: unwrap_impl(exact)))
215
+ end
216
+
217
+ #
218
+ # Allows locating elements by their title attribute.
219
+ #
220
+ # **Usage**
221
+ #
222
+ # Consider the following DOM structure.
223
+ #
224
+ # ```html
225
+ # <span title='Issues count'>25 issues</span>
226
+ # ```
227
+ #
228
+ # You can check the issues count after locating it by the title text:
229
+ #
230
+ # ```python sync
231
+ # expect(page.get_by_title("Issues count")).to_have_text("25 issues")
232
+ # ```
233
+ def get_by_title(text, exact: nil)
234
+ wrap_impl(@impl.get_by_title(unwrap_impl(text), exact: unwrap_impl(exact)))
235
+ end
236
+
237
+ #
238
+ # Returns locator to the last matching frame.
239
+ #
240
+ # @deprecated Use [`method: Locator.last`] followed by [`method: Locator.contentFrame`] instead.
241
+ def last
242
+ wrap_impl(@impl.last)
243
+ end
244
+
245
+ #
246
+ # The method finds an element matching the specified selector in the locator's subtree. It also accepts filter options, similar to [`method: Locator.filter`] method.
247
+ #
248
+ # [Learn more about locators](../locators.md).
249
+ def locator(
250
+ selectorOrLocator,
251
+ has: nil,
252
+ hasNot: nil,
253
+ hasNotText: nil,
254
+ hasText: nil)
255
+ wrap_impl(@impl.locator(unwrap_impl(selectorOrLocator), has: unwrap_impl(has), hasNot: unwrap_impl(hasNot), hasNotText: unwrap_impl(hasNotText), hasText: unwrap_impl(hasText)))
256
+ end
257
+
258
+ #
259
+ # Returns locator to the n-th matching frame. It's zero based, `nth(0)` selects the first frame.
260
+ #
261
+ # @deprecated Use [`method: Locator.nth`] followed by [`method: Locator.contentFrame`] instead.
262
+ def nth(index)
263
+ wrap_impl(@impl.nth(unwrap_impl(index)))
264
+ end
265
+
266
+ #
267
+ # Returns a `Locator` object pointing to the same `iframe` as this frame locator.
268
+ #
269
+ # Useful when you have a `FrameLocator` object obtained somewhere, and later on would like to interact with the `iframe` element.
270
+ #
271
+ # For a reverse operation, use [`method: Locator.contentFrame`].
272
+ #
273
+ # **Usage**
274
+ #
275
+ # ```python sync
276
+ # frame_locator = page.locator("iframe[name=\"embedded\"]").content_frame
277
+ # # ...
278
+ # locator = frame_locator.owner
279
+ # expect(locator).to_be_visible()
280
+ # ```
281
+ def owner
282
+ wrap_impl(@impl.owner)
283
+ end
284
+ end
285
+ end
@@ -1,105 +1,73 @@
1
1
  module Playwright
2
+ #
2
3
  # JSHandle represents an in-page JavaScript object. JSHandles can be created with the [`method: Page.evaluateHandle`]
3
4
  # method.
4
- #
5
5
  #
6
- # ```js
7
- # const windowHandle = await page.evaluateHandle(() => window);
8
- # // ...
9
- # ```
10
- #
11
- # ```python async
12
- # window_handle = await page.evaluate_handle("window")
13
- # # ...
14
- # ```
15
- #
16
6
  # ```python sync
17
7
  # window_handle = page.evaluate_handle("window")
18
8
  # # ...
19
9
  # ```
20
- #
10
+ #
21
11
  # JSHandle prevents the referenced JavaScript object being garbage collected unless the handle is exposed with
22
12
  # [`method: JSHandle.dispose`]. JSHandles are auto-disposed when their origin frame gets navigated or the parent context
23
13
  # gets destroyed.
24
- #
25
- # JSHandle instances can be used as an argument in [`method: Page.$eval`], [`method: Page.evaluate`] and
14
+ #
15
+ # JSHandle instances can be used as an argument in [`method: Page.evalOnSelector`], [`method: Page.evaluate`] and
26
16
  # [`method: Page.evaluateHandle`] methods.
27
17
  class JSHandle < PlaywrightApi
28
18
 
19
+ #
29
20
  # Returns either `null` or the object handle itself, if the object handle is an instance of `ElementHandle`.
30
21
  def as_element
31
22
  wrap_impl(@impl.as_element)
32
23
  end
33
24
 
25
+ #
34
26
  # The `jsHandle.dispose` method stops referencing the element handle.
35
27
  def dispose
36
28
  wrap_impl(@impl.dispose)
37
29
  end
38
30
 
39
- # Returns the return value of `pageFunction`
40
- #
41
- # This method passes this handle as the first argument to `pageFunction`.
42
- #
43
- # If `pageFunction` returns a [Promise], then `handle.evaluate` would wait for the promise to resolve and return its
44
- # value.
45
- #
46
- # Examples:
47
- #
48
- #
49
- # ```js
50
- # const tweetHandle = await page.$('.tweet .retweets');
51
- # expect(await tweetHandle.evaluate(node => node.innerText)).toBe('10 retweets');
52
- # ```
53
- #
54
- # ```python async
55
- # tweet_handle = await page.query_selector(".tweet .retweets")
56
- # assert await tweet_handle.evaluate("node => node.innerText") == "10 retweets"
57
- # ```
58
- #
31
+ #
32
+ # Returns the return value of `expression`.
33
+ #
34
+ # This method passes this handle as the first argument to `expression`.
35
+ #
36
+ # If `expression` returns a [Promise], then `handle.evaluate` would wait for the promise to resolve and return
37
+ # its value.
38
+ #
39
+ # **Usage**
40
+ #
59
41
  # ```python sync
60
42
  # tweet_handle = page.query_selector(".tweet .retweets")
61
43
  # assert tweet_handle.evaluate("node => node.innerText") == "10 retweets"
62
44
  # ```
63
- def evaluate(pageFunction, arg: nil)
64
- wrap_impl(@impl.evaluate(unwrap_impl(pageFunction), arg: unwrap_impl(arg)))
45
+ def evaluate(expression, arg: nil)
46
+ wrap_impl(@impl.evaluate(unwrap_impl(expression), arg: unwrap_impl(arg)))
65
47
  end
66
48
 
67
- # Returns the return value of `pageFunction` as in-page object (JSHandle).
68
- #
69
- # This method passes this handle as the first argument to `pageFunction`.
70
- #
71
- # The only difference between `jsHandle.evaluate` and `jsHandle.evaluateHandle` is that `jsHandle.evaluateHandle` returns
72
- # in-page object (JSHandle).
73
- #
49
+ #
50
+ # Returns the return value of `expression` as a `JSHandle`.
51
+ #
52
+ # This method passes this handle as the first argument to `expression`.
53
+ #
54
+ # The only difference between `jsHandle.evaluate` and `jsHandle.evaluateHandle` is that `jsHandle.evaluateHandle` returns `JSHandle`.
55
+ #
74
56
  # If the function passed to the `jsHandle.evaluateHandle` returns a [Promise], then `jsHandle.evaluateHandle` would wait
75
57
  # for the promise to resolve and return its value.
76
- #
58
+ #
77
59
  # See [`method: Page.evaluateHandle`] for more details.
78
- def evaluate_handle(pageFunction, arg: nil)
79
- wrap_impl(@impl.evaluate_handle(unwrap_impl(pageFunction), arg: unwrap_impl(arg)))
60
+ def evaluate_handle(expression, arg: nil)
61
+ wrap_impl(@impl.evaluate_handle(unwrap_impl(expression), arg: unwrap_impl(arg)))
80
62
  end
81
63
 
64
+ #
82
65
  # The method returns a map with **own property names** as keys and JSHandle instances for the property values.
83
- #
84
- #
85
- # ```js
86
- # const handle = await page.evaluateHandle(() => ({window, document}));
87
- # const properties = await handle.getProperties();
88
- # const windowHandle = properties.get('window');
89
- # const documentHandle = properties.get('document');
90
- # await handle.dispose();
91
- # ```
92
- #
93
- # ```python async
94
- # handle = await page.evaluate_handle("{window, document}")
95
- # properties = await handle.get_properties()
96
- # window_handle = properties.get("window")
97
- # document_handle = properties.get("document")
98
- # await handle.dispose()
99
- # ```
100
- #
66
+ #
67
+ # **Usage**
68
+ #
101
69
  # ```python sync
102
- # handle = page.evaluate_handle("{window, document}")
70
+ # handle = page.evaluate_handle("({ window, document })")
103
71
  # properties = handle.get_properties()
104
72
  # window_handle = properties.get("window")
105
73
  # document_handle = properties.get("document")
@@ -110,40 +78,46 @@ module Playwright
110
78
  end
111
79
  alias_method :properties, :get_properties
112
80
 
81
+ #
113
82
  # Fetches a single property from the referenced object.
114
83
  def get_property(propertyName)
115
84
  wrap_impl(@impl.get_property(unwrap_impl(propertyName)))
116
85
  end
117
86
 
87
+ #
118
88
  # Returns a JSON representation of the object. If the object has a `toJSON` function, it **will not be called**.
119
- #
120
- # > NOTE: The method will return an empty JSON object if the referenced object is not stringifiable. It will throw an
121
- # error if the object has circular references.
89
+ #
90
+ # **NOTE**: The method will return an empty JSON object if the referenced object is not stringifiable. It will throw an error if the
91
+ # object has circular references.
122
92
  def json_value
123
93
  wrap_impl(@impl.json_value)
124
94
  end
125
95
 
126
96
  # @nodoc
127
- def after_initialize
128
- wrap_impl(@impl.after_initialize)
97
+ def to_s
98
+ wrap_impl(@impl.to_s)
129
99
  end
130
100
 
131
101
  # -- inherited from EventEmitter --
132
102
  # @nodoc
133
- def on(event, callback)
134
- wrap_impl(@impl.on(unwrap_impl(event), unwrap_impl(callback)))
103
+ def once(event, callback)
104
+ event_emitter_proxy.once(event, callback)
135
105
  end
136
106
 
137
107
  # -- inherited from EventEmitter --
138
108
  # @nodoc
139
- def off(event, callback)
140
- wrap_impl(@impl.off(unwrap_impl(event), unwrap_impl(callback)))
109
+ def on(event, callback)
110
+ event_emitter_proxy.on(event, callback)
141
111
  end
142
112
 
143
113
  # -- inherited from EventEmitter --
144
114
  # @nodoc
145
- def once(event, callback)
146
- wrap_impl(@impl.once(unwrap_impl(event), unwrap_impl(callback)))
115
+ def off(event, callback)
116
+ event_emitter_proxy.off(event, callback)
117
+ end
118
+
119
+ private def event_emitter_proxy
120
+ @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
147
121
  end
148
122
  end
149
123
  end