playwright-ruby-client 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/lib/playwright.rb +2 -0
  3. data/lib/playwright/channel_owners/element_handle.rb +75 -0
  4. data/lib/playwright/channel_owners/frame.rb +117 -0
  5. data/lib/playwright/channel_owners/page.rb +68 -11
  6. data/lib/playwright/channel_owners/request.rb +90 -0
  7. data/lib/playwright/input_type.rb +19 -0
  8. data/lib/playwright/input_types/keyboard.rb +32 -0
  9. data/lib/playwright/input_types/mouse.rb +4 -0
  10. data/lib/playwright/input_types/touchscreen.rb +4 -0
  11. data/lib/playwright/javascript/expression.rb +22 -0
  12. data/lib/playwright/javascript/function.rb +22 -0
  13. data/lib/playwright/playwright_api.rb +31 -23
  14. data/lib/playwright/timeout_settings.rb +1 -1
  15. data/lib/playwright/url_matcher.rb +19 -0
  16. data/lib/playwright/version.rb +1 -1
  17. data/lib/playwright_api/accessibility.rb +46 -6
  18. data/lib/playwright_api/binding_call.rb +6 -6
  19. data/lib/playwright_api/browser.rb +76 -16
  20. data/lib/playwright_api/browser_context.rb +284 -30
  21. data/lib/playwright_api/browser_type.rb +54 -9
  22. data/lib/playwright_api/cdp_session.rb +23 -1
  23. data/lib/playwright_api/chromium_browser_context.rb +16 -6
  24. data/lib/playwright_api/console_message.rb +10 -10
  25. data/lib/playwright_api/dialog.rb +42 -0
  26. data/lib/playwright_api/download.rb +19 -4
  27. data/lib/playwright_api/element_handle.rb +174 -21
  28. data/lib/playwright_api/file_chooser.rb +8 -0
  29. data/lib/playwright_api/frame.rb +355 -68
  30. data/lib/playwright_api/js_handle.rb +45 -9
  31. data/lib/playwright_api/keyboard.rb +98 -8
  32. data/lib/playwright_api/mouse.rb +22 -0
  33. data/lib/playwright_api/page.rb +779 -127
  34. data/lib/playwright_api/playwright.rb +98 -19
  35. data/lib/playwright_api/request.rb +70 -23
  36. data/lib/playwright_api/response.rb +6 -6
  37. data/lib/playwright_api/route.rb +48 -0
  38. data/lib/playwright_api/selectors.rb +14 -6
  39. data/lib/playwright_api/video.rb +8 -0
  40. data/lib/playwright_api/web_socket.rb +3 -5
  41. data/lib/playwright_api/worker.rb +12 -0
  42. metadata +7 -2
@@ -14,6 +14,39 @@ module Playwright
14
14
  # await browser.close();
15
15
  # })();
16
16
  # ```
17
+ #
18
+ # ```python async
19
+ # import asyncio
20
+ # from playwright.async_api import async_playwright
21
+ #
22
+ # async def run(playwright):
23
+ # chromium = playwright.chromium
24
+ # browser = await chromium.launch()
25
+ # page = await browser.new_page()
26
+ # await page.goto("https://example.com")
27
+ # # other actions...
28
+ # await browser.close()
29
+ #
30
+ # async def main():
31
+ # async with async_playwright() as playwright:
32
+ # await run(playwright)
33
+ # asyncio.run(main())
34
+ # ```
35
+ #
36
+ # ```python sync
37
+ # from playwright.sync_api import sync_playwright
38
+ #
39
+ # def run(playwright):
40
+ # chromium = playwright.chromium
41
+ # browser = chromium.launch()
42
+ # page = browser.new_page()
43
+ # page.goto("https://example.com")
44
+ # # other actions...
45
+ # browser.close()
46
+ #
47
+ # with sync_playwright() as playwright:
48
+ # run(playwright)
49
+ # ```
17
50
  class BrowserType < PlaywrightApi
18
51
 
19
52
  # This methods attaches Playwright to an existing browser instance.
@@ -23,7 +56,7 @@ module Playwright
23
56
 
24
57
  # A path where Playwright expects to find a bundled browser executable.
25
58
  def executable_path
26
- wrap_channel_owner(@channel_owner.executable_path)
59
+ wrap_impl(@impl.executable_path)
27
60
  end
28
61
 
29
62
  # Returns the browser instance.
