playwright-ruby-client 0.8.0 → 1.14.beta2

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/documentation/docs/api/accessibility.md +52 -1
  3. data/documentation/docs/api/browser.md +8 -2
  4. data/documentation/docs/api/browser_context.md +28 -0
  5. data/documentation/docs/api/browser_type.md +1 -0
  6. data/documentation/docs/api/download.md +97 -0
  7. data/documentation/docs/api/element_handle.md +28 -3
  8. data/documentation/docs/api/experimental/android_device.md +1 -0
  9. data/documentation/docs/api/frame.md +78 -18
  10. data/documentation/docs/api/keyboard.md +11 -20
  11. data/documentation/docs/api/locator.md +650 -0
  12. data/documentation/docs/api/page.md +124 -20
  13. data/documentation/docs/api/touchscreen.md +8 -0
  14. data/documentation/docs/api/worker.md +37 -0
  15. data/documentation/docs/article/guides/inspector.md +31 -0
  16. data/documentation/docs/article/guides/playwright_on_alpine_linux.md +91 -0
  17. data/documentation/docs/article/guides/semi_automation.md +5 -1
  18. data/documentation/docs/include/api_coverage.md +72 -15
  19. data/lib/playwright.rb +0 -1
  20. data/lib/playwright/accessibility_impl.rb +50 -0
  21. data/lib/playwright/channel_owners/artifact.rb +4 -0
  22. data/lib/playwright/channel_owners/browser_context.rb +77 -3
  23. data/lib/playwright/channel_owners/frame.rb +101 -35
  24. data/lib/playwright/channel_owners/page.rb +157 -56
  25. data/lib/playwright/channel_owners/worker.rb +23 -0
  26. data/lib/playwright/{download.rb → download_impl.rb} +5 -1
  27. data/lib/playwright/javascript/expression.rb +5 -4
  28. data/lib/playwright/locator_impl.rb +314 -0
  29. data/lib/playwright/route_handler_entry.rb +3 -2
  30. data/lib/playwright/timeout_settings.rb +4 -4
  31. data/lib/playwright/touchscreen_impl.rb +7 -0
  32. data/lib/playwright/tracing_impl.rb +9 -8
  33. data/lib/playwright/url_matcher.rb +12 -2
  34. data/lib/playwright/version.rb +2 -2
  35. data/lib/playwright_api/accessibility.rb +1 -1
  36. data/lib/playwright_api/android.rb +6 -6
  37. data/lib/playwright_api/android_device.rb +8 -7
  38. data/lib/playwright_api/browser.rb +16 -10
  39. data/lib/playwright_api/browser_context.rb +16 -11
  40. data/lib/playwright_api/browser_type.rb +8 -7
  41. data/lib/playwright_api/cdp_session.rb +6 -6
  42. data/lib/playwright_api/console_message.rb +6 -6
  43. data/lib/playwright_api/dialog.rb +6 -6
  44. data/lib/playwright_api/download.rb +70 -0
  45. data/lib/playwright_api/element_handle.rb +34 -20
  46. data/lib/playwright_api/frame.rb +94 -52
  47. data/lib/playwright_api/js_handle.rb +6 -6
  48. data/lib/playwright_api/locator.rb +509 -0
  49. data/lib/playwright_api/page.rb +101 -57
  50. data/lib/playwright_api/playwright.rb +6 -6
  51. data/lib/playwright_api/request.rb +6 -6
  52. data/lib/playwright_api/response.rb +6 -6
  53. data/lib/playwright_api/route.rb +6 -11
  54. data/lib/playwright_api/selectors.rb +6 -6
  55. data/lib/playwright_api/touchscreen.rb +1 -1
  56. data/lib/playwright_api/web_socket.rb +6 -6
  57. data/lib/playwright_api/worker.rb +16 -6
  58. metadata +14 -6
@@ -1,4 +1,27 @@
1
1
  module Playwright
2
2
  define_channel_owner :Worker do
3
+ attr_writer :context, :page
4
+
5
+ private def after_initialize
6
+ @channel.once('close', ->(_) { on_close })
7
+ end
8
+
9
+ private def on_close
10
+ @page&.send(:remove_worker, self)
11
+ @context&.send(:remove_service_worker, self)
12
+ emit(Events::Worker::Close, self)
13
+ end
14
+
15
+ def url
16
+ @initializer['url']
17
+ end
18
+
19
+ def evaluate(expression, arg: nil)
20
+ JavaScript::Expression.new(expression, arg).evaluate(@channel)
21
+ end
22
+
23
+ def evaluate_handle(expression, arg: nil)
24
+ JavaScript::Expression.new(expression, arg).evaluate_handle(@channel)
25
+ end
3
26
  end
4
27
  end
