playwright-ruby-client 1.14.beta3 → 1.15.beta3
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.
- checksums.yaml +4 -4
- data/README.md +10 -14
- data/documentation/docs/api/browser.md +4 -0
- data/documentation/docs/api/browser_context.md +5 -1
- data/documentation/docs/api/browser_type.md +2 -0
- data/documentation/docs/api/element_handle.md +30 -5
- data/documentation/docs/api/experimental/android_device.md +2 -0
- data/documentation/docs/api/frame.md +32 -6
- data/documentation/docs/api/locator.md +67 -38
- data/documentation/docs/api/mouse.md +11 -0
- data/documentation/docs/api/page.md +38 -7
- data/documentation/docs/api/request.md +34 -1
- data/documentation/docs/api/response.md +37 -2
- data/documentation/docs/api/selectors.md +29 -3
- data/documentation/docs/api/tracing.md +42 -8
- data/documentation/docs/api/worker.md +12 -11
- data/documentation/docs/article/getting_started.md +10 -1
- data/documentation/docs/article/guides/download_playwright_driver.md +9 -0
- data/documentation/docs/article/guides/inspector.md +1 -1
- data/documentation/docs/article/guides/playwright_on_alpine_linux.md +56 -3
- data/documentation/docs/article/guides/rails_integration.md +4 -2
- data/documentation/docs/article/guides/rails_integration_with_null_driver.md +86 -0
- data/documentation/docs/article/guides/recording_video.md +1 -1
- data/documentation/docs/article/guides/semi_automation.md +2 -2
- data/documentation/docs/article/guides/use_storage_state.md +78 -0
- data/documentation/docs/include/api_coverage.md +15 -0
- data/documentation/docusaurus.config.js +1 -0
- data/documentation/package.json +2 -2
- data/documentation/src/pages/index.js +0 -1
- data/documentation/static/img/playwright-ruby-client.png +0 -0
- data/documentation/yarn.lock +625 -549
- data/lib/playwright/channel.rb +36 -2
- data/lib/playwright/channel_owners/artifact.rb +6 -2
- data/lib/playwright/channel_owners/browser.rb +4 -0
- data/lib/playwright/channel_owners/browser_context.rb +21 -14
- data/lib/playwright/channel_owners/browser_type.rb +0 -1
- data/lib/playwright/channel_owners/element_handle.rb +10 -2
- data/lib/playwright/channel_owners/frame.rb +8 -0
- data/lib/playwright/channel_owners/page.rb +20 -4
- data/lib/playwright/channel_owners/playwright.rb +9 -0
- data/lib/playwright/channel_owners/request.rb +53 -17
- data/lib/playwright/channel_owners/response.rb +48 -5
- data/lib/playwright/connection.rb +8 -11
- data/lib/playwright/http_headers.rb +0 -6
- data/lib/playwright/locator_impl.rb +8 -0
- data/lib/playwright/mouse_impl.rb +9 -0
- data/lib/playwright/raw_headers.rb +61 -0
- data/lib/playwright/{route_handler_entry.rb → route_handler.rb} +30 -2
- data/lib/playwright/tracing_impl.rb +18 -7
- data/lib/playwright/transport.rb +2 -0
- data/lib/playwright/utils.rb +8 -1
- data/lib/playwright/version.rb +2 -2
- data/lib/playwright/web_socket_transport.rb +2 -0
- data/lib/playwright.rb +46 -5
- data/lib/playwright_api/android.rb +6 -6
- data/lib/playwright_api/android_device.rb +11 -9
- data/lib/playwright_api/browser.rb +12 -8
- data/lib/playwright_api/browser_context.rb +12 -8
- data/lib/playwright_api/browser_type.rb +9 -7
- data/lib/playwright_api/cdp_session.rb +7 -7
- data/lib/playwright_api/console_message.rb +6 -6
- data/lib/playwright_api/dialog.rb +6 -6
- data/lib/playwright_api/element_handle.rb +31 -8
- data/lib/playwright_api/frame.rb +35 -12
- data/lib/playwright_api/js_handle.rb +6 -6
- data/lib/playwright_api/locator.rb +39 -0
- data/lib/playwright_api/mouse.rb +8 -0
- data/lib/playwright_api/page.rb +43 -15
- data/lib/playwright_api/playwright.rb +6 -6
- data/lib/playwright_api/request.rb +33 -7
- data/lib/playwright_api/response.rb +31 -8
- data/lib/playwright_api/route.rb +6 -6
- data/lib/playwright_api/selectors.rb +38 -7
- data/lib/playwright_api/tracing.rb +33 -4
- data/lib/playwright_api/web_socket.rb +6 -6
- data/lib/playwright_api/worker.rb +8 -8
- metadata +8 -4
@@ -66,3 +66,14 @@ def up(button: nil, clickCount: nil)
|
|
66
66
|
```
|
67
67
|
|
68
68
|
Dispatches a `mouseup` event.
|
69
|
+
|
70
|
+
## wheel
|
71
|
+
|
72
|
+
```
|
73
|
+
def wheel(deltaX, deltaY)
|
74
|
+
```
|
75
|
+
|
76
|
+
Dispatches a `wheel` event.
|
77
|
+
|
78
|
+
> NOTE: Wheel events may cause scrolling if they are not handled, and this method does not wait for the scrolling to
|
79
|
+
finish before returning.
|
@@ -281,7 +281,7 @@ def drag_and_drop(
|
|
281
281
|
## emulate_media
|
282
282
|
|
283
283
|
```
|
284
|
-
def emulate_media(colorScheme: nil, media: nil, reducedMotion: nil)
|
284
|
+
def emulate_media(colorScheme: nil, forcedColors: nil, media: nil, reducedMotion: nil)
|
285
285
|
```
|
286
286
|
|
287
287
|
This method changes the `CSS media type` through the `media` argument, and/or the `'prefers-colors-scheme'` media
|
@@ -622,18 +622,18 @@ def goto(url, referer: nil, timeout: nil, waitUntil: nil)
|
|
622
622
|
Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
|
623
623
|
last redirect.
|
624
624
|
|
625
|
-
|
625
|
+
The method will throw an error if:
|
626
626
|
- there's an SSL error (e.g. in case of self-signed certificates).
|
627
627
|
- target URL is invalid.
|
628
628
|
- the `timeout` is exceeded during navigation.
|
629
629
|
- the remote server does not respond or is unreachable.
|
630
630
|
- the main resource failed to load.
|
631
631
|
|
632
|
-
|
632
|
+
The method will not throw an error when any valid HTTP status code is returned by the remote server, including 404 "Not
|
633
633
|
Found" and 500 "Internal Server Error". The status code for such responses can be retrieved by calling
|
634
634
|
[Response#status](./response#status).
|
635
635
|
|
636
|
-
> NOTE:
|
636
|
+
> NOTE: The method either throws an error or returns a main resource response. The only exceptions are navigation to
|
637
637
|
`about:blank` or navigation to the same URL with a different hash, which would succeed and return `null`.
|
638
638
|
> NOTE: Headless mode doesn't support navigation to a PDF document. See the
|
639
639
|
[upstream issue](https://bugs.chromium.org/p/chromium/issues/detail?id=761295).
|
@@ -758,8 +758,6 @@ The method returns an element locator that can be used to perform actions on the
|
|
758
758
|
element immediately before performing an action, so a series of actions on the same locator can in fact be performed on
|
759
759
|
different DOM elements. That would happen if the DOM structure between those actions has changed.
|
760
760
|
|
761
|
-
Note that locator always implies visibility, so it will always be locating visible elements.
|
762
|
-
|
763
761
|
Shortcut for main frame's [Frame#locator](./frame#locator).
|
764
762
|
|
765
763
|
## main_frame
|
@@ -935,7 +933,7 @@ last redirect.
|
|
935
933
|
## route
|
936
934
|
|
937
935
|
```
|
938
|
-
def route(url, handler)
|
936
|
+
def route(url, handler, times: nil)
|
939
937
|
```
|
940
938
|
|
941
939
|
Routing provides the capability to modify network requests that are made by a page.
|
@@ -943,6 +941,9 @@ Routing provides the capability to modify network requests that are made by a pa
|
|
943
941
|
Once routing is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted.
|
944
942
|
|
945
943
|
> NOTE: The handler will only be called for the first url if the response is a redirect.
|
944
|
+
> NOTE: [Page#route](./page#route) will not intercept requests intercepted by Service Worker. See
|
945
|
+
[this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using
|
946
|
+
request interception. Via `await context.addInitScript(() => delete window.navigator.serviceWorker);`
|
946
947
|
|
947
948
|
An example of a naive handler that aborts all image requests:
|
948
949
|
|
@@ -1032,6 +1033,36 @@ page.select_option("select#colors", value: ["red", "green", "blue"])
|
|
1032
1033
|
|
1033
1034
|
Shortcut for main frame's [Frame#select_option](./frame#select_option).
|
1034
1035
|
|
1036
|
+
## set_checked
|
1037
|
+
|
1038
|
+
```
|
1039
|
+
def set_checked(
|
1040
|
+
selector,
|
1041
|
+
checked,
|
1042
|
+
force: nil,
|
1043
|
+
noWaitAfter: nil,
|
1044
|
+
position: nil,
|
1045
|
+
strict: nil,
|
1046
|
+
timeout: nil,
|
1047
|
+
trial: nil)
|
1048
|
+
```
|
1049
|
+
|
1050
|
+
This method checks or unchecks an element matching `selector` by performing the following steps:
|
1051
|
+
1. Find an element matching `selector`. If there is none, wait until a matching element is attached to the DOM.
|
1052
|
+
1. Ensure that matched element is a checkbox or a radio input. If not, this method throws.
|
1053
|
+
1. If the element already has the right checked state, this method returns immediately.
|
1054
|
+
1. Wait for [actionability](https://playwright.dev/python/docs/actionability) checks on the matched element, unless `force` option is set. If the
|
1055
|
+
element is detached during the checks, the whole action is retried.
|
1056
|
+
1. Scroll the element into view if needed.
|
1057
|
+
1. Use [Page#mouse](./page#mouse) to click in the center of the element.
|
1058
|
+
1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
|
1059
|
+
1. Ensure that the element is now checked or unchecked. If not, this method throws.
|
1060
|
+
|
1061
|
+
When all steps combined have not finished during the specified `timeout`, this method throws a `TimeoutError`. Passing
|
1062
|
+
zero timeout disables this.
|
1063
|
+
|
1064
|
+
Shortcut for main frame's [Frame#set_checked](./frame#set_checked).
|
1065
|
+
|
1035
1066
|
## set_content
|
1036
1067
|
|
1037
1068
|
```
|
@@ -18,6 +18,14 @@ complete with `'requestfinished'` event.
|
|
18
18
|
If request gets a 'redirect' response, the request is successfully finished with the 'requestfinished' event, and a new
|
19
19
|
request is issued to a redirected url.
|
20
20
|
|
21
|
+
## all_headers
|
22
|
+
|
23
|
+
```
|
24
|
+
def all_headers
|
25
|
+
```
|
26
|
+
|
27
|
+
An object with all the request HTTP headers associated with this request. The header names are lower-cased.
|
28
|
+
|
21
29
|
## failure
|
22
30
|
|
23
31
|
```
|
@@ -48,7 +56,24 @@ Returns the [Frame](./frame) that initiated this request.
|
|
48
56
|
def headers
|
49
57
|
```
|
50
58
|
|
51
|
-
|
59
|
+
**DEPRECATED** Incomplete list of headers as seen by the rendering engine. Use [Request#all_headers](./request#all_headers) instead.
|
60
|
+
|
61
|
+
## headers_array
|
62
|
+
|
63
|
+
```
|
64
|
+
def headers_array
|
65
|
+
```
|
66
|
+
|
67
|
+
An array with all the request HTTP headers associated with this request. Unlike [Request#all_headers](./request#all_headers), header
|
68
|
+
names are NOT lower-cased. Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times.
|
69
|
+
|
70
|
+
## header_value
|
71
|
+
|
72
|
+
```
|
73
|
+
def header_value(name)
|
74
|
+
```
|
75
|
+
|
76
|
+
Returns the value of the header matching the name. The name is case insensitive.
|
52
77
|
|
53
78
|
## navigation_request?
|
54
79
|
|
@@ -156,6 +181,14 @@ def response
|
|
156
181
|
|
157
182
|
Returns the matching [Response](./response) object, or `null` if the response was not received due to error.
|
158
183
|
|
184
|
+
## sizes
|
185
|
+
|
186
|
+
```
|
187
|
+
def sizes
|
188
|
+
```
|
189
|
+
|
190
|
+
Returns resource size information for given request.
|
191
|
+
|
159
192
|
## timing
|
160
193
|
|
161
194
|
```
|
@@ -6,6 +6,14 @@ sidebar_position: 10
|
|
6
6
|
|
7
7
|
[Response](./response) class represents responses which are received by page.
|
8
8
|
|
9
|
+
## all_headers
|
10
|
+
|
11
|
+
```
|
12
|
+
def all_headers
|
13
|
+
```
|
14
|
+
|
15
|
+
An object with all the response HTTP headers associated with this response.
|
16
|
+
|
9
17
|
## body
|
10
18
|
|
11
19
|
```
|
@@ -20,7 +28,7 @@ Returns the buffer with response body.
|
|
20
28
|
def finished
|
21
29
|
```
|
22
30
|
|
23
|
-
Waits for this response to finish, returns
|
31
|
+
Waits for this response to finish, returns always `null`.
|
24
32
|
|
25
33
|
## frame
|
26
34
|
|
@@ -36,7 +44,34 @@ Returns the [Frame](./frame) that initiated this response.
|
|
36
44
|
def headers
|
37
45
|
```
|
38
46
|
|
39
|
-
|
47
|
+
**DEPRECATED** Incomplete list of headers as seen by the rendering engine. Use [Response#all_headers](./response#all_headers) instead.
|
48
|
+
|
49
|
+
## headers_array
|
50
|
+
|
51
|
+
```
|
52
|
+
def headers_array
|
53
|
+
```
|
54
|
+
|
55
|
+
An array with all the request HTTP headers associated with this response. Unlike [Response#all_headers](./response#all_headers), header
|
56
|
+
names are NOT lower-cased. Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times.
|
57
|
+
|
58
|
+
## header_value
|
59
|
+
|
60
|
+
```
|
61
|
+
def header_value(name)
|
62
|
+
```
|
63
|
+
|
64
|
+
Returns the value of the header matching the name. The name is case insensitive. If multiple headers have the same name
|
65
|
+
(except `set-cookie`), they are returned as a list separated by `, `. For `set-cookie`, the `\n` separator is used. If
|
66
|
+
no headers are found, `null` is returned.
|
67
|
+
|
68
|
+
## header_values
|
69
|
+
|
70
|
+
```
|
71
|
+
def header_values(name)
|
72
|
+
```
|
73
|
+
|
74
|
+
Returns all values of the headers matching the name, for example `set-cookie`. The name is case insensitive.
|
40
75
|
|
41
76
|
## json
|
42
77
|
|
@@ -15,9 +15,35 @@ def register(name, contentScript: nil, path: nil, script: nil)
|
|
15
15
|
|
16
16
|
An example of registering selector engine that queries elements based on a tag name:
|
17
17
|
|
18
|
-
```
|
19
|
-
|
20
|
-
|
18
|
+
```ruby
|
19
|
+
tag_selector = <<~JAVASCRIPT
|
20
|
+
{
|
21
|
+
// Returns the first element matching given selector in the root's subtree.
|
22
|
+
query(root, selector) {
|
23
|
+
return root.querySelector(selector);
|
24
|
+
},
|
25
|
+
// Returns all elements matching given selector in the root's subtree.
|
26
|
+
queryAll(root, selector) {
|
27
|
+
return Array.from(root.querySelectorAll(selector));
|
28
|
+
}
|
29
|
+
}
|
30
|
+
JAVASCRIPT
|
31
|
+
|
32
|
+
# Register the engine. Selectors will be prefixed with "tag=".
|
33
|
+
playwright.selectors.register("tag", script: tag_selector)
|
34
|
+
playwright.chromium.launch do |browser|
|
35
|
+
page = browser.new_page()
|
36
|
+
page.content = '<div><button>Click me</button></div>'
|
37
|
+
|
38
|
+
# Use the selector prefixed with its name.
|
39
|
+
button = page.query_selector('tag=button')
|
40
|
+
# Combine it with other selector engines.
|
41
|
+
page.click('tag=div >> text="Click me"')
|
42
|
+
|
43
|
+
# Can use it in any methods supporting selectors.
|
44
|
+
button_count = page.eval_on_selector_all('tag=button', 'buttons => buttons.length')
|
45
|
+
button_count # => 1
|
46
|
+
end
|
21
47
|
```
|
22
48
|
|
23
49
|
|
@@ -4,16 +4,15 @@ sidebar_position: 10
|
|
4
4
|
|
5
5
|
# Tracing
|
6
6
|
|
7
|
-
API for collecting and saving Playwright traces. Playwright traces can be opened
|
8
|
-
Playwright script runs.
|
7
|
+
API for collecting and saving Playwright traces. Playwright traces can be opened in [Trace Viewer](https://playwright.dev/python/docs/trace-viewer)
|
8
|
+
after Playwright script runs.
|
9
9
|
|
10
|
-
Start
|
10
|
+
Start recording a trace before performing actions. At the end, stop tracing and save it to a file.
|
11
11
|
|
12
12
|
```ruby
|
13
|
-
browser.
|
14
|
-
context = page.context
|
15
|
-
|
13
|
+
browser.new_context do |context|
|
16
14
|
context.tracing.start(screenshots: true, snapshots: true)
|
15
|
+
page = context.new_page
|
17
16
|
page.goto('https://playwright.dev')
|
18
17
|
context.tracing.stop(path: 'trace.zip')
|
19
18
|
end
|
@@ -30,15 +29,42 @@ def start(name: nil, screenshots: nil, snapshots: nil)
|
|
30
29
|
Start tracing.
|
31
30
|
|
32
31
|
```ruby
|
33
|
-
context = page.context
|
34
|
-
|
35
32
|
context.tracing.start(name: 'trace', screenshots: true, snapshots: true)
|
33
|
+
page = context.new_page
|
36
34
|
page.goto('https://playwright.dev')
|
37
35
|
context.tracing.stop(path: 'trace.zip')
|
38
36
|
```
|
39
37
|
|
40
38
|
|
41
39
|
|
40
|
+
## start_chunk
|
41
|
+
|
42
|
+
```
|
43
|
+
def start_chunk
|
44
|
+
```
|
45
|
+
|
46
|
+
Start a new trace chunk. If you'd like to record multiple traces on the same [BrowserContext](./browser_context), use
|
47
|
+
[Tracing#start](./tracing#start) once, and then create multiple trace chunks with [Tracing#start_chunk](./tracing#start_chunk) and
|
48
|
+
[Tracing#stop_chunk](./tracing#stop_chunk).
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
context.tracing.start(name: "trace", screenshots: true, snapshots: true)
|
52
|
+
page = context.new_page
|
53
|
+
page.goto("https://playwright.dev")
|
54
|
+
|
55
|
+
context.tracing.start_chunk
|
56
|
+
page.click("text=Get Started")
|
57
|
+
# Everything between start_chunk and stop_chunk will be recorded in the trace.
|
58
|
+
context.tracing.stop_chunk(path: "trace1.zip")
|
59
|
+
|
60
|
+
context.tracing.start_chunk
|
61
|
+
page.goto("http://example.com")
|
62
|
+
# Save a second trace file with different actions.
|
63
|
+
context.tracing.stop_chunk(path: "trace2.zip")
|
64
|
+
```
|
65
|
+
|
66
|
+
|
67
|
+
|
42
68
|
## stop
|
43
69
|
|
44
70
|
```
|
@@ -46,3 +72,11 @@ def stop(path: nil)
|
|
46
72
|
```
|
47
73
|
|
48
74
|
Stop tracing.
|
75
|
+
|
76
|
+
## stop_chunk
|
77
|
+
|
78
|
+
```
|
79
|
+
def stop_chunk(path: nil)
|
80
|
+
```
|
81
|
+
|
82
|
+
Stop the trace chunk. See [Tracing#start_chunk](./tracing#start_chunk) for more details about multiple trace chunks.
|
@@ -8,17 +8,18 @@ The Worker class represents a [WebWorker](https://developer.mozilla.org/en-US/do
|
|
8
8
|
event is emitted on the page object to signal a worker creation. `close` event is emitted on the worker object when the
|
9
9
|
worker is gone.
|
10
10
|
|
11
|
-
```
|
12
|
-
def handle_worker(worker)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
11
|
+
```ruby
|
12
|
+
def handle_worker(worker)
|
13
|
+
puts "worker created: #{worker.url}"
|
14
|
+
worker.once("close", -> (w) { puts "worker destroyed: #{w.url}" })
|
15
|
+
end
|
16
|
+
|
17
|
+
page.on('worker', method(:handle_worker))
|
18
|
+
|
19
|
+
puts "current workers:"
|
20
|
+
page.workers.each do |worker|
|
21
|
+
puts " #{worker.url}"
|
22
|
+
end
|
22
23
|
```
|
23
24
|
|
24
25
|
|
@@ -4,7 +4,14 @@ sidebar_position: 0
|
|
4
4
|
|
5
5
|
# Getting started
|
6
6
|
|
7
|
-
|
7
|
+
```
|
8
|
+
gem 'playwright-ruby-client'
|
9
|
+
```
|
10
|
+
|
11
|
+
Add the line above and then `bundle install`.
|
12
|
+
|
13
|
+
|
14
|
+
Since `playwright-ruby-client` doesn't include Playwright driver nor its downloader, **we have to install Playwright in advance**
|
8
15
|
|
9
16
|
```shell
|
10
17
|
$ npx playwright install
|
@@ -12,6 +19,8 @@ $ npx playwright install
|
|
12
19
|
|
13
20
|
and then set `playwright_cli_executable_path: "npx playwright"` into `Playwright.create`.
|
14
21
|
|
22
|
+
Other methods of installation is also available. See the detail in [Download Playwright driver](./guides/download_playwright_driver)
|
23
|
+
|
15
24
|
## Enjoy with examples
|
16
25
|
|
17
26
|
### Capture a site
|
@@ -12,6 +12,15 @@ Choose any of the three ways as you prefer to download the driver:
|
|
12
12
|
* `npm install`: the best choice for most use cases, with existing Node.js environment.
|
13
13
|
* Direct download: maybe a good choice for Docker :whale: integration.
|
14
14
|
|
15
|
+
:::note
|
16
|
+
|
17
|
+
Also the article [Playwright on Alpine Linux](./playwright_on_alpine_linux) would be helpful if you plan to
|
18
|
+
|
19
|
+
* Build a browser server/container like Selenium Grid
|
20
|
+
* Run automation scripts on Alpine Linux
|
21
|
+
|
22
|
+
:::
|
23
|
+
|
15
24
|
## Using `npx`
|
16
25
|
|
17
26
|
```shell
|
@@ -1,5 +1,5 @@
|
|
1
1
|
---
|
2
|
-
sidebar_position:
|
2
|
+
sidebar_position: 40
|
3
3
|
---
|
4
4
|
|
5
5
|
# Playwright on Alpine Linux
|
@@ -33,7 +33,23 @@ Playwright server is running on a container of [official Docker image](https://h
|
|
33
33
|
|
34
34
|

|
35
35
|
|
36
|
-
|
36
|
+
### Playwright Server v.s. Browser Server
|
37
|
+
|
38
|
+
Playwright provides two kind of methods to share the browser environments for clients.
|
39
|
+
|
40
|
+
When you want to share only one browser environment, Browser server is suitable. This feature is officially supported in Playwright.
|
41
|
+
|
42
|
+
* Server can be launched with [BrowserType#launchServer](https://playwright.dev/docs/api/class-browsertype#browser-type-launch-server) instead of `BrowserType#launch`.
|
43
|
+
* Client can connect to server with [BrowserType#connect](https://playwright.dev/docs/api/class-browsertype#browser-type-connect). In playwright-ruby-client, `BrowserType#connect` and not implemented yet and use `Playwright#connect_to_browser_server()` instead.
|
44
|
+
|
45
|
+
Another method is sharing all browser environment. This method is very simple, but not an official feature, and can be changed in future.
|
46
|
+
|
47
|
+
* Server can be launched with `playwright run-server` (CLI command).
|
48
|
+
* Client can connect to server with `Playwright.connect_to_playwright_server` instead of `Playwright.create`
|
49
|
+
|
50
|
+
## Playwright server/client
|
51
|
+
|
52
|
+
### Client code
|
37
53
|
|
38
54
|
Many example uses `Playwright#create`, which internally uses Pipe (stdin/stdout) transport for Playwright-protocol messaging. Instead, **just use `Playwright#connect_to_playwright_server(endpoint)`** for WebSocket transport.
|
39
55
|
|
@@ -51,7 +67,7 @@ end
|
|
51
67
|
|
52
68
|
`wss://example.com:8888/ws` is an example of endpoint URL of the Playwright server. In local development environment, it is typically `"ws://127.0.0.1:#{port}/ws"`.
|
53
69
|
|
54
|
-
|
70
|
+
### Server code
|
55
71
|
|
56
72
|
With the [official Docker image](https://hub.docker.com/_/microsoft-playwright) or in the local development environment with Node.js, just execute `npx playwright install && npx playwright run-server $PORT`. (`$PORT` is a port number of the server)
|
57
73
|
|
@@ -67,6 +83,43 @@ ENV PORT 8888
|
|
67
83
|
CMD ["./node_modules/.bin/playwright", "run-server", "$PORT"]
|
68
84
|
```
|
69
85
|
|
86
|
+
## Browser server/client
|
87
|
+
|
88
|
+
### Client code
|
89
|
+
|
90
|
+
Use `Playwright#connect_to_playwright_server` and pass the WebSocket URL for browser server.
|
91
|
+
Note that this method requires a block with `Browser`, not `Playwright` or `BrowserType`.
|
92
|
+
|
93
|
+
```ruby
|
94
|
+
Playwright.connect_to_playwright_server(ws_url) do |browser|
|
95
|
+
page = browser.new_page
|
96
|
+
page.goto(...)
|
97
|
+
...
|
98
|
+
end
|
99
|
+
```
|
100
|
+
|
101
|
+
### Server code
|
102
|
+
|
103
|
+
For instant use, `npx playwright launch-server chromium` generates a WebSocket endpoint URL with a random path.
|
104
|
+
|
105
|
+
More customization can be done by implementing JavaScript server like below:
|
106
|
+
|
107
|
+
```js
|
108
|
+
const playwright = require('playwright')
|
109
|
+
|
110
|
+
option = {
|
111
|
+
channel: 'chrome-canary',
|
112
|
+
headless: false,
|
113
|
+
port: 8080,
|
114
|
+
wsPath: 'ws',
|
115
|
+
}
|
116
|
+
playwright.chromium.launchServer(option).then((server) => { console.log(server.wsEndpoint()) })
|
117
|
+
```
|
118
|
+
|
119
|
+
`port` and `wsPath` would be useful for generating static WebSocket endpoint URL.
|
120
|
+
Other available options for `BrowserType#launchServer` can be found here:
|
121
|
+
https://playwright.dev/docs/api/class-browsertype#browser-type-launch-server
|
122
|
+
|
70
123
|
## Debugging for connection
|
71
124
|
|
72
125
|
The client and server are really quiet. This chapter shows how to check if the communication on the WebSocket works well or not.
|