playwright-ruby-client 0.0.7 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +38 -3
  3. data/docs/api_coverage.md +89 -84
  4. data/lib/playwright.rb +4 -2
  5. data/lib/playwright/android_input_impl.rb +23 -0
  6. data/lib/playwright/api_implementation.rb +18 -0
  7. data/lib/playwright/channel.rb +7 -0
  8. data/lib/playwright/channel_owner.rb +3 -5
  9. data/lib/playwright/channel_owners/android.rb +1 -1
  10. data/lib/playwright/channel_owners/android_device.rb +83 -13
  11. data/lib/playwright/channel_owners/browser.rb +1 -1
  12. data/lib/playwright/channel_owners/browser_context.rb +10 -2
  13. data/lib/playwright/channel_owners/download.rb +27 -0
  14. data/lib/playwright/channel_owners/element_handle.rb +15 -4
  15. data/lib/playwright/channel_owners/frame.rb +228 -19
  16. data/lib/playwright/channel_owners/js_handle.rb +1 -1
  17. data/lib/playwright/channel_owners/page.rb +350 -27
  18. data/lib/playwright/channel_owners/request.rb +9 -1
  19. data/lib/playwright/errors.rb +1 -1
  20. data/lib/playwright/event_emitter.rb +8 -1
  21. data/lib/playwright/event_emitter_proxy.rb +49 -0
  22. data/lib/playwright/file_chooser_impl.rb +23 -0
  23. data/lib/playwright/http_headers.rb +20 -0
  24. data/lib/playwright/input_files.rb +1 -1
  25. data/lib/playwright/javascript/expression.rb +15 -0
  26. data/lib/playwright/javascript/function.rb +15 -0
  27. data/lib/playwright/javascript/value_parser.rb +1 -1
  28. data/lib/playwright/javascript/value_serializer.rb +1 -1
  29. data/lib/playwright/{input_types/keyboard.rb → keyboard_impl.rb} +5 -1
  30. data/lib/playwright/mouse_impl.rb +7 -0
  31. data/lib/playwright/playwright_api.rb +59 -20
  32. data/lib/playwright/select_option_values.rb +14 -4
  33. data/lib/playwright/timeout_settings.rb +1 -1
  34. data/lib/playwright/touchscreen_impl.rb +7 -0
  35. data/lib/playwright/utils.rb +3 -3
  36. data/lib/playwright/version.rb +1 -1
  37. data/lib/playwright/wait_helper.rb +1 -1
  38. data/lib/playwright_api/android.rb +9 -10
  39. data/lib/playwright_api/android_device.rb +43 -14
  40. data/lib/playwright_api/android_input.rb +25 -0
  41. data/lib/playwright_api/binding_call.rb +10 -6
  42. data/lib/playwright_api/browser.rb +20 -21
  43. data/lib/playwright_api/browser_context.rb +29 -20
  44. data/lib/playwright_api/browser_type.rb +16 -56
  45. data/lib/playwright_api/chromium_browser_context.rb +10 -8
  46. data/lib/playwright_api/console_message.rb +10 -6
  47. data/lib/playwright_api/dialog.rb +5 -1
  48. data/lib/playwright_api/download.rb +28 -11
  49. data/lib/playwright_api/element_handle.rb +107 -96
  50. data/lib/playwright_api/file_chooser.rb +17 -9
  51. data/lib/playwright_api/frame.rb +136 -132
  52. data/lib/playwright_api/js_handle.rb +18 -20
  53. data/lib/playwright_api/keyboard.rb +5 -5
  54. data/lib/playwright_api/page.rb +204 -149
  55. data/lib/playwright_api/playwright.rb +32 -44
  56. data/lib/playwright_api/request.rb +7 -8
  57. data/lib/playwright_api/response.rb +10 -6
  58. data/lib/playwright_api/selectors.rb +13 -9
  59. data/lib/playwright_api/web_socket.rb +10 -1
  60. data/lib/playwright_api/worker.rb +13 -13
  61. metadata +12 -6
  62. data/lib/playwright/input_type.rb +0 -19
  63. data/lib/playwright/input_types/mouse.rb +0 -4
  64. data/lib/playwright/input_types/touchscreen.rb +0 -4
@@ -11,12 +11,10 @@ module Playwright
11
11
  # ```
12
12
  #
13
13
  # ```python async
14
- # # FIXME
15
14
  # background_page = await context.wait_for_event("backgroundpage")