@@ -1,5 +1,5 @@
1
1
  module Playwright
2
- class Download
2
+ define_api_implementation :DownloadImpl do
3
3
  def initialize(page:, url:, suggested_filename:, artifact:)
4
4
  @page = page
5
5
  @url = url
@@ -24,5 +24,9 @@ module Playwright
24
24
  def save_as(path)
25
25
  @artifact.save_as(path)
26
26
  end
27
+
28
+ def cancel
29
+ @artifact.cancel
30
+ end
27
31
  end
28
32
  end
@@ -24,13 +24,14 @@ module Playwright
24
24
  ::Playwright::ChannelOwner.from(resp)
25
25
  end
26
26
 
27
- def eval_on_selector(channel, selector)
28
- value = channel.send_message_to_server(
29
- 'evalOnSelector',
27
+ def eval_on_selector(channel, selector, strict: nil)
28
+ params = {
30
29
  selector: selector,
31
30
  expression: @expression,
32
31
  arg: @serialized_arg,
33
- )
32
+ }
33
+ params[:strict] = strict if strict
34
+ value = channel.send_message_to_server('evalOnSelector', params)
34
35
  ValueParser.new(value).parse
35
36
  end
36
37
 
@@ -0,0 +1,314 @@
1
+ module Playwright
2
+ define_api_implementation :LocatorImpl do
3
+ def initialize(frame:, timeout_settings:, selector:)
4
+ @frame = frame
5
+ @timeout_settings = timeout_settings
6
+ @selector = selector
7
+ end
8
+
9
+ def to_s
10
+ "Locator@#{@selector}"
11
+ end
12
+
13
+ private def with_element(timeout: nil, &block)
14
+ start_time = Time.now
15
+
16
+ handle = @frame.wait_for_selector(@selector, strict: true, state: 'attached', timeout: timeout)
17
+ unless handle
18
+ raise "Could not resolve #{@selector} to DOM Element"
19
+ end
20
+
21
+ call_options = {}
22
+ if timeout
23
+ call_options[:timeout] = (timeout - (Time.now - start_time) * 1000).to_i
24
+ end
25
+
26
+ begin
27
+ block.call(handle, call_options)
28
+ ensure
29
+ handle.dispose
30
+ end
31
+ end
32
+
33
+ def bounding_box(timeout: nil)
34
+ with_element(timeout: timeout) do |handle|
35
+ handle.bounding_box
36
+ end
37
+ end
38
+
39
+ def check(
40
+ force: nil,
41
+ noWaitAfter: nil,
42
+ position: nil,
43
+ timeout: nil,
44
+ trial: nil)
45
+
46
+ @frame.check(@selector,
47
+ strict: true,
48
+ force: force,
49
+ noWaitAfter: noWaitAfter,
50
+ position: position,
51
+ timeout: timeout,
52
+ trial: trial)
53
+ end
54
+
55
+ def click(
56
+ button: nil,
57
+ clickCount: nil,
58
+ delay: nil,
59
+ force: nil,
60
+ modifiers: nil,
61
+ noWaitAfter: nil,
62
+ position: nil,
63
+ timeout: nil,
64
+ trial: nil)
65
+
66
+ @frame.click(@selector,
67
+ strict: true,
68
+ button: button,
69
+ clickCount: clickCount,
70
+ delay: delay,
71
+ force: force,
72
+ modifiers: modifiers,
73
+ noWaitAfter: noWaitAfter,
74
+ position: position,
75
+ timeout: timeout,
76
+ trial: trial)
77
+ end
78
+
79
+ def dblclick(
80
+ button: nil,
81
+ delay: nil,
82
+ force: nil,
83
+ modifiers: nil,
84
+ noWaitAfter: nil,
85
+ position: nil,
86
+ timeout: nil,
87
+ trial: nil)
88
+
89
+ @frame.dblclick(@selector,
90
+ strict: true,
91
+ button: button,
92
+ delay: delay,
93
+ force: force,
94
+ modifiers: modifiers,
95
+ noWaitAfter: noWaitAfter,
96
+ position: position,
97
+ timeout: timeout,
98
+ trial: trial)
99
+ end
100
+
101
+ def dispatch_event(type, eventInit: nil, timeout: nil)
102
+ @frame.dispatch_event(@selector, type, strict: true, eventInit: eventInit, timeout: timeout)
103
+ end
104
+
105
+ def evaluate(expression, arg: nil, timeout: nil)
106
+ with_element(timeout: timeout) do |handle|
107
+ handle.evaluate(expression, arg: arg)
108
+ end
109
+ end
110
+
111
+ def evaluate_all(expression, arg: nil)
112
+ @frame.eval_on_selector_all(@selector, expression, arg: arg)
113
+ end
114
+
115
+ def evaluate_handle(expression, arg: nil, timeout: nil)
116
+ with_element(timeout: timeout) do |handle|
117
+ handle.evaluate_handle(expression, arg: arg)
118
+ end
119
+ end
120
+
121
+ def fill(value, force: nil, noWaitAfter: nil, timeout: nil)
122
+ @frame.fill(@selector, value, strict: true, force: force, noWaitAfter: noWaitAfter, timeout: timeout)
123
+ end
124
+
125
+ def locator(selector)
126
+ LocatorImpl.new(
127
+ frame: @frame,
128
+ timeout_settings: @timeout_settings,
129
+ selector: "#{@selector} >> #{selector}",
130
+ )
131
+ end
132
+
133
+ def element_handle(timeout: nil)
134
+ @frame.wait_for_selector(@selector, strict: true, state: 'attached', timeout: timeout)
135
+ end
136
+
137
+ def element_handles
138
+ @frame.query_selector_all(@selector)
139
+ end
140
+
141
+ def first
142
+ LocatorImpl.new(
143
+ frame: @frame,
144
+ timeout_settings: @timeout_settings,
145
+ selector: "#{@selector} >> _nth=first",
146
+ )
147
+ end
148
+
149
+ def last
150
+ LocatorImpl.new(
151
+ frame: @frame,
152
+ timeout_settings: @timeout_settings,
153
+ selector: "#{@selector} >> _nth=last",
154
+ )
155
+ end
156
+
157
+ def nth(index)
158
+ LocatorImpl.new(
159
+ frame: @frame,
160
+ timeout_settings: @timeout_settings,
161
+ selector: "#{@selector} >> _nth=#{index}",
162
+ )
163
+ end
164
+
165
+ def focus(timeout: nil)
166
+ @frame.focus(@selector, strict: true, timeout: timeout)
167
+ end
168
+
169
+ def count
170
+ @frame.eval_on_selector_all(@selector, 'ee => ee.length')
171
+ end
172
+
173
+ def get_attribute(name, timeout: nil)
174
+ @frame.get_attribute(@selector, name, strict: true, timeout: timeout)
175
+ end
176
+
177
+ def hover(
178
+ force: nil,
179
+ modifiers: nil,
180
+ position: nil,
181
+ timeout: nil,
182
+ trial: nil)
183
+ @frame.hover(@selector,
184
+ strict: true,
185
+ force: force,
186
+ modifiers: modifiers,
187
+ position: position,
188
+ timeout: timeout,
189
+ trial: trial)
190
+ end
191
+
192
+ def inner_html(timeout: nil)
193
+ @frame.inner_html(@selector, strict: true, timeout: timeout)
194
+ end
195
+
196
+ def inner_text(timeout: nil)
197
+ @frame.inner_text(@selector, strict: true, timeout: timeout)
198
+ end
199
+
200
+ def input_value(timeout: nil)
201
+ @frame.input_value(@selector, strict: true, timeout: timeout)
202
+ end
203
+
204
+ %i[checked? disabled? editable? enabled? hidden? visible?].each do |method_name|
205
+ define_method(method_name) do |timeout: nil|
206
+ @frame.public_send(method_name, @selector, strict: true, timeout: timeout)
207
+ end
208
+ end
209
+
210
+ def press(key, delay: nil, noWaitAfter: nil, timeout: nil)
211
+ @frame.press(@selector, key, strict: true, noWaitAfter: noWaitAfter, timeout: timeout)
212
+ end
213
+
214
+ def screenshot(
215
+ omitBackground: nil,
216
+ path: nil,
217
+ quality: nil,
218
+ timeout: nil,
219
+ type: nil)
220
+ with_element(timeout: timeout) do |handle, options|
221
+ handle.screenshot(
222
+ omitBackground: omitBackground,
223
+ path: path,
224
+ quality: quality,
225
+ timeout: options[:timeout],
226
+ type: type)
227
+ end
228
+ end
229
+
230
+ def scroll_into_view_if_needed(timeout: nil)
231
+ with_element(timeout: timeout) do |handle, options|
232
+ handle.scroll_into_view_if_needed(timeout: options[:timeout])
233
+ end
234
+ end
235
+
236
+ def select_option(
237
+ element: nil,
238
+ index: nil,
239
+ value: nil,
240
+ label: nil,
241
+ force: nil,
242
+ noWaitAfter: nil,
243
+ timeout: nil)
244
+
245
+ @frame.select_option(@selector,
246
+ strict: true,
247
+ element: element,
248
+ index: index,
249
+ value: value,
250
+ label: label,
251
+ force: force,
252
+ noWaitAfter: noWaitAfter,
253
+ timeout: timeout)
254
+ end
255
+
256
+ def select_text(force: nil, timeout: nil)
257
+ with_element(timeout: timeout) do |handle, options|
258
+ handle.select_text(force: force, timeout: options[:timeout])
259
+ end
260
+ end
261
+
262
+ def set_input_files(files, noWaitAfter: nil, timeout: nil)
263
+ @frame.set_input_files(@selector, files, strict: true, noWaitAfter: noWaitAfter, timeout: timeout)
264
+ end
265
+
266
+ def tap_point(
267
+ force: nil,
268
+ modifiers: nil,
269
+ noWaitAfter: nil,
270
+ position: nil,
271
+ timeout: nil,
272
+ trial: nil)
273
+ @frame.tap_point(@selector,
274
+ strict: true,
275
+ force: force,
276
+ modifiers: modifiers,
277
+ noWaitAfter: noWaitAfter,
278
+ position: position,
279
+ timeout: timeout,
280
+ trial: trial)
281
+ end
282
+
283
+ def text_content(timeout: nil)
284
+ @frame.text_content(@selector, strict: true, timeout: timeout)
285
+ end
286
+
287
+ def type(text, delay: nil, noWaitAfter: nil, timeout: nil)
288
+ @frame.type(@selector, text, strict: true, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout)
289
+ end
290
+
291
+ def uncheck(
292
+ force: nil,
293
+ noWaitAfter: nil,
294
+ position: nil,
295
+ timeout: nil,
296
+ trial: nil)
297
+ @frame.uncheck(@selector,
298
+ strict: true,
299
+ force: force,
300
+ noWaitAfter: noWaitAfter,
301
+ position: position,
302
+ timeout: timeout,
303
+ trial: trial)
304
+ end
305
+
306
+ def all_inner_texts
307
+ @frame.eval_on_selector_all(@selector, 'ee => ee.map(e => e.innerText)')
308
+ end
309
+
310
+ def all_text_contents
311
+ @frame.eval_on_selector_all(@selector, "ee => ee.map(e => e.textContent || '')")
312
+ end
313
+ end
314
+ end
@@ -1,10 +1,11 @@
1
1
  module Playwright
