playwright-ruby-client 0.0.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +114 -2
  3. data/docs/api_coverage.md +351 -0
  4. data/lib/playwright.rb +7 -1
  5. data/lib/playwright/android_input_impl.rb +23 -0
  6. data/lib/playwright/api_implementation.rb +18 -0
  7. data/lib/playwright/channel.rb +7 -0
  8. data/lib/playwright/channel_owner.rb +3 -2
  9. data/lib/playwright/channel_owners/android.rb +10 -1
  10. data/lib/playwright/channel_owners/android_device.rb +163 -0
  11. data/lib/playwright/channel_owners/browser.rb +13 -13
  12. data/lib/playwright/channel_owners/browser_context.rb +9 -1
  13. data/lib/playwright/channel_owners/download.rb +27 -0
  14. data/lib/playwright/channel_owners/element_handle.rb +306 -0
  15. data/lib/playwright/channel_owners/frame.rb +371 -19
  16. data/lib/playwright/channel_owners/js_handle.rb +51 -0
  17. data/lib/playwright/channel_owners/page.rb +416 -19
  18. data/lib/playwright/channel_owners/request.rb +98 -0
  19. data/lib/playwright/channel_owners/webkit_browser.rb +1 -1
  20. data/lib/playwright/connection.rb +9 -6
  21. data/lib/playwright/errors.rb +2 -2
  22. data/lib/playwright/event_emitter.rb +8 -1
  23. data/lib/playwright/event_emitter_proxy.rb +49 -0
  24. data/lib/playwright/file_chooser_impl.rb +23 -0
  25. data/lib/playwright/http_headers.rb +20 -0
  26. data/lib/playwright/input_files.rb +42 -0
  27. data/lib/playwright/javascript/expression.rb +37 -0
  28. data/lib/playwright/javascript/function.rb +37 -0
  29. data/lib/playwright/javascript/value_parser.rb +1 -1
  30. data/lib/playwright/javascript/value_serializer.rb +11 -11
  31. data/lib/playwright/keyboard_impl.rb +36 -0
  32. data/lib/playwright/mouse_impl.rb +7 -0
  33. data/lib/playwright/playwright_api.rb +84 -29
  34. data/lib/playwright/select_option_values.rb +32 -0
  35. data/lib/playwright/timeout_settings.rb +2 -2
  36. data/lib/playwright/touchscreen_impl.rb +7 -0
  37. data/lib/playwright/url_matcher.rb +19 -0
  38. data/lib/playwright/utils.rb +18 -0
  39. data/lib/playwright/version.rb +1 -1
  40. data/lib/playwright/wait_helper.rb +1 -1
  41. data/lib/playwright_api/accessibility.rb +46 -6
  42. data/lib/playwright_api/android.rb +37 -0
  43. data/lib/playwright_api/android_device.rb +82 -0
  44. data/lib/playwright_api/android_input.rb +25 -0
  45. data/lib/playwright_api/binding_call.rb +10 -6
  46. data/lib/playwright_api/browser.rb +85 -18
  47. data/lib/playwright_api/browser_context.rb +269 -37
  48. data/lib/playwright_api/browser_type.rb +60 -11
  49. data/lib/playwright_api/cdp_session.rb +23 -1
  50. data/lib/playwright_api/chromium_browser_context.rb +18 -6
  51. data/lib/playwright_api/console_message.rb +14 -15
  52. data/lib/playwright_api/dialog.rb +48 -2
  53. data/lib/playwright_api/download.rb +47 -10
  54. data/lib/playwright_api/element_handle.rb +269 -110
  55. data/lib/playwright_api/file_chooser.rb +23 -7
  56. data/lib/playwright_api/frame.rb +439 -154
  57. data/lib/playwright_api/js_handle.rb +69 -24
  58. data/lib/playwright_api/keyboard.rb +99 -9
  59. data/lib/playwright_api/mouse.rb +22 -0
  60. data/lib/playwright_api/page.rb +856 -229
  61. data/lib/playwright_api/playwright.rb +108 -20
  62. data/lib/playwright_api/request.rb +77 -29
  63. data/lib/playwright_api/response.rb +10 -13
  64. data/lib/playwright_api/route.rb +49 -0
  65. data/lib/playwright_api/selectors.rb +20 -8
  66. data/lib/playwright_api/video.rb +8 -0
  67. data/lib/playwright_api/web_socket.rb +0 -8
  68. data/lib/playwright_api/worker.rb +25 -13
  69. data/playwright.gemspec +1 -0
  70. metadata +33 -2
