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
@@ -8,6 +8,16 @@ module Playwright
8
8
  # // ...
9
9
  # ```
10
10
  #
11
+ # ```python async
12
+ # window_handle = await page.evaluate_handle("window")
13
+ # # ...
14
+ # ```
15
+ #
16
+ # ```python sync
17
+ # window_handle = page.evaluate_handle("window")
18
+ # # ...
19
+ # ```
20
+ #
11
21
  # JSHandle prevents the referenced JavaScript object being garbage collected unless the handle is exposed with
12
22
  # [`method: JSHandle.dispose`]. JSHandles are auto-disposed when their origin frame gets navigated or the parent context
13
23
  # gets destroyed.
@@ -23,7 +33,7 @@ module Playwright
23
33
 
24
34
  # The `jsHandle.dispose` method stops referencing the element handle.
25
35
  def dispose
26
- wrap_channel_owner(@channel_owner.dispose)
36
+ wrap_impl(@impl.dispose)
27
37
  end
28
38
 
29
39
  # Returns the return value of `pageFunction`
@@ -38,7 +48,17 @@ module Playwright
38
48
  #
39
49
  # ```js
40
50
  # const tweetHandle = await page.$('.tweet .retweets');
41
- # expect(await tweetHandle.evaluate((node, suffix) => node.innerText, ' retweets')).toBe('10 retweets');
51
+ # expect(await tweetHandle.evaluate(node => node.innerText)).toBe('10 retweets');
52
+ # ```
53
+ #
54
+ # ```python async
55
+ # tweet_handle = await page.query_selector(".tweet .retweets")
56
+ # assert await tweet_handle.evaluate("node => node.innerText") == "10 retweets"
57
+ # ```
58
+ #
59
+ # ```python sync
60
+ # tweet_handle = page.query_selector(".tweet .retweets")
61
+ # assert tweet_handle.evaluate("node => node.innerText") == "10 retweets"
42
62
  # ```
43
63
  def evaluate(pageFunction, arg: nil)
44
64
  raise NotImplementedError.new('evaluate is not implemented yet.')
@@ -69,6 +89,22 @@ module Playwright
69
89
  # const documentHandle = properties.get('document');
70
90
  # await handle.dispose();
71
91
  # ```
92
+ #
93
+ # ```python async
94
+ # handle = await page.evaluate_handle("{window, document}")
95
+ # properties = await handle.get_properties()
96
+ # window_handle = properties.get("window")
97
+ # document_handle = properties.get("document")
98
+ # await handle.dispose()
99
+ # ```
100
+ #
101
+ # ```python sync
102
+ # handle = page.evaluate_handle("{window, document}")
103
+ # properties = handle.get_properties()
104
+ # window_handle = properties.get("window")
105
+ # document_handle = properties.get("document")
106
+ # handle.dispose()
107
+ # ```
72
108
  def get_properties
73
109
  raise NotImplementedError.new('get_properties is not implemented yet.')
74
110
  end
@@ -80,7 +116,7 @@ module Playwright
80
116
 
81
117
  # Returns a JSON representation of the object. If the object has a `toJSON` function, it **will not be called**.
82
118
  #
83
- # > **NOTE** The method will return an empty JSON object if the referenced object is not stringifiable. It will throw an
119
+ # > NOTE: The method will return an empty JSON object if the referenced object is not stringifiable. It will throw an
84
120
  # error if the object has circular references.
85
121
  def json_value
86
122
  raise NotImplementedError.new('json_value is not implemented yet.')
@@ -88,20 +124,20 @@ module Playwright
88
124
 
89
125
  # -- inherited from EventEmitter --
90
126
  # @nodoc
91
- def off(event, callback)
92
- wrap_channel_owner(@channel_owner.off(event, callback))
127
+ def on(event, callback)
128
+ wrap_impl(@impl.on(event, callback))
93
129
  end
94
130
 
95
131
  # -- inherited from EventEmitter --
96
132
  # @nodoc
97
- def once(event, callback)
98
- wrap_channel_owner(@channel_owner.once(event, callback))
133
+ def off(event, callback)
134
+ wrap_impl(@impl.off(event, callback))
99
135
  end
100
136
 
101
137
  # -- inherited from EventEmitter --
102
138
  # @nodoc
103
- def on(event, callback)
104
- wrap_channel_owner(@channel_owner.on(event, callback))
139
+ def once(event, callback)
140
+ wrap_impl(@impl.once(event, callback))
105
141
  end
106
142
  end
107
143
  end
@@ -21,6 +21,28 @@ module Playwright
21
21
  # // Result text will end up saying 'Hello!'
22
22
  # ```
23
23
  #
24
+ # ```python async
25
+ # await page.keyboard.type("Hello World!")
26
+ # await page.keyboard.press("ArrowLeft")
27
+ # await page.keyboard.down("Shift")
28
+ # for i in range(6):
29
+ # await page.keyboard.press("ArrowLeft")
30
+ # await page.keyboard.up("Shift")
31
+ # await page.keyboard.press("Backspace")
32
+ # # result text will end up saying "Hello!"
33
+ # ```
34
+ #
35
+ # ```python sync
36
+ # page.keyboard.type("Hello World!")
37
+ # page.keyboard.press("ArrowLeft")
38
+ # page.keyboard.down("Shift")
39
+ # for i in range(6):
40
+ # page.keyboard.press("ArrowLeft")
41
+ # page.keyboard.up("Shift")
42
+ # page.keyboard.press("Backspace")
43
+ # # result text will end up saying "Hello!"
44
+ # ```
45
+ #
24
46
  # An example of pressing uppercase `A`
25
47
  #
26
48
  #
@@ -30,6 +52,18 @@ module Playwright
30
52
  # await page.keyboard.press('Shift+A');
31
53
  # ```
32
54
  #
55
+ # ```python async
56
+ # await page.keyboard.press("Shift+KeyA")
57
+ # # or
58
+ # await page.keyboard.press("Shift+A")
59
+ # ```
60
+ #
61
+ # ```python sync
62
+ # page.keyboard.press("Shift+KeyA")
63
+ # # or
64
+ # page.keyboard.press("Shift+A")
65
+ # ```
66
+ #
33
67
  # An example to trigger select-all with the keyboard
34
68
  #
35
69
  #
@@ -39,6 +73,20 @@ module Playwright
39
73
  # // on macOS
40
74
  # await page.keyboard.press('Meta+A');
41
75
  # ```
76
+ #
77
+ # ```python async
78
+ # # on windows and linux
79
+ # await page.keyboard.press("Control+A")
80
+ # # on mac_os
81
+ # await page.keyboard.press("Meta+A")
82
+ # ```
83
+ #
84
+ # ```python sync
85
+ # # on windows and linux
86
+ # page.keyboard.press("Control+A")
87
+ # # on mac_os
88
+ # page.keyboard.press("Meta+A")
89
+ # ```
42
90
  class Keyboard < PlaywrightApi
43
91
 
44
92
  # Dispatches a `keydown` event.
@@ -64,9 +112,9 @@ module Playwright
64
112
  # [repeat](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/repeat) set to true. To release the key, use
65
113
  # [`method: Keyboard.up`].
66
114
  #
67
- # > **NOTE** Modifier keys DO influence `keyboard.down`. Holding down `Shift` will type the text in upper case.
115
+ # > NOTE: Modifier keys DO influence `keyboard.down`. Holding down `Shift` will type the text in upper case.
68
116
  def down(key)
69
- raise NotImplementedError.new('down is not implemented yet.')
117
+ @impl.down(key)
70
118
  end
71
119
 
72
120
  # Dispatches only `input` event, does not emit the `keydown`, `keyup` or `keypress` events.
@@ -76,9 +124,17 @@ module Playwright
76
124
  # page.keyboard.insertText('嗨');
77
125
  # ```
78
126
  #
79
- # > **NOTE** Modifier keys DO NOT effect `keyboard.insertText`. Holding down `Shift` will not type the text in upper case.
127
+ # ```python async
128
+ # await page.keyboard.insert_text("嗨")
129
+ # ```
130
+ #
131
+ # ```python sync
132
+ # page.keyboard.insert_text("嗨")
133
+ # ```
134
+ #
135
+ # > NOTE: Modifier keys DO NOT effect `keyboard.insertText`. Holding down `Shift` will not type the text in upper case.
80
136
  def insert_text(text)
81
- raise NotImplementedError.new('insert_text is not implemented yet.')
137
+ @impl.insert_text(text)
82
138
  end
83
139
 
84
140
  # `key` can specify the intended [keyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key)
@@ -111,9 +167,33 @@ module Playwright
111
167
  # await browser.close();
112
168
  # ```
113
169
  #
170
+ # ```python async
171
+ # page = await browser.new_page()
172
+ # await page.goto("https://keycode.info")
173
+ # await page.keyboard.press("a")
174
+ # await page.screenshot(path="a.png")
175
+ # await page.keyboard.press("ArrowLeft")
176
+ # await page.screenshot(path="arrow_left.png")
177
+ # await page.keyboard.press("Shift+O")
178
+ # await page.screenshot(path="o.png")
179
+ # await browser.close()
180
+ # ```
181
+ #
182
+ # ```python sync
183
+ # page = browser.new_page()
184
+ # page.goto("https://keycode.info")
185
+ # page.keyboard.press("a")
186
+ # page.screenshot(path="a.png")
187
+ # page.keyboard.press("ArrowLeft")
188
+ # page.screenshot(path="arrow_left.png")
189
+ # page.keyboard.press("Shift+O")
190
+ # page.screenshot(path="o.png")
191
+ # browser.close()
192
+ # ```
193
+ #
114
194
  # Shortcut for [`method: Keyboard.down`] and [`method: Keyboard.up`].
115
195
  def press(key, delay: nil)
116
- raise NotImplementedError.new('press is not implemented yet.')
196
+ @impl.press(key, delay: delay)
117
197
  end
118
198
 
