playwright-ruby-client 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -86,6 +86,14 @@ module Playwright
86
86
  @redirected_to = request
87
87
  end
88
88
 
89
+ private def update_failure_text(failure_text)
90
+ @failure_text = failure_text
91
+ end
92
+
93
+ private def update_response_end_timing(response_end_timing)
94
+ @timing[:responseEnd] = response_end_timing
95
+ end
96
+
89
97
  private def parse_headers(headers)
90
98
  headers.map do |header|
91
99
  [header['name'].downcase, header['value']]
@@ -34,11 +34,14 @@ module Playwright
34
34
  # A subset of Events/EventEmitter in Node.js
35
35
  module EventEmitter
36
36
  # @param event [String]
37
+ # @returns [Boolean]
37
38
  def emit(event, *args)
39
+ handled = false
38
40
  (@__event_emitter ||= {})[event.to_s]&.each do |callback|
39
41
  callback.call(*args)
42
+ handled = true
40
43
  end
41
- self
44
+ handled
42
45
  end
43
46
 
44
47
  # @param event [String]
@@ -0,0 +1,20 @@
1
+ module Playwright
2
+ class HttpHeaders
3
+ # @param headers [Hash]
4
+ def initialize(headers)
5
+ @headers = headers
6
+ end
7
+
8
+ def as_serialized
9
+ @headers.map do |key, value|
10
+ { name: key, value: value }
11
+ end
12
+ end
13
+
14
+ def self.parse_serialized(serialized_headers)
15
+ new(serialized_headers.map do |header|
16
+ [header['name'].downcase, header['value']]
17
+ end.to_h)
18
+ end
19
+ end
20
+ end
@@ -8,7 +8,7 @@ module Playwright
8
8
  params[:noDefaultViewport] = true
9
9
  end
10
10
  if params[:extraHTTPHeaders]
11
- # TODO
11
+ params[:extraHTTPHeaders] = ::Playwright::HttpHeaders.new(params[:extraHTTPHeaders]).as_serialized
12
12
  end
13
13
  if params[:storageState].is_a?(String)
14
14
  params[:storageState] = JSON.parse(File.read(params[:storageState]))
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Playwright
4
- VERSION = '0.0.8'
4
+ VERSION = '0.0.9'
5
5
  end
@@ -3,13 +3,13 @@ module Playwright
3
3
  class Android < PlaywrightApi
4
4
 
5
5
  # @nodoc
6
- def devices
7
- wrap_impl(@impl.devices)
6
+ def after_initialize
7
+ wrap_impl(@impl.after_initialize)
8
8
  end
9
9
 
10
10
  # @nodoc
11
- def after_initialize
12
- wrap_impl(@impl.after_initialize)
11
+ def devices
12
+ wrap_impl(@impl.devices)
13
13
  end
14
14
 
15
15
  # -- inherited from EventEmitter --
@@ -12,6 +12,11 @@ module Playwright
12
12
  wrap_impl(@impl.close)
13
13
  end
14
14
 
15
+ # @nodoc
16
+ def shell(command)
17
+ wrap_impl(@impl.shell(unwrap_impl(command)))
18
+ end
19
+
15
20
  # @nodoc
16
21
  def after_initialize
17
22
  wrap_impl(@impl.after_initialize)
@@ -27,11 +32,6 @@ module Playwright
27
32
  wrap_impl(@impl.screenshot(path: unwrap_impl(path)))
28
33
  end
29
34
 
30
- # @nodoc
31
- def shell(command)
32
- wrap_impl(@impl.shell(unwrap_impl(command)))
33
- end
34
-
35
35
  # @nodoc
36
36
  def input
37
37
  wrap_impl(@impl.input)
@@ -8,8 +8,8 @@ module Playwright
8
8
  end
9
9
 
10
10
  # @nodoc
11
- def tap_point(point)
12
- wrap_impl(@impl.tap_point(unwrap_impl(point)))
11
+ def drag(from, to, steps)
12
+ wrap_impl(@impl.drag(unwrap_impl(from), unwrap_impl(to), unwrap_impl(steps)))
13
13
  end
14
14
 
15
15
  # @nodoc
@@ -18,8 +18,8 @@ module Playwright
18
18
  end
19
19
 
20
20
  # @nodoc
21
- def drag(from, to, steps)
22
- wrap_impl(@impl.drag(unwrap_impl(from), unwrap_impl(to), unwrap_impl(steps)))
21
+ def tap_point(point)
22
+ wrap_impl(@impl.tap_point(unwrap_impl(point)))
23
23
  end
24
24
  end
25
25
  end
@@ -1,7 +1,7 @@
1
1
  module Playwright
2
2
  # - extends: [EventEmitter]
3
3
  #
4
- # A Browser is created via [`method: BrowserType.launch`]. An example of using a `Browser` to create a [Page]:
4
+ # A Browser is created via [`method: BrowserType.launch`]. An example of using a `Browser` to create a `Page`:
5
5
  #
6
6
  #
7
7
  # ```js
@@ -142,13 +142,14 @@ module Playwright
142
142
  recordHar: nil,
