playwright-ruby-client 0.0.8 → 1.58.1.alpha1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. checksums.yaml +4 -4
  2. data/AGENTS.md +4 -0
  3. data/CLAUDE/api_generation.md +28 -0
  4. data/CLAUDE/ci_expectations.md +23 -0
  5. data/CLAUDE/gem_release_flow.md +39 -0
  6. data/CLAUDE/past_upgrade_pr_patterns.md +42 -0
  7. data/CLAUDE/playwright_upgrade_workflow.md +35 -0
  8. data/CLAUDE/rspec_debugging.md +30 -0
  9. data/CLAUDE/unimplemented_examples.md +18 -0
  10. data/CLAUDE.md +32 -0
  11. data/CONTRIBUTING.md +5 -0
  12. data/README.md +60 -16
  13. data/documentation/README.md +33 -0
  14. data/documentation/babel.config.js +3 -0
  15. data/documentation/docs/api/api_request.md +7 -0
  16. data/documentation/docs/api/api_request_context.md +298 -0
  17. data/documentation/docs/api/api_response.md +114 -0
  18. data/documentation/docs/api/browser.md +237 -0
  19. data/documentation/docs/api/browser_context.md +503 -0
  20. data/documentation/docs/api/browser_type.md +184 -0
  21. data/documentation/docs/api/cdp_session.md +44 -0
  22. data/documentation/docs/api/clock.md +154 -0
  23. data/documentation/docs/api/console_message.md +85 -0
  24. data/documentation/docs/api/dialog.md +84 -0
  25. data/documentation/docs/api/download.md +111 -0
  26. data/documentation/docs/api/element_handle.md +694 -0
  27. data/documentation/docs/api/experimental/_category_.yml +3 -0
  28. data/documentation/docs/api/experimental/android.md +42 -0
  29. data/documentation/docs/api/experimental/android_device.md +109 -0
  30. data/documentation/docs/api/experimental/android_input.md +43 -0
  31. data/documentation/docs/api/experimental/android_socket.md +7 -0
  32. data/documentation/docs/api/experimental/android_web_view.md +7 -0
  33. data/documentation/docs/api/file_chooser.md +53 -0
  34. data/documentation/docs/api/frame.md +1218 -0
  35. data/documentation/docs/api/frame_locator.md +348 -0
  36. data/documentation/docs/api/js_handle.md +121 -0
  37. data/documentation/docs/api/keyboard.md +170 -0
  38. data/documentation/docs/api/locator.md +1495 -0
  39. data/documentation/docs/api/locator_assertions.md +827 -0
  40. data/documentation/docs/api/mouse.md +86 -0
  41. data/documentation/docs/api/page.md +1946 -0
  42. data/documentation/docs/api/page_assertions.md +65 -0
  43. data/documentation/docs/api/playwright.md +66 -0
  44. data/documentation/docs/api/request.md +255 -0
  45. data/documentation/docs/api/response.md +176 -0
  46. data/documentation/docs/api/route.md +205 -0
  47. data/documentation/docs/api/selectors.md +63 -0
  48. data/documentation/docs/api/touchscreen.md +22 -0
  49. data/documentation/docs/api/tracing.md +129 -0
  50. data/documentation/docs/api/web_socket.md +51 -0
  51. data/documentation/docs/api/worker.md +83 -0
  52. data/documentation/docs/article/api_coverage.mdx +11 -0
  53. data/documentation/docs/article/getting_started.md +161 -0
  54. data/documentation/docs/article/guides/_category_.yml +3 -0
  55. data/documentation/docs/article/guides/download_playwright_driver.md +55 -0
  56. data/documentation/docs/article/guides/inspector.md +31 -0
  57. data/documentation/docs/article/guides/launch_browser.md +121 -0
  58. data/documentation/docs/article/guides/playwright_on_alpine_linux.md +112 -0
  59. data/documentation/docs/article/guides/rails_integration.md +278 -0
  60. data/documentation/docs/article/guides/rails_integration_with_null_driver.md +145 -0
  61. data/documentation/docs/article/guides/recording_video.md +79 -0
  62. data/documentation/docs/article/guides/rspec_integration.md +59 -0
  63. data/documentation/docs/article/guides/semi_automation.md +71 -0
  64. data/documentation/docs/article/guides/use_storage_state.md +78 -0
  65. data/documentation/docs/include/api_coverage.md +671 -0
  66. data/documentation/docusaurus.config.js +114 -0
  67. data/documentation/package.json +39 -0
  68. data/documentation/sidebars.js +15 -0
  69. data/documentation/src/components/HomepageFeatures.js +61 -0
  70. data/documentation/src/components/HomepageFeatures.module.css +13 -0
  71. data/documentation/src/css/custom.css +44 -0
  72. data/documentation/src/pages/index.js +49 -0
  73. data/documentation/src/pages/index.module.css +41 -0
  74. data/documentation/src/pages/markdown-page.md +7 -0
  75. data/documentation/static/.nojekyll +0 -0
  76. data/documentation/static/img/playwright-logo.svg +9 -0
  77. data/documentation/static/img/playwright-ruby-client.png +0 -0
  78. data/documentation/static/img/undraw_dropdown_menu.svg +1 -0
  79. data/documentation/static/img/undraw_web_development.svg +1 -0
  80. data/documentation/static/img/undraw_windows.svg +1 -0
  81. data/documentation/yarn.lock +9005 -0
  82. data/lib/playwright/{input_types/android_input.rb → android_input_impl.rb} +5 -1
  83. data/lib/playwright/api_implementation.rb +18 -0
  84. data/lib/playwright/api_response_impl.rb +77 -0
  85. data/lib/playwright/channel.rb +62 -1
  86. data/lib/playwright/channel_owner.rb +70 -7
  87. data/lib/playwright/channel_owners/android.rb +16 -3
  88. data/lib/playwright/channel_owners/android_device.rb +22 -66
  89. data/lib/playwright/channel_owners/api_request_context.rb +247 -0
  90. data/lib/playwright/channel_owners/artifact.rb +40 -0
  91. data/lib/playwright/channel_owners/binding_call.rb +70 -0
  92. data/lib/playwright/channel_owners/browser.rb +114 -22
  93. data/lib/playwright/channel_owners/browser_context.rb +589 -15
  94. data/lib/playwright/channel_owners/browser_type.rb +90 -1
  95. data/lib/playwright/channel_owners/cdp_session.rb +19 -0
  96. data/lib/playwright/channel_owners/dialog.rb +32 -0
  97. data/lib/playwright/channel_owners/element_handle.rb +107 -43
  98. data/lib/playwright/channel_owners/fetch_request.rb +8 -0
  99. data/lib/playwright/channel_owners/frame.rb +334 -104
  100. data/lib/playwright/channel_owners/js_handle.rb +9 -13
  101. data/lib/playwright/channel_owners/local_utils.rb +82 -0
  102. data/lib/playwright/channel_owners/page.rb +778 -95
  103. data/lib/playwright/channel_owners/playwright.rb +25 -30
  104. data/lib/playwright/channel_owners/request.rb +120 -18
  105. data/lib/playwright/channel_owners/response.rb +113 -0
  106. data/lib/playwright/channel_owners/route.rb +181 -0
  107. data/lib/playwright/channel_owners/stream.rb +30 -0
  108. data/lib/playwright/channel_owners/tracing.rb +117 -0
  109. data/lib/playwright/channel_owners/web_socket.rb +96 -0
  110. data/lib/playwright/channel_owners/worker.rb +46 -0
  111. data/lib/playwright/channel_owners/writable_stream.rb +14 -0
  112. data/lib/playwright/clock_impl.rb +67 -0
  113. data/lib/playwright/connection.rb +111 -63
  114. data/lib/playwright/console_message_impl.rb +29 -0
  115. data/lib/playwright/download_impl.rb +32 -0
  116. data/lib/playwright/errors.rb +42 -5
  117. data/lib/playwright/event_emitter.rb +17 -3
  118. data/lib/playwright/event_emitter_proxy.rb +49 -0
  119. data/lib/playwright/events.rb +10 -5
  120. data/lib/playwright/file_chooser_impl.rb +24 -0
  121. data/lib/playwright/frame_locator_impl.rb +66 -0
  122. data/lib/playwright/har_router.rb +89 -0
  123. data/lib/playwright/http_headers.rb +14 -0
  124. data/lib/playwright/input_files.rb +102 -15
  125. data/lib/playwright/javascript/expression.rb +7 -11
  126. data/lib/playwright/javascript/regex.rb +23 -0
  127. data/lib/playwright/javascript/source_url.rb +16 -0
  128. data/lib/playwright/javascript/value_parser.rb +108 -19
  129. data/lib/playwright/javascript/value_serializer.rb +47 -8
  130. data/lib/playwright/javascript/visitor_info.rb +26 -0
  131. data/lib/playwright/javascript.rb +2 -10
  132. data/lib/playwright/{input_types/keyboard.rb → keyboard_impl.rb} +6 -2
  133. data/lib/playwright/locator_assertions_impl.rb +571 -0
  134. data/lib/playwright/locator_impl.rb +544 -0
  135. data/lib/playwright/locator_utils.rb +136 -0
  136. data/lib/playwright/mouse_impl.rb +57 -0
  137. data/lib/playwright/page_assertions_impl.rb +154 -0
  138. data/lib/playwright/playwright_api.rb +102 -30
  139. data/lib/playwright/raw_headers.rb +61 -0
  140. data/lib/playwright/route_handler.rb +78 -0
  141. data/lib/playwright/select_option_values.rb +34 -13
  142. data/lib/playwright/selectors_impl.rb +45 -0
  143. data/lib/playwright/test.rb +102 -0
  144. data/lib/playwright/timeout_settings.rb +9 -4
  145. data/lib/playwright/touchscreen_impl.rb +14 -0
  146. data/lib/playwright/transport.rb +61 -10
  147. data/lib/playwright/url_matcher.rb +24 -2
  148. data/lib/playwright/utils.rb +48 -13
  149. data/lib/playwright/version.rb +2 -1
  150. data/lib/playwright/video.rb +54 -0
  151. data/lib/playwright/waiter.rb +166 -0
  152. data/lib/playwright/web_socket_client.rb +167 -0
  153. data/lib/playwright/web_socket_transport.rb +116 -0
  154. data/lib/playwright.rb +188 -11
  155. data/lib/playwright_api/android.rb +46 -11
  156. data/lib/playwright_api/android_device.rb +182 -31
  157. data/lib/playwright_api/android_input.rb +22 -13
  158. data/lib/playwright_api/android_socket.rb +18 -0
  159. data/lib/playwright_api/android_web_view.rb +24 -0
  160. data/lib/playwright_api/api_request.rb +26 -0
  161. data/lib/playwright_api/api_request_context.rb +311 -0
  162. data/lib/playwright_api/api_response.rb +92 -0
  163. data/lib/playwright_api/browser.rb +116 -103
  164. data/lib/playwright_api/browser_context.rb +290 -389
  165. data/lib/playwright_api/browser_type.rb +96 -118
  166. data/lib/playwright_api/cdp_session.rb +36 -39
  167. data/lib/playwright_api/clock.rb +121 -0
  168. data/lib/playwright_api/console_message.rb +35 -19
  169. data/lib/playwright_api/dialog.rb +53 -50
  170. data/lib/playwright_api/download.rb +49 -43
  171. data/lib/playwright_api/element_handle.rb +354 -402
  172. data/lib/playwright_api/file_chooser.rb +15 -18
  173. data/lib/playwright_api/frame.rb +703 -603
  174. data/lib/playwright_api/frame_locator.rb +285 -0
  175. data/lib/playwright_api/js_handle.rb +50 -76
  176. data/lib/playwright_api/keyboard.rb +67 -146
  177. data/lib/playwright_api/locator.rb +1304 -0
  178. data/lib/playwright_api/locator_assertions.rb +704 -0
  179. data/lib/playwright_api/mouse.rb +23 -29
  180. data/lib/playwright_api/page.rb +1196 -1176
  181. data/lib/playwright_api/page_assertions.rb +60 -0
  182. data/lib/playwright_api/playwright.rb +54 -122
  183. data/lib/playwright_api/request.rb +112 -74
  184. data/lib/playwright_api/response.rb +92 -20
  185. data/lib/playwright_api/route.rb +152 -62
  186. data/lib/playwright_api/selectors.rb +47 -61
  187. data/lib/playwright_api/touchscreen.rb +8 -2
  188. data/lib/playwright_api/tracing.rb +128 -0
  189. data/lib/playwright_api/web_socket.rb +43 -5
  190. data/lib/playwright_api/worker.rb +74 -34
  191. data/playwright.gemspec +14 -9
  192. data/sig/playwright.rbs +658 -0
  193. metadata +216 -50
  194. data/docs/api_coverage.md +0 -354
  195. data/lib/playwright/channel_owners/chromium_browser.rb +0 -8
  196. data/lib/playwright/channel_owners/chromium_browser_context.rb +0 -8
  197. data/lib/playwright/channel_owners/console_message.rb +0 -21
  198. data/lib/playwright/channel_owners/firefox_browser.rb +0 -8
  199. data/lib/playwright/channel_owners/selectors.rb +0 -4
  200. data/lib/playwright/channel_owners/webkit_browser.rb +0 -8
  201. data/lib/playwright/input_type.rb +0 -19
  202. data/lib/playwright/input_types/mouse.rb +0 -4
  203. data/lib/playwright/input_types/touchscreen.rb +0 -4
  204. data/lib/playwright/javascript/function.rb +0 -67
  205. data/lib/playwright/wait_helper.rb +0 -73
  206. data/lib/playwright_api/accessibility.rb +0 -93
  207. data/lib/playwright_api/binding_call.rb +0 -23
  208. data/lib/playwright_api/chromium_browser_context.rb +0 -57
  209. data/lib/playwright_api/video.rb +0 -24