119
199
  # Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text.
@@ -126,14 +206,24 @@ module Playwright
126
206
  # await page.keyboard.type('World', {delay: 100}); // Types slower, like a user
127
207
  # ```
128
208
  #
129
- # > **NOTE** Modifier keys DO NOT effect `keyboard.type`. Holding down `Shift` will not type the text in upper case.
209
+ # ```python async
210
+ # await page.keyboard.type("Hello") # types instantly
211
+ # await page.keyboard.type("World", delay=100) # types slower, like a user
212
+ # ```
213
+ #
214
+ # ```python sync
215
+ # page.keyboard.type("Hello") # types instantly
216
+ # page.keyboard.type("World", delay=100) # types slower, like a user
217
+ # ```
218
+ #
219
+ # > NOTE: Modifier keys DO NOT effect `keyboard.type`. Holding down `Shift` will not type the text in upper case.
130
220
  def type_text(text, delay: nil)
131
- raise NotImplementedError.new('type_text is not implemented yet.')
221
+ @impl.type_text(text, delay: delay)
132
222
  end
133
223
 
134
224
  # Dispatches a `keyup` event.
135
225
  def up(key)
136
- raise NotImplementedError.new('up is not implemented yet.')
226
+ @impl.up(key)
137
227
  end
138
228
  end
139
229
  end
@@ -14,6 +14,28 @@ module Playwright
14
14
  # await page.mouse.move(0, 0);
15
15
  # await page.mouse.up();
16
16
  # ```
17
+ #
18
+ # ```python async
19
+ # # using ‘page.mouse’ to trace a 100x100 square.
20
+ # await page.mouse.move(0, 0)
21
+ # await page.mouse.down()
22
+ # await page.mouse.move(0, 100)
23
+ # await page.mouse.move(100, 100)
24
+ # await page.mouse.move(100, 0)
25
+ # await page.mouse.move(0, 0)
26
+ # await page.mouse.up()
27
+ # ```
28
+ #
29
+ # ```python sync
30
+ # # using ‘page.mouse’ to trace a 100x100 square.
31
+ # page.mouse.move(0, 0)
32
+ # page.mouse.down()
33
+ # page.mouse.move(0, 100)
34
+ # page.mouse.move(100, 100)
35
+ # page.mouse.move(100, 0)
36
+ # page.mouse.move(0, 0)
37
+ # page.mouse.up()
38
+ # ```
17
39
  class Mouse < PlaywrightApi
18
40
 
19
41
  # Shortcut for [`method: Mouse.move`], [`method: Mouse.down`], [`method: Mouse.up`].
@@ -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
  # Page provides methods to interact with a single tab in a `Browser`, or an
5
5
  # [extension background page](https://developer.chrome.com/extensions/background_pages) in Chromium. One [Browser]
@@ -21,6 +21,41 @@ module Playwright
21
21
  # })();
22
22
  # ```
23
23
  #
24
+ # ```python async
25
+ # import asyncio
26
+ # from playwright.async_api import async_playwright
27
+ #
28
+ # async def run(playwright):
29
+ # webkit = playwright.webkit
30
+ # browser = await webkit.launch()
31
+ # context = await browser.new_context()
32
+ # page = await context.new_page()
33
+ # await page.goto("https://example.com")
34
+ # await page.screenshot(path="screenshot.png")
35
+ # await browser.close()
36
+ #
37
+ # async def main():
38
+ # async with async_playwright() as playwright:
39
+ # await run(playwright)
40
+ # asyncio.run(main())
41
+ # ```
42
+ #
43
+ # ```python sync
44
+ # from playwright.sync_api import sync_playwright
45
+ #
46
+ # def run(playwright):
47
+ # webkit = playwright.webkit
48
+ # browser = webkit.launch()
49
+ # context = browser.new_context()
50
+ # page = context.new_page()
51
+ # page.goto("https://example.com")
52
+ # page.screenshot(path="screenshot.png")
53
+ # browser.close()
54
+ #
55
+ # with sync_playwright() as playwright:
56
+ # run(playwright)
57
+ # ```
58
+ #
24
59
  # The Page class emits various events (described below) which can be handled using any of Node's native
25
60
  # [`EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter) methods, such as `on`, `once` or
26
61
  # `removeListener`.
@@ -32,6 +67,10 @@ module Playwright
32
67
  # page.once('load', () => console.log('Page loaded!'));
33
68
  # ```
34
69
  #
70
+ # ```py
71
+ # page.once("load", lambda: print("page loaded!"))
72
+ # ```
73
+ #
35
74
  # To unsubscribe from events use the `removeListener` method:
36
75
  #
37
76
  #
@@ -43,10 +82,18 @@ module Playwright
43
82
  # // Sometime later...
44
83
  # page.removeListener('request', logRequest);
45
84
  # ```
85
+ #
86
+ # ```py
87
+ # def log_request(intercepted_request):
88
+ # print("a request was made:", intercepted_request.url)
89
+ # page.on("request", log_request)
90
+ # # sometime later...
91
+ # page.remove_listener("request", log_request)
92
+ # ```
46
93
  class Page < PlaywrightApi
47
94
 
48
95
  def accessibility # property
49
- wrap_channel_owner(@channel_owner.accessibility)
96
+ wrap_impl(@impl.accessibility)
50
97
  end
51
98
 
52
99
  # Browser-specific Coverage implementation, only available for Chromium atm. See
@@ -56,15 +103,15 @@ module Playwright
56
103
  end
57
104
 
58
105
  def keyboard # property
59
- wrap_channel_owner(@channel_owner.keyboard)
106
+ wrap_impl(@impl.keyboard)
60
107
  end
61
108
 
62
109
  def mouse # property
63
- wrap_channel_owner(@channel_owner.mouse)
110
+ wrap_impl(@impl.mouse)
64
111
  end
65
112
 
66
113
  def touchscreen # property
67
- wrap_channel_owner(@channel_owner.touchscreen)
114
+ wrap_impl(@impl.touchscreen)
68
115
  end
69
116
 
70
117
  # The method finds an element matching the specified selector within the page. If no elements match the selector, the
@@ -72,7 +119,7 @@ module Playwright
72
119
  #
73
120
  # Shortcut for main frame's [`method: Frame.$`].
74
121
  def query_selector(selector)
75
- raise NotImplementedError.new('query_selector is not implemented yet.')
122
+ wrap_impl(@impl.query_selector(selector))
76
123
  end
77
124
 
78
125
  # The method finds all elements matching the specified selector within the page. If no elements match the selector, the
@@ -80,7 +127,7 @@ module Playwright
80
127
  #
81
128
  # Shortcut for main frame's [`method: Frame.$$`].
82
129
  def query_selector_all(selector)
83
- raise NotImplementedError.new('query_selector_all is not implemented yet.')
130
+ wrap_impl(@impl.query_selector_all(selector))
84
131
  end
85
132
 
86
133
  # The method finds an element matching the specified selector within the page and passes it as a first argument to
@@ -98,9 +145,21 @@ module Playwright
98
145
  # const html = await page.$eval('.main-container', (e, suffix) => e.outerHTML + suffix, 'hello');
99
146
  # ```
100
147
  #
148
+ # ```python async
149
+ # search_value = await page.eval_on_selector("#search", "el => el.value")
150
+ # preload_href = await page.eval_on_selector("link[rel=preload]", "el => el.href")
151
+ # html = await page.eval_on_selector(".main-container", "(e, suffix) => e.outer_html + suffix", "hello")
152
+ # ```
153
+ #
154
+ # ```python sync
155
+ # search_value = page.eval_on_selector("#search", "el => el.value")
156
+ # preload_href = page.eval_on_selector("link[rel=preload]", "el => el.href")
157
+ # html = page.eval_on_selector(".main-container", "(e, suffix) => e.outer_html + suffix", "hello")
158
+ # ```
159
+ #
101
160
  # Shortcut for main frame's [`method: Frame.$eval`].
102
161
  def eval_on_selector(selector, pageFunction, arg: nil)
103
- raise NotImplementedError.new('eval_on_selector is not implemented yet.')
162
+ wrap_impl(@impl.eval_on_selector(selector, pageFunction, arg: arg))
104
163
  end
105
164
 
106
165
  # The method finds all elements matching the specified selector within the page and passes an array of matched elements as
@@ -113,10 +172,18 @@ module Playwright
113
172
  #
114
173
  #
115
174
  # ```js
116
- # const divsCounts = await page.$$eval('div', (divs, min) => divs.length >= min, 10);
175
+ # const divCounts = await page.$$eval('div', (divs, min) => divs.length >= min, 10);
176
+ # ```
177
+ #
178
+ # ```python async
179
+ # div_counts = await page.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10)
180
+ # ```
181
+ #
182
+ # ```python sync
183
+ # div_counts = page.eval_on_selector_all("div", "(divs, min) => divs.length >= min", 10)
117
184
  # ```
118
185
  def eval_on_selector_all(selector, pageFunction, arg: nil)
119
- raise NotImplementedError.new('eval_on_selector_all is not implemented yet.')
186
+ wrap_impl(@impl.eval_on_selector_all(selector, pageFunction, arg: arg))
120
187
  end
121
188
 
122
189
  # Adds a script which would be evaluated in one of the following scenarios:
@@ -130,16 +197,28 @@ module Playwright
130
197
  # An example of overriding `Math.random` before the page loads:
131
198
  #
132
199
  #
133
- # ```js
200
+ # ```js browser
134
201
  # // preload.js
135
202
  # Math.random = () => 42;
203
+ # ```
136
204
  #
205
+ #
206
+ # ```js
137
207
  # // In your playwright script, assuming the preload.js file is in same directory
138
- # const preloadFile = fs.readFileSync('./preload.js', 'utf8');
139
- # await page.addInitScript(preloadFile);
208
+ # await page.addInitScript({ path: './preload.js' });
209
+ # ```
210
+ #
211
+ # ```python async
212
+ # # in your playwright script, assuming the preload.js file is in same directory
213
+ # await page.add_init_script(path="./preload.js")
140
214
  # ```
