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,827 @@
1
+ ---
2
+ sidebar_position: 10
3
+ ---
4
+
5
+ # LocatorAssertions
6
+
7
+
8
+ The LocatorAssertions class provides assertion methods for RSpec like `expect(locator).to have_text("Something")`. Note that we have to explicitly include `playwright/test` and `Playwright::Test::Matchers` for using RSpec matchers.
9
+
10
+ ```ruby
11
+ require 'playwright/test'
12
+
13
+ describe 'your system testing' do
14
+ include Playwright::Test::Matchers
15
+ ```
16
+
17
+ Since the matcher comes with auto-waiting feature, we don't have to describe trivial codes waiting for elements any more :)
18
+
19
+ ```ruby
20
+ page.content = <<~HTML
21
+ <div id="my_status" class="status">Pending</div>
22
+ <button onClick="setTimeout(() => { document.getElementById('my_status').innerText='Something Submitted!!' }, 2000)">Click me</button>
23
+ HTML
24
+
25
+ page.get_by_role("button").click
26
+ expect(page.locator(".status")).to have_text("Submitted") # auto-waiting
27
+ ```
28
+
29
+ ## not_to_be_attached
30
+
31
+ ```ruby
32
+ expect(locator).not_to be_attached(attached: nil, timeout: nil)
33
+ ```
34
+
35
+
36
+ The opposite of [LocatorAssertions#to_be_attached](./locator_assertions#to_be_attached).
37
+
38
+ ## not_to_be_checked
39
+
40
+ ```ruby
41
+ expect(locator).not_to be_checked(timeout: nil)
42
+ ```
43
+
44
+
45
+ The opposite of [LocatorAssertions#to_be_checked](./locator_assertions#to_be_checked).
46
+
47
+ ## not_to_be_disabled
48
+
49
+ ```ruby
50
+ expect(locator).not_to be_disabled(timeout: nil)
51
+ ```
52
+
53
+
54
+ The opposite of [LocatorAssertions#to_be_disabled](./locator_assertions#to_be_disabled).
55
+
56
+ ## not_to_be_editable
57
+
58
+ ```ruby
59
+ expect(locator).not_to be_editable(editable: nil, timeout: nil)
60
+ ```
61
+
62
+
63
+ The opposite of [LocatorAssertions#to_be_editable](./locator_assertions#to_be_editable).
64
+
65
+ ## not_to_be_empty
66
+
67
+ ```ruby
68
+ expect(locator).not_to be_empty(timeout: nil)
69
+ ```
70
+
71
+
72
+ The opposite of [LocatorAssertions#to_be_empty](./locator_assertions#to_be_empty).
73
+
74
+ ## not_to_be_enabled
75
+
76
+ ```ruby
77
+ expect(locator).not_to be_enabled(enabled: nil, timeout: nil)
78
+ ```
79
+
80
+
81
+ The opposite of [LocatorAssertions#to_be_enabled](./locator_assertions#to_be_enabled).
82
+
83
+ ## not_to_be_focused
84
+
85
+ ```ruby
86
+ expect(locator).not_to be_focused(timeout: nil)
87
+ ```
88
+
89
+
90
+ The opposite of [LocatorAssertions#to_be_focused](./locator_assertions#to_be_focused).
91
+
92
+ ## not_to_be_hidden
93
+
94
+ ```ruby
95
+ expect(locator).not_to be_hidden(timeout: nil)
96
+ ```
97
+
98
+
99
+ The opposite of [LocatorAssertions#to_be_hidden](./locator_assertions#to_be_hidden).
100
+
101
+ ## not_to_be_in_viewport
102
+
103
+ ```ruby
104
+ expect(locator).not_to be_in_viewport(ratio: nil, timeout: nil)
105
+ ```
106
+
107
+
108
+ The opposite of [LocatorAssertions#to_be_in_viewport](./locator_assertions#to_be_in_viewport).
109
+
110
+ ## not_to_be_visible
111
+
112
+ ```ruby
113
+ expect(locator).not_to be_visible(timeout: nil, visible: nil)
114
+ ```
115
+
116
+
117
+ The opposite of [LocatorAssertions#to_be_visible](./locator_assertions#to_be_visible).
118
+
119
+ ## not_to_contain_class
120
+
121
+ ```ruby
122
+ expect(locator).not_to contain_class(expected, timeout: nil)
123
+ ```
124
+
125
+
126
+ The opposite of [LocatorAssertions#to_contain_class](./locator_assertions#to_contain_class).
127
+
128
+ ## not_to_contain_text
129
+
130
+ ```ruby
131
+ expect(locator).not_to contain_text(expected, ignoreCase: nil, timeout: nil, useInnerText: nil)
132
+ ```
133
+
134
+
135
+ The opposite of [LocatorAssertions#to_contain_text](./locator_assertions#to_contain_text).
136
+
137
+ ## not_to_have_accessible_description
138
+
139
+ ```ruby
140
+ expect(locator).not_to have_accessible_description(name, ignoreCase: nil, timeout: nil)
141
+ ```
142
+
143
+
144
+ The opposite of [LocatorAssertions#to_have_accessible_description](./locator_assertions#to_have_accessible_description).
145
+
146
+ ## not_to_have_accessible_error_message
147
+
148
+ ```ruby
149
+ expect(locator).not_to have_accessible_error_message(errorMessage, ignoreCase: nil, timeout: nil)
150
+ ```
151
+
152
+
153
+ The opposite of [LocatorAssertions#to_have_accessible_error_message](./locator_assertions#to_have_accessible_error_message).
154
+
155
+ ## not_to_have_accessible_name
156
+
157
+ ```ruby
158
+ expect(locator).not_to have_accessible_name(name, ignoreCase: nil, timeout: nil)
159
+ ```
160
+
161
+
162
+ The opposite of [LocatorAssertions#to_have_accessible_name](./locator_assertions#to_have_accessible_name).
163
+
164
+ ## not_to_have_attribute
165
+
166
+ ```ruby
167
+ expect(locator).not_to have_attribute(name, value, ignoreCase: nil, timeout: nil)
168
+ ```
169
+
170
+
171
+ The opposite of [LocatorAssertions#to_have_attribute](./locator_assertions#to_have_attribute).
172
+
173
+ ## not_to_have_class
174
+
175
+ ```ruby
176
+ expect(locator).not_to have_class(expected, timeout: nil)
177
+ ```
178
+
179
+
180
+ The opposite of [LocatorAssertions#to_have_class](./locator_assertions#to_have_class).
181
+
182
+ ## not_to_have_count
183
+
184
+ ```ruby
185
+ expect(locator).not_to have_count(count, timeout: nil)
186
+ ```
187
+
188
+
189
+ The opposite of [LocatorAssertions#to_have_count](./locator_assertions#to_have_count).
190
+
191
+ ## not_to_have_css
192
+
193
+ ```ruby
194
+ expect(locator).not_to have_css(name, value, timeout: nil)
195
+ ```
196
+
197
+
198
+ The opposite of [LocatorAssertions#to_have_css](./locator_assertions#to_have_css).
199
+
200
+ ## not_to_have_id
201
+
202
+ ```ruby
203
+ expect(locator).not_to have_id(id, timeout: nil)
204
+ ```
205
+
206
+
207
+ The opposite of [LocatorAssertions#to_have_id](./locator_assertions#to_have_id).
208
+
209
+ ## not_to_have_js_property
210
+
211
+ ```ruby
212
+ expect(locator).not_to have_js_property(name, value, timeout: nil)
213
+ ```
214
+
215
+
216
+ The opposite of [LocatorAssertions#to_have_js_property](./locator_assertions#to_have_js_property).
217
+
218
+ ## not_to_have_role
219
+
220
+ ```ruby
221
+ expect(locator).not_to have_role(role, timeout: nil)
222
+ ```
223
+
224
+
225
+ The opposite of [LocatorAssertions#to_have_role](./locator_assertions#to_have_role).
226
+
227
+ ## not_to_have_text
228
+
229
+ ```ruby
230
+ expect(locator).not_to have_text(expected, ignoreCase: nil, timeout: nil, useInnerText: nil)
231
+ ```
232
+
233
+
234
+ The opposite of [LocatorAssertions#to_have_text](./locator_assertions#to_have_text).
235
+
236
+ ## not_to_have_value
237
+
238
+ ```ruby
239
+ expect(locator).not_to have_value(value, timeout: nil)
240
+ ```
241
+
242
+
243
+ The opposite of [LocatorAssertions#to_have_value](./locator_assertions#to_have_value).
244
+
245
+ ## not_to_have_values
246
+
247
+ ```ruby
248
+ expect(locator).not_to have_values(values, timeout: nil)
249
+ ```
250
+
251
+
252
+ The opposite of [LocatorAssertions#to_have_values](./locator_assertions#to_have_values).
253
+
254
+ ## not_to_match_aria_snapshot
255
+
256
+ ```ruby
257
+ expect(locator).not_to match_aria_snapshot(expected, timeout: nil)
258
+ ```
259
+
260
+
261
+ The opposite of [LocatorAssertions#to_match_aria_snapshot](./locator_assertions#to_match_aria_snapshot).
262
+
263
+ ## to_be_attached
264
+
265
+ ```ruby
266
+ expect(locator).to be_attached(attached: nil, timeout: nil)
267
+ ```
268
+
269
+
270
+ Ensures that [Locator](./locator) points to an element that is [connected](https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected) to a Document or a ShadowRoot.
271
+
272
+ **Usage**
273
+
274
+ ```ruby
275
+ page.content = <<~HTML
276
+ <div id="hidden_status" style="display: none">Pending</div>
277
+ <button onClick="document.getElementById('hidden_status').innerText='Hidden text'">Click me</button>
278
+ HTML
279
+
280
+ page.get_by_role("button").click
281
+ expect(page.get_by_text("Hidden text")).to be_attached
282
+ ```
283
+
284
+ ## to_be_checked
285
+
286
+ ```ruby
287
+ expect(locator).to be_checked(checked: nil, indeterminate: nil, timeout: nil)
288
+ ```
289
+
290
+
291
+ Ensures the [Locator](./locator) points to a checked input.
292
+
293
+ **Usage**
294
+
295
+ ```ruby
296
+ locator = page.get_by_label("Subscribe to newsletter")
297
+ expect(locator).to be_checked
298
+ ```
299
+
300
+ ## to_be_disabled
301
+
302
+ ```ruby
303
+ expect(locator).to be_disabled(timeout: nil)
304
+ ```
305
+
306
+
307
+ Ensures the [Locator](./locator) points to a disabled element. Element is disabled if it has "disabled" attribute
308
+ or is disabled via ['aria-disabled'](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-disabled).
309
+ Note that only native control elements such as HTML `button`, `input`, `select`, `textarea`, `option`, `optgroup`
310
+ can be disabled by setting "disabled" attribute. "disabled" attribute on other elements is ignored
311
+ by the browser.
312
+
313
+ **Usage**
314
+
315
+ ```ruby
316
+ locator = page.locator("button.submit")
317
+ locator.click
318
+ expect(locator).to be_disabled
319
+ ```
320
+
321
+ ## to_be_editable
322
+
323
+ ```ruby
324
+ expect(locator).to be_editable(editable: nil, timeout: nil)
325
+ ```
326
+
327
+
328
+ Ensures the [Locator](./locator) points to an editable element.
329
+
330
+ **Usage**
331
+
332
+ ```ruby
333
+ locator = page.get_by_role("textbox")
334
+ expect(locator).to be_editable
335
+ ```
336
+
337
+ ## to_be_empty
338
+
339
+ ```ruby
340
+ expect(locator).to be_empty(timeout: nil)
341
+ ```
342
+
343
+
344
+ Ensures the [Locator](./locator) points to an empty editable element or to a DOM node that has no text.
345
+
346
+ **Usage**
347
+
348
+ ```ruby
349
+ locator = page.locator("div.warning")
350
+ expect(locator).to be_empty
351
+ ```
352
+
353
+ ## to_be_enabled
354
+
355
+ ```ruby
356
+ expect(locator).to be_enabled(enabled: nil, timeout: nil)
357
+ ```
358
+
359
+
360
+ Ensures the [Locator](./locator) points to an enabled element.
361
+
362
+ **Usage**
363
+
364
+ ```ruby
365
+ locator = page.locator("button.submit")
366
+ expect(locator).to be_enabled
367
+ ```
368
+
369
+ ## to_be_focused
370
+
371
+ ```ruby
372
+ expect(locator).to be_focused(timeout: nil)
373
+ ```
374
+
375
+
376
+ Ensures the [Locator](./locator) points to a focused DOM node.
377
+
378
+ **Usage**
379
+
380
+ ```ruby
381
+ locator = page.get_by_role("textbox")
382
+ expect(locator).to be_focused
383
+ ```
384
+
385
+ ## to_be_hidden
386
+
387
+ ```ruby
388
+ expect(locator).to be_hidden(timeout: nil)
389
+ ```
390
+
391
+
392
+ Ensures that [Locator](./locator) either does not resolve to any DOM node, or resolves to a [non-visible](https://playwright.dev/python/docs/actionability#visible) one.
393
+
394
+ **Usage**
395
+
396
+ ```ruby
397
+ locator = page.locator(".my-element")
398
+ expect(locator).to be_hidden
399
+ ```
400
+
401
+ ## to_be_in_viewport
402
+
403
+ ```ruby
404
+ expect(locator).to be_in_viewport(ratio: nil, timeout: nil)
405
+ ```
406
+
407
+
408
+ Ensures the [Locator](./locator) points to an element that intersects viewport, according to the [intersection observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API).
409
+
410
+ **Usage**
411
+
412
+ ```ruby
413
+ locator = page.get_by_role("button")
414
+ # Make sure at least some part of element intersects viewport.
415
+ expect(locator).to be_in_viewport
416
+ # Make sure element is fully outside of viewport.
417
+ expect(locator).not_to be_in_viewport
418
+ # Make sure that at least half of the element intersects viewport.
419
+ expect(locator).to be_in_viewport(ratio: 0.5)
420
+ ```
421
+
422
+ ## to_be_visible
423
+
424
+ ```ruby
425
+ expect(locator).to be_visible(timeout: nil, visible: nil)
426
+ ```
427
+
428
+
429
+ Ensures that [Locator](./locator) points to an attached and [visible](https://playwright.dev/python/docs/actionability#visible) DOM node.
430
+
431
+ To check that at least one element from the list is visible, use [Locator#first](./locator#first).
432
+
433
+ **Usage**
434
+
435
+ ```ruby
436
+ # A specific element is visible.
437
+ expect(page.get_by_text("Welcome")).to be_visible
438
+
439
+ # At least one item in the list is visible.
440
+ expect(page.get_by_test_id("todo-item").first).to be_visible
441
+
442
+ # At least one of the two elements is visible, possibly both.
443
+ expect(
444
+ page.get_by_role('button', name: 'Sign in').or(page.get_by_role('button', name: 'Sign up')).first
445
+ ).to be_visible
446
+ ```
447
+
448
+ ## to_contain_class
449
+
450
+ ```ruby
451
+ expect(locator).to contain_class(expected, timeout: nil)
452
+ ```
453
+
454
+
455
+ Ensures the [Locator](./locator) points to an element with given CSS classes. All classes from the asserted value, separated by spaces, must be present in the [Element.classList](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList) in any order.
456
+
457
+ **Usage**
458
+
459
+ ```html
460
+ <div class='middle selected row' id='component'></div>
461
+ ```
462
+
463
+ ```ruby
464
+ locator = page.locator("#component")
465
+ expect(locator).to contain_class("middle selected row")
466
+ expect(locator).to contain_class("selected")
467
+ expect(locator).to contain_class("row middle")
468
+ ```
469
+
470
+ When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected class lists. Each element's class attribute is matched against the corresponding class in the array:
471
+
472
+ ```html
473
+ <div class='list'>
474
+ <div class='component inactive'></div>
475
+ <div class='component active'></div>
476
+ <div class='component inactive'></div>
477
+ </div>
478
+ ```
479
+
480
+ ```ruby
481
+ locator = page.locator(".list > .component")
482
+ expect(locator).to contain_class(["inactive", "active", "inactive"])
483
+ ```
484
+
485
+ ## to_contain_text
486
+
487
+ ```ruby
488
+ expect(locator).to contain_text(expected, ignoreCase: nil, timeout: nil, useInnerText: nil)
489
+ ```
490
+
491
+
492
+ Ensures the [Locator](./locator) points to an element that contains the given text. All nested elements will be considered when computing the text content of the element. You can use regular expressions for the value as well.
493
+
494
+ **Details**
495
+
496
+ When `expected` parameter is a string, Playwright will normalize whitespaces and line breaks both in the actual text and
497
+ in the expected string before matching. When regular expression is used, the actual text is matched as is.
498
+
499
+ **Usage**
500
+
501
+ ```ruby
502
+ locator = page.locator('.title')
503
+ expect(locator).to contain_text("substring")
504
+ expect(locator).to contain_text(/\d messages/)
505
+ ```
506
+
507
+ If you pass an array as an expected value, the expectations are:
508
+ 1. Locator resolves to a list of elements.
509
+ 1. Elements from a **subset** of this list contain text from the expected array, respectively.
510
+ 1. The matching subset of elements has the same order as the expected array.
511
+ 1. Each text value from the expected array is matched by some element from the list.
512
+
513
+ For example, consider the following list:
514
+
515
+ ```html
516
+ <ul>
517
+ <li>Item Text 1</li>
518
+ <li>Item Text 2</li>
519
+ <li>Item Text 3</li>
520
+ </ul>
521
+ ```
522
+
523
+ Let's see how we can use the assertion:
524
+
525
+ ```ruby
526
+ # ✓ Contains the right items in the right order
527
+ expect(page.locator("ul > li")).to contain_text(["Text 1", "Text 3"])
528
+
529
+ # ✖ Wrong order
530
+ expect(page.locator("ul > li")).to contain_text(["Text 3", "Text 2"])
531
+
532
+ # ✖ No item contains this text
533
+ expect(page.locator("ul > li")).to contain_text(["Some 33"])
534
+
535
+ # ✖ Locator points to the outer list element, not to the list items
536
+ expect(page.locator("ul")).to contain_text(["Text 3"])
537
+ ```
538
+
539
+ ## to_have_accessible_description
540
+
541
+ ```ruby
542
+ expect(locator).to have_accessible_description(description, ignoreCase: nil, timeout: nil)
543
+ ```
544
+
545
+
546
+ Ensures the [Locator](./locator) points to an element with a given [accessible description](https://w3c.github.io/accname/#dfn-accessible-description).
547
+
548
+ **Usage**
549
+
550
+ ```ruby
551
+ locator = page.get_by_test_id("save-button")
552
+ expect(locator).to have_accessible_description("Save results to disk")
553
+ ```
554
+
555
+ ## to_have_accessible_error_message
556
+
557
+ ```ruby
558
+ expect(locator).to have_accessible_error_message(errorMessage, ignoreCase: nil, timeout: nil)
559
+ ```
560
+
561
+
562
+ Ensures the [Locator](./locator) points to an element with a given [aria errormessage](https://w3c.github.io/aria/#aria-errormessage).
563
+
564
+ **Usage**
565
+
566
+ ```ruby
567
+ locator = page.get_by_test_id("username-input")
568
+ expect(locator).to have_accessible_error_message("Username is required.")
569
+ ```
570
+
571
+ ## to_have_accessible_name
572
+
573
+ ```ruby
574
+ expect(locator).to have_accessible_name(name, ignoreCase: nil, timeout: nil)
575
+ ```
576
+
577
+
578
+ Ensures the [Locator](./locator) points to an element with a given [accessible name](https://w3c.github.io/accname/#dfn-accessible-name).
579
+
580
+ **Usage**
581
+
582
+ ```ruby
583
+ locator = page.get_by_test_id("save-button")
584
+ expect(locator).to have_accessible_name("Save to disk")
585
+ ```
586
+
587
+ ## to_have_attribute
588
+
589
+ ```ruby
590
+ expect(locator).to have_attribute(name, value, ignoreCase: nil, timeout: nil)
591
+ ```
592
+
593
+
594
+ Ensures the [Locator](./locator) points to an element with given attribute.
595
+
596
+ **Usage**
597
+
598
+ ```ruby
599
+ locator = page.locator("input")
600
+ expect(locator).to have_attribute("type", "text")
601
+ ```
602
+
603
+ ## to_have_class
604
+
605
+ ```ruby
606
+ expect(locator).to have_class(expected, timeout: nil)
607
+ ```
608
+
609
+
610
+ Ensures the [Locator](./locator) points to an element with given CSS classes. When a string is provided, it must fully match the element's `class` attribute. To match individual classes use [LocatorAssertions#to_contain_class](./locator_assertions#to_contain_class).
611
+
612
+ **Usage**
613
+
614
+ ```html
615
+ <div class='middle selected row' id='component'></div>
616
+ ```
617
+
618
+ ```ruby
619
+ locator = page.locator("#component")
620
+ expect(locator).to have_class(/(^|\s)selected(\s|$)/)
621
+ expect(locator).to have_class("middle selected row")
622
+ ```
623
+
624
+ When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected class values. Each element's class attribute is matched against the corresponding string or regular expression in the array:
625
+
626
+ ```ruby
627
+ locator = page.locator("list > .component")
628
+ expect(locator).to have_class(["component", "component selected", "component"])
629
+ ```
630
+
631
+ ## to_have_count
632
+
633
+ ```ruby
634
+ expect(locator).to have_count(count, timeout: nil)
635
+ ```
636
+
637
+
638
+ Ensures the [Locator](./locator) resolves to an exact number of DOM nodes.
639
+
640
+ **Usage**
641
+
642
+ ```ruby
643
+ locator = page.locator("list > .component")
644
+ expect(locator).to have_count(3)
645
+ ```
646
+
647
+ ## to_have_css
648
+
649
+ ```ruby
650
+ expect(locator).to have_css(name, value, timeout: nil)
651
+ ```
652
+
653
+
654
+ Ensures the [Locator](./locator) resolves to an element with the given computed CSS style.
655
+
656
+ **Usage**
657
+
658
+ ```ruby
659
+ locator = page.get_by_role("button")
660
+ expect(locator).to have_css("display", "flex")
661
+ ```
662
+
663
+ ## to_have_id
664
+
665
+ ```ruby
666
+ expect(locator).to have_id(id, timeout: nil)
667
+ ```
668
+
669
+
670
+ Ensures the [Locator](./locator) points to an element with the given DOM Node ID.
671
+
672
+ **Usage**
673
+
674
+ ```ruby
675
+ locator = page.get_by_role("textbox")
676
+ expect(locator).to have_id("lastname")
677
+ ```
678
+
679
+ ## to_have_js_property
680
+
681
+ ```ruby
682
+ expect(locator).to have_js_property(name, value, timeout: nil)
683
+ ```
684
+
685
+
686
+ Ensures the [Locator](./locator) points to an element with given JavaScript property. Note that this property can be
687
+ of a primitive type as well as a plain serializable JavaScript object.
688
+
689
+ **Usage**
690
+
691
+ ```ruby
692
+ locator = page.locator(".component")
693
+ expect(locator).to have_js_property("loaded", true)
694
+ ```
695
+
696
+ ## to_have_role
697
+
698
+ ```ruby
699
+ expect(locator).to have_role(role, timeout: nil)
700
+ ```
701
+
702
+
703
+ Ensures the [Locator](./locator) points to an element with a given [ARIA role](https://www.w3.org/TR/wai-aria-1.2/#roles).
704
+
705
+ Note that role is matched as a string, disregarding the ARIA role hierarchy. For example, asserting a superclass role `"checkbox"` on an element with a subclass role `"switch"` will fail.
706
+
707
+ **Usage**
708
+
709
+ ```ruby
710
+ locator = page.get_by_test_id("save-button")
711
+ expect(locator).to have_role("button")
712
+ ```
713
+
714
+ ## to_have_text
715
+
716
+ ```ruby
717
+ expect(locator).to have_text(expected, ignoreCase: nil, timeout: nil, useInnerText: nil)
718
+ ```
719
+
720
+
721
+ Ensures the [Locator](./locator) points to an element with the given text. All nested elements will be considered when computing the text content of the element. You can use regular expressions for the value as well.
722
+
723
+ **Details**
724
+
725
+ When `expected` parameter is a string, Playwright will normalize whitespaces and line breaks both in the actual text and
726
+ in the expected string before matching. When regular expression is used, the actual text is matched as is.
727
+
728
+ **Usage**
729
+
730
+ ```ruby
731
+ locator = page.locator(".title")
732
+ expect(locator).to have_text(/Welcome, Test User/)
733
+ expect(locator).to have_text(/Welcome, .*/)
734
+ ```
735
+
736
+ If you pass an array as an expected value, the expectations are:
737
+ 1. Locator resolves to a list of elements.
738
+ 1. The number of elements equals the number of expected values in the array.
739
+ 1. Elements from the list have text matching expected array values, one by one, in order.
740
+
741
+ For example, consider the following list:
742
+
743
+ ```html
744
+ <ul>
745
+ <li>Text 1</li>
746
+ <li>Text 2</li>
747
+ <li>Text 3</li>
748
+ </ul>
749
+ ```
750
+
751
+ Let's see how we can use the assertion:
752
+
753
+ ```ruby
754
+ # ✓ Has the right items in the right order
755
+ expect(page.locator("ul > li")).to have_text(["Text 1", "Text 2", "Text 3"])
756
+
757
+ # ✖ Wrong order
758
+ expect(page.locator("ul > li")).to have_text(["Text 3", "Text 2", "Text 1"])
759
+
760
+ # ✖ Last item does not match
761
+ expect(page.locator("ul > li")).to have_text(["Text 1", "Text 2", "Text"])
762
+
763
+ # ✖ Locator points to the outer list element, not to the list items
764
+ expect(page.locator("ul")).to have_text(["Text 1", "Text 2", "Text 3"])
765
+ ```
766
+
767
+ ## to_have_value
768
+
769
+ ```ruby
770
+ expect(locator).to have_value(value, timeout: nil)
771
+ ```
772
+
773
+
774
+ Ensures the [Locator](./locator) points to an element with the given input value. You can use regular expressions for the value as well.
775
+
776
+ **Usage**
777
+
778
+ ```ruby
779
+ locator = page.locator("input[type=number]")
780
+ expect(locator).to have_value(/^[0-9]$/)
781
+ ```
782
+
783
+ ## to_have_values
784
+
785
+ ```ruby
786
+ expect(locator).to have_values(values, timeout: nil)
787
+ ```
788
+
789
+
790
+ Ensures the [Locator](./locator) points to multi-select/combobox (i.e. a `select` with the `multiple` attribute) and the specified values are selected.
791
+
792
+ **Usage**
793
+
794
+ For example, given the following element:
795
+
796
+ ```html
797
+ <select id="favorite-colors" multiple>
798
+ <option value="R">Red</option>
799
+ <option value="G">Green</option>
800
+ <option value="B">Blue</option>
801
+ </select>
802
+ ```
803
+
804
+ ```ruby
805
+ locator = page.locator("id=favorite-colors")
806
+ locator.select_option(["R", "G"])
807
+ expect(locator).to have_values([/R/, /G/])
808
+ ```
809
+
810
+ ## to_match_aria_snapshot
811
+
812
+ ```ruby
813
+ expect(locator).to match_aria_snapshot(expected, timeout: nil)
814
+ ```
815
+
816
+
817
+ Asserts that the target element matches the given [accessibility snapshot](https://playwright.dev/python/docs/aria-snapshots).
818
+
819
+ **Usage**
820
+
821
+ ```ruby
822
+ page.goto('https://demo.playwright.dev/todomvc/')
823
+ expect(page.locator('body')).to match_aria_snapshot(<<~YAML)
824
+ - heading "todos"
825
+ - textbox "What needs to be done?"
826
+ YAML
827
+ ```