@@ -0,0 +1,25 @@
1
+ module Playwright
2
+ # @nodoc
3
+ class AndroidInput < PlaywrightApi
4
+
5
+ # @nodoc
6
+ def type(text)
7
+ wrap_impl(@impl.type(unwrap_impl(text)))
8
+ end
9
+
10
+ # @nodoc
11
+ def tap_point(point)
12
+ wrap_impl(@impl.tap_point(unwrap_impl(point)))
13
+ end
14
+
15
+ # @nodoc
16
+ def drag(from, to, steps)
17
+ wrap_impl(@impl.drag(unwrap_impl(from), unwrap_impl(to), unwrap_impl(steps)))
18
+ end
19
+
20
+ # @nodoc
21
+ def press(key)
22
+ wrap_impl(@impl.press(unwrap_impl(key)))
23
+ end
24
+ end
25
+ end
@@ -4,20 +4,24 @@ module Playwright
4
4
 
5
5
  # -- inherited from EventEmitter --
6
6
  # @nodoc
7
- def off(event, callback)
8
- wrap_channel_owner(@channel_owner.off(event, callback))
7
+ def once(event, callback)
8
+ event_emitter_proxy.once(event, callback)
9
9
  end
10
10
 
11
11
  # -- inherited from EventEmitter --
12
12
  # @nodoc
13
- def once(event, callback)
14
- wrap_channel_owner(@channel_owner.once(event, callback))
13
+ def on(event, callback)
14
+ event_emitter_proxy.on(event, callback)
15
15
  end
16
16
 
17
17
  # -- inherited from EventEmitter --
18
18
  # @nodoc
19
- def on(event, callback)
20
- wrap_channel_owner(@channel_owner.on(event, callback))
19
+ def off(event, callback)
20
+ event_emitter_proxy.off(event, callback)
21
+ end
22
+
23
+ private def event_emitter_proxy
24
+ @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
21
25
  end
22
26
  end
23
27
  end
@@ -1,7 +1,7 @@
1
1
  module Playwright
2
- # - extends: [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)
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
@@ -15,8 +15,36 @@ module Playwright
15
15
  # })();
16
16
  # ```
17
17
  #
18
- # See `ChromiumBrowser`, [FirefoxBrowser] and [WebKitBrowser] for browser-specific features. Note that
19
- # [`method: BrowserType.launch`] always returns a specific browser instance, based on the browser being launched.
18
+ # ```python async
19
+ # import asyncio
20
+ # from playwright.async_api import async_playwright
21
+ #
22
+ # async def run(playwright):
23
+ # firefox = playwright.firefox
24
+ # browser = await firefox.launch()
25
+ # page = await browser.new_page()
26
+ # await page.goto("https://example.com")
27
+ # await browser.close()
28
+ #
29
+ # async def main():
30
+ # async with async_playwright() as playwright:
31
+ # await run(playwright)
32
+ # asyncio.run(main())
33
+ # ```
34
+ #
35
+ # ```python sync
36
+ # from playwright.sync_api import sync_playwright
37
+ #
38
+ # def run(playwright):
39
+ # firefox = playwright.firefox
40
+ # browser = firefox.launch()
41
+ # page = browser.new_page()
42
+ # page.goto("https://example.com")
43
+ # browser.close()
44
+ #
45
+ # with sync_playwright() as playwright:
46
+ # run(playwright)
47
+ # ```
20
48
  class Browser < PlaywrightApi
21
49
 
22
50
  # In case this browser is obtained using [`method: BrowserType.launch`], closes the browser and all of its pages (if any
@@ -27,7 +55,7 @@ module Playwright
27
55
  #
28
56
  # The `Browser` object itself is considered to be disposed and cannot be used anymore.
29
57
  def close
