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,571 @@
1
+ module Playwright
2
+ # ref: https://github.com/microsoft/playwright-python/blob/main/playwright/_impl/_assertions.py
3
+ define_api_implementation :LocatorAssertionsImpl do
4
+ def self._define_negation(method_name)
5
+ define_method("not_#{method_name}") do |*args, **kwargs|
6
+ if kwargs.empty? # for Ruby < 2.7
7
+ _not.public_send(method_name, *args)
8
+ else
9
+ _not.public_send(method_name, *args, **kwargs)
10
+ end
11
+ end
12
+ end
13
+
14
+ def initialize(locator, default_expect_timeout, is_not, message)
15
+ @locator = locator
16
+ @default_expect_timeout = default_expect_timeout
17
+ @is_not = is_not
18
+ @custom_message = message
19
+ end
20
+
21
+ private def expect_impl(expression, expect_options, expected, message, title)
22
+ expect_options[:timeout] ||= @default_expect_timeout
23
+ expect_options[:isNot] = @is_not
24
+ message = message.gsub("expected to", "not expected to") if @is_not
25
+ expect_options.delete(:useInnerText) if expect_options.key?(:useInnerText) && expect_options[:useInnerText].nil?
26
+
27
+ result = @locator.expect(expression, expect_options, title)
28
+
29
+ if result["matches"] == @is_not
30
+ actual = result["received"]
31
+
32
+ log =
33
+ if result.key?("log")
34
+ log_contents = result["log"].join("\n").strip
35
+
36
+ "\nCall log:\n #{log_contents}"
37
+ else
38
+ ""
39
+ end
40
+
41
+ out_message =
42
+ if @custom_message && expected
43
+ "\nExpected value: '#{expected}'"
44
+ elsif @custom_message
45
+ @custom_message
46
+ elsif message != "" && expected
47
+ "\n#{message} '#{expected}'"
48
+ else
49
+ "\n#{message}"
50
+ end
51
+
52
+ if result['errorMessage']
53
+ error_message = "\n#{result['errorMessage']}"
54
+ end
55
+ out = "#{out_message}\nActual value #{actual}#{error_message} #{log}"
56
+ raise AssertionError.new(out)
57
+ else
58
+ true
59
+ end
60
+ end
61
+
62
+ private def _not # "not" is reserved in Ruby
63
+ LocatorAssertionsImpl.new(
64
+ @locator,
65
+ @default_expect_timeout,
66
+ !@is_not,
67
+ @message
68
+ )
69
+ end
70
+
71
+ private def expected_regex(pattern, match_substring, normalize_white_space, ignore_case)
72
+ regex = JavaScript::Regex.new(pattern)
73
+ expected = {
74
+ regexSource: regex.source,
75
+ regexFlags: regex.flag,
76
+ matchSubstring: match_substring,
77
+ normalizeWhiteSpace: normalize_white_space,
78
+ ignoreCase: ignore_case
79
+ }
80
+ expected.delete(:ignoreCase) if ignore_case.nil?
81
+
82
+ expected
83
+ end
84
+
85
+ private def to_expected_text_values(items, match_substring: false, normalize_white_space: false, ignore_case: false)
86
+ return [] unless items.respond_to?(:each)
87
+
88
+ items.each.with_object([]) do |item, out|
89
+ out <<
90
+ if item.is_a?(String) && ignore_case
91
+ {
92
+ string: item,
93
+ matchSubstring: match_substring,
94
+ normalizeWhiteSpace: normalize_white_space,
95
+ ignoreCase: ignore_case,
96
+ }
97
+ elsif item.is_a?(String)
98
+ {
99
+ string: item,
100
+ matchSubstring: match_substring,
101
+ normalizeWhiteSpace: normalize_white_space,
102
+ }
103
+ elsif item.is_a?(Regexp)
104
+ expected_regex(item, match_substring, normalize_white_space, ignore_case)
105
+ else
106
+ raise ArgumentError.new("Expected value provided to assertion to be a string or regex, got #{item.class}")
107
+ end
108
+ end
109
+ end
110
+
111
+ def to_contain_text(expected, ignoreCase: nil, timeout: nil, useInnerText: nil)
112
+ useInnerText = false if useInnerText.nil?
113
+
114
+ if expected.respond_to?(:each)
115
+ expected_text = to_expected_text_values(
116
+ expected,
117
+ match_substring: true,
118
+ normalize_white_space: true,
119
+ ignore_case: ignoreCase,
120
+ )
121
+
122
+ expect_impl(
123
+ "to.contain.text.array",
124
+ {
125
+ expectedText: expected_text,
126
+ useInnerText: useInnerText,
127
+ timeout: timeout,
128
+ },
129
+ expected,
130
+ "Locator expected to contain text",
131
+ 'Expect "to_contain_text"',
132
+ )
133
+ else
134
+ expected_text = to_expected_text_values(
135
+ [expected],
136
+ match_substring: true,
137
+ normalize_white_space: true,
138
+ ignore_case: ignoreCase,
139
+ )
140
+
141
+ expect_impl(
142
+ "to.have.text",
143
+ {
144
+ expectedText: expected_text,
145
+ useInnerText: useInnerText,
146
+ timeout: timeout,
147
+ },
148
+ expected,
149
+ "Locator expected to contain text",
150
+ 'Expect "to_contain_text"',
151
+ )
152
+ end
153
+ end
154
+ _define_negation :to_contain_text
155
+
156
+ def to_have_accessible_name(name, ignoreCase: nil, timeout: nil)
157
+ expected_text = to_expected_text_values([name], ignore_case: ignoreCase, normalize_white_space: true)
158
+ expect_impl(
159
+ "to.have.accessible.name",
160
+ {
161
+ expectedText: expected_text,
162
+ timeout: timeout,
163
+ },
164
+ name,
165
+ "Locator expected to have accessible name",
166
+ 'Expect "to_have_accessible_name"',
167
+ )
168
+ end
169
+ _define_negation :to_have_accessible_name
170
+
171
+ def to_have_accessible_description(name, ignoreCase: nil, timeout: nil)
172
+ expected_text = to_expected_text_values([name], ignore_case: ignoreCase, normalize_white_space: true)
173
+ expect_impl(
174
+ "to.have.accessible.description",
175
+ {
176
+ expectedText: expected_text,
177
+ timeout: timeout,
178
+ },
179
+ name,
180
+ "Locator expected to have accessible description",
181
+ 'Expect "to_have_accessible_description"',
182
+ )
183
+ end
184
+ _define_negation :to_have_accessible_description
185
+
186
+ def to_have_accessible_error_message(errorMessage, ignoreCase: nil, timeout: nil)
187
+ expected_text = to_expected_text_values([errorMessage], ignore_case: ignoreCase, normalize_white_space: true)
188
+ expect_impl(
189
+ "to.have.accessible.error.message",
190
+ {
191
+ expectedText: expected_text,
192
+ timeout: timeout,
193
+ },
194
+ errorMessage,
195
+ "Locator expected to have accessible error message",
196
+ 'Expect "to_have_accessible_error_message"',
197
+ )
198
+ end
199
+ _define_negation :to_have_accessible_error_message
200
+
201
+ def to_have_attribute(name, value, ignoreCase: nil, timeout: nil)
202
+ expected_text = to_expected_text_values([value], ignore_case: ignoreCase)
203
+ expect_impl(
204
+ "to.have.attribute.value",
205
+ {
206
+ expressionArg: name,
207
+ expectedText: expected_text,
208
+ timeout: timeout,
209
+ },
210
+ value,
211
+ "Locator expected to have attribute",
212
+ 'Expect "to_have_attribute"',
213
+ )
214
+ end
215
+ _define_negation :to_have_attribute
216
+
217
+ def to_have_class(expected, timeout: nil)
218
+ if expected.respond_to?(:each)
219
+ expected_text = to_expected_text_values(expected)
220
+ expect_impl(
221
+ "to.have.class.array",
222
+ {
223
+ expectedText: expected_text,
224
+ timeout: timeout,
225
+ },
226
+ expected,
227
+ "Locator expected to have class",
228
+ 'Expect "to_have_class"',
229
+ )
230
+ else
231
+ expected_text = to_expected_text_values([expected])
232
+ expect_impl(
233
+ "to.have.class",
234
+ {
235
+ expectedText: expected_text,
236
+ timeout: timeout,
237
+ },
238
+ expected,
239
+ "Locator expected to have class",
240
+ 'Expect "to_have_class"',
241
+ )
242
+ end
243
+ end
244
+ _define_negation :to_have_class
245
+
246
+ def to_contain_class(expected, timeout: nil)
247
+ if expected.is_a?(Enumerable)
248
+ if expected.any? { |e| e.is_a?(Regexp) }
249
+ raise ArgumentError.new('"expected" argument in toContainClass cannot contain RegExp values')
250
+ end
251
+ expected_text = to_expected_text_values(expected)
252
+ expect_impl(
253
+ "to.contain.class.array",
254
+ {
255
+ expectedText: expected_text,
256
+ timeout: timeout,
257
+ },
258
+ expected,
259
+ "Locator expected to contain class names",
260
+ 'Expect "to_contain_class"',
261
+ )
262
+ else # Single string
263
+ if expected.is_a?(Regexp)
264
+ raise ArgumentError.new('"expected" argument in toContainClass cannot be a RegExp value')
265
+ end
266
+ expected_text = to_expected_text_values([expected])
267
+ expect_impl(
268
+ "to.contain.class",
269
+ {
270
+ expectedText: expected_text,
271
+ timeout: timeout,
272
+ },
273
+ expected,
274
+ "Locator expected to contain class",
275
+ 'Expect "to_contain_class"',
276
+ )
277
+ end
278
+ end
279
+ _define_negation :to_contain_class
280
+
281
+ def to_have_count(count, timeout: nil)
282
+ expect_impl(
283
+ "to.have.count",
284
+ {
285
+ expectedNumber: count,
286
+ timeout: timeout,
287
+ },
288
+ count,
289
+ "Locator expected to have count",
290
+ 'Expect "to_have_count"',
291
+ )
292
+ end
293
+ _define_negation :to_have_count
294
+
295
+ def to_have_css(name, value, timeout: nil)
296
+ expected_text = to_expected_text_values([value])
297
+ expect_impl(
298
+ "to.have.css",
299
+ {
300
+ expressionArg: name,
301
+ expectedText: expected_text,
302
+ timeout: timeout,
303
+ },
304
+ value,
305
+ "Locator expected to have CSS",
306
+ 'Expect "to_have_css"',
307
+ )
308
+ end
309
+ _define_negation :to_have_css
310
+
311
+ def to_have_id(id, timeout: nil)
312
+ expected_text = to_expected_text_values([id])
313
+ expect_impl(
314
+ "to.have.id",
315
+ {
316
+ expectedText: expected_text,
317
+ timeout: timeout,
318
+ },
319
+ id,
320
+ "Locator expected to have ID",
321
+ 'Expect "to_have_id"',
322
+ )
323
+ end
324
+ _define_negation :to_have_id
325
+
326
+ def to_have_js_property(name, value, timeout: nil)
327
+ expect_impl(
328
+ "to.have.property",
329
+ {
330
+ expressionArg: name,
331
+ expectedValue: value,
332
+ timeout: timeout,
333
+ },
334
+ value,
335
+ "Locator expected to have JS Property",
336
+ 'Expect "to_have_js_property"',
337
+ )
338
+ end
339
+ _define_negation :to_have_js_property
340
+
341
+ def to_have_role(role, timeout: nil)
342
+ if role.is_a?(Regexp)
343
+ raise ArgumentError.new('"role" argument in to_have_role must be a string')
344
+ end
345
+
346
+ expected_text = to_expected_text_values([role])
347
+ expect_impl(
348
+ "to.have.role",
349
+ {
350
+ expectedText: expected_text,
351
+ timeout: timeout,
352
+ },
353
+ role,
354
+ "Locator expected to have accessible role",
355
+ 'Expect "to_have_role"',
356
+ )
357
+ end
358
+ _define_negation :to_have_role
359
+
360
+ def to_have_value(value, timeout: nil)
361
+ expected_text = to_expected_text_values([value])
362
+
363
+ expect_impl(
364
+ "to.have.value",
365
+ {
366
+ expectedText: expected_text,
367
+ timeout: timeout,
368
+ },
369
+ value,
370
+ "Locator expected to have Value",
371
+ 'Expect "to_have_value"',
372
+ )
373
+ end
374
+ _define_negation :to_have_value
375
+
376
+ def to_have_values(values, timeout: nil)
377
+ expected_text = to_expected_text_values(values)
378
+
379
+ expect_impl(
380
+ "to.have.values",
381
+ {
382
+ expectedText: expected_text,
383
+ timeout: timeout,
384
+ },
385
+ values,
386
+ "Locator expected to have Values",
387
+ 'Expect "to_have_values"',
388
+ )
389
+ end
390
+ _define_negation :to_have_values
391
+
392
+ def to_have_text(expected, ignoreCase: nil, timeout: nil, useInnerText: nil)
393
+ if expected.respond_to?(:each)
394
+ expected_text = to_expected_text_values(
395
+ expected,
396
+ match_substring: true,
397
+ normalize_white_space: true,
398
+ ignore_case: ignoreCase,
399
+ )
400
+ expect_impl(
401
+ "to.have.text.array",
402
+ {
403
+ expectedText: expected_text,
404
+ useInnerText: useInnerText,
405
+ timeout: timeout,
406
+ },
407
+ expected,
408
+ "Locator expected to have text",
409
+ 'Expect "to_have_text"',
410
+ )
411
+ else
412
+ expected_text = to_expected_text_values(
413
+ [expected],
414
+ match_substring: true,
415
+ normalize_white_space: true,
416
+ ignore_case: ignoreCase,
417
+ )
418
+ expect_impl(
419
+ "to.have.text",
420
+ {
421
+ expectedText: expected_text,
422
+ useInnerText: useInnerText,
423
+ timeout: timeout,
424
+ },
425
+ expected,
426
+ "Locator expected to have text",
427
+ 'Expect "to_have_text"',
428
+ )
429
+ end
430
+ end
431
+ _define_negation :to_have_text
432
+
433
+ def to_match_aria_snapshot(expected, timeout: nil)
434
+ expect_impl(
435
+ 'to.match.aria',
436
+ {
437
+ expectedValue: expected,
438
+ timeout: timeout,
439
+ },
440
+ expected,
441
+ 'Locator expected to match Aria snapshot',
442
+ 'Expect "to_match_aria_snapshot"',
443
+ )
444
+ end
445
+ _define_negation :to_match_aria_snapshot
446
+
447
+ def to_be_attached(attached: nil, timeout: nil)
448
+ expect_impl(
449
+ (attached || attached.nil?) ? "to.be.attached" : "to.be.detached",
450
+ { timeout: timeout },
451
+ nil,
452
+ "Locator expected to be attached",
453
+ 'Expect "to_be_attached"',
454
+ )
455
+ end
456
+ _define_negation :to_be_attached
457
+
458
+ def to_be_checked(checked: nil, indeterminate: nil, timeout: nil)
459
+ expected_value = {
460
+ indeterminate: indeterminate,
461
+ checked: checked,
462
+ }.compact
463
+ checked_string =
464
+ if indeterminate
465
+ "indeterminate"
466
+ elsif checked
467
+ "checked"
468
+ else
469
+ "unchecked"
470
+ end
471
+
472
+ expect_impl(
473
+ "to.be.checked",
474
+ { timeout: timeout, expectedValue: expected_value },
475
+ nil,
476
+ "Locator expected to be checked",
477
+ 'Expect "to_be_checked"',
478
+ )
479
+ end
480
+ _define_negation :to_be_checked
481
+
482
+ def to_be_disabled(timeout: nil)
483
+ expect_impl(
484
+ "to.be.disabled",
485
+ { timeout: timeout },
486
+ nil,
487
+ "Locator expected to be disabled",
488
+ 'Expect "to_be_disabled"',
489
+ )
490
+ end
491
+ _define_negation :to_be_disabled
492
+
493
+ def to_be_editable(editable: nil, timeout: nil)
494
+ expect_impl(
495
+ (editable || editable.nil?) ? "to.be.editable" : "to.be.readonly",
496
+ { timeout: timeout },
497
+ nil,
498
+ "Locator expected to be editable",
499
+ 'Expect "to_be_editable"',
500
+ )
501
+ end
502
+ _define_negation :to_be_editable
503
+
504
+ def to_be_empty(timeout: nil)
505
+ expect_impl(
506
+ "to.be.empty",
507
+ { timeout: timeout },
508
+ nil,
509
+ "Locator expected to be empty",
510
+ 'Expect "to_be_empty"',
511
+ )
512
+ end
513
+ _define_negation :to_be_empty
514
+
515
+ def to_be_enabled(enabled: nil, timeout: nil)
516
+ expect_impl(
517
+ (enabled || enabled.nil?) ? "to.be.enabled" : "to.be.disabled",
518
+ { timeout: timeout },
519
+ nil,
520
+ "Locator expected to be enabled",
521
+ 'Expect "to_be_enabled"',
522
+ )
523
+ end
524
+ _define_negation :to_be_enabled
525
+
526
+ def to_be_hidden(timeout: nil)
527
+ expect_impl(
528
+ "to.be.hidden",
529
+ { timeout: timeout },
530
+ nil,
531
+ "Locator expected to be hidden",
532
+ 'Expect "to_be_hidden"',
533
+ )
534
+ end
535
+ _define_negation :to_be_hidden
536
+
537
+ def to_be_visible(timeout: nil, visible: nil)
538
+ expect_impl(
539
+ (visible || visible.nil?) ? "to.be.visible" : "to.be.hidden",
540
+ { timeout: timeout },
541
+ nil,
542
+ "Locator expected to be visible",
543
+ 'Expect "to_be_visible"',
544
+ )
545
+ end
546
+ _define_negation :to_be_visible
547
+
548
+ def to_be_focused(timeout: nil)
549
+ expect_impl(
550
+ "to.be.focused",
551
+ { timeout: timeout },
552
+ nil,
553
+ "Locator expected to be focused",
554
+ 'Expect "to_be_focused"',
555
+ )
556
+ end
557
+ _define_negation :to_be_focused
558
+
559
+ def to_be_in_viewport(ratio: nil, timeout: nil)
560
+ expect_impl(
561
+ "to.be.in.viewport",
562
+ { timeout: timeout, expectedNumber: ratio }.compact,
563
+ nil,
564
+ "Locator expected to be in viewport",
565
+ 'Expect "to_be_in_viewport"',
566
+ )
567
+ end
568
+ _define_negation :to_be_in_viewport
569
+
570
+ end
571
+ end