141
215
  #
142
- # > **NOTE** The order of evaluation of multiple scripts installed via [`method: BrowserContext.addInitScript`] and
216
+ # ```python sync
217
+ # # in your playwright script, assuming the preload.js file is in same directory
218
+ # page.add_init_script(path="./preload.js")
219
+ # ```
220
+ #
221
+ # > NOTE: The order of evaluation of multiple scripts installed via [`method: BrowserContext.addInitScript`] and
143
222
  # [`method: Page.addInitScript`] is not defined.
144
223
  def add_init_script(script, arg: nil)
145
224
  raise NotImplementedError.new('add_init_script is not implemented yet.')
@@ -207,7 +286,7 @@ module Playwright
207
286
  noWaitAfter: nil,
208
287
  position: nil,
209
288
  timeout: nil)
210
- raise NotImplementedError.new('click is not implemented yet.')
289
+ wrap_impl(@impl.click(selector, button: button, clickCount: clickCount, delay: delay, force: force, modifiers: modifiers, noWaitAfter: noWaitAfter, position: position, timeout: timeout))
211
290
  end
212
291
 
213
292
  # If `runBeforeUnload` is `false`, does not run any unload handlers and waits for the page to be closed. If
@@ -215,20 +294,20 @@ module Playwright
215
294
  #
216
295
  # By default, `page.close()` **does not** run `beforeunload` handlers.
217
296
  #
218
- # > **NOTE** if `runBeforeUnload` is passed as true, a `beforeunload` dialog might be summoned
219
- # > and should be handled manually via [`event: Page.dialog`] event.
297
+ # > NOTE: if `runBeforeUnload` is passed as true, a `beforeunload` dialog might be summoned and should be handled manually
298
+ # via [`event: Page.dialog`] event.
220
299
  def close(runBeforeUnload: nil)
221
- wrap_channel_owner(@channel_owner.close(runBeforeUnload: runBeforeUnload))
300
+ wrap_impl(@impl.close(runBeforeUnload: runBeforeUnload))
222
301
  end
223
302
 
224
303
  # Gets the full HTML contents of the page, including the doctype.
225
304
  def content
226
- wrap_channel_owner(@channel_owner.content)
305
+ wrap_impl(@impl.content)
227
306
  end
228
307
 
229
308
  # Get the browser context that the page belongs to.
230
309
  def context
231
- wrap_channel_owner(@channel_owner.context)
310
+ wrap_impl(@impl.context)
232
311
  end
233
312
 
234
313
  # This method double clicks an element matching `selector` by performing the following steps:
@@ -243,7 +322,7 @@ module Playwright
243
322
  # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
244
323
  # Passing zero timeout disables this.
245
324
  #
246
- # > **NOTE** `page.dblclick()` dispatches two `click` events and a single `dblclick` event.
325
+ # > NOTE: `page.dblclick()` dispatches two `click` events and a single `dblclick` event.
247
326
  #
248
327
  # Shortcut for main frame's [`method: Frame.dblclick`].