30
- wrap_channel_owner(@channel_owner.close)
58
+ wrap_impl(@impl.close)
31
59
  end
32
60
 
33
61
  # Returns an array of all open browser contexts. In a newly created browser, this will return zero browser contexts.
@@ -40,13 +68,27 @@ module Playwright
40
68
  # const context = await browser.newContext();
41
69
  # console.log(browser.contexts().length); // prints `1`
42
70
  # ```
71
+ #
72
+ # ```python async
73
+ # browser = await pw.webkit.launch()
74
+ # print(len(browser.contexts())) # prints `0`
75
+ # context = await browser.new_context()
76
+ # print(len(browser.contexts())) # prints `1`
77
+ # ```
78
+ #
79
+ # ```python sync
80
+ # browser = pw.webkit.launch()
81
+ # print(len(browser.contexts())) # prints `0`
82
+ # context = browser.new_context()
83
+ # print(len(browser.contexts())) # prints `1`
84
+ # ```
43
85
  def contexts
44
- wrap_channel_owner(@channel_owner.contexts)
86
+ wrap_impl(@impl.contexts)
45
87
  end
46
88
 
47
89
  # Indicates that the browser is connected.
48
90
  def connected?
49
- wrap_channel_owner(@channel_owner.connected?)
91
+ wrap_impl(@impl.connected?)
50
92
  end
51
93
 
52
94
  # Creates a new browser context. It won't share cookies/cache with other browser contexts.
@@ -62,6 +104,24 @@ module Playwright
62
104
  # await page.goto('https://example.com');
63
105
  # })();
64
106
  # ```
107
+ #
108
+ # ```python async
109
+ # browser = await playwright.firefox.launch() # or "chromium" or "webkit".
110
+ # # create a new incognito browser context.
111
+ # context = await browser.new_context()
112
+ # # create a new page in a pristine context.
113
+ # page = await context.new_page()
114
+ # await page.goto("https://example.com")
115
+ # ```
116
+ #
117
+ # ```python sync
118
+ # browser = playwright.firefox.launch() # or "chromium" or "webkit".
119
+ # # create a new incognito browser context.
120
+ # context = browser.new_context()
121
+ # # create a new page in a pristine context.
122
+ # page = context.new_page()
123
+ # page.goto("https://example.com")
124
+ # ```
65
125
  def new_context(
66
126
  acceptDownloads: nil,
67
127
  bypassCSP: nil,
@@ -82,12 +142,14 @@ module Playwright
82
142
  recordHar: nil,
83
143
  recordVideo: nil,
84
144
  storageState: nil,
145
+ storageStatePath: nil,
85
146
  timezoneId: nil,
86
147
  userAgent: nil,
87
148
  videoSize: nil,
88
149
  videosPath: nil,
89
- viewport: nil)
90
- wrap_channel_owner(@channel_owner.new_context(acceptDownloads: acceptDownloads, bypassCSP: bypassCSP, colorScheme: colorScheme, deviceScaleFactor: deviceScaleFactor, extraHTTPHeaders: extraHTTPHeaders, geolocation: geolocation, hasTouch: hasTouch, httpCredentials: httpCredentials, ignoreHTTPSErrors: ignoreHTTPSErrors, isMobile: isMobile, javaScriptEnabled: javaScriptEnabled, locale: locale, logger: logger, offline: offline, permissions: permissions, proxy: proxy, recordHar: recordHar, recordVideo: recordVideo, storageState: storageState, timezoneId: timezoneId, userAgent: userAgent, videoSize: videoSize, videosPath: videosPath, viewport: viewport))
150
+ viewport: nil,
151
+ &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)))
91
153
  end
92
154
 
93
155
  # Creates a new page in a new browser context. Closing this page will close the context as well.
@@ -115,40 +177,45 @@ module Playwright
115
177
  recordHar: nil,
116
178
  recordVideo: nil,
117
179
  storageState: nil,
180
+ storageStatePath: nil,
118
181
  timezoneId: nil,
119
182
  userAgent: nil,
120
183
  videoSize: nil,
121
184
  videosPath: nil,
122
185
  viewport: nil)