16
15
  # ```
17
16
  #
18
17
  # ```python sync
19
- # # FIXME
20
18
  # background_page = context.wait_for_event("backgroundpage")
21
19
  # ```
22
20
  class ChromiumBrowserContext < BrowserContext
@@ -38,20 +36,24 @@ module Playwright
38
36
 
39
37
  # -- inherited from EventEmitter --
40
38
  # @nodoc
41
- def on(event, callback)
42
- wrap_impl(@impl.on(unwrap_impl(event), unwrap_impl(callback)))
39
+ def once(event, callback)
40
+ event_emitter_proxy.once(event, callback)
43
41
  end
44
42
 
45
43
  # -- inherited from EventEmitter --
46
44
  # @nodoc
47
- def off(event, callback)
48
- wrap_impl(@impl.off(unwrap_impl(event), unwrap_impl(callback)))
45
+ def on(event, callback)
46
+ event_emitter_proxy.on(event, callback)
49
47
  end
50
48
 
51
49
  # -- inherited from EventEmitter --
52
50
  # @nodoc
53
- def once(event, callback)
54
- wrap_impl(@impl.once(unwrap_impl(event), unwrap_impl(callback)))
51
+ def off(event, callback)
52
+ event_emitter_proxy.off(event, callback)
53
+ end
54
+
55
+ private def event_emitter_proxy
56
+ @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
55
57
  end
56
58
  end
57
59
  end
@@ -23,20 +23,24 @@ module Playwright
23
23
 
24
24
  # -- inherited from EventEmitter --
25
25
  # @nodoc
26
- def on(event, callback)
27
- wrap_impl(@impl.on(unwrap_impl(event), unwrap_impl(callback)))
26
+ def once(event, callback)
27
+ event_emitter_proxy.once(event, callback)
28
28
  end
29
29
 
30
30
  # -- inherited from EventEmitter --
31
31
  # @nodoc
32
- def off(event, callback)
33
- wrap_impl(@impl.off(unwrap_impl(event), unwrap_impl(callback)))
32
+ def on(event, callback)
33
+ event_emitter_proxy.on(event, callback)
34
34
  end
35
35
 
36
36
  # -- inherited from EventEmitter --
37
37
  # @nodoc
38
- def once(event, callback)
39
- wrap_impl(@impl.once(unwrap_impl(event), unwrap_impl(callback)))
38
+ def off(event, callback)
39
+ event_emitter_proxy.off(event, callback)
40
+ end
41
+
42
+ private def event_emitter_proxy
43
+ @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
40
44
  end
41
45
  end
42
46
  end
@@ -42,7 +42,6 @@ module Playwright
42
42
  # ```
43
43
  #
44
44
  # ```python sync
45
- # # FIXME
46
45
  # from playwright.sync_api import sync_playwright
47
46
  #
48
47
  # def handle_dialog(dialog):
@@ -60,6 +59,11 @@ module Playwright
60
59
  # with sync_playwright() as playwright:
61
60
  # run(playwright)
62
61
  # ```
62
+ #
63
+ # > NOTE: Dialogs are dismissed automatically, unless there is a [`event: Page.dialog`] listener. When listener is
64
+ # present, it **must** either [`method: Dialog.accept`] or [`method: Dialog.dismiss`] the dialog - otherwise the page will
65
+ # [freeze](https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#never_blocking) waiting for the dialog, and
66
+ # actions like click will never finish.
63
67
  class Dialog < PlaywrightApi
64
68
 
65
69
  # Returns when the dialog has been accepted.
@@ -37,29 +37,24 @@ module Playwright
37
37
  # performed and user has no access to the downloaded files.
38
38
  class Download < PlaywrightApi
39
39
 
40
- # Returns readable stream for current download or `null` if download failed.
41
- def create_read_stream
42
- raise NotImplementedError.new('create_read_stream is not implemented yet.')
43
- end
44
-
45
40
  # Deletes the downloaded file.
46
41
  def delete
47
- raise NotImplementedError.new('delete is not implemented yet.')
42
+ wrap_impl(@impl.delete)
48
43
  end
49
44
 
50
45
  # Returns download error if any.
51
46
  def failure
52
- raise NotImplementedError.new('failure is not implemented yet.')
47
+ wrap_impl(@impl.failure)
53
48
  end
54
49
 
55
50
  # Returns path to the downloaded file in case of successful download.