143
143
  recordVideo: nil,
144
144
  storageState: nil,
145
+ storageStatePath: nil,
145
146
  timezoneId: nil,
146
147
  userAgent: nil,
147
148
  videoSize: nil,
148
149
  videosPath: nil,
149
150
  viewport: nil,
150
151
  &block)
151
- wrap_impl(@impl.new_context(acceptDownloads: unwrap_impl(acceptDownloads), bypassCSP: unwrap_impl(bypassCSP), colorScheme: unwrap_impl(colorScheme), deviceScaleFactor: unwrap_impl(deviceScaleFactor), extraHTTPHeaders: unwrap_impl(extraHTTPHeaders), geolocation: unwrap_impl(geolocation), hasTouch: unwrap_impl(hasTouch), httpCredentials: unwrap_impl(httpCredentials), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), isMobile: unwrap_impl(isMobile), javaScriptEnabled: unwrap_impl(javaScriptEnabled), locale: unwrap_impl(locale), logger: unwrap_impl(logger), offline: unwrap_impl(offline), permissions: unwrap_impl(permissions), proxy: unwrap_impl(proxy), recordHar: unwrap_impl(recordHar), recordVideo: unwrap_impl(recordVideo), storageState: unwrap_impl(storageState), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), videoSize: unwrap_impl(videoSize), videosPath: unwrap_impl(videosPath), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
152
+ wrap_impl(@impl.new_context(acceptDownloads: unwrap_impl(acceptDownloads), bypassCSP: unwrap_impl(bypassCSP), colorScheme: unwrap_impl(colorScheme), deviceScaleFactor: unwrap_impl(deviceScaleFactor), extraHTTPHeaders: unwrap_impl(extraHTTPHeaders), geolocation: unwrap_impl(geolocation), hasTouch: unwrap_impl(hasTouch), httpCredentials: unwrap_impl(httpCredentials), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), isMobile: unwrap_impl(isMobile), javaScriptEnabled: unwrap_impl(javaScriptEnabled), locale: unwrap_impl(locale), logger: unwrap_impl(logger), offline: unwrap_impl(offline), permissions: unwrap_impl(permissions), proxy: unwrap_impl(proxy), recordHar: unwrap_impl(recordHar), recordVideo: unwrap_impl(recordVideo), storageState: unwrap_impl(storageState), storageStatePath: unwrap_impl(storageStatePath), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), videoSize: unwrap_impl(videoSize), videosPath: unwrap_impl(videosPath), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
152
153
  end
153
154
 
154
155
  # Creates a new page in a new browser context. Closing this page will close the context as well.
@@ -176,12 +177,13 @@ module Playwright
176
177
  recordHar: nil,
177
178
  recordVideo: nil,
178
179
  storageState: nil,
180
+ storageStatePath: nil,
179
181
  timezoneId: nil,
180
182
  userAgent: nil,
181
183
  videoSize: nil,
182
184
  videosPath: nil,
183
185
  viewport: nil)
184
- wrap_impl(@impl.new_page(acceptDownloads: unwrap_impl(acceptDownloads), bypassCSP: unwrap_impl(bypassCSP), colorScheme: unwrap_impl(colorScheme), deviceScaleFactor: unwrap_impl(deviceScaleFactor), extraHTTPHeaders: unwrap_impl(extraHTTPHeaders), geolocation: unwrap_impl(geolocation), hasTouch: unwrap_impl(hasTouch), httpCredentials: unwrap_impl(httpCredentials), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), isMobile: unwrap_impl(isMobile), javaScriptEnabled: unwrap_impl(javaScriptEnabled), locale: unwrap_impl(locale), logger: unwrap_impl(logger), offline: unwrap_impl(offline), permissions: unwrap_impl(permissions), proxy: unwrap_impl(proxy), recordHar: unwrap_impl(recordHar), recordVideo: unwrap_impl(recordVideo), storageState: unwrap_impl(storageState), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), videoSize: unwrap_impl(videoSize), videosPath: unwrap_impl(videosPath), viewport: unwrap_impl(viewport)))
186
+ wrap_impl(@impl.new_page(acceptDownloads: unwrap_impl(acceptDownloads), bypassCSP: unwrap_impl(bypassCSP), colorScheme: unwrap_impl(colorScheme), deviceScaleFactor: unwrap_impl(deviceScaleFactor), extraHTTPHeaders: unwrap_impl(extraHTTPHeaders), geolocation: unwrap_impl(geolocation), hasTouch: unwrap_impl(hasTouch), httpCredentials: unwrap_impl(httpCredentials), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), isMobile: unwrap_impl(isMobile), javaScriptEnabled: unwrap_impl(javaScriptEnabled), locale: unwrap_impl(locale), logger: unwrap_impl(logger), offline: unwrap_impl(offline), permissions: unwrap_impl(permissions), proxy: unwrap_impl(proxy), recordHar: unwrap_impl(recordHar), recordVideo: unwrap_impl(recordVideo), storageState: unwrap_impl(storageState), storageStatePath: unwrap_impl(storageStatePath), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), videoSize: unwrap_impl(videoSize), videosPath: unwrap_impl(videosPath), viewport: unwrap_impl(viewport)))
185
187
  end