@@ -37,6 +70,18 @@ module Playwright
37
70
  # });
38
71
  # ```
39
72
  #
73
+ # ```python async
74
+ # browser = await playwright.chromium.launch( # or "firefox" or "webkit".
75
+ # ignore_default_args=["--mute-audio"]
76
+ # )
77
+ # ```
78
+ #
79
+ # ```python sync
80
+ # browser = playwright.chromium.launch( # or "firefox" or "webkit".
81
+ # ignore_default_args=["--mute-audio"]
82
+ # )
83
+ # ```
84
+ #
40
85
  # > **Chromium-only** Playwright can also be used to control the Chrome browser, but it works best with the version of
41
86
  # Chromium it is bundled with. There is no guarantee it will work with any other version. Use `executablePath` option with
42
87
  # extreme caution.
@@ -69,7 +114,7 @@ module Playwright
69
114
  slowMo: nil,
70
115
  timeout: nil,
71
116
  &block)
72
- wrap_channel_owner(@channel_owner.launch(args: args, chromiumSandbox: chromiumSandbox, devtools: devtools, downloadsPath: downloadsPath, env: env, executablePath: executablePath, firefoxUserPrefs: firefoxUserPrefs, handleSIGHUP: handleSIGHUP, handleSIGINT: handleSIGINT, handleSIGTERM: handleSIGTERM, headless: headless, ignoreDefaultArgs: ignoreDefaultArgs, logger: logger, proxy: proxy, slowMo: slowMo, timeout: timeout, &wrap_block_call(block)))
117
+ wrap_impl(@impl.launch(args: args, chromiumSandbox: chromiumSandbox, devtools: devtools, downloadsPath: downloadsPath, env: env, executablePath: executablePath, firefoxUserPrefs: firefoxUserPrefs, handleSIGHUP: handleSIGHUP, handleSIGINT: handleSIGINT, handleSIGTERM: handleSIGTERM, headless: headless, ignoreDefaultArgs: ignoreDefaultArgs, logger: logger, proxy: proxy, slowMo: slowMo, timeout: timeout, &wrap_block_call(block)))
73
118
  end
74
119
 
75
120
  # Returns the persistent browser context instance.
@@ -157,25 +202,25 @@ module Playwright
157
202
 
158
203
  # Returns browser name. For example: `'chromium'`, `'webkit'` or `'firefox'`.
159
204
  def name
160
- wrap_channel_owner(@channel_owner.name)
205
+ wrap_impl(@impl.name)
161
206
  end
162
207
 
163
208
  # -- inherited from EventEmitter --
164
209
  # @nodoc
165
- def off(event, callback)
166
- wrap_channel_owner(@channel_owner.off(event, callback))
210
+ def on(event, callback)
211
+ wrap_impl(@impl.on(event, callback))
167
212
  end
168
213
 
169
214
  # -- inherited from EventEmitter --
170
215
  # @nodoc
171
- def once(event, callback)
172
- wrap_channel_owner(@channel_owner.once(event, callback))
216
+ def off(event, callback)
217
+ wrap_impl(@impl.off(event, callback))
173
218
  end
174
219
 
175
220
  # -- inherited from EventEmitter --
176
221
  # @nodoc
177
- def on(event, callback)
178
- wrap_channel_owner(@channel_owner.on(event, callback))
222
+ def once(event, callback)
223
+ wrap_impl(@impl.once(event, callback))
179
224
  end
180
225
  end
181
226
  end
@@ -1,5 +1,5 @@
1
1
  module Playwright
2
- # - extends: [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)
2
+ # - extends: [EventEmitter]
3
3
  #
4
4
  # The `CDPSession` instances are used to talk raw Chrome Devtools Protocol:
5
5
  # - protocol methods can be called with `session.send` method.
@@ -22,6 +22,28 @@ module Playwright
22
22
  # playbackRate: response.playbackRate / 2
23
23
  # });
24
24
  # ```