56
51
  def path
57
- raise NotImplementedError.new('path is not implemented yet.')
52
+ wrap_impl(@impl.path)
58
53
  end
59
54
 
60
55
  # Saves the download to a user-specified path.
61
56
  def save_as(path)
62
- raise NotImplementedError.new('save_as is not implemented yet.')
57
+ wrap_impl(@impl.save_as(unwrap_impl(path)))
63
58
  end
64
59
 
65
60
  # Returns suggested filename for this download. It is typically computed by the browser from the
@@ -67,12 +62,34 @@ module Playwright
67
62
  # or the `download` attribute. See the spec on [whatwg](https://html.spec.whatwg.org/#downloading-resources). Different
68
63
  # browsers can use different logic for computing it.
69
64
  def suggested_filename
70
- raise NotImplementedError.new('suggested_filename is not implemented yet.')
65
+ wrap_impl(@impl.suggested_filename)
71
66
  end
72
67
 
73
68
  # Returns downloaded url.
74
69
  def url
75
- raise NotImplementedError.new('url is not implemented yet.')
70
+ wrap_impl(@impl.url)
71
+ end
72
+
73
+ # -- inherited from EventEmitter --
74
+ # @nodoc
75
+ def once(event, callback)
76
+ event_emitter_proxy.once(event, callback)
77
+ end
78
+
79
+ # -- inherited from EventEmitter --
80
+ # @nodoc
81
+ def on(event, callback)
82
+ event_emitter_proxy.on(event, callback)
83
+ end
84
+
85
+ # -- inherited from EventEmitter --
86
+ # @nodoc
87
+ def off(event, callback)
88
+ event_emitter_proxy.off(event, callback)
89
+ end
90
+
91
+ private def event_emitter_proxy
92
+ @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
76
93
  end
77
94
  end
78
95
  end
@@ -3,7 +3,8 @@ require_relative './js_handle.rb'
3
3
  module Playwright
4
4
  # - extends: `JSHandle`
5
5
  #
6
- # ElementHandle represents an in-page DOM element. ElementHandles can be created with the [`method: Page.$`] method.
6
+ # ElementHandle represents an in-page DOM element. ElementHandles can be created with the [`method: Page.querySelector`]
7
+ # method.
7
8
  #
8
9
  #
9
10
  # ```js
@@ -57,92 +58,10 @@ module Playwright
57
58
  # ElementHandle prevents DOM element from garbage collection unless the handle is disposed with
58
59
  # [`method: JSHandle.dispose`]. ElementHandles are auto-disposed when their origin frame gets navigated.
59
60
  #
60
- # ElementHandle instances can be used as an argument in [`method: Page.$eval`] and [`method: Page.evaluate`] methods.
61
+ # ElementHandle instances can be used as an argument in [`method: Page.evalOnSelector`] and [`method: Page.evaluate`]
62
+ # methods.
61
63
  class ElementHandle < JSHandle
62
64
 