249
328
  def dblclick(
@@ -267,6 +346,14 @@ module Playwright
267
346
  # await page.dispatchEvent('button#submit', 'click');
268
347
  # ```
269
348
  #
349
+ # ```python async
350
+ # await page.dispatch_event("button#submit", "click")
351
+ # ```
352
+ #
353
+ # ```python sync
354
+ # page.dispatch_event("button#submit", "click")
355
+ # ```
356
+ #
270
357
  # Under the hood, it creates an instance of an event based on the given `type`, initializes it with `eventInit` properties
271
358
  # and dispatches it on the element. Events are `composed`, `cancelable` and bubble by default.
272
359
  #
@@ -287,6 +374,18 @@ module Playwright
287
374
  # const dataTransfer = await page.evaluateHandle(() => new DataTransfer());
288
375
  # await page.dispatchEvent('#source', 'dragstart', { dataTransfer });
289
376
  # ```
377
+ #
378
+ # ```python async
379
+ # # note you can only create data_transfer in chromium and firefox
380
+ # data_transfer = await page.evaluate_handle("new DataTransfer()")
381
+ # await page.dispatch_event("#source", "dragstart", { "dataTransfer": data_transfer })
382
+ # ```
383
+ #
384
+ # ```python sync
385
+ # # note you can only create data_transfer in chromium and firefox
386
+ # data_transfer = page.evaluate_handle("new DataTransfer()")
387
+ # page.dispatch_event("#source", "dragstart", { "dataTransfer": data_transfer })
388
+ # ```
290
389
  def dispatch_event(selector, type, eventInit: nil, timeout: nil)
291
390
  raise NotImplementedError.new('dispatch_event is not implemented yet.')
292
391
  end
@@ -312,6 +411,44 @@ module Playwright
312
411
  # // → false
313
412
  # ```
314
413
  #
414
+ # ```python async
415
+ # await page.evaluate("matchMedia('screen').matches")
416
+ # # → True
417
+ # await page.evaluate("matchMedia('print').matches")
418
+ # # → False
419
+ #
420
+ # await page.emulate_media(media="print")
421
+ # await page.evaluate("matchMedia('screen').matches")
422
+ # # → False
423
+ # await page.evaluate("matchMedia('print').matches")
424
+ # # → True
425
+ #
426
+ # await page.emulate_media()
427
+ # await page.evaluate("matchMedia('screen').matches")
428
+ # # → True
429
+ # await page.evaluate("matchMedia('print').matches")
430
+ # # → False
431
+ # ```
432
+ #
433
+ # ```python sync
434
+ # page.evaluate("matchMedia('screen').matches")
435
+ # # → True
436
+ # page.evaluate("matchMedia('print').matches")
437
+ # # → False
438
+ #
439
+ # page.emulate_media(media="print")
440
+ # page.evaluate("matchMedia('screen').matches")
441
+ # # → False
442
+ # page.evaluate("matchMedia('print').matches")
443
+ # # → True
444
+ #
445
+ # page.emulate_media()
446
+ # page.evaluate("matchMedia('screen').matches")
447
+ # # → True
448
+ # page.evaluate("matchMedia('print').matches")
449
+ # # → False
450
+ # ```
451
+ #
315
452
  #
316
453
  # ```js
317
454
  # await page.emulateMedia({ colorScheme: 'dark' });
@@ -322,18 +459,37 @@ module Playwright
322
459
  # await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches);
323
460
  # // → false
324
461
  # ```
462
+ #
463
+ # ```python async
464
+ # await page.emulate_media(color_scheme="dark")
465
+ # await page.evaluate("matchMedia('(prefers-color-scheme: dark)').matches")
466
+ # # → True
467
+ # await page.evaluate("matchMedia('(prefers-color-scheme: light)').matches")
468
+ # # → False
469
+ # await page.evaluate("matchMedia('(prefers-color-scheme: no-preference)').matches")
470
+ # # → False
471
+ # ```
472
+ #
473
+ # ```python sync
474
+ # page.emulate_media(color_scheme="dark")
475
+ # page.evaluate("matchMedia('(prefers-color-scheme: dark)').matches")
476
+ # # → True
477
+ # page.evaluate("matchMedia('(prefers-color-scheme: light)').matches")
478
+ # # → False
479
+ # page.evaluate("matchMedia('(prefers-color-scheme: no-preference)').matches")
480
+ # ```
325
481
  def emulate_media(params)
326
482
  raise NotImplementedError.new('emulate_media is not implemented yet.')
327
483
  end
328
484
 
329
485
  # Returns the value of the `pageFunction` invocation.
330
486
  #
331
- # If the function passed to the `page.evaluate` returns a [Promise], then `page.evaluate` would wait for the promise to
332
- # resolve and return its value.
487
+ # If the function passed to the [`method: Page.evaluate`] returns a [Promise], then [`method: Page.evaluate`] would wait
488
+ # for the promise to resolve and return its value.
333
489
  #
334
- # If the function passed to the `page.evaluate` returns a non-[Serializable] value, then `page.evaluate` resolves to
335
- # `undefined`. DevTools Protocol also supports transferring some additional values that are not serializable by `JSON`:
336
- # `-0`, `NaN`, `Infinity`, `-Infinity`, and bigint literals.
490
+ # If the function passed to the [`method: Page.evaluate`] returns a non-[Serializable] value,
491
+ # then[ method: `Page.evaluate`] resolves to `undefined`. DevTools Protocol also supports transferring some additional
492
+ # values that are not serializable by `JSON`: `-0`, `NaN`, `Infinity`, `-Infinity`, and bigint literals.
337
493
  #
338
494
  # Passing argument to `pageFunction`:
339
495
  #
@@ -345,6 +501,16 @@ module Playwright
345
501
  # console.log(result); // prints "56"
346
502
  # ```
347
503
  #
504
+ # ```python async
505
+ # result = await page.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8])
506
+ # print(result) # prints "56"
507
+ # ```
508
+ #
509
+ # ```python sync
510
+ # result = page.evaluate("([x, y]) => Promise.resolve(x * y)", [7, 8])
511
+ # print(result) # prints "56"
512
+ # ```
513
+ #
348
514
  # A string can also be passed in instead of a function:
349
515
  #
350
516
  #
@@ -354,7 +520,19 @@ module Playwright
354
520
  # console.log(await page.evaluate(`1 + ${x}`)); // prints "11"
355
521
  # ```
356
522
  #
357
- # `ElementHandle` instances can be passed as an argument to the `page.evaluate`:
523
+ # ```python async
524
+ # print(await page.evaluate("1 + 2")) # prints "3"
525
+ # x = 10
526
+ # print(await page.evaluate(f"1 + {x}")) # prints "11"
527
+ # ```
528
+ #
529
+ # ```python sync
530
+ # print(page.evaluate("1 + 2")) # prints "3"
531
+ # x = 10
532
+ # print(page.evaluate(f"1 + {x}")) # prints "11"
533
+ # ```
534
+ #
535
+ # `ElementHandle` instances can be passed as an argument to the [`method: Page.evaluate`]:
358
536
  #
359
537
  #
360
538
  # ```js
@@ -363,18 +541,47 @@ module Playwright
363
541
  # await bodyHandle.dispose();
364
542
  # ```
365
543
  #
544
+ # ```python async
545
+ # body_handle = await page.query_selector("body")
546
+ # html = await page.evaluate("([body, suffix]) => body.innerHTML + suffix", [body_handle, "hello"])
547
+ # await body_handle.dispose()
548
+ # ```
549
+ #
550
+ # ```python sync
551
+ # body_handle = page.query_selector("body")
552
+ # html = page.evaluate("([body, suffix]) => body.innerHTML + suffix", [body_handle, "hello"])
553
+ # body_handle.dispose()
554
+ # ```
555
+ #
366
556
  # Shortcut for main frame's [`method: Frame.evaluate`].
367
557
  def evaluate(pageFunction, arg: nil)
368
- wrap_channel_owner(@channel_owner.evaluate(pageFunction, arg: arg))
558
+ wrap_impl(@impl.evaluate(pageFunction, arg: arg))
369
559
  end
370
560
 
371
561
  # Returns the value of the `pageFunction` invocation as in-page object (JSHandle).
372
562
  #
373
- # The only difference between `page.evaluate` and `page.evaluateHandle` is that `page.evaluateHandle` returns in-page
374
- # object (JSHandle).
563
+ # The only difference between [`method: Page.evaluate`] and [`method: Page.evaluateHandle`] is that
564
+ # [`method: Page.evaluateHandle`] returns in-page object (JSHandle).
565
+ #
566
+ # If the function passed to the [`method: Page.evaluateHandle`] returns a [Promise], then [`method: Page.evaluateHandle`]
567
+ # would wait for the promise to resolve and return its value.
375
568
  #
376
- # If the function passed to the `page.evaluateHandle` returns a [Promise], then `page.evaluateHandle` would wait for the
377
- # promise to resolve and return its value.
569
+ #
570
+ # ```js
571
+ # const aWindowHandle = await page.evaluateHandle(() => Promise.resolve(window));
572
+ # aWindowHandle; // Handle for the window object.
573
+ # ```
574
+ #
575
+ # ```python async
576
+ # # FIXME
577
+ # a_window_handle = await page.evaluate_handle("Promise.resolve(window)")
578
+ # a_window_handle # handle for the window object.
579
+ # ```
580
+ #
581
+ # ```python sync
582
+ # a_window_handle = page.evaluate_handle("Promise.resolve(window)")
583
+ # a_window_handle # handle for the window object.
584
+ # ```
378
585
  #
379
586
  # A string can also be passed in instead of a function:
380
587
  #
@@ -383,7 +590,15 @@ module Playwright
383
590
  # const aHandle = await page.evaluateHandle('document'); // Handle for the 'document'
384
591
  # ```
385
592
  #
386
- # `JSHandle` instances can be passed as an argument to the `page.evaluateHandle`:
593
+ # ```python async
594
+ # a_handle = await page.evaluate_handle("document") # handle for the "document"
595
+ # ```
596
+ #
597
+ # ```python sync
598
+ # a_handle = page.evaluate_handle("document") # handle for the "document"
599
+ # ```
600
+ #
601
+ # `JSHandle` instances can be passed as an argument to the [`method: Page.evaluateHandle`]:
387
602
  #
388
603
  #
389
604
  # ```js
@@ -392,8 +607,22 @@ module Playwright
392
607
  # console.log(await resultHandle.jsonValue());
393
608
  # await resultHandle.dispose();
394
609
  # ```
610
+ #
611
+ # ```python async
612
+ # a_handle = await page.evaluate_handle("document.body")
613
+ # result_handle = await page.evaluate_handle("body => body.innerHTML", a_handle)
614
+ # print(await result_handle.json_value())
615
+ # await result_handle.dispose()
616
+ # ```
617
+ #
618
+ # ```python sync
619
+ # a_handle = page.evaluate_handle("document.body")
620
+ # result_handle = page.evaluate_handle("body => body.innerHTML", a_handle)
621
+ # print(result_handle.json_value())
622
+ # result_handle.dispose()
623
+ # ```
395
624
  def evaluate_handle(pageFunction, arg: nil)
396
- wrap_channel_owner(@channel_owner.evaluate_handle(pageFunction, arg: arg))
625
+ wrap_impl(@impl.evaluate_handle(pageFunction, arg: arg))
397
626
  end
398
627
 
399
628
  # The method adds a function called `name` on the `window` object of every frame in this page. When called, the function
@@ -405,7 +634,7 @@ module Playwright
405
634
  #
406
635
  # See [`method: BrowserContext.exposeBinding`] for the context-wide version.
407
636
  #
408
- # > **NOTE** Functions installed via `page.exposeBinding` survive navigations.
637
+ # > NOTE: Functions installed via [`method: Page.exposeBinding`] survive navigations.
409
638
  #
410
639
  # An example of exposing page URL to all frames in a page:
411
640
  #
@@ -431,6 +660,57 @@ module Playwright
431
660
  # })();
432
661
  # ```
433
662
  #
663
+ # ```python async
664
+ # import asyncio
665
+ # from playwright.async_api import async_playwright
666
+ #
667
+ # async def run(playwright):
668
+ # webkit = playwright.webkit
669
+ # browser = await webkit.launch(headless=false)
670
+ # context = await browser.new_context()
671
+ # page = await context.new_page()
672
+ # await page.expose_binding("pageURL", lambda source: source["page"].url)
673
+ # await page.set_content("""
674
+ # <script>
675
+ # async function onClick() {
676
+ # document.querySelector('div').textContent = await window.pageURL();
677
+ # }
678
+ # </script>
679
+ # <button onclick="onClick()">Click me</button>
680
+ # <div></div>
681
+ # """)
682
+ # await page.click("button")
683
+ #
684
+ # async def main():
685
+ # async with async_playwright() as playwright:
686
+ # await run(playwright)
687
+ # asyncio.run(main())
688
+ # ```
689
+ #
690
+ # ```python sync
691
+ # from playwright.sync_api import sync_playwright
692
+ #
693
+ # def run(playwright):
694
+ # webkit = playwright.webkit
695
+ # browser = webkit.launch(headless=false)
696
+ # context = browser.new_context()
697
+ # page = context.new_page()
698
+ # page.expose_binding("pageURL", lambda source: source["page"].url)
699
+ # page.set_content("""
700
+ # <script>
701
+ # async function onClick() {
702
+ # document.querySelector('div').textContent = await window.pageURL();
703
+ # }
704
+ # </script>
705
+ # <button onclick="onClick()">Click me</button>
706
+ # <div></div>
707
+ # """)
708
+ # page.click("button")
709
+ #
710
+ # with sync_playwright() as playwright:
711
+ # run(playwright)
712
+ # ```
713
+ #
434
714
  # An example of passing an element handle:
435
715
  #
436
716
  #
@@ -446,6 +726,34 @@ module Playwright
446
726
  # <div>Or click me</div>
447
727
  # `);
448
728
  # ```
729
+ #
730
+ # ```python async
731
+ # async def print(source, element):
732
+ # print(await element.text_content())
733
+ #
734
+ # await page.expose_binding("clicked", print, handle=true)
735
+ # await page.set_content("""
736
+ # <script>
737
+ # document.addEventListener('click', event => window.clicked(event.target));
738
+ # </script>
739
+ # <div>Click me</div>
740
+ # <div>Or click me</div>
741
+ # """)
742
+ # ```
743
+ #
744
+ # ```python sync
745
+ # def print(source, element):
746
+ # print(element.text_content())
747
+ #
748
+ # page.expose_binding("clicked", print, handle=true)
749
+ # page.set_content("""
750
+ # <script>
751
+ # document.addEventListener('click', event => window.clicked(event.target));
752
+ # </script>
753
+ # <div>Click me</div>
754
+ # <div>Or click me</div>
755
+ # """)
756
+ # ```
449
757
  def expose_binding(name, callback, handle: nil)
450
758
  raise NotImplementedError.new('expose_binding is not implemented yet.')
451
759
  end
@@ -457,9 +765,9 @@ module Playwright
457
765
  #
458
766
  # See [`method: BrowserContext.exposeFunction`] for context-wide exposed function.
459
767
  #
460
- # > **NOTE** Functions installed via `page.exposeFunction` survive navigations.
768
+ # > NOTE: Functions installed via [`method: Page.exposeFunction`] survive navigations.
461
769
  #
462
- # An example of adding an `md5` function to the page:
770
+ # An example of adding an `sha1` function to the page:
463
771
  #
464
772
  #
465
773
  # ```js
@@ -469,11 +777,11 @@ module Playwright
469
777
  # (async () => {
470
778
  # const browser = await webkit.launch({ headless: false });
471
779
  # const page = await browser.newPage();
472
- # await page.exposeFunction('md5', text => crypto.createHash('md5').update(text).digest('hex'));
780
+ # await page.exposeFunction('sha1', text => crypto.createHash('sha1').update(text).digest('hex'));
473
781
  # await page.setContent(`
474
782
  # <script>
475
783
  # async function onClick() {
476
- # document.querySelector('div').textContent = await window.md5('PLAYWRIGHT');
784
+ # document.querySelector('div').textContent = await window.sha1('PLAYWRIGHT');
477
785
  # }
478
786
  # </script>
479
787
  # <button onclick="onClick()">Click me</button>
@@ -483,34 +791,67 @@ module Playwright
483
791
  # })();
484
792
  # ```
485
793
  #
486
- # An example of adding a `window.readfile` function to the page:
487
- #
488
- #
489
- # ```js
490
- # const { chromium } = require('playwright'); // Or 'firefox' or 'webkit'.
491
- # const fs = require('fs');
794
+ # ```python async
795
+ # import asyncio
796
+ # import hashlib
797
+ # from playwright.async_api import async_playwright
798
+ #
799
+ # async def sha1(text):
800
+ # m = hashlib.sha1()
801
+ # m.update(bytes(text, "utf8"))
802
+ # return m.hexdigest()
803
+ #
804
+ #
805
+ # async def run(playwright):
806
+ # webkit = playwright.webkit
807
+ # browser = await webkit.launch(headless=False)
808
+ # page = await browser.new_page()
809
+ # await page.expose_function("sha1", sha1)
810
+ # await page.set_content("""
811
+ # <script>
812
+ # async function onClick() {
813
+ # document.querySelector('div').textContent = await window.sha1('PLAYWRIGHT');
814
+ # }
815
+ # </script>
816
+ # <button onclick="onClick()">Click me</button>
817
+ # <div></div>
818
+ # """)
819
+ # await page.click("button")
820
+ #
821
+ # async def main():
822
+ # async with async_playwright() as playwright:
823
+ # await run(playwright)
824
+ # asyncio.run(main())
825
+ # ```
492
826
  #
493
- # (async () => {
494
- # const browser = await chromium.launch();
495
- # const page = await browser.newPage();
496
- # page.on('console', msg => console.log(msg.text()));
497
- # await page.exposeFunction('readfile', async filePath => {
498
- # return new Promise((resolve, reject) => {
499
- # fs.readFile(filePath, 'utf8', (err, text) => {
500
- # if (err)
501
- # reject(err);
502
- # else
503
- # resolve(text);
504
- # });
505
- # });
506
- # });
507
- # await page.evaluate(async () => {
508
- # // use window.readfile to read contents of a file
509
- # const content = await window.readfile('/etc/hosts');
510
- # console.log(content);
511
- # });
512
- # await browser.close();
513
- # })();
827
+ # ```python sync
828
+ # import hashlib
829
+ # from playwright.sync_api import sync_playwright
830
+ #
831
+ # def sha1(text):
832
+ # m = hashlib.sha1()
833
+ # m.update(bytes(text, "utf8"))
834
+ # return m.hexdigest()
835
+ #
836
+ #
837
+ # def run(playwright):
838
+ # webkit = playwright.webkit
839
+ # browser = webkit.launch(headless=False)
840
+ # page = browser.new_page()
841
+ # page.expose_function("sha1", sha1)
842
+ # page.set_content("""
843
+ # <script>
844
+ # async function onClick() {
845
+ # document.querySelector('div').textContent = await window.sha1('PLAYWRIGHT');
846
+ # }
847
+ # </script>
848
+ # <button onclick="onClick()">Click me</button>
849
+ # <div></div>
850
+ # """)
851
+ # page.click("button")
852
+ #
853
+ # with sync_playwright() as playwright:
854
+ # run(playwright)
514
855
  # ```
515
856
  def expose_function(name, callback)
516
857
  raise NotImplementedError.new('expose_function is not implemented yet.')
@@ -533,7 +874,7 @@ module Playwright
533
874
  #
534
875
  # Shortcut for main frame's [`method: Frame.focus`].
535
876
  def focus(selector, timeout: nil)
536
- wrap_channel_owner(@channel_owner.focus(selector, timeout: timeout))
877
+ wrap_impl(@impl.focus(selector, timeout: timeout))
537
878
  end
538
879
 
539
880
  # Returns frame matching the specified criteria. Either `name` or `url` must be specified.
@@ -543,17 +884,25 @@ module Playwright
543
884
  # const frame = page.frame('frame-name');
544
885
  # ```
545
886
  #
887
+ # ```py
888
+ # frame = page.frame(name="frame-name")
889
+ # ```
890
+ #
546
891
  #
547
892
  # ```js
548
893
  # const frame = page.frame({ url: /.*domain.*/ });
549
894
  # ```
895
+ #
896
+ # ```py
897
+ # frame = page.frame(url=r".*domain.*")
898
+ # ```
550
899
  def frame(frameSelector)
551
- wrap_channel_owner(@channel_owner.frame(frameSelector))
900
+ wrap_impl(@impl.frame(frameSelector))
552
901
  end
553
902
 
554
903
  # An array of all frames attached to the page.
555
904
  def frames
556
- wrap_channel_owner(@channel_owner.frames)
905
+ wrap_impl(@impl.frames)
557
906
  end
558
907
 
559
908
  # Returns element attribute value.
@@ -591,14 +940,14 @@ module Playwright
591
940
  # Found" and 500 "Internal Server Error". The status code for such responses can be retrieved by calling
592
941
  # [`method: Response.status`].
593
942
  #
594
- # > **NOTE** `page.goto` either throws an error or returns a main resource response. The only exceptions are navigation to
943
+ # > NOTE: `page.goto` either throws an error or returns a main resource response. The only exceptions are navigation to
595
944
  # `about:blank` or navigation to the same URL with a different hash, which would succeed and return `null`.
596
- # > **NOTE** Headless mode doesn't support navigation to a PDF document. See the
945
+ # > NOTE: Headless mode doesn't support navigation to a PDF document. See the
597
946
  # [upstream issue](https://bugs.chromium.org/p/chromium/issues/detail?id=761295).
598
947
  #
599
948
  # Shortcut for main frame's [`method: Frame.goto`]
600
949
  def goto(url, referer: nil, timeout: nil, waitUntil: nil)
601
- wrap_channel_owner(@channel_owner.goto(url, referer: referer, timeout: timeout, waitUntil: waitUntil))
950
+ wrap_impl(@impl.goto(url, referer: referer, timeout: timeout, waitUntil: waitUntil))
602
951
  end
603
952
 
604
953
  # This method hovers over an element matching `selector` by performing the following steps:
@@ -639,7 +988,7 @@ module Playwright
639
988
 
640
989
  # Indicates that the page has been closed.
641
990
  def closed?
642
- wrap_channel_owner(@channel_owner.closed?)
991
+ wrap_impl(@impl.closed?)
643
992
  end
644
993
 
645
994
  # Returns whether the element is disabled, the opposite of [enabled](./actionability.md#enabled).
@@ -669,22 +1018,22 @@ module Playwright
669
1018
 
670
1019
  # The page's main frame. Page is guaranteed to have a main frame which persists during navigations.
671
1020
  def main_frame
672
- wrap_channel_owner(@channel_owner.main_frame)
1021
+ wrap_impl(@impl.main_frame)
673
1022
  end
674
1023
 
675
1024
  # Returns the opener for popup pages and `null` for others. If the opener has been closed already the returns `null`.
676
1025
  def opener
677
- wrap_channel_owner(@channel_owner.opener)
1026
+ wrap_impl(@impl.opener)
678
1027
  end
679
1028
 
680
1029
  # Returns the PDF buffer.
681
1030
  #
682
- # > **NOTE** Generating a pdf is currently only supported in Chromium headless.
1031
+ # > NOTE: Generating a pdf is currently only supported in Chromium headless.
683
1032
  #
684
1033
  # `page.pdf()` generates a pdf of the page with `print` css media. To generate a pdf with `screen` media, call
685
1034
  # [`method: Page.emulateMedia`] before calling `page.pdf()`:
686
1035
  #
687
- # > **NOTE** By default, `page.pdf()` generates a pdf with modified colors for printing. Use the
1036
+ # > NOTE: By default, `page.pdf()` generates a pdf with modified colors for printing. Use the
688
1037
  # [`-webkit-print-color-adjust`](https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-print-color-adjust) property to
689
1038
  # force rendering of exact colors.
690
1039
  #
@@ -695,6 +1044,18 @@ module Playwright
695
1044
  # await page.pdf({path: 'page.pdf'});
696
1045
  # ```
697
1046
  #
1047
+ # ```python async
1048
+ # # generates a pdf with "screen" media type.
1049
+ # await page.emulate_media(media="screen")
1050
+ # await page.pdf(path="page.pdf")
1051
+ # ```
1052
+ #
1053
+ # ```python sync
1054
+ # # generates a pdf with "screen" media type.
1055
+ # page.emulate_media(media="screen")
1056
+ # page.pdf(path="page.pdf")
1057
+ # ```
1058
+ #
698
1059
  # The `width`, `height`, and `margin` options accept values labeled with units. Unlabeled values are treated as pixels.
699
1060
  #
700
1061
  # A few examples:
@@ -721,9 +1082,8 @@ module Playwright
721
1082
  # - `A5`: 5.83in x 8.27in
722
1083
  # - `A6`: 4.13in x 5.83in
723
1084
  #
724
- # > **NOTE** `headerTemplate` and `footerTemplate` markup have the following limitations:
725
- # > 1. Script tags inside templates are not evaluated.
726
- # > 2. Page styles are not visible inside templates.
1085
+ # > NOTE: `headerTemplate` and `footerTemplate` markup have the following limitations: > 1. Script tags inside templates
1086
+ # are not evaluated. > 2. Page styles are not visible inside templates.
727
1087
  def pdf(
728
1088
  displayHeaderFooter: nil,
729
1089
  footerTemplate: nil,
@@ -772,13 +1132,37 @@ module Playwright
772
1132
  # await page.screenshot({ path: 'O.png' });
773
1133
  # await browser.close();
774
1134
  # ```
1135
+ #
1136
+ # ```python async
1137
+ # page = await browser.new_page()
1138
+ # await page.goto("https://keycode.info")
1139
+ # await page.press("body", "A")
1140
+ # await page.screenshot(path="a.png")
1141
+ # await page.press("body", "ArrowLeft")
1142
+ # await page.screenshot(path="arrow_left.png")
1143
+ # await page.press("body", "Shift+O")
1144
+ # await page.screenshot(path="o.png")
1145
+ # await browser.close()
1146
+ # ```
1147
+ #
1148
+ # ```python sync
1149
+ # page = browser.new_page()
1150
+ # page.goto("https://keycode.info")
1151
+ # page.press("body", "A")
1152
+ # page.screenshot(path="a.png")
1153
+ # page.press("body", "ArrowLeft")
1154
+ # page.screenshot(path="arrow_left.png")
1155
+ # page.press("body", "Shift+O")
1156
+ # page.screenshot(path="o.png")
1157
+ # browser.close()
1158
+ # ```
775
1159
  def press(
776
1160
  selector,
777
1161
  key,
778
1162
  delay: nil,
779
1163
  noWaitAfter: nil,
780
1164
  timeout: nil)
781
- wrap_channel_owner(@channel_owner.press(selector, key, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout))
1165
+ wrap_impl(@impl.press(selector, key, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout))
782
1166
  end
783
1167
 
784
1168
  # Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
@@ -791,7 +1175,7 @@ module Playwright
791
1175
  #
792
1176
  # Once routing is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted.
793
1177
  #
794
- # > **NOTE** The handler will only be called for the first url if the response is a redirect.
1178
+ # > NOTE: The handler will only be called for the first url if the response is a redirect.
795
1179
  #
796
1180
  # An example of a naïve handler that aborts all image requests:
797
1181
  #
@@ -803,6 +1187,20 @@ module Playwright
803
1187
  # await browser.close();
804
1188
  # ```
805
1189
  #
1190
+ # ```python async
1191
+ # page = await browser.new_page()
1192
+ # await page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())
1193
+ # await page.goto("https://example.com")
1194
+ # await browser.close()
1195
+ # ```
1196
+ #
1197
+ # ```python sync
1198
+ # page = browser.new_page()
1199
+ # page.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())
1200
+ # page.goto("https://example.com")
1201
+ # browser.close()
1202
+ # ```
1203
+ #
806
1204
  # or the same snippet using a regex pattern instead:
807
1205
  #
808
1206
  #
@@ -813,17 +1211,31 @@ module Playwright
813
1211
  # await browser.close();
814
1212
  # ```
815
1213
  #
1214
+ # ```python async
1215
+ # page = await browser.new_page()
1216
+ # await page.route(re.compile(r"(\.png$)|(\.jpg$)"), lambda route: route.abort())
1217
+ # await page.goto("https://example.com")
1218
+ # await browser.close()
1219
+ # ```
1220
+ #
1221
+ # ```python sync
1222
+ # page = browser.new_page()
1223
+ # page.route(re.compile(r"(\.png$)|(\.jpg$)"), lambda route: route.abort())
1224
+ # page.goto("https://example.com")
1225
+ # browser.close()
1226
+ # ```
1227
+ #
816
1228
  # Page routes take precedence over browser context routes (set up with [`method: BrowserContext.route`]) when request
817
1229
  # matches both handlers.
818
1230
  #
819
- # > **NOTE** Enabling routing disables http cache.
1231
+ # > NOTE: Enabling routing disables http cache.
820
1232
  def route(url, handler)
821
1233
  raise NotImplementedError.new('route is not implemented yet.')
822
1234
  end
823
1235
 
824
1236
  # Returns the buffer with the captured screenshot.
825
1237
  #
826
- # > **NOTE** Screenshots take at least 1/6 second on Chromium OS X and Chromium Windows. See https://crbug.com/741689 for
1238
+ # > NOTE: Screenshots take at least 1/6 second on Chromium OS X and Chromium Windows. See https://crbug.com/741689 for
827
1239
  # discussion.
828
1240
  def screenshot(
829
1241
  clip: nil,
@@ -833,7 +1245,7 @@ module Playwright
833
1245
  quality: nil,
834
1246
  timeout: nil,
835
1247
  type: nil)
836
- wrap_channel_owner(@channel_owner.screenshot(clip: clip, fullPage: fullPage, omitBackground: omitBackground, path: path, quality: quality, timeout: timeout, type: type))
1248
+ wrap_impl(@impl.screenshot(clip: clip, fullPage: fullPage, omitBackground: omitBackground, path: path, quality: quality, timeout: timeout, type: type))
837
1249
  end
838
1250
 
839
1251
  # Returns the array of option values that have been successfully selected.
@@ -841,12 +1253,14 @@ module Playwright
841
1253
  # Triggers a `change` and `input` event once all the provided options have been selected. If there's no `<select>` element
842
1254
  # matching `selector`, the method throws an error.
843
1255
  #
1256
+ # Will wait until all specified options are present in the `<select>` element.
1257
+ #
844
1258
  #
845
1259
  # ```js
846
1260
  # // single selection matching the value
847
1261
  # page.selectOption('select#colors', 'blue');
848
1262
  #
849
- # // single selection matching both the value and the label
1263
+ # // single selection matching the label
850
1264
  # page.selectOption('select#colors', { label: 'Blue' });
851
1265
  #
852
1266
  # // multiple selection
@@ -854,13 +1268,31 @@ module Playwright
854
1268
  #
855
1269
  # ```
856
1270
  #
1271
+ # ```python async
1272
+ # # single selection matching the value
1273
+ # await page.select_option("select#colors", "blue")
1274
+ # # single selection matching the label
1275
+ # await page.select_option("select#colors", label="blue")
1276
+ # # multiple selection
1277
+ # await page.select_option("select#colors", value=["red", "green", "blue"])
1278
+ # ```
1279
+ #
1280
+ # ```python sync
1281
+ # # single selection matching the value
1282
+ # page.select_option("select#colors", "blue")
1283
+ # # single selection matching both the label
1284
+ # page.select_option("select#colors", label="blue")
1285
+ # # multiple selection
1286
+ # page.select_option("select#colors", value=["red", "green", "blue"])
1287
+ # ```
1288
+ #
857
1289
  # Shortcut for main frame's [`method: Frame.selectOption`]
858
1290
  def select_option(selector, values, noWaitAfter: nil, timeout: nil)
859
1291
  raise NotImplementedError.new('select_option is not implemented yet.')
860
1292
  end
861
1293
 
862
1294
  def set_content(html, timeout: nil, waitUntil: nil)
863
- wrap_channel_owner(@channel_owner.set_content(html, timeout: timeout, waitUntil: waitUntil))
1295
+ wrap_impl(@impl.set_content(html, timeout: timeout, waitUntil: waitUntil))
864
1296
  end
865
1297
  alias_method :content=, :set_content
866
1298
 
@@ -872,7 +1304,7 @@ module Playwright
872
1304
  # - [`method: Page.setContent`]
873
1305
  # - [`method: Page.waitForNavigation`]
874
1306
  #
875
- # > **NOTE** [`method: Page.setDefaultNavigationTimeout`] takes priority over [`method: Page.setDefaultTimeout`],
1307
+ # > NOTE: [`method: Page.setDefaultNavigationTimeout`] takes priority over [`method: Page.setDefaultTimeout`],
876
1308
  # [`method: BrowserContext.setDefaultTimeout`] and [`method: BrowserContext.setDefaultNavigationTimeout`].
877
1309
  def set_default_navigation_timeout(timeout)
878
1310
  raise NotImplementedError.new('set_default_navigation_timeout is not implemented yet.')
@@ -881,7 +1313,7 @@ module Playwright
881
1313
 
882
1314
  # This setting will change the default maximum time for all the methods accepting `timeout` option.
883
1315
  #
884
- # > **NOTE** [`method: Page.setDefaultNavigationTimeout`] takes priority over [`method: Page.setDefaultTimeout`].
1316
+ # > NOTE: [`method: Page.setDefaultNavigationTimeout`] takes priority over [`method: Page.setDefaultTimeout`].
885
1317
  def set_default_timeout(timeout)
886
1318
  raise NotImplementedError.new('set_default_timeout is not implemented yet.')
887
1319
  end
@@ -889,7 +1321,7 @@ module Playwright
889
1321
 
890
1322
  # The extra HTTP headers will be sent with every request the page initiates.
891
1323
  #
892
- # > **NOTE** page.setExtraHTTPHeaders does not guarantee the order of headers in the outgoing requests.
1324
+ # > NOTE: [`method: Page.setExtraHTTPHeaders`] does not guarantee the order of headers in the outgoing requests.
893
1325
  def set_extra_http_headers(headers)
894
1326
  raise NotImplementedError.new('set_extra_http_headers is not implemented yet.')
895
1327
  end
@@ -919,8 +1351,20 @@ module Playwright
919
1351
  # });
920
1352
  # await page.goto('https://example.com');
921
1353
  # ```
1354
+ #
1355
+ # ```python async
1356
+ # page = await browser.new_page()
1357
+ # await page.set_viewport_size({"width": 640, "height": 480})
1358
+ # await page.goto("https://example.com")
1359
+ # ```
1360
+ #
1361
+ # ```python sync
1362
+ # page = browser.new_page()
1363
+ # page.set_viewport_size({"width": 640, "height": 480})
1364
+ # page.goto("https://example.com")
1365
+ # ```
922
1366
  def set_viewport_size(viewportSize)
923
- wrap_channel_owner(@channel_owner.set_viewport_size(viewportSize))
1367
+ wrap_impl(@impl.set_viewport_size(viewportSize))
924
1368
  end
925
1369
  alias_method :viewport_size=, :set_viewport_size
926
1370
 
@@ -935,7 +1379,7 @@ module Playwright
935
1379
  # When all steps combined have not finished during the specified `timeout`, this method rejects with a `TimeoutError`.
936
1380
  # Passing zero timeout disables this.
937
1381
  #
938
- # > **NOTE** `page.tap()` requires that the `hasTouch` option of the browser context be set to true.
1382
+ # > NOTE: [`method: Page.tap`] requires that the `hasTouch` option of the browser context be set to true.
939
1383
  #
940
1384
  # Shortcut for main frame's [`method: Frame.tap`].
941
1385
  def tap_point(
@@ -955,7 +1399,7 @@ module Playwright
955
1399
 
956
1400
  # Returns the page's title. Shortcut for main frame's [`method: Frame.title`].
957
1401
  def title
958
- wrap_channel_owner(@channel_owner.title)
1402
+ wrap_impl(@impl.title)
959
1403
  end
960
1404
 
961
1405
  # Sends a `keydown`, `keypress`/`input`, and `keyup` event for each character in the text. `page.type` can be used to send
@@ -969,6 +1413,16 @@ module Playwright
969
1413
  # await page.type('#mytextarea', 'World', {delay: 100}); // Types slower, like a user
970
1414
  # ```
971
1415
  #
1416
+ # ```python async
1417
+ # await page.type("#mytextarea", "hello") # types instantly
1418
+ # await page.type("#mytextarea", "world", delay=100) # types slower, like a user
1419
+ # ```
1420
+ #
1421
+ # ```python sync
1422
+ # page.type("#mytextarea", "hello") # types instantly
1423
+ # page.type("#mytextarea", "world", delay=100) # types slower, like a user
1424
+ # ```
1425
+ #
972
1426
  # Shortcut for main frame's [`method: Frame.type`].
973
1427
  def type_text(
974
1428
  selector,
@@ -976,7 +1430,7 @@ module Playwright
976
1430
  delay: nil,
977
1431
  noWaitAfter: nil,
978
1432
  timeout: nil)
979
- wrap_channel_owner(@channel_owner.type_text(selector, text, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout))
1433
+ wrap_impl(@impl.type_text(selector, text, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout))
980
1434
  end
981
1435
 
982
1436
  # This method unchecks an element matching `selector` by performing the following steps:
@@ -1005,7 +1459,7 @@ module Playwright
1005
1459
 
1006
1460
  # Shortcut for main frame's [`method: Frame.url`].
1007
1461
  def url
1008
- wrap_channel_owner(@channel_owner.url)
1462
+ wrap_impl(@impl.url)
1009
1463
  end
1010
1464
 
1011
1465
  # Video object associated with this page.
@@ -1014,15 +1468,33 @@ module Playwright
1014
1468
  end
1015
1469
 
1016
1470
  def viewport_size
1017
- wrap_channel_owner(@channel_owner.viewport_size)
1471
+ wrap_impl(@impl.viewport_size)
1018
1472
  end
1019
1473
 
1020
- # Returns the event data value.
1021
- #
1022
1474
  # Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy
1023
- # value. Will throw an error if the page is closed before the event is fired.
1024
- def wait_for_event(event, optionsOrPredicate: nil, &block)
1025
- wrap_channel_owner(@channel_owner.wait_for_event(event, optionsOrPredicate: optionsOrPredicate, &wrap_block_call(block)))
1475
+ # value. Will throw an error if the page is closed before the event is fired. Returns the event data value.
1476
+ #
1477
+ #
1478
+ # ```js
1479
+ # const [frame, _] = await Promise.all([
1480
+ # page.waitForEvent('framenavigated'),
1481
+ # page.click('button')
1482
+ # ]);
1483
+ # ```
1484
+ #
1485
+ # ```python async
1486
+ # async with page.expect_event("framenavigated") as event_info:
1487
+ # await page.click("button")
1488
+ # frame = await event_info.value
1489
+ # ```
1490
+ #
1491
+ # ```python sync
1492
+ # with page.expect_event("framenavigated") as event_info:
1493
+ # page.click("button")
1494
+ # frame = event_info.value
1495
+ # ```
1496
+ def expect_event(event, optionsOrPredicate: nil)
1497
+ raise NotImplementedError.new('expect_event is not implemented yet.')
1026
1498
  end
1027
1499
 
1028
1500
  # Returns when the `pageFunction` returns a truthy value. It resolves to a JSHandle of the truthy value.
@@ -1036,14 +1508,47 @@ module Playwright
1036
1508
  # (async () => {
1037
1509
  # const browser = await webkit.launch();
1038
1510
  # const page = await browser.newPage();
1039
- # const watchDog = page.waitForFunction('window.innerWidth < 100');
1511
+ # const watchDog = page.waitForFunction(() => window.innerWidth < 100);
1040
1512
  # await page.setViewportSize({width: 50, height: 50});
1041
1513
  # await watchDog;
1042
1514
  # await browser.close();
1043
1515
  # })();
1044
1516
  # ```
1045
1517
  #
1046
- # To pass an argument to the predicate of `page.waitForFunction` function:
1518
+ # ```python async
1519
+ # import asyncio
1520
+ # from playwright.async_api import async_playwright
1521
+ #
1522
+ # async def run(playwright):
1523
+ # webkit = playwright.webkit
1524
+ # browser = await webkit.launch()
1525
+ # page = await browser.new_page()
1526
+ # await page.evaluate("window.x = 0; setTimeout(() => { window.x = 100 }, 1000);", force_expr=True)
1527
+ # await page.wait_for_function("() => window.x > 0")
1528
+ # await browser.close()
1529
+ #
1530
+ # async def main():
1531
+ # async with async_playwright() as playwright:
1532
+ # await run(playwright)
1533
+ # asyncio.run(main())
1534
+ # ```
1535
+ #
1536
+ # ```python sync
1537
+ # from playwright.sync_api import sync_playwright
1538
+ #
1539
+ # def run(playwright):
1540
+ # webkit = playwright.webkit
1541
+ # browser = webkit.launch()
1542
+ # page = browser.new_page()
1543
+ # page.evaluate("window.x = 0; setTimeout(() => { window.x = 100 }, 1000);", force_expr=True)
1544
+ # page.wait_for_function("() => window.x > 0")
1545
+ # browser.close()
1546
+ #
1547
+ # with sync_playwright() as playwright:
1548
+ # run(playwright)
1549
+ # ```
1550
+ #
1551
+ # To pass an argument to the predicate of [`method: Page.waitForFunction`] function:
1047
1552
  #
1048
1553
  #
1049
1554
  # ```js
@@ -1051,6 +1556,16 @@ module Playwright
1051
1556
  # await page.waitForFunction(selector => !!document.querySelector(selector), selector);
1052
1557
  # ```
1053
1558
  #
1559
+ # ```python async
1560
+ # selector = ".foo"
1561
+ # await page.wait_for_function("selector => !!document.querySelector(selector)", selector)
1562
+ # ```
1563
+ #
1564
+ # ```python sync
1565
+ # selector = ".foo"
1566
+ # page.wait_for_function("selector => !!document.querySelector(selector)", selector)
1567
+ # ```
1568
+ #
1054
1569
  # Shortcut for main frame's [`method: Frame.waitForFunction`].
1055
1570
  def wait_for_function(pageFunction, arg: nil, polling: nil, timeout: nil)
1056
1571
  raise NotImplementedError.new('wait_for_function is not implemented yet.')
@@ -1067,6 +1582,16 @@ module Playwright
1067
1582
  # await page.waitForLoadState(); // The promise resolves after 'load' event.
1068
1583
  # ```
1069
1584
  #
1585
+ # ```python async
1586
+ # await page.click("button") # click triggers navigation.
1587
+ # await page.wait_for_load_state() # the promise resolves after "load" event.
1588
+ # ```
1589
+ #
1590
+ # ```python sync
1591
+ # page.click("button") # click triggers navigation.
1592
+ # page.wait_for_load_state() # the promise resolves after "load" event.
1593
+ # ```
1594
+ #
1070
1595
  #
1071
1596
  # ```js
1072
1597
  # const [popup] = await Promise.all([
@@ -1077,14 +1602,32 @@ module Playwright
1077
1602
  # console.log(await popup.title()); // Popup is ready to use.
1078
1603
  # ```
1079
1604
  #
1605
+ # ```python async
1606
+ # async with page.expect_popup() as page_info:
1607
+ # await page.click("button") # click triggers a popup.
1608
+ # popup = await page_info.value
1609
+ # # Following resolves after "domcontentloaded" event.
1610
+ # await popup.wait_for_load_state("domcontentloaded")
1611
+ # print(await popup.title()) # popup is ready to use.
1612
+ # ```
1613
+ #
1614
+ # ```python sync
1615
+ # with page.expect_popup() as page_info:
1616
+ # page.click("button") # click triggers a popup.
1617
+ # popup = page_info.value
1618
+ # # Following resolves after "domcontentloaded" event.
1619
+ # popup.wait_for_load_state("domcontentloaded")
1620
+ # print(popup.title()) # popup is ready to use.
1621
+ # ```
1622
+ #
1080
1623
  # Shortcut for main frame's [`method: Frame.waitForLoadState`].
1081
1624
  def wait_for_load_state(state: nil, timeout: nil)
1082
1625
  raise NotImplementedError.new('wait_for_load_state is not implemented yet.')
1083
1626
  end
1084
1627
 
1085
- # Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
1086
- # last redirect. In case of navigation to a different anchor or navigation due to History API usage, the navigation will
1087
- # resolve with `null`.
1628
+ # Waits for the main frame navigation and returns the main resource response. In case of multiple redirects, the
1629
+ # navigation will resolve with the response of the last redirect. In case of navigation to a different anchor or
1630
+ # navigation due to History API usage, the navigation will resolve with `null`.
1088
1631
  #
1089
1632
  # This resolves when the page navigates to a new URL or reloads. It is useful for when you run code which will indirectly
1090
1633
  # cause the page to navigate. e.g. The click target has an `onclick` handler that triggers navigation from a `setTimeout`.
@@ -1098,12 +1641,24 @@ module Playwright
1098
1641
  # ]);
1099
1642
  # ```
1100
1643
  #
1101
- # **NOTE** Usage of the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) to change the URL is
1644
+ # ```python async
1645
+ # async with page.expect_navigation():
1646
+ # await page.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
1647
+ # # Resolves after navigation has finished
1648
+ # ```
1649
+ #
1650
+ # ```python sync
1651
+ # with page.expect_navigation():
1652
+ # page.click("a.delayed-navigation") # clicking the link will indirectly cause a navigation
1653
+ # # Resolves after navigation has finished
1654
+ # ```
1655
+ #
1656
+ # > NOTE: Usage of the [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) to change the URL is
1102
1657
  # considered a navigation.
1103
1658
  #
1104
1659
  # Shortcut for main frame's [`method: Frame.waitForNavigation`].
1105
- def wait_for_navigation(timeout: nil, url: nil, waitUntil: nil)
1106
- raise NotImplementedError.new('wait_for_navigation is not implemented yet.')
1660
+ def expect_navigation(timeout: nil, url: nil, waitUntil: nil)
1661
+ raise NotImplementedError.new('expect_navigation is not implemented yet.')
1107
1662
  end
1108
1663
 
1109
1664
  # Waits for the matching request and returns it.
@@ -1115,12 +1670,32 @@ module Playwright
1115
1670
  # return firstRequest.url();
1116
1671
  # ```
1117
1672
  #
1673
+ # ```python async
1674
+ # async with page.expect_request("http://example.com/resource") as first:
1675
+ # await page.click('button')
1676
+ # first_request = await first.value
1677
+ #
1678
+ # async with page.expect_request(lambda request: request.url == "http://example.com" and request.method == "get") as second:
1679
+ # await page.click('img')
1680
+ # second_request = await second.value
1681
+ # ```
1682
+ #
1683
+ # ```python sync
1684
+ # with page.expect_request("http://example.com/resource") as first:
1685
+ # page.click('button')
1686
+ # first_request = first.value
1687
+ #
1688
+ # with page.expect_request(lambda request: request.url == "http://example.com" and request.method == "get") as second:
1689
+ # page.click('img')
1690
+ # second_request = second.value
1691
+ # ```
1692
+ #
1118
1693
  #
1119
1694
  # ```js
1120
1695
  # await page.waitForRequest(request => request.url().searchParams.get('foo') === 'bar' && request.url().searchParams.get('foo2') === 'bar2');
1121
1696
  # ```
1122
- def wait_for_request(urlOrPredicate, timeout: nil)
1123
- wrap_channel_owner(@channel_owner.wait_for_request(urlOrPredicate, timeout: timeout))
1697
+ def expect_request(urlOrPredicate, timeout: nil)
1698
+ raise NotImplementedError.new('expect_request is not implemented yet.')
1124
1699
  end
1125
1700
 
1126
1701
  # Returns the matched response.
@@ -1131,8 +1706,20 @@ module Playwright
1131
1706
  # const finalResponse = await page.waitForResponse(response => response.url() === 'https://example.com' && response.status() === 200);
1132
1707
  # return finalResponse.ok();
1133
1708
  # ```
1134
- def wait_for_response(urlOrPredicate, timeout: nil)
1135
- wrap_channel_owner(@channel_owner.wait_for_response(urlOrPredicate, timeout: timeout))
1709
+ #
1710
+ # ```python async
1711
+ # first_response = await page.wait_for_response("https://example.com/resource")
1712
+ # final_response = await page.wait_for_response(lambda response: response.url == "https://example.com" and response.status === 200)
1713
+ # return final_response.ok
1714
+ # ```
1715
+ #
1716
+ # ```python sync
1717
+ # first_response = page.wait_for_response("https://example.com/resource")
1718
+ # final_response = page.wait_for_response(lambda response: response.url == "https://example.com" and response.status === 200)
1719
+ # return final_response.ok
1720
+ # ```
1721
+ def expect_response(urlOrPredicate, timeout: nil)
1722
+ raise NotImplementedError.new('expect_response is not implemented yet.')
1136
1723
  end
1137
1724
 
1138
1725
  # Returns when element specified by selector satisfies `state` option. Returns `null` if waiting for `hidden` or
@@ -1151,16 +1738,51 @@ module Playwright
1151
1738
  # (async () => {
1152
1739
  # const browser = await chromium.launch();
1153
1740
  # const page = await browser.newPage();
1154
- # let currentURL;
1155
- # page
1156
- # .waitForSelector('img')
1157
- # .then(() => console.log('First URL with image: ' + currentURL));
1158
- # for (currentURL of ['https://example.com', 'https://google.com', 'https://bbc.com']) {
1741
+ # for (let currentURL of ['https://google.com', 'https://bbc.com']) {
1159
1742
  # await page.goto(currentURL);
1743
+ # const element = await page.waitForSelector('img');
1744
+ # console.log('Loaded image: ' + await element.getAttribute('src'));
1160
1745
  # }
1161
1746
  # await browser.close();
1162
1747
  # })();
1163
1748
  # ```
1749
+ #
1750
+ # ```python async
1751
+ # import asyncio
1752
+ # from playwright.async_api import async_playwright
1753
+ #
1754
+ # async def run(playwright):
1755
+ # chromium = playwright.chromium
1756
+ # browser = await chromium.launch()
1757
+ # page = await browser.new_page()
1758
+ # for current_url in ["https://google.com", "https://bbc.com"]:
1759
+ # await page.goto(current_url, wait_until="domcontentloaded")
1760
+ # element = await page.wait_for_selector("img")
1761
+ # print("Loaded image: " + str(await element.get_attribute("src")))
1762
+ # await browser.close()
1763
+ #
1764
+ # async def main():
1765
+ # async with async_playwright() as playwright:
1766
+ # await run(playwright)
1767
+ # asyncio.run(main())
1768
+ # ```
1769
+ #
1770
+ # ```python sync
1771
+ # from playwright.sync_api import sync_playwright
1772
+ #
1773
+ # def run(playwright):
1774
+ # chromium = playwright.chromium
1775
+ # browser = chromium.launch()
1776
+ # page = browser.new_page()
1777
+ # for current_url in ["https://google.com", "https://bbc.com"]:
1778
+ # page.goto(current_url, wait_until="domcontentloaded")
1779
+ # element = page.wait_for_selector("img")
1780
+ # print("Loaded image: " + str(element.get_attribute("src")))
1781
+ # browser.close()
1782
+ #
1783
+ # with sync_playwright() as playwright:
1784
+ # run(playwright)
1785
+ # ```
1164
1786
  def wait_for_selector(selector, state: nil, timeout: nil)
1165
1787
  raise NotImplementedError.new('wait_for_selector is not implemented yet.')
1166
1788
  end
@@ -1176,6 +1798,16 @@ module Playwright
1176
1798
  # await page.waitForTimeout(1000);
1177
1799
  # ```
1178
1800
  #
1801
+ # ```python async
1802
+ # # wait for 1 second
1803
+ # await page.wait_for_timeout(1000)
1804
+ # ```
1805
+ #
1806
+ # ```python sync
1807
+ # # wait for 1 second
1808
+ # page.wait_for_timeout(1000)
1809
+ # ```
1810
+ #
1179
1811
  # Shortcut for main frame's [`method: Frame.waitForTimeout`].
1180
1812
  def wait_for_timeout(timeout)
1181
1813
  raise NotImplementedError.new('wait_for_timeout is not implemented yet.')
@@ -1184,37 +1816,57 @@ module Playwright
1184
1816
  # This method returns all of the dedicated [WebWorkers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API)
1185
1817
  # associated with the page.
1186
1818
  #
1187
- # > **NOTE** This does not contain ServiceWorkers
1819
+ # > NOTE: This does not contain ServiceWorkers
1188
1820
  def workers
1189
1821
  raise NotImplementedError.new('workers is not implemented yet.')
1190
1822
  end
1191
1823
 
1192
1824
  # @nodoc
1193
1825
  def owned_context=(req)
1194
- wrap_channel_owner(@channel_owner.owned_context=(req))
1826
+ wrap_impl(@impl.owned_context=(req))
1827
+ end
1828
+
1829
+ # @nodoc
1830
+ def wait_for_navigation(timeout: nil, url: nil, waitUntil: nil, &block)
1831
+ wrap_impl(@impl.wait_for_navigation(timeout: timeout, url: url, waitUntil: waitUntil, &wrap_block_call(block)))
1832
+ end
1833
+
1834
+ # @nodoc
1835
+ def wait_for_request(urlOrPredicate, timeout: nil)
1836
+ wrap_impl(@impl.wait_for_request(urlOrPredicate, timeout: timeout))
1837
+ end
1838
+
1839
+ # @nodoc
1840
+ def wait_for_event(event, optionsOrPredicate: nil, &block)
1841
+ wrap_impl(@impl.wait_for_event(event, optionsOrPredicate: optionsOrPredicate, &wrap_block_call(block)))
1842
+ end
1843
+
1844
+ # @nodoc
1845
+ def wait_for_response(urlOrPredicate, timeout: nil)
1846
+ wrap_impl(@impl.wait_for_response(urlOrPredicate, timeout: timeout))
1195
1847
  end
1196
1848
 
1197
1849
  # @nodoc
1198
1850
  def after_initialize
1199
- wrap_channel_owner(@channel_owner.after_initialize)
1851
+ wrap_impl(@impl.after_initialize)
1200
1852
  end
1201
1853
 
1202
1854
  # -- inherited from EventEmitter --
1203
1855
  # @nodoc
1204
- def off(event, callback)
1205
- wrap_channel_owner(@channel_owner.off(event, callback))
1856
+ def on(event, callback)
1857
+ wrap_impl(@impl.on(event, callback))
1206
1858
  end
1207
1859
 
1208
1860
  # -- inherited from EventEmitter --
1209
1861
  # @nodoc
1210
- def once(event, callback)
1211
- wrap_channel_owner(@channel_owner.once(event, callback))
1862
+ def off(event, callback)
1863
+ wrap_impl(@impl.off(event, callback))
1212
1864
  end
1213
1865
 
1214
1866
  # -- inherited from EventEmitter --
1215
1867
  # @nodoc
1216
- def on(event, callback)
1217
- wrap_channel_owner(@channel_owner.on(event, callback))
1868
+ def once(event, callback)
1869
+ wrap_impl(@impl.once(event, callback))
1218
1870
  end
1219
1871
  end
1220
1872
  end