123
- wrap_channel_owner(@channel_owner.new_page(acceptDownloads: acceptDownloads, bypassCSP: bypassCSP, colorScheme: colorScheme, deviceScaleFactor: deviceScaleFactor, extraHTTPHeaders: extraHTTPHeaders, geolocation: geolocation, hasTouch: hasTouch, httpCredentials: httpCredentials, ignoreHTTPSErrors: ignoreHTTPSErrors, isMobile: isMobile, javaScriptEnabled: javaScriptEnabled, locale: locale, logger: logger, offline: offline, permissions: permissions, proxy: proxy, recordHar: recordHar, recordVideo: recordVideo, storageState: storageState, timezoneId: timezoneId, userAgent: userAgent, videoSize: videoSize, videosPath: videosPath, viewport: 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)))
124
187
  end
125
188
 
126
189
  # Returns the browser version.
127
190
  def version
128
- wrap_channel_owner(@channel_owner.version)
191
+ wrap_impl(@impl.version)
129
192
  end
130
193
 
131
194
  # @nodoc
132
195
  def after_initialize
133
- wrap_channel_owner(@channel_owner.after_initialize)
196
+ wrap_impl(@impl.after_initialize)
134
197
  end
135
198
 
136
199
  # -- inherited from EventEmitter --
137
200
  # @nodoc
138
- def off(event, callback)
139
- wrap_channel_owner(@channel_owner.off(event, callback))
201
+ def once(event, callback)
202
+ event_emitter_proxy.once(event, callback)
140
203
  end
141
204
 
142
205
  # -- inherited from EventEmitter --
143
206
  # @nodoc
144
- def once(event, callback)
145
- wrap_channel_owner(@channel_owner.once(event, callback))
207
+ def on(event, callback)
208
+ event_emitter_proxy.on(event, callback)
146
209
  end
147
210
 
148
211
  # -- inherited from EventEmitter --
149
212
  # @nodoc
150
- def on(event, callback)
151
- wrap_channel_owner(@channel_owner.on(event, callback))
213
+ def off(event, callback)
214
+ event_emitter_proxy.off(event, callback)
215
+ end
216
+
217
+ private def event_emitter_proxy
218
+ @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
152
219
  end
153
220
  end
154
221
  end
@@ -1,5 +1,5 @@
1
1
  module Playwright
2
- # - extends: [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter)
2
+ # - extends: [EventEmitter]
3
3
  #
4
4
  # BrowserContexts provide a way to operate multiple independent browser sessions.
5
5
  #
@@ -19,6 +19,26 @@ module Playwright
19
19
  # // Dispose context once it's no longer needed.
20
20
  # await context.close();
21
21
  # ```
22
+ #
23
+ # ```python async
24
+ # # create a new incognito browser context
25
+ # context = await browser.new_context()
26
+ # # create a new page inside context.
27
+ # page = await context.new_page()
28
+ # await page.goto("https://example.com")
29
+ # # dispose context once it"s no longer needed.
30
+ # await context.close()
31
+ # ```
32
+ #
33
+ # ```python sync
34
+ # # create a new incognito browser context
35
+ # context = browser.new_context()
36
+ # # create a new page inside context.
37
+ # page = context.new_page()
38
+ # page.goto("https://example.com")
39
+ # # dispose context once it"s no longer needed.
40
+ # context.close()
41
+ # ```
22
42
  class BrowserContext < PlaywrightApi
23
43
 
24
44
  # Adds cookies into this browser context. All pages within this context will have these cookies installed. Cookies can be
@@ -28,6 +48,14 @@ module Playwright
28
48
  # ```js
29
49
  # await browserContext.addCookies([cookieObject1, cookieObject2]);
30
50
  # ```
51
+ #
52
+ # ```python async
53
+ # await browser_context.add_cookies([cookie_object1, cookie_object2])
54
+ # ```
55
+ #
56
+ # ```python sync
57
+ # browser_context.add_cookies([cookie_object1, cookie_object2])
58
+ # ```
31
59
  def add_cookies(cookies)
32
60
  raise NotImplementedError.new('add_cookies is not implemented yet.')
33
61
  end
@@ -43,7 +71,7 @@ module Playwright
43
71
  # An example of overriding `Math.random` before the page loads:
44
72
  #
45
73
  #
46
- # ```js
74
+ # ```js browser
47
75
  # // preload.js
48
76
  # Math.random = () => 42;
49
77
  # ```
@@ -56,7 +84,17 @@ module Playwright
56
84
  # });
57
85
  # ```
58
86
  #
59
- # > **NOTE** The order of evaluation of multiple scripts installed via [`method: BrowserContext.addInitScript`] and
87
+ # ```python async
88
+ # # in your playwright script, assuming the preload.js file is in same directory.
89
+ # await browser_context.add_init_script(path="preload.js")
90
+ # ```
91
+ #
92
+ # ```python sync
93
+ # # in your playwright script, assuming the preload.js file is in same directory.
94
+ # browser_context.add_init_script(path="preload.js")
95
+ # ```
96
+ #
97
+ # > NOTE: The order of evaluation of multiple scripts installed via [`method: BrowserContext.addInitScript`] and
60
98
  # [`method: Page.addInitScript`] is not defined.
61
99
  def add_init_script(script, arg: nil)
62
100
  raise NotImplementedError.new('add_init_script is not implemented yet.')
@@ -81,15 +119,29 @@ module Playwright
81
119
  # // do stuff ..
82
120
  # context.clearPermissions();
83
121
  # ```
122
+ #
123
+ # ```python async
124
+ # context = await browser.new_context()
125
+ # await context.grant_permissions(["clipboard-read"])
126
+ # # do stuff ..
127
+ # context.clear_permissions()
128
+ # ```
129
+ #
130
+ # ```python sync
131
+ # context = browser.new_context()
132
+ # context.grant_permissions(["clipboard-read"])
133
+ # # do stuff ..
134
+ # context.clear_permissions()
135
+ # ```
84
136
  def clear_permissions
85
137
  raise NotImplementedError.new('clear_permissions is not implemented yet.')
86
138
  end
87
139
 
88
140
  # Closes the browser context. All the pages that belong to the browser context will be closed.
89
141
  #
90
- # > **NOTE** the default browser context cannot be closed.
142
+ # > NOTE: The default browser context cannot be closed.
91
143
  def close
92
- wrap_channel_owner(@channel_owner.close)
144
+ wrap_impl(@impl.close)
93
145
  end
94
146
 
95
147
  # If no URLs are specified, this method returns all cookies. If URLs are specified, only cookies that affect those URLs
@@ -131,6 +183,57 @@ module Playwright
131
183
  # })();
132
184
  # ```
133
185
  #
186
+ # ```python async
187
+ # import asyncio
188
+ # from playwright.async_api import async_playwright
189
+ #
190
+ # async def run(playwright):
191
+ # webkit = playwright.webkit
192
+ # browser = await webkit.launch(headless=false)
193
+ # context = await browser.new_context()
194
+ # await context.expose_binding("pageURL", lambda source: source["page"].url)
195
+ # page = await context.new_page()
196
+ # await page.set_content("""
197
+ # <script>
198
+ # async function onClick() {
199
+ # document.querySelector('div').textContent = await window.pageURL();
200
+ # }
201
+ # </script>
202
+ # <button onclick="onClick()">Click me</button>
203
+ # <div></div>
204
+ # """)
205
+ # await page.click("button")
206
+ #
207
+ # async def main():
208
+ # async with async_playwright() as playwright:
209
+ # await run(playwright)
210
+ # asyncio.run(main())
211
+ # ```
212
+ #
213
+ # ```python sync
214
+ # from playwright.sync_api import sync_playwright
215
+ #
216
+ # def run(playwright):
217
+ # webkit = playwright.webkit
218
+ # browser = webkit.launch(headless=false)
219
+ # context = browser.new_context()
220
+ # context.expose_binding("pageURL", lambda source: source["page"].url)
221
+ # page = context.new_page()
222
+ # page.set_content("""
223
+ # <script>
224
+ # async function onClick() {
225
+ # document.querySelector('div').textContent = await window.pageURL();
226
+ # }
227
+ # </script>
228
+ # <button onclick="onClick()">Click me</button>
229
+ # <div></div>
230
+ # """)
231
+ # page.click("button")
232
+ #
233
+ # with sync_playwright() as playwright:
234
+ # run(playwright)
235
+ # ```
236
+ #
134
237
  # An example of passing an element handle:
135
238
  #
136
239
  #
@@ -146,6 +249,34 @@ module Playwright
146
249
  # <div>Or click me</div>
147
250
  # `);
148
251
  # ```
252
+ #
253
+ # ```python async
254
+ # async def print(source, element):
255
+ # print(await element.text_content())
256
+ #
257
+ # await context.expose_binding("clicked", print, handle=true)
258
+ # await page.set_content("""
259
+ # <script>
260
+ # document.addEventListener('click', event => window.clicked(event.target));
261
+ # </script>
262
+ # <div>Click me</div>
263
+ # <div>Or click me</div>
264
+ # """)
265
+ # ```
266
+ #
267
+ # ```python sync
268
+ # def print(source, element):
269
+ # print(element.text_content())
270
+ #
271
+ # context.expose_binding("clicked", print, handle=true)
272
+ # page.set_content("""
273
+ # <script>
274
+ # document.addEventListener('click', event => window.clicked(event.target));
275
+ # </script>
276
+ # <div>Click me</div>
277
+ # <div>Or click me</div>
278
+ # """)
279
+ # ```
149
280
  def expose_binding(name, callback, handle: nil)
150
281
  raise NotImplementedError.new('expose_binding is not implemented yet.')
151
282
  end
@@ -181,6 +312,72 @@ module Playwright
181
312
  # await page.click('button');
182
313
  # })();
183
314
  # ```
315
+ #
316
+ # ```python async
317
+ # import asyncio
318
+ # import hashlib
319
+ # from playwright.async_api import async_playwright
320
+ #
321
+ # async def sha1(text):
322
+ # m = hashlib.sha1()
323
+ # m.update(bytes(text, "utf8"))
324
+ # return m.hexdigest()
325
+ #
326
+ #
327
+ # async def run(playwright):
328
+ # webkit = playwright.webkit
329
+ # browser = await webkit.launch(headless=False)
330
+ # context = await browser.new_context()
331
+ # await context.expose_function("sha1", sha1)
332
+ # page = await context.new_page()
333
+ # await page.set_content("""
334
+ # <script>
335
+ # async function onClick() {
336
+ # document.querySelector('div').textContent = await window.sha1('PLAYWRIGHT');
337
+ # }
338
+ # </script>
339
+ # <button onclick="onClick()">Click me</button>
340
+ # <div></div>
341
+ # """)
342
+ # await page.click("button")
343
+ #
344
+ # async def main():
345
+ # async with async_playwright() as playwright:
346
+ # await run(playwright)
347
+ # asyncio.run(main())
348
+ # ```
349
+ #
350
+ # ```python sync
351
+ # import hashlib
352
+ # from playwright.sync_api import sync_playwright
353
+ #
354
+ # def sha1(text):
355
+ # m = hashlib.sha1()
356
+ # m.update(bytes(text, "utf8"))
357
+ # return m.hexdigest()
358
+ #
359
+ #
360
+ # def run(playwright):
361
+ # webkit = playwright.webkit
362
+ # browser = webkit.launch(headless=False)
363
+ # context = browser.new_context()
364
+ # context.expose_function("sha1", sha1)
365
+ # page = context.new_page()
366
+ # page.expose_function("sha1", sha1)
367
+ # page.set_content("""
368
+ # <script>
369
+ # async function onClick() {
370
+ # document.querySelector('div').textContent = await window.sha1('PLAYWRIGHT');
371
+ # }
372
+ # </script>
373
+ # <button onclick="onClick()">Click me</button>
374
+ # <div></div>
375
+ # """)
376
+ # page.click("button")
377
+ #
378
+ # with sync_playwright() as playwright:
379
+ # run(playwright)
380
+ # ```
184
381
  def expose_function(name, callback)
185
382
  raise NotImplementedError.new('expose_function is not implemented yet.')
186
383
  end
@@ -193,13 +390,13 @@ module Playwright
193
390
 
194
391
  # Creates a new page in the browser context.
195
392
  def new_page