25
+ #
26
+ # ```python async
27
+ # client = await page.context().new_cdp_session(page)
28
+ # await client.send("animation.enable")
29
+ # client.on("animation.animation_created", lambda: print("animation created!"))
30
+ # response = await client.send("animation.get_playback_rate")
31
+ # print("playback rate is " + response["playback_rate"])
32
+ # await client.send("animation.set_playback_rate", {
33
+ # playback_rate: response["playback_rate"] / 2
34
+ # })
35
+ # ```
36
+ #
37
+ # ```python sync
38
+ # client = page.context().new_cdp_session(page)
39
+ # client.send("animation.enable")
40
+ # client.on("animation.animation_created", lambda: print("animation created!"))
41
+ # response = client.send("animation.get_playback_rate")
42
+ # print("playback rate is " + response["playback_rate"])
43
+ # client.send("animation.set_playback_rate", {
44
+ # playback_rate: response["playback_rate"] / 2
45
+ # })
46
+ # ```
25
47
  class CDPSession < PlaywrightApi
26
48
 
27
49
  # Detaches the CDPSession from the target. Once detached, the CDPSession object won't emit any events and can't be used to
@@ -9,6 +9,16 @@ module Playwright
9
9
  # ```js
10
10
  # const backgroundPage = await context.waitForEvent('backgroundpage');
11
11
  # ```
12
+ #
13
+ # ```python async
14
+ # # FIXME
15
+ # background_page = await context.wait_for_event("backgroundpage")
16
+ # ```
17
+ #
18
+ # ```python sync
19
+ # # FIXME
20
+ # background_page = context.wait_for_event("backgroundpage")
21
+ # ```
12
22
  class ChromiumBrowserContext < BrowserContext
13
23
 
14
24
  # All existing background pages in the context.
@@ -28,20 +38,20 @@ module Playwright
28
38
 
29
39
  # -- inherited from EventEmitter --
30
40
  # @nodoc
31
- def off(event, callback)
32
- wrap_channel_owner(@channel_owner.off(event, callback))
41
+ def on(event, callback)
42
+ wrap_impl(@impl.on(event, callback))
33
43
  end
34
44
 
35
45
  # -- inherited from EventEmitter --
36
46
  # @nodoc
37
- def once(event, callback)
38
- wrap_channel_owner(@channel_owner.once(event, callback))
47
+ def off(event, callback)
48
+ wrap_impl(@impl.off(event, callback))
39
49
  end
40
50
 
41
51
  # -- inherited from EventEmitter --
42
52
  # @nodoc
43
- def on(event, callback)
44
- wrap_channel_owner(@channel_owner.on(event, callback))
53
+ def once(event, callback)
54
+ wrap_impl(@impl.once(event, callback))
45
55
  end
46
56
  end
47
57
  end
@@ -3,15 +3,15 @@ module Playwright
3
3
  class ConsoleMessage < PlaywrightApi
4
4
 
5
5
  def args
6
- wrap_channel_owner(@channel_owner.args)
6
+ wrap_impl(@impl.args)
7
7
  end
8
8
 
9
9
  def location
10
- wrap_channel_owner(@channel_owner.location)
10
+ wrap_impl(@impl.location)
11
11
  end
12
12
 
13
13
  def text
14
- wrap_channel_owner(@channel_owner.text)
14
+ wrap_impl(@impl.text)
15
15
  end
16
16
 
17
17
  # One of the following values: `'log'`, `'debug'`, `'info'`, `'error'`, `'warning'`, `'dir'`, `'dirxml'`, `'table'`,
@@ -23,25 +23,25 @@ module Playwright
23
23
 
24
24
  # @nodoc
25
25
  def type
26
- wrap_channel_owner(@channel_owner.type)
26
+ wrap_impl(@impl.type)
27
27
  end
28
28
 
29
29
  # -- inherited from EventEmitter --
30
30
  # @nodoc
31
- def off(event, callback)
32
- wrap_channel_owner(@channel_owner.off(event, callback))
31
+ def on(event, callback)
32
+ wrap_impl(@impl.on(event, callback))
33
33
  end
34
34
 
35
35
  # -- inherited from EventEmitter --
36
36
  # @nodoc
37
- def once(event, callback)
38
- wrap_channel_owner(@channel_owner.once(event, callback))
37
+ def off(event, callback)
38
+ wrap_impl(@impl.off(event, callback))
39
39
  end
40
40
 
41
41
  # -- inherited from EventEmitter --
42
42
  # @nodoc
43
- def on(event, callback)
44
- wrap_channel_owner(@channel_owner.on(event, callback))
43
+ def once(event, callback)
44
+ wrap_impl(@impl.once(event, callback))
45
45
  end
46
46
  end
47
47
  end