63
- # The method finds an element matching the specified selector in the `ElementHandle`'s subtree. See
64
- # [Working with selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector,
65
- # returns `null`.
66
- def query_selector(selector)
67
- wrap_impl(@impl.query_selector(unwrap_impl(selector)))
68
- end
69
-
70
- # The method finds all elements matching the specified selector in the `ElementHandle`s subtree. See
71
- # [Working with selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector,
72
- # returns empty array.
73
- def query_selector_all(selector)
74
- wrap_impl(@impl.query_selector_all(unwrap_impl(selector)))
75
- end
76
-
77
- # Returns the return value of `pageFunction`
78
- #
79
- # The method finds an element matching the specified selector in the `ElementHandle`s subtree and passes it as a first
80
- # argument to `pageFunction`. See [Working with selectors](./selectors.md#working-with-selectors) for more details. If no
81
- # elements match the selector, the method throws an error.
82
- #
83
- # If `pageFunction` returns a [Promise], then `frame.$eval` would wait for the promise to resolve and return its value.
84
- #
85
- # Examples:
86
- #
87
- #
88
- # ```js
89
- # const tweetHandle = await page.$('.tweet');
90
- # expect(await tweetHandle.$eval('.like', node => node.innerText)).toBe('100');
91
- # expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe('10');
92
- # ```
93
- #
94
- # ```python async
95
- # tweet_handle = await page.query_selector(".tweet")
96
- # assert await tweet_handle.eval_on_selector(".like", "node => node.innerText") == "100"
97
- # assert await tweet_handle.eval_on_selector(".retweets", "node => node.innerText") = "10"
98
- # ```
99
- #
100
- # ```python sync
101
- # tweet_handle = page.query_selector(".tweet")
102
- # assert tweet_handle.eval_on_selector(".like", "node => node.innerText") == "100"
103
- # assert tweet_handle.eval_on_selector(".retweets", "node => node.innerText") = "10"
104
- # ```
105
- def eval_on_selector(selector, pageFunction, arg: nil)
106
- wrap_impl(@impl.eval_on_selector(unwrap_impl(selector), unwrap_impl(pageFunction), arg: unwrap_impl(arg)))
107
- end
108
-
109
- # Returns the return value of `pageFunction`
110
- #
111
- # The method finds all elements matching the specified selector in the `ElementHandle`'s subtree and passes an array of
112
- # matched elements as a first argument to `pageFunction`. See
113
- # [Working with selectors](./selectors.md#working-with-selectors) for more details.
114
- #
115
- # If `pageFunction` returns a [Promise], then `frame.$$eval` would wait for the promise to resolve and return its value.
116
- #
117
- # Examples:
118
- #
119
- # ```html
120
- # <div class="feed">
121
- # <div class="tweet">Hello!</div>
122
- # <div class="tweet">Hi!</div>
123
- # </div>
124
- # ```
125
- #
126
- #
127
- # ```js
128
- # const feedHandle = await page.$('.feed');
129
- # expect(await feedHandle.$$eval('.tweet', nodes => nodes.map(n => n.innerText))).toEqual(['Hello!', 'Hi!']);
130
- # ```
131
- #
132
- # ```python async
133
- # # FIXME
134
- # feed_handle = await page.query_selector(".feed")
135
- # assert await feed_handle.eval_on_selector_all(".tweet", "nodes => nodes.map(n => n.innerText)") == ["hello!", "hi!"]
136
- # ```
137
- #
138
- # ```python sync
139
- # feed_handle = page.query_selector(".feed")
140
- # assert feed_handle.eval_on_selector_all(".tweet", "nodes => nodes.map(n => n.innerText)") == ["hello!", "hi!"]
141
- # ```
142
- def eval_on_selector_all(selector, pageFunction, arg: nil)
143
- wrap_impl(@impl.eval_on_selector_all(unwrap_impl(selector), unwrap_impl(pageFunction), arg: unwrap_impl(arg)))
144
- end
145
-
146
65
  # This method returns the bounding box of the element, or `null` if the element is not visible. The bounding box is
147
66
  # calculated relative to the main frame viewport - which is usually the same as the browser window.
148
67
  #
@@ -296,9 +215,80 @@ module Playwright
296
215
  wrap_impl(@impl.dispatch_event(unwrap_impl(type), eventInit: unwrap_impl(eventInit)))
297
216
  end
298
217
 