@@ -1,80 +1,152 @@
1
1
  module Playwright
2
+ #
2
3
  # `Response` class represents responses which are received by page.
3
4
  class Response < PlaywrightApi
4
5
 
6
+ #
7
+ # An object with all the response HTTP headers associated with this response.
8
+ def all_headers
9
+ wrap_impl(@impl.all_headers)
10
+ end
11
+
12
+ #
5
13
  # Returns the buffer with response body.
6
14
  def body
7
- raise NotImplementedError.new('body is not implemented yet.')
15
+ wrap_impl(@impl.body)
8
16
  end
9
17
 
10
- # Waits for this response to finish, returns failure error if request failed.
18
+ #
19
+ # Waits for this response to finish, returns always `null`.
11
20
  def finished
12
- raise NotImplementedError.new('finished is not implemented yet.')
21
+ wrap_impl(@impl.finished)
13
22
  end
14
23
 
24
+ #
15
25
  # Returns the `Frame` that initiated this response.
16
26
  def frame
17
- raise NotImplementedError.new('frame is not implemented yet.')
27
+ wrap_impl(@impl.frame)
28
+ end
29
+
30
+ #
31
+ # Indicates whether this Response was fulfilled by a Service Worker's Fetch Handler (i.e. via [FetchEvent.respondWith](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/respondWith)).
32
+ def from_service_worker
33
+ wrap_impl(@impl.from_service_worker)
18
34
  end