@@ -18,6 +18,48 @@ module Playwright
18
18
  # page.evaluate(() => alert('1'));
19
19
  # })();
20
20
  # ```
21
+ #
22
+ # ```python async
23
+ # import asyncio
24
+ # from playwright.async_api import async_playwright
25
+ #
26
+ # async def handle_dialog(dialog):
27
+ # print(dialog.message)
28
+ # await dialog.dismiss()
29
+ #
30
+ # async def run(playwright):
31
+ # chromium = playwright.chromium
32
+ # browser = await chromium.launch()
33
+ # page = await browser.new_page()
34
+ # page.on("dialog", handle_dialog)
35
+ # page.evaluate("alert('1')")
36
+ # await browser.close()
37
+ #
38
+ # async def main():
39
+ # async with async_playwright() as playwright:
40
+ # await run(playwright)
41
+ # asyncio.run(main())
42
+ # ```
43
+ #
44
+ # ```python sync
45
+ # # FIXME
46
+ # from playwright.sync_api import sync_playwright
47
+ #
48
+ # def handle_dialog(dialog):
49
+ # print(dialog.message)
50
+ # dialog.dismiss()
51
+ #
52
+ # def run(playwright):
53
+ # chromium = playwright.chromium
54
+ # browser = chromium.launch()
55
+ # page = browser.new_page()
56
+ # page.on("dialog", handle_dialog)
57
+ # page.evaluate("alert('1')")
58
+ # browser.close()
59
+ #
60
+ # with sync_playwright() as playwright:
61
+ # run(playwright)
62
+ # ```
21
63
  class Dialog < PlaywrightApi
22
64
 
23
65
  # Returns when the dialog has been accepted.
@@ -14,12 +14,27 @@ module Playwright
14
14
  # ]);
15
15
  # // wait for download to complete
16
16
  # const path = await download.path();
17
- # ...
18
17
  # ```
19
18
  #
20
- # > **NOTE** Browser context **must** be created with the `acceptDownloads` set to `true` when user needs access to the
21
- # downloaded content. If `acceptDownloads` is not set or set to `false`, download events are emitted, but the actual
22
- # download is not performed and user has no access to the downloaded files.
19
+ # ```python async
20
+ # async with page.expect_download() as download_info:
21
+ # await page.click("a")
22
+ # download = await download_info.value
23
+ # # waits for download to complete
24
+ # path = await download.path()
25
+ # ```
26
+ #
27
+ # ```python sync
28
+ # with page.expect_download() as download_info:
29
+ # page.click("a")
30
+ # download = download_info.value
31
+ # # wait for download to complete
32
+ # path = download.path()
33
+ # ```
34
+ #
35
+ # > NOTE: Browser context **must** be created with the `acceptDownloads` set to `true` when user needs access to the
36
+ # downloaded content. If `acceptDownloads` is not set, download events are emitted, but the actual download is not
37
+ # performed and user has no access to the downloaded files.
23
38
  class Download < PlaywrightApi
24
39
 
25
40
  # Returns readable stream for current download or `null` if download failed.
@@ -19,6 +19,41 @@ module Playwright
19
19
  # })();
20
20
  # ```
21
21
  #
22
+ # ```python async
23
+ # import asyncio
24
+ # from playwright.async_api import async_playwright
25
+ #
26
+ # async def run(playwright):
27
+ # chromium = playwright.chromium
28
+ # browser = await chromium.launch()
29
+ # page = await browser.new_page()
30
+ # await page.goto("https://example.com")
31
+ # href_element = await page.query_selector("a")
32
+ # await href_element.click()
33
+ # # ...
34
+ #
35
+ # async def main():
36
+ # async with async_playwright() as playwright:
37
+ # await run(playwright)
38
+ # asyncio.run(main())
39
+ # ```
40
+ #
41
+ # ```python sync
42
+ # from playwright.sync_api import sync_playwright
43
+ #
44
+ # def run(playwright):
45
+ # chromium = playwright.chromium
46
+ # browser = chromium.launch()
47
+ # page = browser.new_page()
48
+ # page.goto("https://example.com")
49
+ # href_element = page.query_selector("a")
50
+ # href_element.click()
51
+ # # ...
52
+ #
53
+ # with sync_playwright() as playwright:
54
+ # run(playwright)
55
+ # ```
56
+ #
22
57
  # ElementHandle prevents DOM element from garbage collection unless the handle is disposed with