218
+ # Returns the return value of `expression`.
219
+ #
220
+ # The method finds an element matching the specified selector in the `ElementHandle`s subtree and passes it as a first
221
+ # argument to `expression`. See [Working with selectors](./selectors.md) for more details. If no elements match the
222
+ # selector, the method throws an error.
223
+ #
224
+ # If `expression` returns a [Promise], then [`method: ElementHandle.evalOnSelector`] would wait for the promise to resolve
225
+ # and return its value.
226
+ #
227
+ # Examples:
228
+ #
229
+ #
230
+ # ```js
231
+ # const tweetHandle = await page.$('.tweet');
232
+ # expect(await tweetHandle.$eval('.like', node => node.innerText)).toBe('100');
233
+ # expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe('10');
234
+ # ```
235
+ #
236
+ # ```python async
237
+ # tweet_handle = await page.query_selector(".tweet")
238
+ # assert await tweet_handle.eval_on_selector(".like", "node => node.innerText") == "100"
239
+ # assert await tweet_handle.eval_on_selector(".retweets", "node => node.innerText") = "10"
240
+ # ```
241
+ #
242
+ # ```python sync
243
+ # tweet_handle = page.query_selector(".tweet")
244
+ # assert tweet_handle.eval_on_selector(".like", "node => node.innerText") == "100"
245
+ # assert tweet_handle.eval_on_selector(".retweets", "node => node.innerText") = "10"
246
+ # ```
247
+ def eval_on_selector(selector, expression, arg: nil)
248
+ wrap_impl(@impl.eval_on_selector(unwrap_impl(selector), unwrap_impl(expression), arg: unwrap_impl(arg)))
249
+ end
250
+
251
+ # Returns the return value of `expression`.
252
+ #
253
+ # The method finds all elements matching the specified selector in the `ElementHandle`'s subtree and passes an array of
254
+ # matched elements as a first argument to `expression`. See [Working with selectors](./selectors.md) for more details.
255
+ #
256
+ # If `expression` returns a [Promise], then [`method: ElementHandle.evalOnSelectorAll`] would wait for the promise to
257
+ # resolve and return its value.
258
+ #
259
+ # Examples:
260
+ #
261
+ # ```html
262
+ # <div class="feed">
263
+ # <div class="tweet">Hello!</div>
264
+ # <div class="tweet">Hi!</div>
265
+ # </div>
266
+ # ```
267
+ #
268
+ #
269
+ # ```js
270
+ # const feedHandle = await page.$('.feed');
271
+ # expect(await feedHandle.$$eval('.tweet', nodes => nodes.map(n => n.innerText))).toEqual(['Hello!', 'Hi!']);
272
+ # ```
273
+ #
274
+ # ```python async
275
+ # feed_handle = await page.query_selector(".feed")
276
+ # assert await feed_handle.eval_on_selector_all(".tweet", "nodes => nodes.map(n => n.innerText)") == ["hello!", "hi!"]
277
+ # ```
278
+ #
279
+ # ```python sync
280
+ # feed_handle = page.query_selector(".feed")
281
+ # assert feed_handle.eval_on_selector_all(".tweet", "nodes => nodes.map(n => n.innerText)") == ["hello!", "hi!"]
282
+ # ```
283
+ def eval_on_selector_all(selector, expression, arg: nil)
284
+ wrap_impl(@impl.eval_on_selector_all(unwrap_impl(selector), unwrap_impl(expression), arg: unwrap_impl(arg)))
285
+ end
286
+
299
287
  # This method waits for [actionability](./actionability.md) checks, focuses the element, fills it and triggers an `input`
300
- # event after filling. If the element is not an `<input>`, `<textarea>` or `[contenteditable]` element, this method throws
301
- # an error. Note that you can pass an empty string to clear the input field.
288
+ # event after filling. If the element is inside the `<label>` element that has associated
289
+ # [control](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/control), that control will be filled
290
+ # instead. If the element to be filled is not an `<input>`, `<textarea>` or `[contenteditable]` element, this method
291
+ # throws an error. Note that you can pass an empty string to clear the input field.
302
292
  def fill(value, noWaitAfter: nil, timeout: nil)