19
35
 
20
- # Returns the object with HTTP headers associated with the response. All header names are lower-case.
36
+ #
37
+ # An object with the response HTTP headers. The header names are lower-cased.
38
+ # Note that this method does not return security-related headers, including cookie-related ones.
39
+ # You can use [`method: Response.allHeaders`] for complete list of headers that include `cookie` information.
21
40
  def headers
22
- raise NotImplementedError.new('headers is not implemented yet.')
41
+ wrap_impl(@impl.headers)
42
+ end
43
+
44
+ #
45
+ # An array with all the request HTTP headers associated with this response. Unlike [`method: Response.allHeaders`], header names are NOT lower-cased.
46
+ # Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times.
47
+ def headers_array
48
+ wrap_impl(@impl.headers_array)
49
+ end
50
+
51
+ #
52
+ # Returns the value of the header matching the name. The name is case-insensitive. If multiple headers have
53
+ # the same name (except `set-cookie`), they are returned as a list separated by `, `. For `set-cookie`, the `\n` separator is used. If no headers are found, `null` is returned.
54
+ def header_value(name)
55
+ wrap_impl(@impl.header_value(unwrap_impl(name)))
56
+ end
57
+
58
+ #
59
+ # Returns all values of the headers matching the name, for example `set-cookie`. The name is case-insensitive.
60
+ def header_values(name)
61
+ wrap_impl(@impl.header_values(unwrap_impl(name)))
23
62
  end