2
2
  class RouteHandlerEntry
3
3
  # @param url [String]
4
+ # @param base_url [String|nil]
4
5
  # @param handler [Proc]
5
- def initialize(url, handler)
6
+ def initialize(url, base_url, handler)
6
7
  @url_value = url
7
- @url_matcher = UrlMatcher.new(url)
8
+ @url_matcher = UrlMatcher.new(url, base_url: base_url)
8
9
  @handler = handler
9
10
  end
10
11
 
@@ -8,12 +8,12 @@ module Playwright
8
8
 
9
9
  attr_writer :default_timeout, :default_navigation_timeout
10
10
 
11
- def navigation_timeout
12
- @default_navigation_timeout || @default_timeout || @parent&.navigation_timeout || DEFAULT_TIMEOUT
11
+ def navigation_timeout(timeout_override = nil)
12
+ timeout_override || @default_navigation_timeout || @default_timeout || @parent&.navigation_timeout || DEFAULT_TIMEOUT
13
13
  end
14
14
 
15
- def timeout
16
- @default_timeout || @parent&.timeout || DEFAULT_TIMEOUT
15
+ def timeout(timeout_override = nil)
16
+ timeout_override || @default_timeout || @parent&.timeout || DEFAULT_TIMEOUT
17
17
  end