23
58
  # [`method: JSHandle.dispose`]. ElementHandles are auto-disposed when their origin frame gets navigated.
24
59
  #
@@ -29,14 +64,14 @@ module Playwright
29
64
  # [Working with selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector,
30
65
  # returns `null`.
31
66
  def query_selector(selector)
32
- raise NotImplementedError.new('query_selector is not implemented yet.')
67
+ wrap_impl(@impl.query_selector(selector))
33
68
  end
34
69
 
35
70
  # The method finds all elements matching the specified selector in the `ElementHandle`s subtree. See
36
71
  # [Working with selectors](./selectors.md#working-with-selectors) for more details. If no elements match the selector,
37
72
  # returns empty array.
38
73
  def query_selector_all(selector)
39
- raise NotImplementedError.new('query_selector_all is not implemented yet.')
74
+ wrap_impl(@impl.query_selector_all(selector))
40
75
  end
41
76
 
42
77
  # Returns the return value of `pageFunction`
@@ -55,8 +90,20 @@ module Playwright
55
90
  # expect(await tweetHandle.$eval('.like', node => node.innerText)).toBe('100');
56
91
  # expect(await tweetHandle.$eval('.retweets', node => node.innerText)).toBe('10');
57
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
+ # ```
58
105
  def eval_on_selector(selector, pageFunction, arg: nil)
59
- raise NotImplementedError.new('eval_on_selector is not implemented yet.')
106
+ wrap_impl(@impl.eval_on_selector(selector, pageFunction, arg: arg))
60
107
  end
61
108
 
62
109
  # Returns the return value of `pageFunction`
@@ -81,8 +128,19 @@ module Playwright
81
128
  # const feedHandle = await page.$('.feed');
82
129
  # expect(await feedHandle.$$eval('.tweet', nodes => nodes.map(n => n.innerText))).toEqual(['Hello!', 'Hi!']);
83
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
+ # ```
84
142
  def eval_on_selector_all(selector, pageFunction, arg: nil)
85
- raise NotImplementedError.new('eval_on_selector_all is not implemented yet.')
143
+ wrap_impl(@impl.eval_on_selector_all(selector, pageFunction, arg: arg))
86
144
  end
87
145
 
88
146
  # This method returns the bounding box of the element, or `null` if the element is not visible. The bounding box is
@@ -103,6 +161,16 @@ module Playwright
103
161
  # const box = await elementHandle.boundingBox();
104
162
  # await page.mouse.click(box.x + box.width / 2, box.y + box.height / 2);
105
163
  # ```
164
+ #
165
+ # ```python async
166
+ # box = await element_handle.bounding_box()
167
+ # await page.mouse.click(box["x"] + box["width"] / 2, box["y"] + box["height"] / 2)
168
+ # ```
169
+ #
170
+ # ```python sync
171
+ # box = element_handle.bounding_box()
172
+ # page.mouse.click(box["x"] + box["width"] / 2, box["y"] + box["height"] / 2)
173
+ # ```
106
174
  def bounding_box
107
175
  raise NotImplementedError.new('bounding_box is not implemented yet.')
108
176
  end
@@ -143,7 +211,7 @@ module Playwright
143
211
  noWaitAfter: nil,
144
212
  position: nil,
145
213
  timeout: nil)
146
- raise NotImplementedError.new('click is not implemented yet.')
214
+ wrap_impl(@impl.click(button: button, clickCount: clickCount, delay: delay, force: force, modifiers: modifiers, noWaitAfter: noWaitAfter, position: position, timeout: timeout))
147
215
  end
148
216
 
149
217
  # Returns the content frame for element handles referencing iframe nodes, or `null` otherwise
@@ -163,7 +231,7 @@ module Playwright
163
231
  # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
164
232
  # Passing zero timeout disables this.
165
233
  #