24
63
 
64
+ #
25
65
  # Returns the JSON representation of response body.
26
- #
66
+ #
27
67
  # This method will throw if the response body is not parsable via `JSON.parse`.
28
68
  def json
29
- raise NotImplementedError.new('json is not implemented yet.')
69
+ wrap_impl(@impl.json)
30
70
  end
31
71
 
72
+ #
32
73
  # Contains a boolean stating whether the response was successful (status in the range 200-299) or not.
33
74
  def ok
34
- raise NotImplementedError.new('ok is not implemented yet.')
75
+ wrap_impl(@impl.ok)
35
76
  end
36
77
 
78
+ #
37
79
  # Returns the matching `Request` object.
38
80
  def request
39
- raise NotImplementedError.new('request is not implemented yet.')
81
+ wrap_impl(@impl.request)
82
+ end
83
+
84
+ #
85
+ # Returns SSL and other security information.
86
+ def security_details
87
+ wrap_impl(@impl.security_details)
88
+ end
89
+
90
+ #
91
+ # Returns the IP address and port of the server.
92
+ def server_addr
93
+ wrap_impl(@impl.server_addr)
40
94
  end
41
95
 
96
+ #
42
97
  # Contains the status code of the response (e.g., 200 for a success).
43
98
  def status
44
- raise NotImplementedError.new('status is not implemented yet.')
99
+ wrap_impl(@impl.status)
45
100
  end
46
101
 
102
+ #
47
103
  # Contains the status text of the response (e.g. usually an "OK" for a success).
48
104
  def status_text
