playwright-ruby-client 1.57.1 → 1.58.0
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/documentation/docs/api/browser_type.md +1 -2
- data/documentation/docs/api/locator.md +1 -1
- data/documentation/docs/api/locator_assertions.md +1 -1
- data/documentation/docs/api/route.md +4 -1
- data/documentation/docs/article/getting_started.md +1 -1
- data/documentation/docs/article/guides/inspector.md +1 -1
- data/documentation/docs/article/guides/launch_browser.md +5 -5
- data/documentation/docs/article/guides/rails_integration.md +1 -1
- data/documentation/docs/article/guides/recording_video.md +2 -2
- data/documentation/docs/article/guides/semi_automation.md +1 -1
- data/documentation/docs/include/api_coverage.md +1 -0
- data/lib/playwright/channel_owners/binding_call.rb +37 -3
- data/lib/playwright/channel_owners/browser_type.rb +2 -1
- data/lib/playwright/channel_owners/page.rb +4 -1
- data/lib/playwright/channel_owners/web_socket.rb +14 -0
- data/lib/playwright/connection.rb +25 -20
- data/lib/playwright/javascript/value_serializer.rb +2 -1
- data/lib/playwright/locator_assertions_impl.rb +1 -1
- data/lib/playwright/page_assertions_impl.rb +1 -1
- data/lib/playwright/version.rb +2 -2
- data/lib/playwright/waiter.rb +24 -6
- data/lib/playwright_api/android.rb +4 -4
- data/lib/playwright_api/android_device.rb +8 -8
- data/lib/playwright_api/api_request_context.rb +4 -4
- data/lib/playwright_api/browser.rb +4 -4
- data/lib/playwright_api/browser_context.rb +14 -14
- data/lib/playwright_api/browser_type.rb +8 -9
- data/lib/playwright_api/cdp_session.rb +4 -4
- data/lib/playwright_api/dialog.rb +4 -4
- data/lib/playwright_api/element_handle.rb +4 -4
- data/lib/playwright_api/frame.rb +4 -4
- data/lib/playwright_api/js_handle.rb +4 -4
- data/lib/playwright_api/locator.rb +5 -5
- data/lib/playwright_api/locator_assertions.rb +1 -1
- data/lib/playwright_api/page.rb +9 -9
- data/lib/playwright_api/playwright.rb +4 -4
- data/lib/playwright_api/request.rb +16 -4
- data/lib/playwright_api/response.rb +8 -8
- data/lib/playwright_api/route.rb +8 -5
- data/lib/playwright_api/tracing.rb +4 -4
- data/lib/playwright_api/web_socket.rb +4 -4
- data/lib/playwright_api/worker.rb +8 -8
- data/sig/playwright.rbs +4 -4
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '08aec35a2cb057d2af0f12a380e0a56393671043a9f4f1cf2af5315009fe1172'
|
|
4
|
+
data.tar.gz: cc722558227d085896e30d6819c391404770d319da4a6bb10b5ef72ed2317212
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3de09e030621846244bc6c59d26a7d18b00ad716f315fa4ea0ebffe93a2095a1b33401480a20617e26a28987bf11703f37a85a6be8dfb37dc6d11c2a9a5a574c
|
|
7
|
+
data.tar.gz: 29527ac83824caf1c2f4ce51e691fad3af9d3213f7d7d6df3877e25118981a3c9c5a62b44878434fb6cc61667d3c2088d4c36fef58b59c0a135e975cd634dd4d
|
|
@@ -25,6 +25,7 @@ end
|
|
|
25
25
|
def connect_over_cdp(
|
|
26
26
|
endpointURL,
|
|
27
27
|
headers: nil,
|
|
28
|
+
isLocal: nil,
|
|
28
29
|
slowMo: nil,
|
|
29
30
|
timeout: nil,
|
|
30
31
|
&block)
|
|
@@ -63,7 +64,6 @@ def launch(
|
|
|
63
64
|
args: nil,
|
|
64
65
|
channel: nil,
|
|
65
66
|
chromiumSandbox: nil,
|
|
66
|
-
devtools: nil,
|
|
67
67
|
downloadsPath: nil,
|
|
68
68
|
env: nil,
|
|
69
69
|
executablePath: nil,
|
|
@@ -126,7 +126,6 @@ def launch_persistent_context(
|
|
|
126
126
|
colorScheme: nil,
|
|
127
127
|
contrast: nil,
|
|
128
128
|
deviceScaleFactor: nil,
|
|
129
|
-
devtools: nil,
|
|
130
129
|
downloadsPath: nil,
|
|
131
130
|
env: nil,
|
|
132
131
|
executablePath: nil,
|
|
@@ -343,7 +343,7 @@ def description
|
|
|
343
343
|
```
|
|
344
344
|
|
|
345
345
|
|
|
346
|
-
Returns locator description previously set with [Locator#describe](./locator#describe). Returns `null` if no custom description has been set.
|
|
346
|
+
Returns locator description previously set with [Locator#describe](./locator#describe). Returns `null` if no custom description has been set.
|
|
347
347
|
|
|
348
348
|
**Usage**
|
|
349
349
|
|
|
@@ -524,7 +524,7 @@ Let's see how we can use the assertion:
|
|
|
524
524
|
|
|
525
525
|
```ruby
|
|
526
526
|
# ✓ Contains the right items in the right order
|
|
527
|
-
expect(page.locator("ul > li")).to contain_text(["Text 1", "Text 3"
|
|
527
|
+
expect(page.locator("ul > li")).to contain_text(["Text 1", "Text 3"])
|
|
528
528
|
|
|
529
529
|
# ✖ Wrong order
|
|
530
530
|
expect(page.locator("ul > li")).to contain_text(["Text 3", "Text 2"])
|
|
@@ -49,7 +49,10 @@ The `headers` option applies to both the routed request and any redirects it ini
|
|
|
49
49
|
|
|
50
50
|
[Route#continue](./route#continue) will immediately send the request to the network, other matching handlers won't be invoked. Use [Route#fallback](./route#fallback) If you want next matching handler in the chain to be invoked.
|
|
51
51
|
|
|
52
|
-
**NOTE**:
|
|
52
|
+
**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).
|
|
53
|
+
If an override is provided for a forbidden header, it will be ignored and the original request header will be used.
|
|
54
|
+
|
|
55
|
+
To set custom cookies, use [BrowserContext#add_cookies](./browser_context#add_cookies).
|
|
53
56
|
|
|
54
57
|
## fallback
|
|
55
58
|
|
|
@@ -19,7 +19,7 @@ $ npx playwright install
|
|
|
19
19
|
|
|
20
20
|
and then set `playwright_cli_executable_path: "npx playwright"` into `Playwright.create`.
|
|
21
21
|
|
|
22
|
-
Other methods of installation
|
|
22
|
+
Other methods of installation are also available. See the detail in [Download Playwright driver](./guides/download_playwright_driver)
|
|
23
23
|
|
|
24
24
|
## Enjoy with examples
|
|
25
25
|
|
|
@@ -8,7 +8,7 @@ sidebar_position: 2
|
|
|
8
8
|
|
|
9
9
|
## Create Playwright session
|
|
10
10
|
|
|
11
|
-
In
|
|
11
|
+
In order to launch browser, it is required to create Playwright session.
|
|
12
12
|
|
|
13
13
|
In previous examples,
|
|
14
14
|
|
|
@@ -18,7 +18,7 @@ Playwright.create(playwright_cli_executable_path: 'npx playwright') do |playwrig
|
|
|
18
18
|
end
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
this is the exact procedure for creating Playwright session. Choose either
|
|
21
|
+
this is the exact procedure for creating Playwright session. Choose either method for creating the session.
|
|
22
22
|
|
|
23
23
|
### Define scoped Playwright session with block
|
|
24
24
|
|
|
@@ -28,13 +28,13 @@ Playwright.create(playwright_cli_executable_path: 'npx playwright') do |playwrig
|
|
|
28
28
|
end
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
As
|
|
31
|
+
As described repeatedly, this is the recommended way for creating a Playwright session. Even when any exception happens, Playwright session is safely ended on leaving the block.
|
|
32
32
|
|
|
33
33
|
Internally `playwright run-driver` session is alive during the block.
|
|
34
34
|
|
|
35
35
|
### Define start/end of the Playwright session separately without block.
|
|
36
36
|
|
|
37
|
-
Sometimes we have to define
|
|
37
|
+
Sometimes we have to define separate start/end definitions. `playwright-ruby-client` also allows it.
|
|
38
38
|
|
|
39
39
|
```rb
|
|
40
40
|
class SomeClass
|
|
@@ -103,7 +103,7 @@ Also we can use `Browser#new_page` to create a new window and new tab at once.
|
|
|
103
103
|
|
|
104
104
|
```rb
|
|
105
105
|
Playwright.create(playwright_cli_executable_path: 'npx playwright') do |playwright|
|
|
106
|
-
playwright.chromium.launch(headless: false) do |browser| # Chromium task icon
|
|
106
|
+
playwright.chromium.launch(headless: false) do |browser| # Chromium task icon appears.
|
|
107
107
|
context = browser.new_context # Prepare new window.
|
|
108
108
|
page = context.new_page # Open new window and new tab here. (about:blank)
|
|
109
109
|
page.goto('https://example.com') # Navigate to a site.
|
|
@@ -217,7 +217,7 @@ before do |example|
|
|
|
217
217
|
end
|
|
218
218
|
```
|
|
219
219
|
|
|
220
|
-

|
|
221
221
|
|
|
222
222
|
For more details, refer [Recording video](./recording_video.md#using-screen-recording-from-capybara-driver)
|
|
223
223
|
|
|
@@ -33,7 +33,7 @@ playwright.chromium.launch do |browser|
|
|
|
33
33
|
|
|
34
34
|
Playwright puts videos on the directory specified at `record_video_dir`.
|
|
35
35
|
|
|
36
|
-
The previous example uses [Dir#mktmpdir](https://docs.ruby-lang.org/ja/latest/method/Dir/s/mktmpdir.html) for storing videos into a
|
|
36
|
+
The previous example uses [Dir#mktmpdir](https://docs.ruby-lang.org/ja/latest/method/Dir/s/mktmpdir.html) for storing videos into a temporary directory. Also we simply specify a relative or absolute path like `./my_videos/` or `/path/to/videos`.
|
|
37
37
|
|
|
38
38
|
## Getting video path and recorded video
|
|
39
39
|
|
|
@@ -42,7 +42,7 @@ This is really confusing for beginners, but in Playwright
|
|
|
42
42
|
* We can get the video path **only when page is alive (before calling BrowserContext#close or Page#close)**
|
|
43
43
|
* We can acquire the completely saved video **only after calling BrowserContext#close**
|
|
44
44
|
|
|
45
|
-
So in most
|
|
45
|
+
So in most cases, we have to store the video path in advance, and handle the saved video after BrowserContext is closed, as shown in the previous example code.
|
|
46
46
|
|
|
47
47
|
### Using `video#save_as(path)`
|
|
48
48
|
|
|
@@ -5,7 +5,7 @@ sidebar_position: 20
|
|
|
5
5
|
# Semi-automation
|
|
6
6
|
|
|
7
7
|
Playwright Browser context is isolated and not persisted by default. But we can also use persistent browser context using [BrowserType#launch_persistent_context](/docs/api/browser_type#launch_persistent_context).
|
|
8
|
-
This
|
|
8
|
+
This allows us to intervene in automation, for example
|
|
9
9
|
|
|
10
10
|
* Authenticate with OAuth2 manually before automation
|
|
11
11
|
* Testing a page after some chrome extensions are installed manually
|
|
@@ -1,11 +1,45 @@
|
|
|
1
1
|
module Playwright
|
|
2
2
|
define_channel_owner :BindingCall do
|
|
3
|
+
class << self
|
|
4
|
+
def call_queue
|
|
5
|
+
@call_queue ||= Queue.new
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def worker_mutex
|
|
9
|
+
@worker_mutex ||= Mutex.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def ensure_worker
|
|
13
|
+
worker_mutex.synchronize do
|
|
14
|
+
return if @worker&.alive?
|
|
15
|
+
|
|
16
|
+
@worker = Thread.new do
|
|
17
|
+
loop do
|
|
18
|
+
job = call_queue.pop
|
|
19
|
+
begin
|
|
20
|
+
job.call
|
|
21
|
+
rescue => err
|
|
22
|
+
$stderr.write("BindingCall worker error: #{err.class}: #{err.message}\n")
|
|
23
|
+
err.backtrace&.each { |line| $stderr.write("#{line}\n") }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
3
31
|
def name
|
|
4
32
|
@initializer['name']
|
|
5
33
|
end
|
|
6
34
|
|
|
7
35
|
def call_async(callback)
|
|
8
|
-
|
|
36
|
+
# Binding callbacks can be fired concurrently from multiple threads.
|
|
37
|
+
# Enqueue and execute them on a single worker thread so we:
|
|
38
|
+
# - preserve the delivery order of binding calls
|
|
39
|
+
# - avoid spawning a thread per call (bursty timers create many callbacks)
|
|
40
|
+
# - keep the protocol dispatch thread unblocked
|
|
41
|
+
self.class.ensure_worker
|
|
42
|
+
self.class.call_queue << -> { call(callback) }
|
|
9
43
|
end
|
|
10
44
|
|
|
11
45
|
# @param callback [Proc]
|
|
@@ -31,9 +65,9 @@ module Playwright
|
|
|
31
65
|
|
|
32
66
|
begin
|
|
33
67
|
result = PlaywrightApi.unwrap(callback.call(source, *args))
|
|
34
|
-
@channel.
|
|
68
|
+
@channel.async_send_message_to_server('resolve', result: JavaScript::ValueSerializer.new(result).serialize)
|
|
35
69
|
rescue => err
|
|
36
|
-
@channel.
|
|
70
|
+
@channel.async_send_message_to_server('reject', error: { error: { message: err.message, name: 'Error' }})
|
|
37
71
|
end
|
|
38
72
|
end
|
|
39
73
|
end
|
|
@@ -60,12 +60,13 @@ module Playwright
|
|
|
60
60
|
end
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
-
def connect_over_cdp(endpointURL, headers: nil, slowMo: nil, timeout: nil, &block)
|
|
63
|
+
def connect_over_cdp(endpointURL, headers: nil, isLocal: nil, slowMo: nil, timeout: nil, &block)
|
|
64
64
|
raise 'Connecting over CDP is only supported in Chromium.' unless name == 'chromium'
|
|
65
65
|
|
|
66
66
|
params = {
|
|
67
67
|
endpointURL: endpointURL,
|
|
68
68
|
headers: headers,
|
|
69
|
+
isLocal: isLocal,
|
|
69
70
|
slowMo: slowMo,
|
|
70
71
|
timeout: @timeout_settings.timeout(timeout),
|
|
71
72
|
}.compact
|
|
@@ -98,7 +98,7 @@ module Playwright
|
|
|
98
98
|
|
|
99
99
|
private def on_route(route)
|
|
100
100
|
route.send(:update_context, self)
|
|
101
|
-
|
|
101
|
+
return if @close_was_called
|
|
102
102
|
# It is not desired to use PlaywrightApi.wrap directly.
|
|
103
103
|
# However it is a little difficult to define wrapper for `handler` parameter in generate_api.
|
|
104
104
|
# Just a workaround...
|
|
@@ -508,6 +508,9 @@ module Playwright
|
|
|
508
508
|
|
|
509
509
|
def close(runBeforeUnload: nil, reason: nil)
|
|
510
510
|
@close_reason = reason
|
|
511
|
+
unless runBeforeUnload
|
|
512
|
+
@close_was_called = true
|
|
513
|
+
end
|
|
511
514
|
if @owned_context
|
|
512
515
|
@owned_context.close
|
|
513
516
|
else
|
|
@@ -48,7 +48,21 @@ module Playwright
|
|
|
48
48
|
|
|
49
49
|
waiter.reject_on_event(@parent, 'close', -> { @parent.send(:close_error_with_reason) })
|
|
50
50
|
waiter.wait_for_event(self, event, predicate: predicate)
|
|
51
|
+
if @closed
|
|
52
|
+
if event == Events::WebSocket::Close
|
|
53
|
+
waiter.force_fulfill(nil)
|
|
54
|
+
else
|
|
55
|
+
waiter.force_reject(SocketClosedError.new)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
51
58
|
block&.call
|
|
59
|
+
if @closed
|
|
60
|
+
if event == Events::WebSocket::Close
|
|
61
|
+
waiter.force_fulfill(nil)
|
|
62
|
+
else
|
|
63
|
+
waiter.force_reject(SocketClosedError.new)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
52
66
|
|
|
53
67
|
waiter.result.value!
|
|
54
68
|
end
|
|
@@ -11,9 +11,8 @@ module Playwright
|
|
|
11
11
|
dispatch(message)
|
|
12
12
|
end
|
|
13
13
|
@transport.on_driver_crashed do
|
|
14
|
-
@callbacks.
|
|
15
|
-
|
|
16
|
-
end
|
|
14
|
+
callbacks = @callbacks_mutex.synchronize { @callbacks.values }
|
|
15
|
+
callbacks.each { |callback| callback.reject(::Playwright::DriverCrashedError.new) }
|
|
17
16
|
raise ::Playwright::DriverCrashedError.new
|
|
18
17
|
end
|
|
19
18
|
@transport.on_driver_closed do
|
|
@@ -21,8 +20,10 @@ module Playwright
|
|
|
21
20
|
end
|
|
22
21
|
|
|
23
22
|
@objects = {} # Hash[ guid => ChannelOwner ]
|
|
23
|
+
@objects_mutex = Mutex.new
|
|
24
24
|
@waiting_for_object = {} # Hash[ guid => Promise<ChannelOwner> ]
|
|
25
25
|
@callbacks = {} # Hash [ guid => Promise<ChannelOwner> ]
|
|
26
|
+
@callbacks_mutex = Mutex.new
|
|
26
27
|
@root_object = RootChannelOwner.new(self)
|
|
27
28
|
@remote = false
|
|
28
29
|
@tracing_count = 0
|
|
@@ -50,10 +51,10 @@ module Playwright
|
|
|
50
51
|
|
|
51
52
|
def cleanup(cause: nil)
|
|
52
53
|
@closed_error = TargetClosedError.new(message: cause)
|
|
53
|
-
@
|
|
54
|
-
|
|
54
|
+
callbacks = @callbacks_mutex.synchronize do
|
|
55
|
+
@callbacks.values.tap { @callbacks.clear }
|
|
55
56
|
end
|
|
56
|
-
|
|
57
|
+
callbacks.each { |callback| callback.reject(@closed_error) }
|
|
57
58
|
end
|
|
58
59
|
|
|
59
60
|
def initialize_playwright
|
|
@@ -80,7 +81,7 @@ module Playwright
|
|
|
80
81
|
with_generated_id do |id|
|
|
81
82
|
# register callback promise object first.
|
|
82
83
|
# @see https://github.com/YusukeIwaki/puppeteer-ruby/pull/34
|
|
83
|
-
@callbacks[id] = callback
|
|
84
|
+
@callbacks_mutex.synchronize { @callbacks[id] = callback }
|
|
84
85
|
|
|
85
86
|
_metadata = {}
|
|
86
87
|
frames = []
|
|
@@ -107,12 +108,12 @@ module Playwright
|
|
|
107
108
|
begin
|
|
108
109
|
@transport.send_message(message)
|
|
109
110
|
rescue => err
|
|
110
|
-
@callbacks.delete(id)
|
|
111
|
+
@callbacks_mutex.synchronize { @callbacks.delete(id) }
|
|
111
112
|
callback.reject(err)
|
|
112
113
|
raise unless err.is_a?(Transport::AlreadyDisconnectedError)
|
|
113
114
|
end
|
|
114
115
|
|
|
115
|
-
if @tracing_count > 0 && !frames.empty? && guid != 'localUtils'
|
|
116
|
+
if @tracing_count > 0 && !frames.empty? && guid != 'localUtils' && !remote?
|
|
116
117
|
@local_utils.add_stack_to_tracing_no_reply(id, frames)
|
|
117
118
|
end
|
|
118
119
|
end
|
|
@@ -132,21 +133,24 @@ module Playwright
|
|
|
132
133
|
# end
|
|
133
134
|
# ````
|
|
134
135
|
def with_generated_id(&block)
|
|
135
|
-
@
|
|
136
|
-
|
|
136
|
+
id = @callbacks_mutex.synchronize do
|
|
137
|
+
@last_id ||= 0
|
|
138
|
+
@last_id += 1
|
|
139
|
+
end
|
|
140
|
+
block.call(id)
|
|
137
141
|
end
|
|
138
142
|
|
|
139
143
|
# @param guid [String]
|
|
140
144
|
# @param parent [Playwright::ChannelOwner]
|
|
141
145
|
# @note This method should be used internally. Accessed via .send method from Playwright::ChannelOwner, so keep private!
|
|
142
146
|
def update_object_from_channel_owner(guid, parent)
|
|
143
|
-
@objects[guid] = parent
|
|
147
|
+
@objects_mutex.synchronize { @objects[guid] = parent }
|
|
144
148
|
end
|
|
145
149
|
|
|
146
150
|
# @param guid [String]
|
|
147
151
|
# @note This method should be used internally. Accessed via .send method from Playwright::ChannelOwner, so keep private!
|
|
148
152
|
def delete_object_from_channel_owner(guid)
|
|
149
|
-
@objects.delete(guid)
|
|
153
|
+
@objects_mutex.synchronize { @objects.delete(guid) }
|
|
150
154
|
end
|
|
151
155
|
|
|
152
156
|
def dispatch(msg)
|
|
@@ -154,7 +158,7 @@ module Playwright
|
|
|
154
158
|
|
|
155
159
|
id = msg['id']
|
|
156
160
|
if id
|
|
157
|
-
callback = @callbacks.delete(id)
|
|
161
|
+
callback = @callbacks_mutex.synchronize { @callbacks.delete(id) }
|
|
158
162
|
|
|
159
163
|
unless callback
|
|
160
164
|
raise "Cannot find command to respond: #{id}"
|
|
@@ -190,13 +194,13 @@ module Playwright
|
|
|
190
194
|
return
|
|
191
195
|
end
|
|
192
196
|
|
|
193
|
-
object = @objects[guid]
|
|
197
|
+
object = @objects_mutex.synchronize { @objects[guid] }
|
|
194
198
|
unless object
|
|
195
199
|
raise "Cannot find object to \"#{method}\": #{guid}"
|
|
196
200
|
end
|
|
197
201
|
|
|
198
202
|
if method == "__adopt__"
|
|
199
|
-
child = @objects[params["guid"]]
|
|
203
|
+
child = @objects_mutex.synchronize { @objects[params["guid"]] }
|
|
200
204
|
unless child
|
|
201
205
|
raise "Unknown new child: #{params['guid']}"
|
|
202
206
|
end
|
|
@@ -243,8 +247,9 @@ module Playwright
|
|
|
243
247
|
|
|
244
248
|
if payload.is_a?(Hash)
|
|
245
249
|
guid = payload['guid']
|
|
246
|
-
if guid
|
|
247
|
-
|
|
250
|
+
if guid
|
|
251
|
+
object = @objects_mutex.synchronize { @objects[guid] }
|
|
252
|
+
return object.channel if object
|
|
248
253
|
end
|
|
249
254
|
|
|
250
255
|
return payload.map { |k, v| [k, replace_guids_with_channels(v)] }.to_h
|
|
@@ -255,7 +260,7 @@ module Playwright
|
|
|
255
260
|
|
|
256
261
|
# @return [Playwright::ChannelOwner|nil]
|
|
257
262
|
def create_remote_object(parent_guid:, type:, guid:, initializer:)
|
|
258
|
-
parent = @objects[parent_guid]
|
|
263
|
+
parent = @objects_mutex.synchronize { @objects[parent_guid] }
|
|
259
264
|
unless parent
|
|
260
265
|
raise "Cannot find parent object #{parent_guid} to create #{guid}"
|
|
261
266
|
end
|
|
@@ -273,7 +278,7 @@ module Playwright
|
|
|
273
278
|
raise "Missing type #{type}"
|
|
274
279
|
end
|
|
275
280
|
|
|
276
|
-
callback = @waiting_for_object.delete(guid)
|
|
281
|
+
callback = @objects_mutex.synchronize { @waiting_for_object.delete(guid) }
|
|
277
282
|
callback&.fulfill(result)
|
|
278
283
|
|
|
279
284
|
result
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require_relative './visitor_info'
|
|
2
2
|
require_relative './regex'
|
|
3
|
+
require 'uri'
|
|
3
4
|
|
|
4
5
|
module Playwright
|
|
5
6
|
module JavaScript
|
|
@@ -60,7 +61,7 @@ module Playwright
|
|
|
60
61
|
when Time
|
|
61
62
|
require 'time'
|
|
62
63
|
{ d: value.utc.iso8601 }
|
|
63
|
-
when URI
|
|
64
|
+
when ::URI
|
|
64
65
|
{ u: value.to_s }
|
|
65
66
|
when Regexp
|
|
66
67
|
regex_value = Regex.new(value)
|
|
@@ -21,7 +21,7 @@ module Playwright
|
|
|
21
21
|
private def expect_impl(expression, expect_options, expected, message, title)
|
|
22
22
|
expect_options[:timeout] ||= @default_expect_timeout
|
|
23
23
|
expect_options[:isNot] = @is_not
|
|
24
|
-
message.gsub
|
|
24
|
+
message = message.gsub("expected to", "not expected to") if @is_not
|
|
25
25
|
expect_options.delete(:useInnerText) if expect_options.key?(:useInnerText) && expect_options[:useInnerText].nil?
|
|
26
26
|
|
|
27
27
|
result = @locator.expect(expression, expect_options, title)
|
|
@@ -22,7 +22,7 @@ module Playwright
|
|
|
22
22
|
private def expect_impl(expression, expect_options, expected, message, title)
|
|
23
23
|
expect_options[:timeout] ||= @default_expect_timeout
|
|
24
24
|
expect_options[:isNot] = @is_not
|
|
25
|
-
message.gsub
|
|
25
|
+
message = message.gsub("expected to", "not expected to") if @is_not
|
|
26
26
|
expect_options.delete(:useInnerText) if expect_options.key?(:useInnerText) && expect_options[:useInnerText].nil?
|
|
27
27
|
|
|
28
28
|
result = @frame.expect(nil, expression, expect_options, title)
|
data/lib/playwright/version.rb
CHANGED
data/lib/playwright/waiter.rb
CHANGED
|
@@ -10,6 +10,7 @@ module Playwright
|
|
|
10
10
|
@event = wait_name
|
|
11
11
|
@channel = channel_owner.channel
|
|
12
12
|
@registered_listeners = Set.new
|
|
13
|
+
@listeners_mutex = Mutex.new
|
|
13
14
|
@logs = []
|
|
14
15
|
wait_for_event_info_before
|
|
15
16
|
end
|
|
@@ -50,8 +51,7 @@ module Playwright
|
|
|
50
51
|
end
|
|
51
52
|
end
|
|
52
53
|
}
|
|
53
|
-
emitter
|
|
54
|
-
@registered_listeners << [emitter, event, listener]
|
|
54
|
+
register_listener(emitter, event, listener)
|
|
55
55
|
|
|
56
56
|
self
|
|
57
57
|
end
|
|
@@ -69,16 +69,22 @@ module Playwright
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
private def cleanup
|
|
72
|
-
@
|
|
72
|
+
listeners = @listeners_mutex.synchronize do
|
|
73
|
+
@registered_listeners.to_a.tap { @registered_listeners.clear }
|
|
74
|
+
end
|
|
75
|
+
listeners.each do |emitter, event, listener|
|
|
73
76
|
emitter.off(event, listener)
|
|
74
77
|
end
|
|
75
|
-
@registered_listeners.clear
|
|
76
78
|
end
|
|
77
79
|
|
|
78
80
|
def force_fulfill(result)
|
|
79
81
|
fulfill(result)
|
|
80
82
|
end
|
|
81
83
|
|
|
84
|
+
def force_reject(error)
|
|
85
|
+
reject(error)
|
|
86
|
+
end
|
|
87
|
+
|
|
82
88
|
private def fulfill(result)
|
|
83
89
|
cleanup
|
|
84
90
|
return if @result.resolved?
|
|
@@ -107,12 +113,24 @@ module Playwright
|
|
|
107
113
|
reject(err)
|
|
108
114
|
end
|
|
109
115
|
}
|
|
110
|
-
emitter
|
|
111
|
-
@registered_listeners << [emitter, event, listener]
|
|
116
|
+
register_listener(emitter, event, listener)
|
|
112
117
|
|
|
113
118
|
self
|
|
114
119
|
end
|
|
115
120
|
|
|
121
|
+
private def register_listener(emitter, event, listener)
|
|
122
|
+
emitter.on(event, listener)
|
|
123
|
+
remove_later = false
|
|
124
|
+
@listeners_mutex.synchronize do
|
|
125
|
+
if @result.resolved?
|
|
126
|
+
remove_later = true
|
|
127
|
+
else
|
|
128
|
+
@registered_listeners << [emitter, event, listener]
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
emitter.off(event, listener) if remove_later
|
|
132
|
+
end
|
|
133
|
+
|
|
116
134
|
attr_reader :result
|
|
117
135
|
|
|
118
136
|
def log(message)
|
|
@@ -45,8 +45,8 @@ module Playwright
|
|
|
45
45
|
|
|
46
46
|
# -- inherited from EventEmitter --
|
|
47
47
|
# @nodoc
|
|
48
|
-
def
|
|
49
|
-
event_emitter_proxy.
|
|
48
|
+
def once(event, callback)
|
|
49
|
+
event_emitter_proxy.once(event, callback)
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
# -- inherited from EventEmitter --
|
|
@@ -57,8 +57,8 @@ module Playwright
|
|
|
57
57
|
|
|
58
58
|
# -- inherited from EventEmitter --
|
|
59
59
|
# @nodoc
|
|
60
|
-
def
|
|
61
|
-
event_emitter_proxy.
|
|
60
|
+
def off(event, callback)
|
|
61
|
+
event_emitter_proxy.off(event, callback)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
private def event_emitter_proxy
|
|
@@ -195,19 +195,19 @@ module Playwright
|
|
|
195
195
|
end
|
|
196
196
|
|
|
197
197
|
# @nodoc
|
|
198
|
-
def
|
|
199
|
-
wrap_impl(@impl.
|
|
198
|
+
def should_close_connection_on_close!
|
|
199
|
+
wrap_impl(@impl.should_close_connection_on_close!)
|
|
200
200
|
end
|
|
201
201
|
|
|
202
202
|
# @nodoc
|
|
203
|
-
def
|
|
204
|
-
wrap_impl(@impl.
|
|
203
|
+
def tap_on(selector, duration: nil, timeout: nil)
|
|
204
|
+
wrap_impl(@impl.tap_on(unwrap_impl(selector), duration: unwrap_impl(duration), timeout: unwrap_impl(timeout)))
|
|
205
205
|
end
|
|
206
206
|
|
|
207
207
|
# -- inherited from EventEmitter --
|
|
208
208
|
# @nodoc
|
|
209
|
-
def
|
|
210
|
-
event_emitter_proxy.
|
|
209
|
+
def once(event, callback)
|
|
210
|
+
event_emitter_proxy.once(event, callback)
|
|
211
211
|
end
|
|
212
212
|
|
|
213
213
|
# -- inherited from EventEmitter --
|
|
@@ -218,8 +218,8 @@ module Playwright
|
|
|
218
218
|
|
|
219
219
|
# -- inherited from EventEmitter --
|
|
220
220
|
# @nodoc
|
|
221
|
-
def
|
|
222
|
-
event_emitter_proxy.
|
|
221
|
+
def off(event, callback)
|
|
222
|
+
event_emitter_proxy.off(event, callback)
|
|
223
223
|
end
|
|
224
224
|
|
|
225
225
|
private def event_emitter_proxy
|
|
@@ -288,8 +288,8 @@ module Playwright
|
|
|
288
288
|
|
|
289
289
|
# -- inherited from EventEmitter --
|
|
290
290
|
# @nodoc
|
|
291
|
-
def
|
|
292
|
-
event_emitter_proxy.
|
|
291
|
+
def once(event, callback)
|
|
292
|
+
event_emitter_proxy.once(event, callback)
|
|
293
293
|
end
|
|
294
294
|
|
|
295
295
|
# -- inherited from EventEmitter --
|
|
@@ -300,8 +300,8 @@ module Playwright
|
|
|
300
300
|
|
|
301
301
|
# -- inherited from EventEmitter --
|
|
302
302
|
# @nodoc
|
|
303
|
-
def
|
|
304
|
-
event_emitter_proxy.
|
|
303
|
+
def off(event, callback)
|
|
304
|
+
event_emitter_proxy.off(event, callback)
|
|
305
305
|
end
|
|
306
306
|
|
|
307
307
|
private def event_emitter_proxy
|
|
@@ -205,8 +205,8 @@ module Playwright
|
|
|
205
205
|
|
|
206
206
|
# -- inherited from EventEmitter --
|
|
207
207
|
# @nodoc
|
|
208
|
-
def
|
|
209
|
-
event_emitter_proxy.
|
|
208
|
+
def once(event, callback)
|
|
209
|
+
event_emitter_proxy.once(event, callback)
|
|
210
210
|
end
|
|
211
211
|
|
|
212
212
|
# -- inherited from EventEmitter --
|
|
@@ -217,8 +217,8 @@ module Playwright
|
|
|
217
217
|
|
|
218
218
|
# -- inherited from EventEmitter --
|
|
219
219
|
# @nodoc
|
|
220
|
-
def
|
|
221
|
-
event_emitter_proxy.
|
|
220
|
+
def off(event, callback)
|
|
221
|
+
event_emitter_proxy.off(event, callback)
|
|
222
222
|
end
|
|
223
223
|
|
|
224
224
|
private def event_emitter_proxy
|