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,348 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 10
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# FrameLocator
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
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 [Locator#content_frame](./locator#content_frame), [Page#frame_locator](./page#frame_locator) or [Locator#frame_locator](./locator#frame_locator) method.
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
locator = page.locator("my-frame").content_frame.get_by_text("Submit")
|
|
12
|
+
locator.click
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Strictness**
|
|
16
|
+
|
|
17
|
+
Frame locators are strict. This means that all operations on frame locators will throw if more than one element matches a given selector.
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
# Throws if there are several frames in DOM:
|
|
21
|
+
page.locator('.result-frame').content_frame.get_by_role('button').click
|
|
22
|
+
|
|
23
|
+
# Works because we explicitly tell locator to pick the first frame:
|
|
24
|
+
page.locator('.result-frame').first.content_frame.get_by_role('button').click
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Converting Locator to FrameLocator**
|
|
28
|
+
|
|
29
|
+
If you have a [Locator](./locator) object pointing to an `iframe` it can be converted to [FrameLocator](./frame_locator) using [Locator#content_frame](./locator#content_frame).
|
|
30
|
+
|
|
31
|
+
**Converting FrameLocator to Locator**
|
|
32
|
+
|
|
33
|
+
If you have a [FrameLocator](./frame_locator) object it can be converted to [Locator](./locator) pointing to the same `iframe` using [FrameLocator#owner](./frame_locator#owner).
|
|
34
|
+
|
|
35
|
+
## first
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
def first
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
:::warning
|
|
42
|
+
|
|
43
|
+
Use [Locator#first](./locator#first) followed by [Locator#content_frame](./locator#content_frame) instead.
|
|
44
|
+
|
|
45
|
+
:::
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
Returns locator to the first matching frame.
|
|
49
|
+
|
|
50
|
+
## frame_locator
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
def frame_locator(selector)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
When working with iframes, you can create a frame locator that will enter the iframe and allow selecting elements
|
|
58
|
+
in that iframe.
|
|
59
|
+
|
|
60
|
+
## get_by_alt_text
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
def get_by_alt_text(text, exact: nil)
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
Allows locating elements by their alt text.
|
|
68
|
+
|
|
69
|
+
**Usage**
|
|
70
|
+
|
|
71
|
+
For example, this method will find the image by alt text "Playwright logo":
|
|
72
|
+
|
|
73
|
+
```html
|
|
74
|
+
<img alt='Playwright logo'>
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
page.get_by_alt_text("Playwright logo").click
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## get_by_label
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
def get_by_label(text, exact: nil)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
Allows locating input elements by the text of the associated `<label>` or `aria-labelledby` element, or by the `aria-label` attribute.
|
|
89
|
+
|
|
90
|
+
**Usage**
|
|
91
|
+
|
|
92
|
+
For example, this method will find inputs by label "Username" and "Password" in the following DOM:
|
|
93
|
+
|
|
94
|
+
```html
|
|
95
|
+
<input aria-label="Username">
|
|
96
|
+
<label for="password-input">Password:</label>
|
|
97
|
+
<input id="password-input">
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
page.get_by_label("Username").fill("john")
|
|
102
|
+
page.get_by_label("Password").fill("secret")
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## get_by_placeholder
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
def get_by_placeholder(text, exact: nil)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
Allows locating input elements by the placeholder text.
|
|
113
|
+
|
|
114
|
+
**Usage**
|
|
115
|
+
|
|
116
|
+
For example, consider the following DOM structure.
|
|
117
|
+
|
|
118
|
+
```html
|
|
119
|
+
<input type="email" placeholder="name@example.com" />
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
You can fill the input after locating it by the placeholder text:
|
|
123
|
+
|
|
124
|
+
```ruby
|
|
125
|
+
page.get_by_placeholder("name@example.com").fill("playwright@microsoft.com")
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## get_by_role
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
def get_by_role(
|
|
132
|
+
role,
|
|
133
|
+
checked: nil,
|
|
134
|
+
disabled: nil,
|
|
135
|
+
exact: nil,
|
|
136
|
+
expanded: nil,
|
|
137
|
+
includeHidden: nil,
|
|
138
|
+
level: nil,
|
|
139
|
+
name: nil,
|
|
140
|
+
pressed: nil,
|
|
141
|
+
selected: nil)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
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).
|
|
146
|
+
|
|
147
|
+
**Usage**
|
|
148
|
+
|
|
149
|
+
Consider the following DOM structure.
|
|
150
|
+
|
|
151
|
+
```html
|
|
152
|
+
<h3>Sign up</h3>
|
|
153
|
+
<label>
|
|
154
|
+
<input type="checkbox" /> Subscribe
|
|
155
|
+
</label>
|
|
156
|
+
<br/>
|
|
157
|
+
<button>Submit</button>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
You can locate each element by it's implicit role:
|
|
161
|
+
|
|
162
|
+
```ruby
|
|
163
|
+
page.get_by_role("heading", name: "Sign up").visible? # => true
|
|
164
|
+
page.get_by_role("checkbox", name: "Subscribe").check
|
|
165
|
+
page.get_by_role("button", name: /submit/i).click
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Details**
|
|
169
|
+
|
|
170
|
+
Role selector **does not replace** accessibility audits and conformance tests, but rather gives early feedback about the ARIA guidelines.
|
|
171
|
+
|
|
172
|
+
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.
|
|
173
|
+
|
|
174
|
+
## get_by_test_id
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
def get_by_test_id(testId)
|
|
178
|
+
```
|
|
179
|
+
alias: `get_by_testid`
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
Locate element by the test id.
|
|
183
|
+
|
|
184
|
+
**Usage**
|
|
185
|
+
|
|
186
|
+
Consider the following DOM structure.
|
|
187
|
+
|
|
188
|
+
```html
|
|
189
|
+
<button data-testid="directions">Itinéraire</button>
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
You can locate the element by it's test id:
|
|
193
|
+
|
|
194
|
+
```ruby
|
|
195
|
+
page.get_by_test_id("directions").click
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Details**
|
|
199
|
+
|
|
200
|
+
By default, the `data-testid` attribute is used as a test id. Use [Selectors#set_test_id_attribute](./selectors#set_test_id_attribute) to configure a different test id attribute if necessary.
|
|
201
|
+
|
|
202
|
+
## get_by_text
|
|
203
|
+
|
|
204
|
+
```
|
|
205
|
+
def get_by_text(text, exact: nil)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
Allows locating elements that contain given text.
|
|
210
|
+
|
|
211
|
+
See also [Locator#filter](./locator#filter) that allows to match by another criteria, like an accessible role, and then filter by the text content.
|
|
212
|
+
|
|
213
|
+
**Usage**
|
|
214
|
+
|
|
215
|
+
Consider the following DOM structure:
|
|
216
|
+
|
|
217
|
+
```html
|
|
218
|
+
<div>Hello <span>world</span></div>
|
|
219
|
+
<div>Hello</div>
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
You can locate by text substring, exact string, or a regular expression:
|
|
223
|
+
|
|
224
|
+
```ruby
|
|
225
|
+
page.content = <<~HTML
|
|
226
|
+
<div>Hello <span>world</span></div>
|
|
227
|
+
<div>Hello</div>
|
|
228
|
+
HTML
|
|
229
|
+
|
|
230
|
+
# Matches <span>
|
|
231
|
+
locator = page.get_by_text("world")
|
|
232
|
+
expect(locator.evaluate('e => e.outerHTML')).to eq('<span>world</span>')
|
|
233
|
+
|
|
234
|
+
# Matches first <div>
|
|
235
|
+
locator = page.get_by_text("Hello world")
|
|
236
|
+
expect(locator.evaluate('e => e.outerHTML')).to eq('<div>Hello <span>world</span></div>')
|
|
237
|
+
|
|
238
|
+
# Matches second <div>
|
|
239
|
+
locator = page.get_by_text("Hello", exact: true)
|
|
240
|
+
expect(locator.evaluate('e => e.outerHTML')).to eq('<div>Hello</div>')
|
|
241
|
+
|
|
242
|
+
# Matches both <div>s
|
|
243
|
+
locator = page.get_by_text(/Hello/)
|
|
244
|
+
expect(locator.count).to eq(2)
|
|
245
|
+
expect(locator.first.evaluate('e => e.outerHTML')).to eq('<div>Hello <span>world</span></div>')
|
|
246
|
+
expect(locator.last.evaluate('e => e.outerHTML')).to eq('<div>Hello</div>')
|
|
247
|
+
|
|
248
|
+
# Matches second <div>
|
|
249
|
+
locator = page.get_by_text(/^hello$/i)
|
|
250
|
+
expect(locator.evaluate('e => e.outerHTML')).to eq('<div>Hello</div>')
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
**Details**
|
|
254
|
+
|
|
255
|
+
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.
|
|
256
|
+
|
|
257
|
+
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">`.
|
|
258
|
+
|
|
259
|
+
## get_by_title
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
def get_by_title(text, exact: nil)
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
Allows locating elements by their title attribute.
|
|
267
|
+
|
|
268
|
+
**Usage**
|
|
269
|
+
|
|
270
|
+
Consider the following DOM structure.
|
|
271
|
+
|
|
272
|
+
```html
|
|
273
|
+
<span title='Issues count'>25 issues</span>
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
You can check the issues count after locating it by the title text:
|
|
277
|
+
|
|
278
|
+
```ruby
|
|
279
|
+
page.get_by_title("Issues count").text_content # => "25 issues"
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
## last
|
|
283
|
+
|
|
284
|
+
```
|
|
285
|
+
def last
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
:::warning
|
|
289
|
+
|
|
290
|
+
Use [Locator#last](./locator#last) followed by [Locator#content_frame](./locator#content_frame) instead.
|
|
291
|
+
|
|
292
|
+
:::
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
Returns locator to the last matching frame.
|
|
296
|
+
|
|
297
|
+
## locator
|
|
298
|
+
|
|
299
|
+
```
|
|
300
|
+
def locator(
|
|
301
|
+
selectorOrLocator,
|
|
302
|
+
has: nil,
|
|
303
|
+
hasNot: nil,
|
|
304
|
+
hasNotText: nil,
|
|
305
|
+
hasText: nil)
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
The method finds an element matching the specified selector in the locator's subtree. It also accepts filter options, similar to [Locator#filter](./locator#filter) method.
|
|
310
|
+
|
|
311
|
+
[Learn more about locators](https://playwright.dev/python/docs/locators).
|
|
312
|
+
|
|
313
|
+
## nth
|
|
314
|
+
|
|
315
|
+
```
|
|
316
|
+
def nth(index)
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
:::warning
|
|
320
|
+
|
|
321
|
+
Use [Locator#nth](./locator#nth) followed by [Locator#content_frame](./locator#content_frame) instead.
|
|
322
|
+
|
|
323
|
+
:::
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
Returns locator to the n-th matching frame. It's zero based, `nth(0)` selects the first frame.
|
|
327
|
+
|
|
328
|
+
## owner
|
|
329
|
+
|
|
330
|
+
```
|
|
331
|
+
def owner
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
Returns a [Locator](./locator) object pointing to the same `iframe` as this frame locator.
|
|
336
|
+
|
|
337
|
+
Useful when you have a [FrameLocator](./frame_locator) object obtained somewhere, and later on would like to interact with the `iframe` element.
|
|
338
|
+
|
|
339
|
+
For a reverse operation, use [Locator#content_frame](./locator#content_frame).
|
|
340
|
+
|
|
341
|
+
**Usage**
|
|
342
|
+
|
|
343
|
+
```ruby
|
|
344
|
+
frame_locator = page.locator('iframe[name="embedded"]').content_frame
|
|
345
|
+
# ...
|
|
346
|
+
locator = frame_locator.owner
|
|
347
|
+
locator.get_attribute('src') # => frame1.html
|
|
348
|
+
```
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 10
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# JSHandle
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
JSHandle represents an in-page JavaScript object. JSHandles can be created with the [Page#evaluate_handle](./page#evaluate_handle)
|
|
9
|
+
method.
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
window_handle = page.evaluate_handle("window")
|
|
13
|
+
# ...
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
JSHandle prevents the referenced JavaScript object being garbage collected unless the handle is exposed with
|
|
17
|
+
[JSHandle#dispose](./js_handle#dispose). JSHandles are auto-disposed when their origin frame gets navigated or the parent context
|
|
18
|
+
gets destroyed.
|
|
19
|
+
|
|
20
|
+
JSHandle instances can be used as an argument in [Page#eval_on_selector](./page#eval_on_selector), [Page#evaluate](./page#evaluate) and
|
|
21
|
+
[Page#evaluate_handle](./page#evaluate_handle) methods.
|
|
22
|
+
|
|
23
|
+
## as_element
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
def as_element
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
Returns either `null` or the object handle itself, if the object handle is an instance of [ElementHandle](./element_handle).
|
|
31
|
+
|
|
32
|
+
## dispose
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
def dispose
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
The `jsHandle.dispose` method stops referencing the element handle.
|
|
40
|
+
|
|
41
|
+
## evaluate
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
def evaluate(expression, arg: nil)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
Returns the return value of `expression`.
|
|
49
|
+
|
|
50
|
+
This method passes this handle as the first argument to `expression`.
|
|
51
|
+
|
|
52
|
+
If `expression` returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), then `handle.evaluate` would wait for the promise to resolve and return
|
|
53
|
+
its value.
|
|
54
|
+
|
|
55
|
+
**Usage**
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
tweet_handle = page.query_selector(".tweet .retweets")
|
|
59
|
+
tweet_handle.evaluate("node => node.innerText") # => "10 retweets"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## evaluate_handle
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
def evaluate_handle(expression, arg: nil)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
Returns the return value of `expression` as a [JSHandle](./js_handle).
|
|
70
|
+
|
|
71
|
+
This method passes this handle as the first argument to `expression`.
|
|
72
|
+
|
|
73
|
+
The only difference between [JSHandle#evaluate](./js_handle#evaluate) and [JSHandle#evaluate_handle](./js_handle#evaluate_handle) is that [JSHandle#evaluate_handle](./js_handle#evaluate_handle) returns [JSHandle](./js_handle).
|
|
74
|
+
|
|
75
|
+
If the function passed to the [JSHandle#evaluate_handle](./js_handle#evaluate_handle) returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), then [JSHandle#evaluate_handle](./js_handle#evaluate_handle) would wait
|
|
76
|
+
for the promise to resolve and return its value.
|
|
77
|
+
|
|
78
|
+
See [Page#evaluate_handle](./page#evaluate_handle) for more details.
|
|
79
|
+
|
|
80
|
+
## get_properties
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
def get_properties
|
|
84
|
+
```
|
|
85
|
+
alias: `properties`
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
The method returns a map with **own property names** as keys and JSHandle instances for the property values.
|
|
89
|
+
|
|
90
|
+
**Usage**
|
|
91
|
+
|
|
92
|
+
```ruby
|
|
93
|
+
page.goto('https://example.com/')
|
|
94
|
+
handle = page.evaluate_handle("({window, document})")
|
|
95
|
+
properties = handle.properties
|
|
96
|
+
puts properties
|
|
97
|
+
window_handle = properties["window"]
|
|
98
|
+
document_handle = properties["document"]
|
|
99
|
+
handle.dispose
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## get_property
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
def get_property(propertyName)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
Fetches a single property from the referenced object.
|
|
110
|
+
|
|
111
|
+
## json_value
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
def json_value
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
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 error if the
|
|
121
|
+
object has circular references.
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 10
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Keyboard
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
Keyboard provides an api for managing a virtual keyboard. The high level api is [Keyboard#type](./keyboard#type), which takes
|
|
9
|
+
raw characters and generates proper `keydown`, `keypress`/`input`, and `keyup` events on your page.
|
|
10
|
+
|
|
11
|
+
For finer control, you can use [Keyboard#down](./keyboard#down), [Keyboard#up](./keyboard#up), and [Keyboard#insert_text](./keyboard#insert_text)
|
|
12
|
+
to manually fire events as if they were generated from a real keyboard.
|
|
13
|
+
|
|
14
|
+
An example of holding down `Shift` in order to select and delete some text:
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
page.keyboard.type("Hello World!")
|
|
18
|
+
page.keyboard.press("ArrowLeft")
|
|
19
|
+
page.keyboard.down("Shift")
|
|
20
|
+
6.times { page.keyboard.press("ArrowLeft") }
|
|
21
|
+
page.keyboard.up("Shift")
|
|
22
|
+
page.keyboard.press("Backspace")
|
|
23
|
+
# result text will end up saying "Hello!"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
An example of pressing uppercase `A`
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
page.keyboard.press("Shift+KeyA")
|
|
30
|
+
# or
|
|
31
|
+
page.keyboard.press("Shift+A")
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
An example to trigger select-all with the keyboard
|
|
35
|
+
|
|
36
|
+
```ruby
|
|
37
|
+
# RECOMMENDED
|
|
38
|
+
page.keyboard.press("ControlOrMeta+A")
|
|
39
|
+
|
|
40
|
+
# or just on windows and linux
|
|
41
|
+
page.keyboard.press("Control+A")
|
|
42
|
+
# or just on macOS
|
|
43
|
+
page.keyboard.press("Meta+A")
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## down
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
def down(key)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
Dispatches a `keydown` event.
|
|
54
|
+
|
|
55
|
+
`key` can specify the intended
|
|
56
|
+
[keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character to
|
|
57
|
+
generate the text for. A superset of the `key` values can be found
|
|
58
|
+
[here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Examples of the keys are:
|
|
59
|
+
|
|
60
|
+
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
|
61
|
+
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
|
62
|
+
|
|
63
|
+
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
|
64
|
+
`ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
|
65
|
+
|
|
66
|
+
Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
|
|
67
|
+
|
|
68
|
+
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different
|
|
69
|
+
respective texts.
|
|
70
|
+
|
|
71
|
+
If `key` is a modifier key, `Shift`, `Meta`, `Control`, or `Alt`, subsequent key presses will be sent with that
|
|
72
|
+
modifier active. To release the modifier key, use [Keyboard#up](./keyboard#up).
|
|
73
|
+
|
|
74
|
+
After the key is pressed once, subsequent calls to [Keyboard#down](./keyboard#down) will have
|
|
75
|
+
[repeat](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat) set to true. To release the key, use
|
|
76
|
+
[Keyboard#up](./keyboard#up).
|
|
77
|
+
|
|
78
|
+
**NOTE**: Modifier keys DO influence `keyboard.down`. Holding down `Shift` will type the text in upper case.
|
|
79
|
+
|
|
80
|
+
## insert_text
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
def insert_text(text)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
Dispatches only `input` event, does not emit the `keydown`, `keyup` or `keypress` events.
|
|
88
|
+
|
|
89
|
+
**Usage**
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
page.keyboard.insert_text("嗨")
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
**NOTE**: Modifier keys DO NOT effect `keyboard.insertText`. Holding down `Shift` will not type the text in upper case.
|
|
96
|
+
|
|
97
|
+
## press
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
def press(key, delay: nil)
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
**NOTE**: In most cases, you should use [Locator#press](./locator#press) instead.
|
|
105
|
+
|
|
106
|
+
`key` can specify the intended
|
|
107
|
+
[keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) value or a single character to
|
|
108
|
+
generate the text for. A superset of the `key` values can be found
|
|
109
|
+
[here](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values). Examples of the keys are:
|
|
110
|
+
|
|
111
|
+
`F1` - `F12`, `Digit0`- `Digit9`, `KeyA`- `KeyZ`, `Backquote`, `Minus`, `Equal`, `Backslash`, `Backspace`, `Tab`,
|
|
112
|
+
`Delete`, `Escape`, `ArrowDown`, `End`, `Enter`, `Home`, `Insert`, `PageDown`, `PageUp`, `ArrowRight`, `ArrowUp`, etc.
|
|
113
|
+
|
|
114
|
+
Following modification shortcuts are also supported: `Shift`, `Control`, `Alt`, `Meta`, `ShiftLeft`, `ControlOrMeta`.
|
|
115
|
+
`ControlOrMeta` resolves to `Control` on Windows and Linux and to `Meta` on macOS.
|
|
116
|
+
|
|
117
|
+
Holding down `Shift` will type the text that corresponds to the `key` in the upper case.
|
|
118
|
+
|
|
119
|
+
If `key` is a single character, it is case-sensitive, so the values `a` and `A` will generate different
|
|
120
|
+
respective texts.
|
|
121
|
+
|
|
122
|
+
Shortcuts such as `key: "Control+o"`, `key: "Control++` or `key: "Control+Shift+T"` are supported as well. When specified with the
|
|
123
|
+
modifier, modifier is pressed and being held while the subsequent key is being pressed.
|
|
124
|
+
|
|
125
|
+
**Usage**
|
|
126
|
+
|
|
127
|
+
```ruby
|
|
128
|
+
page.goto("https://keycode.info")
|
|
129
|
+
page.keyboard.press("a")
|
|
130
|
+
page.screenshot(path: "a.png")
|
|
131
|
+
page.keyboard.press("ArrowLeft")
|
|
132
|
+
page.screenshot(path: "arrow_left.png")
|
|
133
|
+
page.keyboard.press("Shift+O")
|
|
134
|
+
page.screenshot(path: "o.png")
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Shortcut for [Keyboard#down](./keyboard#down) and [Keyboard#up](./keyboard#up).
|
|
138
|
+
|
|
139
|
+
## type
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
def type(text, delay: nil)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
**NOTE**: In most cases, you should use [Locator#fill](./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 [Locator#press_sequentially](./locator#press_sequentially).
|
|
147
|
+
|
|
148
|
+
Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text.
|
|
149
|
+
|
|
150
|
+
To press a special key, like `Control` or `ArrowDown`, use [Keyboard#press](./keyboard#press).
|
|
151
|
+
|
|
152
|
+
**Usage**
|
|
153
|
+
|
|
154
|
+
```ruby
|
|
155
|
+
page.keyboard.type("Hello") # types instantly
|
|
156
|
+
page.keyboard.type("World", delay: 100) # types slower, like a user
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**NOTE**: Modifier keys DO NOT effect `keyboard.type`. Holding down `Shift` will not type the text in upper case.
|
|
160
|
+
|
|
161
|
+
**NOTE**: For characters that are not on a US keyboard, only an `input` event will be sent.
|
|
162
|
+
|
|
163
|
+
## up
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
def up(key)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
Dispatches a `keyup` event.
|