49
- raise NotImplementedError.new('status_text is not implemented yet.')
105
+ wrap_impl(@impl.status_text)
50
106
  end
51
107
 
108
+ #
52
109
  # Returns the text representation of response body.
53
110
  def text
54
- raise NotImplementedError.new('text is not implemented yet.')
111
+ wrap_impl(@impl.text)
55
112
  end
56
113
 
114
+ #
57
115
  # Contains the URL of the response.
58
116
  def url
59
- raise NotImplementedError.new('url is not implemented yet.')
117
+ wrap_impl(@impl.url)
118
+ end
119
+
120
+ # @nodoc
121
+ def ok?
122
+ wrap_impl(@impl.ok?)
123
+ end
124
+
125
+ # @nodoc
126
+ def from_service_worker?
127
+ wrap_impl(@impl.from_service_worker?)
60
128
  end
61
129
 
62
130
  # -- inherited from EventEmitter --
63
131
  # @nodoc
64
- def on(event, callback)
65
- wrap_impl(@impl.on(unwrap_impl(event), unwrap_impl(callback)))
132
+ def once(event, callback)
133
+ event_emitter_proxy.once(event, callback)
66
134
  end
67
135
 
68
136
  # -- inherited from EventEmitter --
69
137
  # @nodoc
70
- def off(event, callback)
71
- wrap_impl(@impl.off(unwrap_impl(event), unwrap_impl(callback)))
138
+ def on(event, callback)
139
+ event_emitter_proxy.on(event, callback)
72
140
  end
73
141
 
74
142
  # -- inherited from EventEmitter --
75
143
  # @nodoc
76
- def once(event, callback)
77
- wrap_impl(@impl.once(unwrap_impl(event), unwrap_impl(callback)))
144
+ def off(event, callback)
145
+ event_emitter_proxy.off(event, callback)
146
+ end
147
+
148
+ private def event_emitter_proxy
149
+ @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
78
150
  end
79
151
  end
80
152
  end
@@ -1,97 +1,157 @@
1
1
  module Playwright
2
+ #
2
3
  # Whenever a network route is set up with [`method: Page.route`] or [`method: BrowserContext.route`], the `Route` object
3
4
  # allows to handle the route.
5
+ #
6
+ # Learn more about [networking](../network.md).
4
7
  class Route < PlaywrightApi
5
8
 
9
+ #
6
10
  # Aborts the route's request.
7
11
  def abort(errorCode: nil)
8
- raise NotImplementedError.new('abort is not implemented yet.')
12
+ wrap_impl(@impl.abort(errorCode: unwrap_impl(errorCode)))
9
13
  end
10
14
 
11
- # Continues route's request with optional overrides.
12
- #
13
- #
14
- # ```js
15
- # await page.route('**/*', (route, request) => {
16
- # // Override headers
17
- # const headers = {
18
- # ...request.headers(),
19
- # foo: 'bar', // set "foo" header
20
- # origin: undefined, // remove "origin" header
21
- # };
22
- # route.continue({headers});
23
- # });
24
- # ```
25
- #
26
- # ```python async
27
- # async def handle(route, request):
15
+ #
16
+ # Sends route's request to the network with optional overrides.
17
+ #
18
+ # **Usage**
19
+ #
20
+ # ```python sync
21
+ # def handle(route, request):
28
22
  # # override headers
29
23
  # headers = {
30
24
  # **request.headers,
31
- # "foo": "bar" # set "foo" header
32
- # "origin": None # remove "origin" header
25
+ # "foo": "foo-value", # set "foo" header
26
+ # "bar": None # remove "bar" header
33
27
  # }
34
- # await route.continue(headers=headers)
35
- # }
36
- # await page.route("**/*", handle)
28
+ # route.continue_(headers=headers)
29
+ #
30
+ # page.route("**/*", handle)
37
31
  # ```