18
18
  end
19
19
  end
@@ -3,5 +3,12 @@ module Playwright
3
3
  def initialize(channel)
4
4
  @channel = channel
5
5
  end
6
+
7
+ def tap_point(x, y)
8
+ @channel.send_message_to_server('touchscreenTap', {
9
+ x: x,
10
+ y: y,
11
+ })
12
+ end
6
13
  end
7
14
  end
@@ -16,16 +16,17 @@ module Playwright
16
16
 
17
17
  # Stop tracing.
18
18
  def stop(path: nil)
19
+ export(path: path) if path
19
20
  @channel.send_message_to_server('tracingStop')
21
+ end
20
22
 
21
- if path
22
- resp = @channel.send_message_to_server('tracingExport')
23
- artifact = ChannelOwners::Artifact.from(resp)
24
- # if self._context._browser:
25
- # artifact._is_remote = self._context._browser._is_remote
26
- artifact.save_as(path)
27
- artifact.delete
28
- end
23
+ private def export(path:)
24
+ resp = @channel.send_message_to_server('tracingExport')
25
+ artifact = ChannelOwners::Artifact.from(resp)
26
+ # if self._context._browser:
27
+ # artifact._is_remote = self._context._browser._is_remote
28
+ artifact.save_as(path)
29
+ artifact.delete
29
30
  end
30
31
  end
31
32
  end