303
293
  wrap_impl(@impl.fill(unwrap_impl(value), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
304
294
  end
@@ -395,6 +385,18 @@ module Playwright
395
385
  wrap_impl(@impl.press(unwrap_impl(key), delay: unwrap_impl(delay), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
396
386
  end
397
387
 
388
+ # The method finds an element matching the specified selector in the `ElementHandle`'s subtree. See
389
+ # [Working with selectors](./selectors.md) for more details. If no elements match the selector, returns `null`.
390
+ def query_selector(selector)
391
+ wrap_impl(@impl.query_selector(unwrap_impl(selector)))
392
+ end
393
+
394
+ # The method finds all elements matching the specified selector in the `ElementHandle`s subtree. See
395
+ # [Working with selectors](./selectors.md) for more details. If no elements match the selector, returns empty array.
396
+ def query_selector_all(selector)
397
+ wrap_impl(@impl.query_selector_all(unwrap_impl(selector)))
398
+ end
399
+
398
400
  # Returns the buffer with the captured screenshot.
399
401
  #
400
402
  # This method waits for the [actionability](./actionability.md) checks, then scrolls element into view before taking a
@@ -456,7 +458,6 @@ module Playwright
456
458
  # ```
457
459
  #
458
460
  # ```python sync
459
- # # FIXME
460
461
  # # single selection matching the value
461
462
  # handle.select_option("blue")
462
463
  # # single selection matching both the value and the label
@@ -466,8 +467,14 @@ module Playwright
466
467
  # # multiple selection for blue, red and second option
467
468
  # handle.select_option(value="blue", { index: 2 }, "red")
468
469
  # ```
469
- def select_option(values, noWaitAfter: nil, timeout: nil)
470
- wrap_impl(@impl.select_option(unwrap_impl(values), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
470
+ def select_option(
471
+ element: nil,
472
+ index: nil,
473
+ value: nil,
474
+ label: nil,
475
+ noWaitAfter: nil,
476
+ timeout: nil)
477
+ wrap_impl(@impl.select_option(element: unwrap_impl(element), index: unwrap_impl(index), value: unwrap_impl(value), label: unwrap_impl(label), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
471
478
  end
472
479
 
473
480
  # This method waits for [actionability](./actionability.md) checks, then focuses the element and selects all its text
@@ -628,20 +635,24 @@ module Playwright
628
635
 
629
636
  # -- inherited from EventEmitter --
630
637
  # @nodoc
631
- def on(event, callback)
632
- wrap_impl(@impl.on(unwrap_impl(event), unwrap_impl(callback)))
638
+ def once(event, callback)
639
+ event_emitter_proxy.once(event, callback)
633
640
  end
634
641
 
635
642
  # -- inherited from EventEmitter --
636
643
  # @nodoc
637
- def off(event, callback)
638
- wrap_impl(@impl.off(unwrap_impl(event), unwrap_impl(callback)))
644
+ def on(event, callback)
645
+ event_emitter_proxy.on(event, callback)
639
646
  end
640
647
 
641
648
  # -- inherited from EventEmitter --
642
649
  # @nodoc
643
- def once(event, callback)
644
- wrap_impl(@impl.once(unwrap_impl(event), unwrap_impl(callback)))
650
+ def off(event, callback)
651
+ event_emitter_proxy.off(event, callback)
652
+ end
653
+
654
+ private def event_emitter_proxy
655
+ @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
645
656
  end
646
657
  end
647
658
  end
@@ -3,39 +3,47 @@ module Playwright
3
3
  #
4
4
  #
5
5
  # ```js
6
- # page.on('filechooser', async (fileChooser) => {
7
- # await fileChooser.setFiles('/tmp/myfile.pdf');
8
- # });
6
+ # const [fileChooser] = await Promise.all([
7
+ # page.waitForEvent('filechooser'),
8
+ # page.click('upload')
9
+ # ]);
10
+ # await fileChooser.setFiles('myfile.pdf');
9
11
  # ```
10
12
  #
11
13
  # ```python async
12
- # page.on("filechooser", lambda file_chooser: file_chooser.set_files("/tmp/myfile.pdf"))
14
+ # async with page.expect_file_chooser() as fc_info:
15
+ # await page.click("upload")
16
+ # file_chooser = await fc_info.value
17
+ # await file_chooser.set_files("myfile.pdf")
13
18
  # ```
14
19
  #
15
20
  # ```python sync
16
- # page.on("filechooser", lambda file_chooser: file_chooser.set_files("/tmp/myfile.pdf"))
21
+ # with page.expect_file_chooser() as fc_info:
22
+ # page.click("upload")
23
+ # file_chooser = fc_info.value
24
+ # file_chooser.set_files("myfile.pdf")
17
25
  # ```
18
26
  class FileChooser < PlaywrightApi
19
27
 
20
28
  # Returns input element associated with this file chooser.
21
29
  def element
22
- raise NotImplementedError.new('element is not implemented yet.')
30
+ wrap_impl(@impl.element)
23
31
  end
24
32
 
25
33
  # Returns whether this file chooser accepts multiple files.
26
34
  def multiple?
27
- raise NotImplementedError.new('multiple? is not implemented yet.')
35
+ wrap_impl(@impl.multiple?)
28
36
  end
29
37
 
30
38
  # Returns page this file chooser belongs to.
31
39
  def page
32
- raise NotImplementedError.new('page is not implemented yet.')
40
+ wrap_impl(@impl.page)
33
41
  end
34
42
 
35
43
  # Sets the value of the file input this chooser is associated with. If some of the `filePaths` are relative paths, then
36
44
  # they are resolved relative to the the current working directory. For empty array, clears the selected files.
37
45
  def set_files(files, noWaitAfter: nil, timeout: nil)
38
- raise NotImplementedError.new('set_files is not implemented yet.')
46
+ wrap_impl(@impl.set_files(unwrap_impl(files), noWaitAfter: unwrap_impl(noWaitAfter), timeout: unwrap_impl(timeout)))
39
47
  end
40
48
  alias_method :files=, :set_files
41
49
  end