186
188
 
187
189
  # Returns the browser version.
@@ -545,30 +545,9 @@ module Playwright
545
545
  raise NotImplementedError.new('unroute is not implemented yet.')
546
546
  end
547
547
 
548
- # Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy
549
- # value. Will throw an error if the context closes before the event is fired. Returns the event data value.
550
- #
551
- #
552
- # ```js
553
- # const [page, _] = await Promise.all([
554
- # context.waitForEvent('page'),
555
- # page.click('button')
556
- # ]);
557
- # ```
558
- #
559
- # ```python async
560
- # async with context.expect_event("page") as event_info:
561
- # await page.click("button")
562
- # page = await event_info.value
563
- # ```
564
- #
565
- # ```python sync
566
- # with context.expect_event("page") as event_info:
567
- # page.click("button")
568
- # page = event_info.value
569
- # ```
570
- def expect_event(event, optionsOrPredicate: nil)
571
- raise NotImplementedError.new('expect_event is not implemented yet.')
548
+ # @nodoc
549
+ def after_initialize
550
+ wrap_impl(@impl.after_initialize)
572
551
  end
573
552
 
574
553
  # @nodoc
@@ -576,11 +555,6 @@ module Playwright
576
555
  wrap_impl(@impl.browser=(unwrap_impl(req)))
577
556
  end
578
557
 
579
- # @nodoc
580
- def after_initialize
581
- wrap_impl(@impl.after_initialize)
582
- end
583
-
584
558
  # @nodoc
585
559
  def owner_page=(req)
586
560
  wrap_impl(@impl.owner_page=(unwrap_impl(req)))
@@ -108,13 +108,14 @@ module Playwright
108
108
  handleSIGINT: nil,
109
109
  handleSIGTERM: nil,
110
110
  headless: nil,
111
+ ignoreAllDefaultArgs: nil,
111
112
  ignoreDefaultArgs: nil,
112
113
  logger: nil,
113
114
  proxy: nil,
114
115
  slowMo: nil,
115
116
  timeout: nil,
116
117
  &block)
117
- wrap_impl(@impl.launch(args: unwrap_impl(args), chromiumSandbox: unwrap_impl(chromiumSandbox), devtools: unwrap_impl(devtools), downloadsPath: unwrap_impl(downloadsPath), env: unwrap_impl(env), executablePath: unwrap_impl(executablePath), firefoxUserPrefs: unwrap_impl(firefoxUserPrefs), handleSIGHUP: unwrap_impl(handleSIGHUP), handleSIGINT: unwrap_impl(handleSIGINT), handleSIGTERM: unwrap_impl(handleSIGTERM), headless: unwrap_impl(headless), ignoreDefaultArgs: unwrap_impl(ignoreDefaultArgs), logger: unwrap_impl(logger), proxy: unwrap_impl(proxy), slowMo: unwrap_impl(slowMo), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
118
+ wrap_impl(@impl.launch(args: unwrap_impl(args), chromiumSandbox: unwrap_impl(chromiumSandbox), devtools: unwrap_impl(devtools), downloadsPath: unwrap_impl(downloadsPath), env: unwrap_impl(env), executablePath: unwrap_impl(executablePath), firefoxUserPrefs: unwrap_impl(firefoxUserPrefs), handleSIGHUP: unwrap_impl(handleSIGHUP), handleSIGINT: unwrap_impl(handleSIGINT), handleSIGTERM: unwrap_impl(handleSIGTERM), headless: unwrap_impl(headless), ignoreAllDefaultArgs: unwrap_impl(ignoreAllDefaultArgs), ignoreDefaultArgs: unwrap_impl(ignoreDefaultArgs), logger: unwrap_impl(logger), proxy: unwrap_impl(proxy), slowMo: unwrap_impl(slowMo), timeout: unwrap_impl(timeout), &wrap_block_call(block)))
118
119
  end
119
120
 
120
121
  # Returns the persistent browser context instance.
@@ -141,6 +142,7 @@ module Playwright
141
142
  hasTouch: nil,
142
143
  headless: nil,
143
144
  httpCredentials: nil,
145
+ ignoreAllDefaultArgs: nil,
144
146
  ignoreDefaultArgs: nil,
145
147
  ignoreHTTPSErrors: nil,
146
148
  isMobile: nil,
@@ -185,14 +187,12 @@ module Playwright
185
187
  chromiumSandbox: nil,
186
188
  devtools: nil,
187
189
  downloadsPath: nil,
188
- env: nil,
189
190
  executablePath: nil,
190
191
  firefoxUserPrefs: nil,
191
192
  handleSIGHUP: nil,
192
193
  handleSIGINT: nil,
193
194
  handleSIGTERM: nil,
194
195
  headless: nil,
195
- ignoreDefaultArgs: nil,
196
196
  logger: nil,
197
197
  port: nil,
198
198
  proxy: nil,
@@ -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
@@ -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.
@@ -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