38
- #
32
+ #
33
+ # **Details**
34
+ #
35
+ # The `headers` option applies to both the routed request and any redirects it initiates. However, `url`, `method`, and `postData` only apply to the original request and are not carried over to redirected requests.
36
+ #
37
+ # [`method: Route.continue`] will immediately send the request to the network, other matching handlers won't be invoked. Use [`method: Route.fallback`] If you want next matching handler in the chain to be invoked.
38
+ #
39
+ # **NOTE**: Some request headers are **forbidden** and cannot be overridden (for example, `Cookie`, `Host`, `Content-Length` and others, see [this MDN page](https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_request_header) for full list).
40
+ # If an override is provided for a forbidden header, it will be ignored and the original request header will be used.
41
+ #
42
+ # To set custom cookies, use [`method: BrowserContext.addCookies`].
43
+ def continue(headers: nil, method: nil, postData: nil, url: nil)
44
+ wrap_impl(@impl.continue(headers: unwrap_impl(headers), method: unwrap_impl(method), postData: unwrap_impl(postData), url: unwrap_impl(url)))
45
+ end
46
+
47
+ #
48
+ # Continues route's request with optional overrides. The method is similar to [`method: Route.continue`] with the difference that other matching handlers will be invoked before sending the request.
49
+ #
50
+ # **Usage**
51
+ #
52
+ # When several routes match the given pattern, they run in the order opposite to their registration.
53
+ # That way the last registered route can always override all the previous ones. In the example below,
54
+ # request will be handled by the bottom-most handler first, then it'll fall back to the previous one and
55
+ # in the end will be aborted by the first registered route.
56
+ #
57
+ # ```python sync
58
+ # page.route("**/*", lambda route: route.abort()) # Runs last.
59
+ # page.route("**/*", lambda route: route.fallback()) # Runs second.
60
+ # page.route("**/*", lambda route: route.fallback()) # Runs first.
61
+ # ```
62
+ #
63
+ # Registering multiple routes is useful when you want separate handlers to
64
+ # handle different kinds of requests, for example API calls vs page resources or
65
+ # GET requests vs POST requests as in the example below.
66
+ #
67
+ # ```python sync
68
+ # # Handle GET requests.
69
+ # def handle_get(route):
70
+ # if route.request.method != "GET":
71
+ # route.fallback()
72
+ # return
73
+ # # Handling GET only.
74
+ # # ...
75
+ #
76
+ # # Handle POST requests.
77
+ # def handle_post(route):
78
+ # if route.request.method != "POST":
79
+ # route.fallback()
80
+ # return
81
+ # # Handling POST only.
82
+ # # ...
83
+ #
84
+ # page.route("**/*", handle_get)
85
+ # page.route("**/*", handle_post)
86
+ # ```
87
+ #
88
+ # One can also modify request while falling back to the subsequent handler, that way intermediate
89
+ # route handler can modify url, method, headers and postData of the request.
90
+ #
39
91
  # ```python sync
40
92
  # def handle(route, request):
41
93
  # # override headers
42
94
  # headers = {
43
95
  # **request.headers,
44
- # "foo": "bar" # set "foo" header
45
- # "origin": None # remove "origin" header
96
+ # "foo": "foo-value", # set "foo" header
97
+ # "bar": None # remove "bar" header
46
98
  # }
47
- # route.continue(headers=headers)
48
- # }
99
+ # route.fallback(headers=headers)
100
+ #
49
101
  # page.route("**/*", handle)
50
102
  # ```
51
- def continue_(headers: nil, method: nil, postData: nil, url: nil)
52
- raise NotImplementedError.new('continue_ is not implemented yet.')
103
+ #
104
+ # Use [`method: Route.continue`] to immediately send the request to the network, other matching handlers won't be invoked in that case.
105
+ def fallback(headers: nil, method: nil, postData: nil, url: nil)
106
+ wrap_impl(@impl.fallback(headers: unwrap_impl(headers), method: unwrap_impl(method), postData: unwrap_impl(postData), url: unwrap_impl(url)))
107
+ end
108
+
109
+ #
110
+ # Performs the request and fetches result without fulfilling it, so that the response
111
+ # could be modified and then fulfilled.
112
+ #
113
+ # **Usage**
114
+ #
115
+ # ```python sync
116
+ # def handle(route):
117
+ # response = route.fetch()
118
+ # json = response.json()
119
+ # json["message"]["big_red_dog"] = []
120
+ # route.fulfill(response=response, json=json)
121
+ #
122
+ # page.route("https://dog.ceo/api/breeds/list/all", handle)
123
+ # ```
124
+ #
125
+ # **Details**
126
+ #
127
+ # Note that `headers` option will apply to the fetched request as well as any redirects initiated by it. If you want to only apply `headers` to the original request, but not to redirects, look into [`method: Route.continue`] instead.
128
+ def fetch(
129
+ headers: nil,
130
+ maxRedirects: nil,
131
+ maxRetries: nil,
132
+ method: nil,
133
+ postData: nil,
134
+ timeout: nil,
135
+ url: nil)
136
+ wrap_impl(@impl.fetch(headers: unwrap_impl(headers), maxRedirects: unwrap_impl(maxRedirects), maxRetries: unwrap_impl(maxRetries), method: unwrap_impl(method), postData: unwrap_impl(postData), timeout: unwrap_impl(timeout), url: unwrap_impl(url)))
53
137
  end
54
138
 
139
+ #
55
140
  # Fulfills route's request with given response.