166
- # > **NOTE** `elementHandle.dblclick()` dispatches two `click` events and a single `dblclick` event.
234
+ # > NOTE: `elementHandle.dblclick()` dispatches two `click` events and a single `dblclick` event.
167
235
  def dblclick(
168
236
  button: nil,
169
237
  delay: nil,
@@ -184,6 +252,14 @@ module Playwright
184
252
  # await elementHandle.dispatchEvent('click');
185
253
  # ```
186
254
  #
255
+ # ```python async
256
+ # await element_handle.dispatch_event("click")
257
+ # ```
258
+ #
259
+ # ```python sync
260
+ # element_handle.dispatch_event("click")
261
+ # ```
262
+ #
187
263
  # Under the hood, it creates an instance of an event based on the given `type`, initializes it with `eventInit` properties
188
264
  # and dispatches it on the element. Events are `composed`, `cancelable` and bubble by default.
189
265
  #
@@ -204,6 +280,18 @@ module Playwright
204
280
  # const dataTransfer = await page.evaluateHandle(() => new DataTransfer());
205
281
  # await elementHandle.dispatchEvent('dragstart', { dataTransfer });
206
282
  # ```
283
+ #
284
+ # ```python async
285
+ # # note you can only create data_transfer in chromium and firefox
286
+ # data_transfer = await page.evaluate_handle("new DataTransfer()")
287
+ # await element_handle.dispatch_event("#source", "dragstart", {"dataTransfer": data_transfer})
288
+ # ```
289
+ #
290
+ # ```python sync
291
+ # # note you can only create data_transfer in chromium and firefox
292
+ # data_transfer = page.evaluate_handle("new DataTransfer()")
293
+ # element_handle.dispatch_event("#source", "dragstart", {"dataTransfer": data_transfer})
294
+ # ```
207
295
  def dispatch_event(type, eventInit: nil)
208
296
  raise NotImplementedError.new('dispatch_event is not implemented yet.')
209
297
  end
@@ -303,7 +391,7 @@ module Playwright
303
391
  # Shortcuts such as `key: "Control+o"` or `key: "Control+Shift+T"` are supported as well. When speficied with the
304
392
  # modifier, modifier is pressed and being held while the subsequent key is being pressed.
305
393
  def press(key, delay: nil, noWaitAfter: nil, timeout: nil)
306
- raise NotImplementedError.new('press is not implemented yet.')
394
+ wrap_impl(@impl.press(key, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout))
307
395
  end
308
396
 
309
397
  # Returns the buffer with the captured screenshot.
@@ -321,7 +409,7 @@ module Playwright
321
409
 
322
410
  # This method waits for [actionability](./actionability.md) checks, then tries to scroll element into view, unless it is
323
411
  # completely visible as defined by
324
- # [IntersectionObserver](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)'s ```ratio```.
412
+ # [IntersectionObserver](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)'s `ratio`.
325
413
  #
326
414
  # Throws when `elementHandle` does not point to an element
327
415
  # [connected](https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected) to a Document or a ShadowRoot.
@@ -334,19 +422,48 @@ module Playwright
334
422
  # Triggers a `change` and `input` event once all the provided options have been selected. If element is not a `<select>`
335
423
  # element, the method throws an error.
336
424
  #
425
+ # Will wait until all specified options are present in the `<select>` element.
426
+ #
337
427
  #
338
428
  # ```js
339
429
  # // single selection matching the value
340
430
  # handle.selectOption('blue');
341
431
  #
342
- # // single selection matching both the value and the label
432
+ # // single selection matching the label
343
433
  # handle.selectOption({ label: 'Blue' });
344
434
  #
345
435
  # // multiple selection
346
- # handle.selectOption('red', 'green', 'blue');
436
+ # handle.selectOption(['red', 'green', 'blue']);
437
+ # ```
347
438
  #
348
- # // multiple selection for blue, red and second option
349
- # handle.selectOption({ value: 'blue' }, { index: 2 }, 'red');
439
+ # ```python async
440
+ # # single selection matching the value
441
+ # await handle.select_option("blue")
442
+ # # single selection matching the label
443
+ # await handle.select_option(label="blue")
444
+ # # multiple selection
445
+ # await handle.select_option(value=["red", "green", "blue"])
446
+ # ```
447
+ #
448
+ # ```python sync
449
+ # # single selection matching the value
450
+ # handle.select_option("blue")
451
+ # # single selection matching both the label
452
+ # handle.select_option(label="blue")
453
+ # # multiple selection
454
+ # handle.select_option(value=["red", "green", "blue"])
455
+ # ```
456
+ #
457
+ # ```python sync
458
+ # # FIXME
459
+ # # single selection matching the value
460
+ # handle.select_option("blue")
461
+ # # single selection matching both the value and the label
462
+ # handle.select_option(label="blue")
463
+ # # multiple selection
464
+ # handle.select_option("red", "green", "blue")
465
+ # # multiple selection for blue, red and second option
466
+ # handle.select_option(value="blue", { index: 2 }, "red")
350
467
  # ```
351
468
  def select_option(values, noWaitAfter: nil, timeout: nil)
352
469
  raise NotImplementedError.new('select_option is not implemented yet.')
@@ -379,7 +496,7 @@ module Playwright
379
496
  # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
380
497
  # Passing zero timeout disables this.
381
498
  #
382
- # > **NOTE** `elementHandle.tap()` requires that the `hasTouch` option of the browser context be set to true.
499
+ # > NOTE: `elementHandle.tap()` requires that the `hasTouch` option of the browser context be set to true.
383
500
  def tap_point(
384
501
  force: nil,
385
502
  modifiers: nil,
@@ -404,6 +521,16 @@ module Playwright
404
521
  # await elementHandle.type('World', {delay: 100}); // Types slower, like a user
405
522
  # ```
406
523
  #
524
+ # ```python async
525
+ # await element_handle.type("hello") # types instantly
526
+ # await element_handle.type("world", delay=100) # types slower, like a user
527
+ # ```
528
+ #
529
+ # ```python sync
530
+ # element_handle.type("hello") # types instantly
531
+ # element_handle.type("world", delay=100) # types slower, like a user
532
+ # ```
533
+ #
407
534
  # An example of typing into a text field and then submitting the form:
408
535
  #
409
536
  #
@@ -412,8 +539,20 @@ module Playwright
412
539
  # await elementHandle.type('some text');
413
540
  # await elementHandle.press('Enter');
414
541
  # ```
542
+ #
543
+ # ```python async
544
+ # element_handle = await page.query_selector("input")
545
+ # await element_handle.type("some text")
546
+ # await element_handle.press("Enter")
547
+ # ```
548
+ #
549
+ # ```python sync
550
+ # element_handle = page.query_selector("input")
551
+ # element_handle.type("some text")
552
+ # element_handle.press("Enter")
553
+ # ```
415
554
  def type_text(text, delay: nil, noWaitAfter: nil, timeout: nil)
416
- raise NotImplementedError.new('type_text is not implemented yet.')
555
+ wrap_impl(@impl.type_text(text, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout))
417
556
  end
418
557
 
419
558
  # This method checks the element by performing the following steps:
@@ -467,27 +606,41 @@ module Playwright
467
606
  # const span = await div.waitForSelector('span', { state: 'attached' });
468
607
  # ```
469
608
  #
470
- # > **NOTE** This method does not work across navigations, use [`method: Page.waitForSelector`] instead.
609
+ # ```python async
610
+ # await page.set_content("<div><span></span></div>")
611
+ # div = await page.query_selector("div")
612
+ # # waiting for the "span" selector relative to the div.
613
+ # span = await div.wait_for_selector("span", state="attached")
614
+ # ```
615
+ #
616
+ # ```python sync
617
+ # page.set_content("<div><span></span></div>")
618
+ # div = page.query_selector("div")
619
+ # # waiting for the "span" selector relative to the div.
620
+ # span = div.wait_for_selector("span", state="attached")
621
+ # ```
622
+ #
623
+ # > NOTE: This method does not work across navigations, use [`method: Page.waitForSelector`] instead.
471
624
  def wait_for_selector(selector, state: nil, timeout: nil)
472
625
  raise NotImplementedError.new('wait_for_selector is not implemented yet.')
473
626
  end
474
627
 
475
628
  # -- inherited from EventEmitter --
476
629
  # @nodoc
477
- def off(event, callback)
478
- wrap_channel_owner(@channel_owner.off(event, callback))
630
+ def on(event, callback)
631
+ wrap_impl(@impl.on(event, callback))
479
632
  end
480
633
 
481
634
  # -- inherited from EventEmitter --
482
635
  # @nodoc
483
- def once(event, callback)
484
- wrap_channel_owner(@channel_owner.once(event, callback))
636
+ def off(event, callback)
637
+ wrap_impl(@impl.off(event, callback))
485
638
  end
486
639
 
487
640
  # -- inherited from EventEmitter --
488
641
  # @nodoc
489
- def on(event, callback)
490
- wrap_channel_owner(@channel_owner.on(event, callback))
642
+ def once(event, callback)
643
+ wrap_impl(@impl.once(event, callback))
491
644
  end
492
645
  end
493
646
  end