196
- wrap_channel_owner(@channel_owner.new_page)
393
+ wrap_impl(@impl.new_page)
197
394
  end
198
395
 
199
396
  # Returns all open pages in the context. Non visible pages, such as `"background_page"`, will not be listed here. You can
200
397
  # find them using [`method: ChromiumBrowserContext.backgroundPages`].
201
398
  def pages
202
- wrap_channel_owner(@channel_owner.pages)
399
+ wrap_impl(@impl.pages)
203
400
  end
204
401
 
205
402
  # Routing provides the capability to modify network requests that are made by any page in the browser context. Once route
@@ -216,6 +413,22 @@ module Playwright
216
413
  # await browser.close();
217
414
  # ```
218
415
  #
416
+ # ```python async
417
+ # context = await browser.new_context()
418
+ # page = await context.new_page()
419
+ # await context.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())
420
+ # await page.goto("https://example.com")
421
+ # await browser.close()
422
+ # ```
423
+ #
424
+ # ```python sync
425
+ # context = browser.new_context()
426
+ # page = context.new_page()
427
+ # context.route("**/*.{png,jpg,jpeg}", lambda route: route.abort())
428
+ # page.goto("https://example.com")
429
+ # browser.close()
430
+ # ```
431
+ #
219
432
  # or the same snippet using a regex pattern instead:
220
433
  #
221
434
  #
@@ -227,10 +440,29 @@ module Playwright
227
440
  # await browser.close();
228
441
  # ```
229
442
  #
443
+ # ```python async
444
+ # context = await browser.new_context()
445
+ # page = await context.new_page()
446
+ # await context.route(re.compile(r"(\.png$)|(\.jpg$)"), lambda route: route.abort())
447
+ # page = await context.new_page()
448
+ # await page.goto("https://example.com")
449
+ # await browser.close()
450
+ # ```
451
+ #
452
+ # ```python sync
453
+ # context = browser.new_context()
454
+ # page = context.new_page()
455
+ # context.route(re.compile(r"(\.png$)|(\.jpg$)"), lambda route: route.abort())
456
+ # page = await context.new_page()
457
+ # page = context.new_page()
458
+ # page.goto("https://example.com")
459
+ # browser.close()
460
+ # ```
461
+ #
230
462
  # Page routes (set up with [`method: Page.route`]) take precedence over browser context routes when request matches both
231
463
  # handlers.
232
464
  #
233
- # > **NOTE** Enabling routing disables http cache.
465
+ # > NOTE: Enabling routing disables http cache.
234
466
  def route(url, handler)
235
467
  raise NotImplementedError.new('route is not implemented yet.')
236
468
  end
@@ -243,7 +475,7 @@ module Playwright
243
475
  # - [`method: Page.setContent`]
244
476
  # - [`method: Page.waitForNavigation`]
245
477
  #
246
- # > **NOTE** [`method: Page.setDefaultNavigationTimeout`] and [`method: Page.setDefaultTimeout`] take priority over
478
+ # > NOTE: [`method: Page.setDefaultNavigationTimeout`] and [`method: Page.setDefaultTimeout`] take priority over
247
479
  # [`method: BrowserContext.setDefaultNavigationTimeout`].
248
480
  def set_default_navigation_timeout(timeout)
249
481
  raise NotImplementedError.new('set_default_navigation_timeout is not implemented yet.')
@@ -252,7 +484,7 @@ module Playwright
252
484
 
253
485
  # This setting will change the default maximum time for all the methods accepting `timeout` option.
254
486
  #
255
- # > **NOTE** [`method: Page.setDefaultNavigationTimeout`], [`method: Page.setDefaultTimeout`] and
487
+ # > NOTE: [`method: Page.setDefaultNavigationTimeout`], [`method: Page.setDefaultTimeout`] and
256
488
  # [`method: BrowserContext.setDefaultNavigationTimeout`] take priority over [`method: BrowserContext.setDefaultTimeout`].
257
489
  def set_default_timeout(timeout)
258
490
  raise NotImplementedError.new('set_default_timeout is not implemented yet.')
@@ -263,7 +495,7 @@ module Playwright
263
495
  # with page-specific extra HTTP headers set with [`method: Page.setExtraHTTPHeaders`]. If page overrides a particular