56
- #
141
+ #
142
+ # **Usage**
143
+ #
57
144
  # An example of fulfilling all requests with 404 responses:
58
- #
59
- #
60
- # ```js
61
- # await page.route('**/*', route => {
62
- # route.fulfill({
63
- # status: 404,
64
- # contentType: 'text/plain',
65
- # body: 'Not Found!'
66
- # });
67
- # });
68
- # ```
69
- #
70
- # ```python async
71
- # await page.route("**/*", lambda route: route.fulfill(
72
- # status=404,
73
- # content_type="text/plain",
74
- # body="not found!"))
75
- # ```
76
- #
145
+ #
77
146
  # ```python sync
78
147
  # page.route("**/*", lambda route: route.fulfill(
79
148
  # status=404,
80
149
  # content_type="text/plain",
81
150
  # body="not found!"))
82
151
  # ```
83
- #
152
+ #
84
153
  # An example of serving static file:
85
- #
86
154
  #
87
- # ```js
88
- # await page.route('**/xhr_endpoint', route => route.fulfill({ path: 'mock_data.json' }));
89
- # ```
90
- #
91
- # ```python async
92
- # await page.route("**/xhr_endpoint", lambda route: route.fulfill(path="mock_data.json"))
93
- # ```
94
- #
95
155
  # ```python sync
96
156
  # page.route("**/xhr_endpoint", lambda route: route.fulfill(path="mock_data.json"))
97
157
  # ```
@@ -99,14 +159,44 @@ module Playwright
99
159
  body: nil,
100
160
  contentType: nil,
101
161
  headers: nil,
162
+ json: nil,
102
163
  path: nil,
164
+ response: nil,
103
165
  status: nil)
104
- raise NotImplementedError.new('fulfill is not implemented yet.')
166
+ wrap_impl(@impl.fulfill(body: unwrap_impl(body), contentType: unwrap_impl(contentType), headers: unwrap_impl(headers), json: unwrap_impl(json), path: unwrap_impl(path), response: unwrap_impl(response), status: unwrap_impl(status)))
105
167
  end
106
168
 
169
+ #
107
170
  # A request to be routed.
108
171
  def request
109
- raise NotImplementedError.new('request is not implemented yet.')
172
+ wrap_impl(@impl.request)
173
+ end
174
+
175
+ # @nodoc
176
+ def redirect_navigation_request(url)
177
+ wrap_impl(@impl.redirect_navigation_request(unwrap_impl(url)))
178
+ end
179
+
180
+ # -- inherited from EventEmitter --
181
+ # @nodoc
182
+ def once(event, callback)
183
+ event_emitter_proxy.once(event, callback)
184
+ end
185
+
186
+ # -- inherited from EventEmitter --
187
+ # @nodoc
188
+ def on(event, callback)
189
+ event_emitter_proxy.on(event, callback)
190
+ end
191
+
192
+ # -- inherited from EventEmitter --
193
+ # @nodoc
194
+ def off(event, callback)
195
+ event_emitter_proxy.off(event, callback)
196
+ end
197
+
198
+ private def event_emitter_proxy
199
+ @event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
110
200
  end
111
201
  end
112
202
  end
@@ -1,73 +1,59 @@
1
1
  module Playwright
2
- # Selectors can be used to install custom selector engines. See
3
- # [Working with selectors](./selectors.md#working-with-selectors) for more information.
2
+ #
3
+ # Selectors can be used to install custom selector engines. See [extensibility](../extensibility.md) for more
4
+ # information.
4
5
  class Selectors < PlaywrightApi
5
6
 
7
+ #
8
+ # Selectors must be registered before creating the page.
9
+ #
10
+ # **Usage**
11
+ #
6
12
  # An example of registering selector engine that queries elements based on a tag name:
7
- #
8
13
  #
9
- # ```js
10
- # const { selectors, firefox } = require('playwright'); // Or 'chromium' or 'webkit'.
11
- #
12
- # (async () => {
13
- # // Must be a function that evaluates to a selector engine instance.
14
- # const createTagNameEngine = () => ({
15
- # // Returns the first element matching given selector in the root's subtree.
16
- # query(root, selector) {
17
- # return root.querySelector(selector);
18
- # },
19
- #
20
- # // Returns all elements matching given selector in the root's subtree.
21
- # queryAll(root, selector) {
22
- # return Array.from(root.querySelectorAll(selector));
23
- # }
24
- # });
25
- #
26
- # // Register the engine. Selectors will be prefixed with "tag=".
27
- # await selectors.register('tag', createTagNameEngine);
28
- #
29
- # const browser = await firefox.launch();
30
- # const page = await browser.newPage();
31
- # await page.setContent(`<div><button>Click me</button></div>`);
32
- #
33
- # // Use the selector prefixed with its name.
34
- # const button = await page.$('tag=button');
35
- # // Combine it with other selector engines.
36
- # await page.click('tag=div >> text="Click me"');
37
- # // Can use it in any methods supporting selectors.
38
- # const buttonCount = await page.$$eval('tag=button', buttons => buttons.length);
39
- #
40
- # await browser.close();
41
- # })();
42
- # ```
43
- #
44
- # ```python async
45
- # # FIXME: add snippet
46
- # ```
47
- #
48
14
  # ```python sync
