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.
- checksums.yaml +4 -4
- data/AGENTS.md +4 -0
- data/CLAUDE/api_generation.md +28 -0
- data/CLAUDE/ci_expectations.md +23 -0
- data/CLAUDE/gem_release_flow.md +39 -0
- data/CLAUDE/past_upgrade_pr_patterns.md +42 -0
- data/CLAUDE/playwright_upgrade_workflow.md +35 -0
- data/CLAUDE/rspec_debugging.md +30 -0
- data/CLAUDE/unimplemented_examples.md +18 -0
- data/CLAUDE.md +32 -0
- data/CONTRIBUTING.md +5 -0
- data/README.md +60 -16
- data/documentation/README.md +33 -0
- data/documentation/babel.config.js +3 -0
- data/documentation/docs/api/api_request.md +7 -0
- data/documentation/docs/api/api_request_context.md +298 -0
- data/documentation/docs/api/api_response.md +114 -0
- data/documentation/docs/api/browser.md +237 -0
- data/documentation/docs/api/browser_context.md +503 -0
- data/documentation/docs/api/browser_type.md +184 -0
- data/documentation/docs/api/cdp_session.md +44 -0
- data/documentation/docs/api/clock.md +154 -0
- data/documentation/docs/api/console_message.md +85 -0
- data/documentation/docs/api/dialog.md +84 -0
- data/documentation/docs/api/download.md +111 -0
- data/documentation/docs/api/element_handle.md +694 -0
- data/documentation/docs/api/experimental/_category_.yml +3 -0
- data/documentation/docs/api/experimental/android.md +42 -0
- data/documentation/docs/api/experimental/android_device.md +109 -0
- data/documentation/docs/api/experimental/android_input.md +43 -0
- data/documentation/docs/api/experimental/android_socket.md +7 -0
- data/documentation/docs/api/experimental/android_web_view.md +7 -0
- data/documentation/docs/api/file_chooser.md +53 -0
- data/documentation/docs/api/frame.md +1218 -0
- data/documentation/docs/api/frame_locator.md +348 -0
- data/documentation/docs/api/js_handle.md +121 -0
- data/documentation/docs/api/keyboard.md +170 -0
- data/documentation/docs/api/locator.md +1495 -0
- data/documentation/docs/api/locator_assertions.md +827 -0
- data/documentation/docs/api/mouse.md +86 -0
- data/documentation/docs/api/page.md +1946 -0
- data/documentation/docs/api/page_assertions.md +65 -0
- data/documentation/docs/api/playwright.md +66 -0
- data/documentation/docs/api/request.md +255 -0
- data/documentation/docs/api/response.md +176 -0
- data/documentation/docs/api/route.md +205 -0
- data/documentation/docs/api/selectors.md +63 -0
- data/documentation/docs/api/touchscreen.md +22 -0
- data/documentation/docs/api/tracing.md +129 -0
- data/documentation/docs/api/web_socket.md +51 -0
- data/documentation/docs/api/worker.md +83 -0
- data/documentation/docs/article/api_coverage.mdx +11 -0
- data/documentation/docs/article/getting_started.md +161 -0
- data/documentation/docs/article/guides/_category_.yml +3 -0
- data/documentation/docs/article/guides/download_playwright_driver.md +55 -0
- data/documentation/docs/article/guides/inspector.md +31 -0
- data/documentation/docs/article/guides/launch_browser.md +121 -0
- data/documentation/docs/article/guides/playwright_on_alpine_linux.md +112 -0
- data/documentation/docs/article/guides/rails_integration.md +278 -0
- data/documentation/docs/article/guides/rails_integration_with_null_driver.md +145 -0
- data/documentation/docs/article/guides/recording_video.md +79 -0
- data/documentation/docs/article/guides/rspec_integration.md +59 -0
- data/documentation/docs/article/guides/semi_automation.md +71 -0
- data/documentation/docs/article/guides/use_storage_state.md +78 -0
- data/documentation/docs/include/api_coverage.md +671 -0
- data/documentation/docusaurus.config.js +114 -0
- data/documentation/package.json +39 -0
- data/documentation/sidebars.js +15 -0
- data/documentation/src/components/HomepageFeatures.js +61 -0
- data/documentation/src/components/HomepageFeatures.module.css +13 -0
- data/documentation/src/css/custom.css +44 -0
- data/documentation/src/pages/index.js +49 -0
- data/documentation/src/pages/index.module.css +41 -0
- data/documentation/src/pages/markdown-page.md +7 -0
- data/documentation/static/.nojekyll +0 -0
- data/documentation/static/img/playwright-logo.svg +9 -0
- data/documentation/static/img/playwright-ruby-client.png +0 -0
- data/documentation/static/img/undraw_dropdown_menu.svg +1 -0
- data/documentation/static/img/undraw_web_development.svg +1 -0
- data/documentation/static/img/undraw_windows.svg +1 -0
- data/documentation/yarn.lock +9005 -0
- data/lib/playwright/{input_types/android_input.rb → android_input_impl.rb} +5 -1
- data/lib/playwright/api_implementation.rb +18 -0
- data/lib/playwright/api_response_impl.rb +77 -0
- data/lib/playwright/channel.rb +62 -1
- data/lib/playwright/channel_owner.rb +70 -7
- data/lib/playwright/channel_owners/android.rb +16 -3
- data/lib/playwright/channel_owners/android_device.rb +22 -66
- data/lib/playwright/channel_owners/api_request_context.rb +247 -0
- data/lib/playwright/channel_owners/artifact.rb +40 -0
- data/lib/playwright/channel_owners/binding_call.rb +70 -0
- data/lib/playwright/channel_owners/browser.rb +114 -22
- data/lib/playwright/channel_owners/browser_context.rb +589 -15
- data/lib/playwright/channel_owners/browser_type.rb +90 -1
- data/lib/playwright/channel_owners/cdp_session.rb +19 -0
- data/lib/playwright/channel_owners/dialog.rb +32 -0
- data/lib/playwright/channel_owners/element_handle.rb +107 -43
- data/lib/playwright/channel_owners/fetch_request.rb +8 -0
- data/lib/playwright/channel_owners/frame.rb +334 -104
- data/lib/playwright/channel_owners/js_handle.rb +9 -13
- data/lib/playwright/channel_owners/local_utils.rb +82 -0
- data/lib/playwright/channel_owners/page.rb +778 -95
- data/lib/playwright/channel_owners/playwright.rb +25 -30
- data/lib/playwright/channel_owners/request.rb +120 -18
- data/lib/playwright/channel_owners/response.rb +113 -0
- data/lib/playwright/channel_owners/route.rb +181 -0
- data/lib/playwright/channel_owners/stream.rb +30 -0
- data/lib/playwright/channel_owners/tracing.rb +117 -0
- data/lib/playwright/channel_owners/web_socket.rb +96 -0
- data/lib/playwright/channel_owners/worker.rb +46 -0
- data/lib/playwright/channel_owners/writable_stream.rb +14 -0
- data/lib/playwright/clock_impl.rb +67 -0
- data/lib/playwright/connection.rb +111 -63
- data/lib/playwright/console_message_impl.rb +29 -0
- data/lib/playwright/download_impl.rb +32 -0
- data/lib/playwright/errors.rb +42 -5
- data/lib/playwright/event_emitter.rb +17 -3
- data/lib/playwright/event_emitter_proxy.rb +49 -0
- data/lib/playwright/events.rb +10 -5
- data/lib/playwright/file_chooser_impl.rb +24 -0
- data/lib/playwright/frame_locator_impl.rb +66 -0
- data/lib/playwright/har_router.rb +89 -0
- data/lib/playwright/http_headers.rb +14 -0
- data/lib/playwright/input_files.rb +102 -15
- data/lib/playwright/javascript/expression.rb +7 -11
- data/lib/playwright/javascript/regex.rb +23 -0
- data/lib/playwright/javascript/source_url.rb +16 -0
- data/lib/playwright/javascript/value_parser.rb +108 -19
- data/lib/playwright/javascript/value_serializer.rb +47 -8
- data/lib/playwright/javascript/visitor_info.rb +26 -0
- data/lib/playwright/javascript.rb +2 -10
- data/lib/playwright/{input_types/keyboard.rb → keyboard_impl.rb} +6 -2
- data/lib/playwright/locator_assertions_impl.rb +571 -0
- data/lib/playwright/locator_impl.rb +544 -0
- data/lib/playwright/locator_utils.rb +136 -0
- data/lib/playwright/mouse_impl.rb +57 -0
- data/lib/playwright/page_assertions_impl.rb +154 -0
- data/lib/playwright/playwright_api.rb +102 -30
- data/lib/playwright/raw_headers.rb +61 -0
- data/lib/playwright/route_handler.rb +78 -0
- data/lib/playwright/select_option_values.rb +34 -13
- data/lib/playwright/selectors_impl.rb +45 -0
- data/lib/playwright/test.rb +102 -0
- data/lib/playwright/timeout_settings.rb +9 -4
- data/lib/playwright/touchscreen_impl.rb +14 -0
- data/lib/playwright/transport.rb +61 -10
- data/lib/playwright/url_matcher.rb +24 -2
- data/lib/playwright/utils.rb +48 -13
- data/lib/playwright/version.rb +2 -1
- data/lib/playwright/video.rb +54 -0
- data/lib/playwright/waiter.rb +166 -0
- data/lib/playwright/web_socket_client.rb +167 -0
- data/lib/playwright/web_socket_transport.rb +116 -0
- data/lib/playwright.rb +188 -11
- data/lib/playwright_api/android.rb +46 -11
- data/lib/playwright_api/android_device.rb +182 -31
- data/lib/playwright_api/android_input.rb +22 -13
- data/lib/playwright_api/android_socket.rb +18 -0
- data/lib/playwright_api/android_web_view.rb +24 -0
- data/lib/playwright_api/api_request.rb +26 -0
- data/lib/playwright_api/api_request_context.rb +311 -0
- data/lib/playwright_api/api_response.rb +92 -0
- data/lib/playwright_api/browser.rb +116 -103
- data/lib/playwright_api/browser_context.rb +290 -389
- data/lib/playwright_api/browser_type.rb +96 -118
- data/lib/playwright_api/cdp_session.rb +36 -39
- data/lib/playwright_api/clock.rb +121 -0
- data/lib/playwright_api/console_message.rb +35 -19
- data/lib/playwright_api/dialog.rb +53 -50
- data/lib/playwright_api/download.rb +49 -43
- data/lib/playwright_api/element_handle.rb +354 -402
- data/lib/playwright_api/file_chooser.rb +15 -18
- data/lib/playwright_api/frame.rb +703 -603
- data/lib/playwright_api/frame_locator.rb +285 -0
- data/lib/playwright_api/js_handle.rb +50 -76
- data/lib/playwright_api/keyboard.rb +67 -146
- data/lib/playwright_api/locator.rb +1304 -0
- data/lib/playwright_api/locator_assertions.rb +704 -0
- data/lib/playwright_api/mouse.rb +23 -29
- data/lib/playwright_api/page.rb +1196 -1176
- data/lib/playwright_api/page_assertions.rb +60 -0
- data/lib/playwright_api/playwright.rb +54 -122
- data/lib/playwright_api/request.rb +112 -74
- data/lib/playwright_api/response.rb +92 -20
- data/lib/playwright_api/route.rb +152 -62
- data/lib/playwright_api/selectors.rb +47 -61
- data/lib/playwright_api/touchscreen.rb +8 -2
- data/lib/playwright_api/tracing.rb +128 -0
- data/lib/playwright_api/web_socket.rb +43 -5
- data/lib/playwright_api/worker.rb +74 -34
- data/playwright.gemspec +14 -9
- data/sig/playwright.rbs +658 -0
- metadata +216 -50
- data/docs/api_coverage.md +0 -354
- data/lib/playwright/channel_owners/chromium_browser.rb +0 -8
- data/lib/playwright/channel_owners/chromium_browser_context.rb +0 -8
- data/lib/playwright/channel_owners/console_message.rb +0 -21
- data/lib/playwright/channel_owners/firefox_browser.rb +0 -8
- data/lib/playwright/channel_owners/selectors.rb +0 -4
- data/lib/playwright/channel_owners/webkit_browser.rb +0 -8
- data/lib/playwright/input_type.rb +0 -19
- data/lib/playwright/input_types/mouse.rb +0 -4
- data/lib/playwright/input_types/touchscreen.rb +0 -4
- data/lib/playwright/javascript/function.rb +0 -67
- data/lib/playwright/wait_helper.rb +0 -73
- data/lib/playwright_api/accessibility.rb +0 -93
- data/lib/playwright_api/binding_call.rb +0 -23
- data/lib/playwright_api/chromium_browser_context.rb +0 -57
- 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
|
|
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
|
-
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
#
|
|
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(
|
|
64
|
-
wrap_impl(@impl.evaluate(unwrap_impl(
|
|
45
|
+
def evaluate(expression, arg: nil)
|
|
46
|
+
wrap_impl(@impl.evaluate(unwrap_impl(expression), arg: unwrap_impl(arg)))
|
|
65
47
|
end
|
|
66
48
|
|
|
67
|
-
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
#
|
|
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(
|
|
79
|
-
wrap_impl(@impl.evaluate_handle(unwrap_impl(
|
|
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
|
-
#
|
|
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
|
-
#
|
|
121
|
-
#
|
|
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
|
|
128
|
-
wrap_impl(@impl.
|
|
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
|
|
134
|
-
|
|
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
|
|
140
|
-
|
|
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
|
|
146
|
-
|
|
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
|