264
496
  # header, page-specific header value will be used instead of the browser context header value.
265
497
  #
266
- # > **NOTE** `browserContext.setExtraHTTPHeaders` does not guarantee the order of headers in the outgoing requests.
498
+ # > NOTE: [`method: BrowserContext.setExtraHTTPHeaders`] does not guarantee the order of headers in the outgoing requests.
267
499
  def set_extra_http_headers(headers)
268
500
  raise NotImplementedError.new('set_extra_http_headers is not implemented yet.')
269
501
  end
@@ -276,8 +508,16 @@ module Playwright
276
508
  # await browserContext.setGeolocation({latitude: 59.95, longitude: 30.31667});
277
509
  # ```
278
510
  #
279
- # > **NOTE** Consider using [`method: BrowserContext.grantPermissions`] to grant permissions for the browser context pages
280
- # to read its geolocation.
511
+ # ```python async
512
+ # await browser_context.set_geolocation({"latitude": 59.95, "longitude": 30.31667})
513
+ # ```
514
+ #
515
+ # ```python sync
516
+ # browser_context.set_geolocation({"latitude": 59.95, "longitude": 30.31667})
517
+ # ```
518
+ #
519
+ # > NOTE: Consider using [`method: BrowserContext.grantPermissions`] to grant permissions for the browser context pages to
520
+ # read its geolocation.
281
521
  def set_geolocation(geolocation)
282
522
  raise NotImplementedError.new('set_geolocation is not implemented yet.')
283
523
  end
@@ -305,54 +545,46 @@ module Playwright
305
545
  raise NotImplementedError.new('unroute is not implemented yet.')
306
546
  end
307
547
 
308
- # Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy
309
- # value. Will throw an error if the context closes before the event is fired. Returns the event data value.
310
- #
311
- #
312
- # ```js
313
- # const context = await browser.newContext();
314
- # await context.grantPermissions(['geolocation']);
315
- # ```
316
- def wait_for_event(event, optionsOrPredicate: nil)
317
- raise NotImplementedError.new('wait_for_event is not implemented yet.')
548
+ # @nodoc
549
+ def after_initialize
550
+ wrap_impl(@impl.after_initialize)
318
551
  end
319
552
 
320
553
  # @nodoc
321
554
  def browser=(req)
322
- wrap_channel_owner(@channel_owner.browser=(req))
555
+ wrap_impl(@impl.browser=(unwrap_impl(req)))
323
556
  end
324
557
 
325
558
  # @nodoc
326
559
  def owner_page=(req)
327
- wrap_channel_owner(@channel_owner.owner_page=(req))
328
- end
329
-
330
- # @nodoc
331
- def after_initialize
332
- wrap_channel_owner(@channel_owner.after_initialize)
560
+ wrap_impl(@impl.owner_page=(unwrap_impl(req)))
333
561
  end
334
562
 
335
563
  # @nodoc
336
564
  def options=(req)
337
- wrap_channel_owner(@channel_owner.options=(req))
565
+ wrap_impl(@impl.options=(unwrap_impl(req)))
338
566
  end
339
567
 
340
568
  # -- inherited from EventEmitter --
341
569
  # @nodoc
342
- def off(event, callback)
343
- wrap_channel_owner(@channel_owner.off(event, callback))
570
+ def once(event, callback)
571
+ event_emitter_proxy.once(event, callback)
344
572
  end
345
573
 
346
574
  # -- inherited from EventEmitter --
347
575
  # @nodoc
348
- def once(event, callback)
349
- wrap_channel_owner(@channel_owner.once(event, callback))
576
+ def on(event, callback)
577
+ event_emitter_proxy.on(event, callback)
350
578
  end
351
579
 
352
580
  # -- inherited from EventEmitter --
353
581
  # @nodoc
354
- def on(event, callback)
355
- wrap_channel_owner(@channel_owner.on(event, callback))
582
+ def off(event, callback)
583
+ event_emitter_proxy.off(event, callback)
584
+ end
585
+
586
+ private def event_emitter_proxy
587
+ @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
356
588
  end
357
589
  end
358
590
  end