playwright-ruby-client 1.61.0 → 1.63.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/README.md +12 -17
- data/documentation/docs/api/api_request_context.md +3 -0
- data/documentation/docs/api/api_response.md +12 -0
- data/documentation/docs/api/browser_context.md +5 -3
- data/documentation/docs/api/browser_type.md +2 -0
- data/documentation/docs/api/credentials.md +6 -2
- data/documentation/docs/api/element_handle.md +7 -0
- data/documentation/docs/api/frame.md +20 -1
- data/documentation/docs/api/frame_locator.md +20 -0
- data/documentation/docs/api/locator.md +57 -0
- data/documentation/docs/api/locator_assertions.md +4 -2
- data/documentation/docs/api/page.md +26 -1
- data/documentation/docs/api/playwright.md +2 -2
- data/documentation/docs/api/tracing.md +3 -1
- data/documentation/docs/article/getting_started.md +12 -11
- data/documentation/docs/article/guides/download_playwright_driver.md +11 -32
- data/documentation/docs/article/guides/launch_browser.md +5 -4
- data/documentation/docs/article/guides/playwright_on_alpine_linux.md +6 -5
- data/documentation/docs/article/guides/rails_integration.md +72 -4
- data/documentation/docs/article/guides/rails_integration_with_null_driver.md +4 -3
- data/documentation/docs/article/guides/semi_automation.md +1 -1
- data/documentation/docs/article/guides/use_storage_state.md +1 -1
- data/documentation/docs/include/api_coverage.md +3 -0
- data/documentation/docusaurus.config.js +31 -0
- data/documentation/package.json +3 -0
- data/documentation/yarn.lock +159 -174
- data/lib/playwright/api_request_impl.rb +3 -1
- data/lib/playwright/api_response_impl.rb +16 -0
- data/lib/playwright/channel.rb +2 -1
- data/lib/playwright/channel_owners/browser.rb +1 -0
- data/lib/playwright/channel_owners/browser_context.rb +22 -3
- data/lib/playwright/channel_owners/element_handle.rb +14 -4
- data/lib/playwright/channel_owners/frame.rb +16 -2
- data/lib/playwright/channel_owners/page.rb +21 -9
- data/lib/playwright/channel_owners/tracing.rb +43 -13
- data/lib/playwright/connection.rb +9 -1
- data/lib/playwright/events.rb +2 -0
- data/lib/playwright/frame_locator_impl.rb +20 -5
- data/lib/playwright/locator_assertions_impl.rb +14 -1
- data/lib/playwright/locator_impl.rb +32 -5
- data/lib/playwright/screencast.rb +20 -6
- data/lib/playwright/screenshot_utils.rb +24 -0
- data/lib/playwright/test.rb +12 -2
- data/lib/playwright/url_matcher.rb +120 -4
- data/lib/playwright/utils.rb +12 -0
- data/lib/playwright/version.rb +2 -2
- data/lib/playwright.rb +2 -2
- data/lib/playwright_api/api_request_context.rb +3 -1
- data/lib/playwright_api/api_response.rb +9 -0
- data/lib/playwright_api/browser_context.rb +16 -14
- data/lib/playwright_api/browser_type.rb +2 -0
- data/lib/playwright_api/credentials.rb +6 -2
- data/lib/playwright_api/element_handle.rb +14 -7
- data/lib/playwright_api/frame.rb +28 -9
- data/lib/playwright_api/frame_locator.rb +20 -0
- data/lib/playwright_api/locator.rb +64 -13
- data/lib/playwright_api/locator_assertions.rb +6 -4
- data/lib/playwright_api/page.rb +46 -21
- data/lib/playwright_api/tracing.rb +4 -2
- data/playwright.gemspec +5 -0
- data/sig/playwright.rbs +49 -46
- metadata +7 -3
|
@@ -13,6 +13,21 @@ module Playwright
|
|
|
13
13
|
@frame.send(:_timeout, timeout)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
private def child_selector(selector)
|
|
17
|
+
if @frame_selector == 'internal:control=any-frame'
|
|
18
|
+
"#{@frame_selector} >> #{selector}"
|
|
19
|
+
else
|
|
20
|
+
"#{@frame_selector} >> internal:control=enter-frame >> #{selector}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private def nth_selector(index)
|
|
25
|
+
if @frame_selector == 'internal:control=any-frame'
|
|
26
|
+
raise 'Selecting the nth frame is not allowed on frameLocator().'
|
|
27
|
+
end
|
|
28
|
+
"#{@frame_selector} >> nth=#{index}"
|
|
29
|
+
end
|
|
30
|
+
|
|
16
31
|
def locator(
|
|
17
32
|
selector,
|
|
18
33
|
has: nil,
|
|
@@ -21,7 +36,7 @@ module Playwright
|
|
|
21
36
|
hasText: nil)
|
|
22
37
|
LocatorImpl.new(
|
|
23
38
|
frame: @frame,
|
|
24
|
-
selector:
|
|
39
|
+
selector: child_selector(selector),
|
|
25
40
|
has: has,
|
|
26
41
|
hasNot: hasNot,
|
|
27
42
|
hasNotText: hasNotText,
|
|
@@ -38,28 +53,28 @@ module Playwright
|
|
|
38
53
|
def frame_locator(selector)
|
|
39
54
|
FrameLocatorImpl.new(
|
|
40
55
|
frame: @frame,
|
|
41
|
-
frame_selector:
|
|
56
|
+
frame_selector: child_selector(selector),
|
|
42
57
|
)
|
|
43
58
|
end
|
|
44
59
|
|
|
45
60
|
def first
|
|
46
61
|
FrameLocatorImpl.new(
|
|
47
62
|
frame: @frame,
|
|
48
|
-
frame_selector:
|
|
63
|
+
frame_selector: nth_selector(0),
|
|
49
64
|
)
|
|
50
65
|
end
|
|
51
66
|
|
|
52
67
|
def last
|
|
53
68
|
FrameLocatorImpl.new(
|
|
54
69
|
frame: @frame,
|
|
55
|
-
frame_selector:
|
|
70
|
+
frame_selector: nth_selector(-1),
|
|
56
71
|
)
|
|
57
72
|
end
|
|
58
73
|
|
|
59
74
|
def nth(index)
|
|
60
75
|
FrameLocatorImpl.new(
|
|
61
76
|
frame: @frame,
|
|
62
|
-
frame_selector:
|
|
77
|
+
frame_selector: nth_selector(index),
|
|
63
78
|
)
|
|
64
79
|
end
|
|
65
80
|
end
|
|
@@ -214,7 +214,20 @@ module Playwright
|
|
|
214
214
|
end
|
|
215
215
|
_define_negation :to_have_accessible_error_message
|
|
216
216
|
|
|
217
|
-
def to_have_attribute(name, value, ignoreCase: nil, timeout: nil)
|
|
217
|
+
def to_have_attribute(name, value: nil, ignoreCase: nil, timeout: nil)
|
|
218
|
+
if value.nil?
|
|
219
|
+
return expect_impl(
|
|
220
|
+
'to.have.attribute',
|
|
221
|
+
{
|
|
222
|
+
expressionArg: name,
|
|
223
|
+
timeout: timeout,
|
|
224
|
+
},
|
|
225
|
+
nil,
|
|
226
|
+
'Locator expected to have attribute',
|
|
227
|
+
'Expect "to_have_attribute"',
|
|
228
|
+
)
|
|
229
|
+
end
|
|
230
|
+
|
|
218
231
|
expected_text = to_expected_text_values([value], ignore_case: ignoreCase)
|
|
219
232
|
expect_impl(
|
|
220
233
|
"to.have.attribute.value",
|
|
@@ -105,6 +105,7 @@ module Playwright
|
|
|
105
105
|
force: nil,
|
|
106
106
|
noWaitAfter: nil,
|
|
107
107
|
position: nil,
|
|
108
|
+
scroll: nil,
|
|
108
109
|
timeout: nil,
|
|
109
110
|
trial: nil)
|
|
110
111
|
|
|
@@ -113,6 +114,7 @@ module Playwright
|
|
|
113
114
|
force: force,
|
|
114
115
|
noWaitAfter: noWaitAfter,
|
|
115
116
|
position: position,
|
|
117
|
+
scroll: scroll,
|
|
116
118
|
timeout: timeout,
|
|
117
119
|
trial: trial)
|
|
118
120
|
end
|
|
@@ -125,6 +127,7 @@ module Playwright
|
|
|
125
127
|
modifiers: nil,
|
|
126
128
|
noWaitAfter: nil,
|
|
127
129
|
position: nil,
|
|
130
|
+
scroll: nil,
|
|
128
131
|
timeout: nil,
|
|
129
132
|
trial: nil,
|
|
130
133
|
steps: nil)
|
|
@@ -138,6 +141,7 @@ module Playwright
|
|
|
138
141
|
modifiers: modifiers,
|
|
139
142
|
noWaitAfter: noWaitAfter,
|
|
140
143
|
position: position,
|
|
144
|
+
scroll: scroll,
|
|
141
145
|
timeout: timeout,
|
|
142
146
|
trial: trial,
|
|
143
147
|
steps: steps)
|
|
@@ -150,6 +154,7 @@ module Playwright
|
|
|
150
154
|
modifiers: nil,
|
|
151
155
|
noWaitAfter: nil,
|
|
152
156
|
position: nil,
|
|
157
|
+
scroll: nil,
|
|
153
158
|
timeout: nil,
|
|
154
159
|
trial: nil,
|
|
155
160
|
steps: nil)
|
|
@@ -162,6 +167,7 @@ module Playwright
|
|
|
162
167
|
modifiers: modifiers,
|
|
163
168
|
noWaitAfter: noWaitAfter,
|
|
164
169
|
position: position,
|
|
170
|
+
scroll: scroll,
|
|
165
171
|
timeout: timeout,
|
|
166
172
|
trial: trial,
|
|
167
173
|
steps: steps)
|
|
@@ -174,6 +180,7 @@ module Playwright
|
|
|
174
180
|
def drag_to(target,
|
|
175
181
|
force: nil,
|
|
176
182
|
noWaitAfter: nil,
|
|
183
|
+
scroll: nil,
|
|
177
184
|
sourcePosition: nil,
|
|
178
185
|
targetPosition: nil,
|
|
179
186
|
timeout: nil,
|
|
@@ -185,6 +192,7 @@ module Playwright
|
|
|
185
192
|
target.instance_variable_get(:@selector),
|
|
186
193
|
force: force,
|
|
187
194
|
noWaitAfter: noWaitAfter,
|
|
195
|
+
scroll: scroll,
|
|
188
196
|
sourcePosition: sourcePosition,
|
|
189
197
|
targetPosition: targetPosition,
|
|
190
198
|
timeout: timeout,
|
|
@@ -288,6 +296,10 @@ module Playwright
|
|
|
288
296
|
)
|
|
289
297
|
end
|
|
290
298
|
|
|
299
|
+
def visible
|
|
300
|
+
filter(visible: true)
|
|
301
|
+
end
|
|
302
|
+
|
|
291
303
|
def first
|
|
292
304
|
LocatorImpl.new(
|
|
293
305
|
frame: @frame,
|
|
@@ -363,6 +375,7 @@ module Playwright
|
|
|
363
375
|
modifiers: nil,
|
|
364
376
|
noWaitAfter: nil,
|
|
365
377
|
position: nil,
|
|
378
|
+
scroll: nil,
|
|
366
379
|
timeout: nil,
|
|
367
380
|
trial: nil)
|
|
368
381
|
@frame.hover(@selector,
|
|
@@ -371,6 +384,7 @@ module Playwright
|
|
|
371
384
|
modifiers: modifiers,
|
|
372
385
|
noWaitAfter: noWaitAfter,
|
|
373
386
|
position: position,
|
|
387
|
+
scroll: scroll,
|
|
374
388
|
timeout: timeout,
|
|
375
389
|
trial: trial)
|
|
376
390
|
end
|
|
@@ -426,7 +440,7 @@ module Playwright
|
|
|
426
440
|
end
|
|
427
441
|
end
|
|
428
442
|
|
|
429
|
-
def aria_snapshot(boxes: nil, depth: nil, mode: nil, timeout: nil
|
|
443
|
+
def aria_snapshot(boxes: nil, depth: nil, mode: nil, timeout: nil)
|
|
430
444
|
params = {
|
|
431
445
|
selector: @selector,
|
|
432
446
|
timeout: _timeout(timeout),
|
|
@@ -434,10 +448,6 @@ module Playwright
|
|
|
434
448
|
params[:boxes] = boxes unless boxes.nil?
|
|
435
449
|
params[:depth] = depth if depth
|
|
436
450
|
params[:mode] = mode if mode
|
|
437
|
-
if _track
|
|
438
|
-
params.delete(:selector)
|
|
439
|
-
params[:track] = _track
|
|
440
|
-
end
|
|
441
451
|
result = @frame.channel.send_message_to_server_result('ariaSnapshot', params.compact)
|
|
442
452
|
result['snapshot']
|
|
443
453
|
end
|
|
@@ -499,6 +509,7 @@ module Playwright
|
|
|
499
509
|
modifiers: nil,
|
|
500
510
|
noWaitAfter: nil,
|
|
501
511
|
position: nil,
|
|
512
|
+
scroll: nil,
|
|
502
513
|
timeout: nil,
|
|
503
514
|
trial: nil)
|
|
504
515
|
@frame.tap_point(@selector,
|
|
@@ -507,6 +518,7 @@ module Playwright
|
|
|
507
518
|
modifiers: modifiers,
|
|
508
519
|
noWaitAfter: noWaitAfter,
|
|
509
520
|
position: position,
|
|
521
|
+
scroll: scroll,
|
|
510
522
|
timeout: timeout,
|
|
511
523
|
trial: trial)
|
|
512
524
|
end
|
|
@@ -527,6 +539,7 @@ module Playwright
|
|
|
527
539
|
force: nil,
|
|
528
540
|
noWaitAfter: nil,
|
|
529
541
|
position: nil,
|
|
542
|
+
scroll: nil,
|
|
530
543
|
timeout: nil,
|
|
531
544
|
trial: nil)
|
|
532
545
|
@frame.uncheck(@selector,
|
|
@@ -534,10 +547,24 @@ module Playwright
|
|
|
534
547
|
force: force,
|
|
535
548
|
noWaitAfter: noWaitAfter,
|
|
536
549
|
position: position,
|
|
550
|
+
scroll: scroll,
|
|
537
551
|
timeout: timeout,
|
|
538
552
|
trial: trial)
|
|
539
553
|
end
|
|
540
554
|
|
|
555
|
+
def wait_for_function(expression, arg: nil, timeout: nil)
|
|
556
|
+
@frame.channel.send_message_to_server(
|
|
557
|
+
'waitForFunction',
|
|
558
|
+
selector: @selector,
|
|
559
|
+
strict: true,
|
|
560
|
+
expression: expression,
|
|
561
|
+
isFunction: true,
|
|
562
|
+
arg: JavaScript::ValueSerializer.new(arg).serialize,
|
|
563
|
+
timeout: _timeout(timeout),
|
|
564
|
+
)
|
|
565
|
+
nil
|
|
566
|
+
end
|
|
567
|
+
|
|
541
568
|
def wait_for(state: nil, timeout: nil)
|
|
542
569
|
@frame.wait_for_selector(@selector, strict: true, state: state, timeout: timeout)
|
|
543
570
|
end
|
|
@@ -86,12 +86,26 @@ module Playwright
|
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
private def handle_screencast_frame(event)
|
|
89
|
-
@on_frame
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
on_frame = @on_frame
|
|
90
|
+
Thread.new do
|
|
91
|
+
begin
|
|
92
|
+
on_frame&.call({
|
|
93
|
+
data: Base64.strict_decode64(event['data']),
|
|
94
|
+
timestamp: event['timestamp'],
|
|
95
|
+
viewportWidth: event['viewportWidth'],
|
|
96
|
+
viewportHeight: event['viewportHeight'],
|
|
97
|
+
})
|
|
98
|
+
ensure
|
|
99
|
+
begin
|
|
100
|
+
@page.send(:channel).async_send_message_to_server(
|
|
101
|
+
'screencastFrameAck',
|
|
102
|
+
frameId: event['frameId'],
|
|
103
|
+
)
|
|
104
|
+
rescue Transport::AlreadyDisconnectedError
|
|
105
|
+
# The page or driver may close while a callback is running.
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
95
109
|
end
|
|
96
110
|
end
|
|
97
111
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require 'mime/types'
|
|
2
|
+
|
|
3
|
+
module Playwright
|
|
4
|
+
module ScreenshotUtils
|
|
5
|
+
module_function
|
|
6
|
+
|
|
7
|
+
def determine_type(path:, type:)
|
|
8
|
+
return type if type
|
|
9
|
+
return nil unless path
|
|
10
|
+
|
|
11
|
+
mime_type = MIME::Types.type_for(path).first
|
|
12
|
+
case mime_type&.content_type
|
|
13
|
+
when 'image/png'
|
|
14
|
+
'png'
|
|
15
|
+
when 'image/jpeg'
|
|
16
|
+
'jpeg'
|
|
17
|
+
when 'image/webp'
|
|
18
|
+
'webp'
|
|
19
|
+
else
|
|
20
|
+
raise ArgumentError.new("path: unsupported mime type \"#{mime_type}\"")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/playwright/test.rb
CHANGED
|
@@ -30,7 +30,7 @@ module Playwright
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
def matches?(actual)
|
|
33
|
-
|
|
33
|
+
call_assertion(actual, false)
|
|
34
34
|
true
|
|
35
35
|
rescue AssertionError => e
|
|
36
36
|
@failure_message = e.full_message
|
|
@@ -38,7 +38,7 @@ module Playwright
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def does_not_match?(actual)
|
|
41
|
-
|
|
41
|
+
call_assertion(actual, true)
|
|
42
42
|
true
|
|
43
43
|
rescue AssertionError => e
|
|
44
44
|
@failure_message = e.full_message
|
|
@@ -55,6 +55,16 @@ module Playwright
|
|
|
55
55
|
|
|
56
56
|
private
|
|
57
57
|
|
|
58
|
+
def call_assertion(actual, is_not)
|
|
59
|
+
args = @args
|
|
60
|
+
kwargs = @kwargs
|
|
61
|
+
if ['to_have_attribute', 'not_to_have_attribute'].include?(@method) && args.length == 2 && !kwargs.key?(:value)
|
|
62
|
+
args = [args.first]
|
|
63
|
+
kwargs = kwargs.merge(value: @args.last)
|
|
64
|
+
end
|
|
65
|
+
assertions_for(actual, is_not).send(@method, *args, **kwargs)
|
|
66
|
+
end
|
|
67
|
+
|
|
58
68
|
def assertions_for(actual, is_not)
|
|
59
69
|
if actual.respond_to?(:_assertions)
|
|
60
70
|
actual._assertions(::Playwright::Test.expect_timeout, is_not, nil)
|
|
@@ -23,7 +23,7 @@ module Playwright
|
|
|
23
23
|
def match?(target_url)
|
|
24
24
|
case @url
|
|
25
25
|
when String
|
|
26
|
-
joined_url == target_url || File.fnmatch?(
|
|
26
|
+
joined_url == target_url || File.fnmatch?(joined_url, target_url)
|
|
27
27
|
when Regexp
|
|
28
28
|
@url.match?(target_url)
|
|
29
29
|
else
|
|
@@ -32,13 +32,129 @@ module Playwright
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
private def joined_url
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
normalized_url = normalize_literal_url(@url)
|
|
36
|
+
if @base_url && !normalized_url.start_with?('*')
|
|
37
|
+
normalize_literal_url(URI.join(normalize_literal_url(@base_url), normalized_url).to_s)
|
|
37
38
|
else
|
|
38
|
-
|
|
39
|
+
normalized_url
|
|
39
40
|
end
|
|
40
41
|
end
|
|
41
42
|
|
|
43
|
+
private def normalize_literal_url(url)
|
|
44
|
+
match = url.match(/\A([a-z][a-z0-9+.-]*):\/\/([^\/?#]*)(.*)\z/i)
|
|
45
|
+
return percent_encode_literal_characters(url) unless match
|
|
46
|
+
|
|
47
|
+
scheme = match[1].downcase
|
|
48
|
+
authority = match[2]
|
|
49
|
+
suffix = percent_encode_literal_characters(match[3])
|
|
50
|
+
|
|
51
|
+
before, separator, after = authority.rpartition('@')
|
|
52
|
+
if separator.empty?
|
|
53
|
+
userinfo = nil
|
|
54
|
+
host_port = authority
|
|
55
|
+
else
|
|
56
|
+
userinfo = before
|
|
57
|
+
host_port = after
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
if host_port.start_with?('[')
|
|
61
|
+
host = host_port
|
|
62
|
+
port = nil
|
|
63
|
+
else
|
|
64
|
+
host, separator, candidate_port = host_port.rpartition(':')
|
|
65
|
+
if separator.empty? || candidate_port !~ /\A\d+\z/
|
|
66
|
+
host = host_port
|
|
67
|
+
port = nil
|
|
68
|
+
else
|
|
69
|
+
port = candidate_port
|
|
70
|
+
end
|
|
71
|
+
host = host.split('.').map { |label| punycode_label(label.downcase) }.join('.')
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
port = nil if (scheme == 'http' && port == '80') || (scheme == 'https' && port == '443')
|
|
75
|
+
normalized_authority = String.new
|
|
76
|
+
normalized_authority << "#{userinfo}@" if userinfo
|
|
77
|
+
normalized_authority << host
|
|
78
|
+
normalized_authority << ":#{port}" if port
|
|
79
|
+
"#{scheme}://#{normalized_authority}#{suffix}"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
private def percent_encode_literal_characters(value)
|
|
83
|
+
value.each_char.map do |char|
|
|
84
|
+
if char == ' '
|
|
85
|
+
'%20'
|
|
86
|
+
elsif char.ascii_only?
|
|
87
|
+
char
|
|
88
|
+
else
|
|
89
|
+
char.encode(Encoding::UTF_8).bytes.map { |byte| format('%%%02X', byte) }.join
|
|
90
|
+
end
|
|
91
|
+
end.join
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# RFC 3492 Punycode encoder for the non-ASCII URL host labels normalized by WHATWG URL.
|
|
95
|
+
private def punycode_label(label)
|
|
96
|
+
return label if label.ascii_only?
|
|
97
|
+
|
|
98
|
+
codepoints = label.codepoints
|
|
99
|
+
output = codepoints.select { |codepoint| codepoint < 0x80 }.map(&:chr).join
|
|
100
|
+
basic_length = output.length
|
|
101
|
+
output << '-' if basic_length > 0
|
|
102
|
+
|
|
103
|
+
handled = basic_length
|
|
104
|
+
n = 128
|
|
105
|
+
delta = 0
|
|
106
|
+
bias = 72
|
|
107
|
+
while handled < codepoints.length
|
|
108
|
+
next_codepoint = codepoints.select { |codepoint| codepoint >= n }.min
|
|
109
|
+
delta += (next_codepoint - n) * (handled + 1)
|
|
110
|
+
n = next_codepoint
|
|
111
|
+
|
|
112
|
+
codepoints.each do |codepoint|
|
|
113
|
+
delta += 1 if codepoint < n
|
|
114
|
+
next unless codepoint == n
|
|
115
|
+
|
|
116
|
+
q = delta
|
|
117
|
+
k = 36
|
|
118
|
+
loop do
|
|
119
|
+
threshold = if k <= bias
|
|
120
|
+
1
|
|
121
|
+
elsif k >= bias + 26
|
|
122
|
+
26
|
|
123
|
+
else
|
|
124
|
+
k - bias
|
|
125
|
+
end
|
|
126
|
+
break if q < threshold
|
|
127
|
+
|
|
128
|
+
output << punycode_digit(threshold + ((q - threshold) % (36 - threshold)))
|
|
129
|
+
q = (q - threshold) / (36 - threshold)
|
|
130
|
+
k += 36
|
|
131
|
+
end
|
|
132
|
+
output << punycode_digit(q)
|
|
133
|
+
bias = adapt_punycode_bias(delta, handled + 1, handled == basic_length)
|
|
134
|
+
delta = 0
|
|
135
|
+
handled += 1
|
|
136
|
+
end
|
|
137
|
+
delta += 1
|
|
138
|
+
n += 1
|
|
139
|
+
end
|
|
140
|
+
"xn--#{output}"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
private def punycode_digit(value)
|
|
144
|
+
value < 26 ? (value + 97).chr : (value - 26 + 48).chr
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
private def adapt_punycode_bias(delta, points, first_time)
|
|
148
|
+
delta = first_time ? delta / 700 : delta / 2
|
|
149
|
+
delta += delta / points
|
|
150
|
+
k = 0
|
|
151
|
+
while delta > 455
|
|
152
|
+
delta /= 35
|
|
153
|
+
k += 36
|
|
154
|
+
end
|
|
155
|
+
k + ((36 * delta) / (delta + 38))
|
|
156
|
+
end
|
|
157
|
+
|
|
42
158
|
private def validate_glob_pattern
|
|
43
159
|
in_group = false
|
|
44
160
|
escaped = false
|
data/lib/playwright/utils.rb
CHANGED
|
@@ -18,9 +18,21 @@ module Playwright
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
module Utils
|
|
21
|
+
module PrepareHttpCredentials
|
|
22
|
+
private def prepare_http_credentials(credentials)
|
|
23
|
+
return nil unless credentials
|
|
24
|
+
|
|
25
|
+
list = credentials.is_a?(Array) ? credentials : [credentials]
|
|
26
|
+
list.empty? ? nil : list
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
21
30
|
module PrepareBrowserContextOptions
|
|
31
|
+
include PrepareHttpCredentials
|
|
32
|
+
|
|
22
33
|
# @see https://github.com/microsoft/playwright/blob/5a2cfdbd47ed3c3deff77bb73e5fac34241f649d/src/client/browserContext.ts#L265
|
|
23
34
|
private def prepare_browser_context_options(params)
|
|
35
|
+
params[:httpCredentials] = prepare_http_credentials(params[:httpCredentials])
|
|
24
36
|
if params[:noViewport] == 0
|
|
25
37
|
params.delete(:noViewport)
|
|
26
38
|
params[:noDefaultViewport] = true
|
data/lib/playwright/version.rb
CHANGED
data/lib/playwright.rb
CHANGED
|
@@ -138,7 +138,7 @@ module Playwright
|
|
|
138
138
|
end
|
|
139
139
|
end
|
|
140
140
|
|
|
141
|
-
# Connects to Playwright server, launched by `
|
|
141
|
+
# Connects to Playwright server, launched by `playwright-core launch-server --browser chromium` or `playwright-core run-server`
|
|
142
142
|
#
|
|
143
143
|
# Playwright.connect_to_browser_server('ws://....') do |browser|
|
|
144
144
|
# page = browser.new_page
|
|
@@ -186,7 +186,7 @@ module Playwright
|
|
|
186
186
|
end
|
|
187
187
|
end
|
|
188
188
|
|
|
189
|
-
# Connects to Playwright server, launched by `
|
|
189
|
+
# Connects to Playwright server, launched by `playwright-core launch-server --browser _android` or `playwright._android.launchServer()`
|
|
190
190
|
#
|
|
191
191
|
# Playwright.connect_to_android_server('ws://....') do |browser|
|
|
192
192
|
# page = browser.new_page
|
|
@@ -67,6 +67,8 @@ module Playwright
|
|
|
67
67
|
# ```
|
|
68
68
|
class APIRequestContext < PlaywrightApi
|
|
69
69
|
|
|
70
|
+
#
|
|
71
|
+
# Tracing recorder for requests made through this API request context.
|
|
70
72
|
def tracing # property
|
|
71
73
|
wrap_impl(@impl.tracing)
|
|
72
74
|
end
|
|
@@ -286,7 +288,7 @@ module Playwright
|
|
|
286
288
|
|
|
287
289
|
#
|
|
288
290
|
# Returns storage state for this request context, contains current cookies and local storage snapshot if it was passed to the constructor.
|
|
289
|
-
def storage_state(indexedDB: nil, path: nil)
|
|
291
|
+
def storage_state(indexedDB: nil, opfs: nil, path: nil)
|
|
290
292
|
raise NotImplementedError.new('storage_state is not implemented yet.')
|
|
291
293
|
end
|
|
292
294
|
|
|
@@ -85,6 +85,15 @@ module Playwright
|
|
|
85
85
|
wrap_impl(@impl.text)
|
|
86
86
|
end
|
|
87
87
|
|
|
88
|
+
#
|
|
89
|
+
# Returns resource timing information for given response. For redirected requests, returns the information for the last
|
|
90
|
+
# request in the redirect chain. When the response is served [from the HAR file](../mock.md#replaying-from-har), timing
|
|
91
|
+
# information is not available and all the values are -1. Find more information at
|
|
92
|
+
# [Resource Timing API](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming).
|
|
93
|
+
def timing
|
|
94
|
+
wrap_impl(@impl.timing)
|
|
95
|
+
end
|
|
96
|
+
|
|
88
97
|
#
|
|
89
98
|
# Contains the URL of the response.
|
|
90
99
|
def url
|
|
@@ -423,13 +423,15 @@ module Playwright
|
|
|
423
423
|
alias_method :offline=, :set_offline
|
|
424
424
|
|
|
425
425
|
#
|
|
426
|
-
# Returns storage state for this browser context, contains current cookies, local storage snapshot and
|
|
427
|
-
def storage_state(indexedDB: nil, path: nil)
|
|
428
|
-
wrap_impl(@impl.storage_state(indexedDB: unwrap_impl(indexedDB), path: unwrap_impl(path)))
|
|
426
|
+
# Returns storage state for this browser context, contains current cookies, local storage snapshot, IndexedDB snapshot, origin private file system snapshot and virtual WebAuthn credentials.
|
|
427
|
+
def storage_state(credentials: nil, indexedDB: nil, opfs: nil, path: nil)
|
|
428
|
+
wrap_impl(@impl.storage_state(credentials: unwrap_impl(credentials), indexedDB: unwrap_impl(indexedDB), opfs: unwrap_impl(opfs), path: unwrap_impl(path)))
|
|
429
429
|
end
|
|
430
430
|
|
|
431
431
|
#
|
|
432
|
-
# Clears the existing cookies, local storage
|
|
432
|
+
# Clears the existing cookies, local storage, IndexedDB entries, origin private file system entries and virtual WebAuthn credentials, and sets the new storage
|
|
433
|
+
# state. When the storage state contains credentials, the virtual WebAuthn authenticator is installed (equivalent to
|
|
434
|
+
# [`method: Credentials.install`]), preventing all real authenticators from working in this context.
|
|
433
435
|
#
|
|
434
436
|
# **Usage**
|
|
435
437
|
#
|
|
@@ -497,28 +499,28 @@ module Playwright
|
|
|
497
499
|
end
|
|
498
500
|
|
|
499
501
|
# @nodoc
|
|
500
|
-
def
|
|
501
|
-
wrap_impl(@impl.
|
|
502
|
+
def owner_page=(req)
|
|
503
|
+
wrap_impl(@impl.owner_page=(unwrap_impl(req)))
|
|
502
504
|
end
|
|
503
505
|
|
|
504
506
|
# @nodoc
|
|
505
|
-
def
|
|
506
|
-
wrap_impl(@impl.
|
|
507
|
+
def browser=(req)
|
|
508
|
+
wrap_impl(@impl.browser=(unwrap_impl(req)))
|
|
507
509
|
end
|
|
508
510
|
|
|
509
511
|
# @nodoc
|
|
510
|
-
def
|
|
511
|
-
wrap_impl(@impl.
|
|
512
|
+
def options=(req)
|
|
513
|
+
wrap_impl(@impl.options=(unwrap_impl(req)))
|
|
512
514
|
end
|
|
513
515
|
|
|
514
516
|
# @nodoc
|
|
515
|
-
def
|
|
516
|
-
wrap_impl(@impl.
|
|
517
|
+
def enable_debug_console!
|
|
518
|
+
wrap_impl(@impl.enable_debug_console!)
|
|
517
519
|
end
|
|
518
520
|
|
|
519
521
|
# @nodoc
|
|
520
|
-
def
|
|
521
|
-
wrap_impl(@impl.
|
|
522
|
+
def pause
|
|
523
|
+
wrap_impl(@impl.pause)
|
|
522
524
|
end
|
|
523
525
|
|
|
524
526
|
# -- inherited from EventEmitter --
|
|
@@ -42,6 +42,8 @@ module Playwright
|
|
|
42
42
|
#
|
|
43
43
|
# **NOTE**: This connection is significantly lower fidelity than the Playwright protocol connection via [`method: BrowserType.connect`]. If you are experiencing issues or attempting to use advanced functionality, you probably want to use [`method: BrowserType.connect`].
|
|
44
44
|
#
|
|
45
|
+
# **NOTE**: Playwright maintains a curated list of arguments for launching the browser. If you launch the browser without Playwright and do not pass the exact same arguments, some of Playwright functionality may be broken upon connecting to the browser.
|
|
46
|
+
#
|
|
45
47
|
# **Usage**
|
|
46
48
|
#
|
|
47
49
|
# ```python sync
|
|
@@ -4,7 +4,7 @@ module Playwright
|
|
|
4
4
|
# register passkeys and answer `navigator.credentials.create()` / `navigator.credentials.get()`
|
|
5
5
|
# ceremonies in the page, without a real authenticator or hardware security key.
|
|
6
6
|
#
|
|
7
|
-
# There are
|
|
7
|
+
# There are three common ways to use it:
|
|
8
8
|
#
|
|
9
9
|
# **Usage: seed a known credential**
|
|
10
10
|
#
|
|
@@ -26,7 +26,7 @@ module Playwright
|
|
|
26
26
|
# # The page's navigator.credentials.get() is answered with the seeded passkey.
|
|
27
27
|
# ```
|
|
28
28
|
#
|
|
29
|
-
# **Usage: capture a
|
|
29
|
+
# **Usage: capture a credential, then reuse it**
|
|
30
30
|
#
|
|
31
31
|
# ```python sync
|
|
32
32
|
# # setup test: let the app register a passkey, then save it.
|
|
@@ -62,6 +62,10 @@ module Playwright
|
|
|
62
62
|
# # navigator.credentials.get() resolves the captured passkey — already signed in.
|
|
63
63
|
# ```
|
|
64
64
|
#
|
|
65
|
+
# **Usage: save credentials in the storage state, restore later**
|
|
66
|
+
#
|
|
67
|
+
# See [authentication guide](../auth.md) for examples of using saving and resotring the storage state.
|
|
68
|
+
#
|
|
65
69
|
# **Defaults**
|
|
66
70
|
class Credentials < PlaywrightApi
|
|
67
71
|
|