49
- # # FIXME: add snippet
15
+ # from playwright.sync_api import sync_playwright, Playwright
16
+ #
17
+ # def run(playwright: Playwright):
18
+ # tag_selector = """
19
+ # {
20
+ # // Returns the first element matching given selector in the root's subtree.
21
+ # query(root, selector) {
22
+ # return root.querySelector(selector);
23
+ # },
24
+ # // Returns all elements matching given selector in the root's subtree.
25
+ # queryAll(root, selector) {
26
+ # return Array.from(root.querySelectorAll(selector));
27
+ # }
28
+ # }"""
29
+ #
30
+ # # Register the engine. Selectors will be prefixed with "tag=".
31
+ # playwright.selectors.register("tag", tag_selector)
32
+ # browser = playwright.chromium.launch()
33
+ # page = browser.new_page()
34
+ # page.set_content('<div><button>Click me</button></div>')
35
+ #
36
+ # # Use the selector prefixed with its name.
37
+ # button = page.locator('tag=button')
38
+ # # Combine it with built-in locators.
39
+ # page.locator('tag=div').get_by_text('Click me').click()
40
+ # # Can use it in any methods supporting selectors.
41
+ # button_count = page.locator('tag=button').count()
42
+ # print(button_count)
43
+ # browser.close()
44
+ #
45
+ # with sync_playwright() as playwright:
46
+ # run(playwright)
50
47
  # ```
51
- def register(name, script, contentScript: nil)
52
- raise NotImplementedError.new('register is not implemented yet.')
53
- end
54
-
55
- # -- inherited from EventEmitter --
56
- # @nodoc
57
- def on(event, callback)
58
- wrap_impl(@impl.on(unwrap_impl(event), unwrap_impl(callback)))
48
+ def register(name, script: nil, contentScript: nil, path: nil)
49
+ wrap_impl(@impl.register(unwrap_impl(name), script: unwrap_impl(script), contentScript: unwrap_impl(contentScript), path: unwrap_impl(path)))
59
50
  end
60
51
 
61
- # -- inherited from EventEmitter --
62
- # @nodoc
63
- def off(event, callback)
64
- wrap_impl(@impl.off(unwrap_impl(event), unwrap_impl(callback)))
65
- end
66
-
67
- # -- inherited from EventEmitter --
68
- # @nodoc
69
- def once(event, callback)
70
- wrap_impl(@impl.once(unwrap_impl(event), unwrap_impl(callback)))
52
+ #
53
+ # Defines custom attribute name to be used in [`method: Page.getByTestId`]. `data-testid` is used by default.
54
+ def set_test_id_attribute(attributeName)
55
+ wrap_impl(@impl.set_test_id_attribute(unwrap_impl(attributeName)))
71
56
  end
57
+ alias_method :test_id_attribute=, :set_test_id_attribute
72
58
  end
73
59
  end
@@ -1,11 +1,17 @@
1
1
  module Playwright
2
+ #
2
3
  # The Touchscreen class operates in main-frame CSS pixels relative to the top-left corner of the viewport. Methods on the
3
- # touchscreen can only be used in browser contexts that have been intialized with `hasTouch` set to true.
4
+ # touchscreen can only be used in browser contexts that have been initialized with `hasTouch` set to true.
5
+ #
6
+ # This class is limited to emulating tap gestures. For examples of other gestures simulated by manually dispatching touch events, see the [emulating legacy touch events](../touch-events.md) page.
4
7
  class Touchscreen < PlaywrightApi
5
8
 
9
+ #
6
10
  # Dispatches a `touchstart` and `touchend` event with a single touch at the position (`x`,`y`).
11
+ #
12
+ # **NOTE**: [`method: Page.tap`] the method will throw if `hasTouch` option of the browser context is false.
7
13
  def tap_point(x, y)
8
- raise NotImplementedError.new('tap_point is not implemented yet.')
14
+ wrap_impl(@impl.tap_point(unwrap_impl(x), unwrap_impl(y)))
9
15
  end
10
16
  end
11
17
  end