playwright-ruby-client 1.58.1 → 1.59.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.
- checksums.yaml +4 -4
- data/README.md +7 -7
- data/documentation/docs/api/browser_context.md +26 -0
- data/documentation/docs/api/browser_type.md +2 -0
- data/documentation/docs/api/console_message.md +9 -0
- data/documentation/docs/api/frame.md +2 -2
- data/documentation/docs/api/frame_locator.md +2 -2
- data/documentation/docs/api/locator.md +16 -3
- data/documentation/docs/api/page.md +68 -5
- data/documentation/docs/api/request.md +13 -0
- data/documentation/docs/api/response.md +9 -0
- data/documentation/docs/api/tracing.md +1 -0
- data/documentation/docs/article/guides/rails_integration_with_null_driver.md +46 -0
- data/documentation/docs/include/api_coverage.md +15 -0
- data/lib/playwright/channel_owners/browser_context.rb +24 -4
- data/lib/playwright/channel_owners/debugger.rb +4 -0
- data/lib/playwright/channel_owners/dialog.rb +3 -1
- data/lib/playwright/channel_owners/disposable.rb +9 -0
- data/lib/playwright/channel_owners/overlay.rb +4 -0
- data/lib/playwright/channel_owners/page.rb +58 -31
- data/lib/playwright/channel_owners/request.rb +8 -0
- data/lib/playwright/channel_owners/response.rb +5 -0
- data/lib/playwright/channel_owners/tracing.rb +2 -1
- data/lib/playwright/console_message_impl.rb +4 -0
- data/lib/playwright/disposable.rb +11 -0
- data/lib/playwright/har_router.rb +16 -1
- data/lib/playwright/locator_impl.rb +23 -3
- data/lib/playwright/screencast.rb +91 -0
- data/lib/playwright/test.rb +12 -33
- data/lib/playwright/utils.rb +19 -0
- data/lib/playwright/version.rb +2 -2
- data/lib/playwright/video.rb +6 -4
- data/lib/playwright.rb +2 -0
- data/lib/playwright_api/android.rb +7 -7
- data/lib/playwright_api/android_device.rb +6 -6
- data/lib/playwright_api/api_request_context.rb +6 -6
- data/lib/playwright_api/browser.rb +18 -6
- data/lib/playwright_api/browser_context.rb +42 -16
- data/lib/playwright_api/browser_type.rb +11 -9
- data/lib/playwright_api/cdp_session.rb +6 -6
- data/lib/playwright_api/console_message.rb +6 -0
- data/lib/playwright_api/dialog.rb +6 -6
- data/lib/playwright_api/element_handle.rb +6 -6
- data/lib/playwright_api/frame.rb +8 -8
- data/lib/playwright_api/frame_locator.rb +2 -2
- data/lib/playwright_api/js_handle.rb +6 -6
- data/lib/playwright_api/locator.rb +19 -4
- data/lib/playwright_api/page.rb +72 -18
- data/lib/playwright_api/playwright.rb +6 -6
- data/lib/playwright_api/request.rb +16 -6
- data/lib/playwright_api/response.rb +12 -6
- data/lib/playwright_api/route.rb +6 -6
- data/lib/playwright_api/tracing.rb +8 -7
- data/lib/playwright_api/web_socket.rb +6 -6
- data/lib/playwright_api/worker.rb +8 -8
- data/playwright.gemspec +7 -1
- data/sig/playwright.rbs +28 -15
- metadata +7 -11
- data/AGENTS.md +0 -4
- data/CLAUDE/api_generation.md +0 -28
- data/CLAUDE/ci_expectations.md +0 -23
- data/CLAUDE/gem_release_flow.md +0 -39
- data/CLAUDE/past_upgrade_pr_patterns.md +0 -42
- data/CLAUDE/playwright_upgrade_workflow.md +0 -35
- data/CLAUDE/rspec_debugging.md +0 -30
- data/CLAUDE/unimplemented_examples.md +0 -18
- data/CLAUDE.md +0 -32
|
@@ -56,7 +56,9 @@ module Playwright
|
|
|
56
56
|
emit(Events::Page::PageError, Error.parse(params['error']['error']))
|
|
57
57
|
})
|
|
58
58
|
@channel.on('route', ->(params) { on_route(ChannelOwners::Route.from(params['route'])) })
|
|
59
|
-
@
|
|
59
|
+
if @initializer['video']
|
|
60
|
+
@video_artifact = ChannelOwners::Artifact.from(@initializer['video'])
|
|
61
|
+
end
|
|
60
62
|
@channel.on('viewportSizeChanged', method(:on_viewport_size_changed))
|
|
61
63
|
@channel.on('webSocket', ->(params) {
|
|
62
64
|
emit(Events::Page::WebSocket, ChannelOwners::WebSocket.from(params['webSocket']))
|
|
@@ -171,11 +173,6 @@ module Playwright
|
|
|
171
173
|
emit(Events::Page::Download, download)
|
|
172
174
|
end
|
|
173
175
|
|
|
174
|
-
private def on_video(params)
|
|
175
|
-
artifact = ChannelOwners::Artifact.from(params['artifact'])
|
|
176
|
-
video.send(:set_artifact, artifact)
|
|
177
|
-
end
|
|
178
|
-
|
|
179
176
|
private def on_viewport_size_changed(params)
|
|
180
177
|
@viewport_size = {
|
|
181
178
|
width: params['viewportSize']['width'],
|
|
@@ -307,8 +304,9 @@ module Playwright
|
|
|
307
304
|
end
|
|
308
305
|
|
|
309
306
|
def expose_function(name, callback)
|
|
310
|
-
@channel.
|
|
307
|
+
result = @channel.send_message_to_server_result('exposeBinding', name: name)
|
|
311
308
|
@bindings[name] = ->(_source, *args) { callback.call(*args) }
|
|
309
|
+
ChannelOwners::Disposable.from(result['disposable'])
|
|
312
310
|
end
|
|
313
311
|
|
|
314
312
|
def expose_binding(name, callback, handle: nil)
|
|
@@ -316,8 +314,9 @@ module Playwright
|
|
|
316
314
|
name: name,
|
|
317
315
|
needsHandle: handle,
|
|
318
316
|
}.compact
|
|
319
|
-
@channel.
|
|
317
|
+
result = @channel.send_message_to_server_result('exposeBinding', params)
|
|
320
318
|
@bindings[name] = callback
|
|
319
|
+
ChannelOwners::Disposable.from(result['disposable'])
|
|
321
320
|
end
|
|
322
321
|
|
|
323
322
|
def set_extra_http_headers(headers)
|
|
@@ -412,14 +411,15 @@ module Playwright
|
|
|
412
411
|
raise ArgumentError.new('Either path or script parameter must be specified')
|
|
413
412
|
end
|
|
414
413
|
|
|
415
|
-
@channel.
|
|
416
|
-
|
|
414
|
+
result = @channel.send_message_to_server_result('addInitScript', source: source)
|
|
415
|
+
ChannelOwners::Disposable.from(result['disposable'])
|
|
417
416
|
end
|
|
418
417
|
|
|
419
418
|
def route(url, handler, times: nil)
|
|
420
419
|
entry = RouteHandler.new(url, @browser_context.send(:base_url), handler, times)
|
|
421
420
|
@routes.unshift(entry)
|
|
422
421
|
update_interception_patterns
|
|
422
|
+
DisposableStub.new { unroute(url, handler: handler) }
|
|
423
423
|
end
|
|
424
424
|
|
|
425
425
|
def unroute_all(behavior: nil)
|
|
@@ -646,20 +646,49 @@ module Playwright
|
|
|
646
646
|
timeout: timeout)
|
|
647
647
|
end
|
|
648
648
|
|
|
649
|
-
def console_messages
|
|
650
|
-
|
|
649
|
+
def console_messages(filter: nil)
|
|
650
|
+
params = {}
|
|
651
|
+
params[:filter] = filter if filter
|
|
652
|
+
messages = @channel.send_message_to_server('consoleMessages', params)
|
|
651
653
|
messages.map do |message|
|
|
652
654
|
ConsoleMessageImpl.new(message, self, nil)
|
|
653
655
|
end
|
|
654
656
|
end
|
|
655
657
|
|
|
656
|
-
def page_errors
|
|
657
|
-
|
|
658
|
+
def page_errors(filter: nil)
|
|
659
|
+
params = {}
|
|
660
|
+
params[:filter] = filter if filter
|
|
661
|
+
errors = @channel.send_message_to_server('pageErrors', params)
|
|
658
662
|
errors.map do |error|
|
|
659
663
|
Error.parse(error['error'])
|
|
660
664
|
end
|
|
661
665
|
end
|
|
662
666
|
|
|
667
|
+
def clear_console_messages
|
|
668
|
+
@channel.send_message_to_server('clearConsoleMessages')
|
|
669
|
+
end
|
|
670
|
+
|
|
671
|
+
def clear_page_errors
|
|
672
|
+
@channel.send_message_to_server('clearPageErrors')
|
|
673
|
+
end
|
|
674
|
+
|
|
675
|
+
def cancel_pick_locator
|
|
676
|
+
@channel.send_message_to_server('cancelPickLocator')
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
def aria_snapshot(depth: nil, mode: nil, timeout: nil, _track: nil)
|
|
680
|
+
params = { selector: 'body' }
|
|
681
|
+
params[:timeout] = @timeout_settings.timeout(timeout)
|
|
682
|
+
params[:depth] = depth if depth
|
|
683
|
+
params[:mode] = mode if mode
|
|
684
|
+
if _track
|
|
685
|
+
params.delete(:selector)
|
|
686
|
+
params[:track] = _track
|
|
687
|
+
end
|
|
688
|
+
result = @main_frame.channel.send_message_to_server_result('ariaSnapshot', params)
|
|
689
|
+
result['snapshot']
|
|
690
|
+
end
|
|
691
|
+
|
|
663
692
|
def locator(
|
|
664
693
|
selector,
|
|
665
694
|
has: nil,
|
|
@@ -904,28 +933,26 @@ module Playwright
|
|
|
904
933
|
decoded_binary
|
|
905
934
|
end
|
|
906
935
|
|
|
936
|
+
def screencast
|
|
937
|
+
@screencast ||= Screencast.new(self)
|
|
938
|
+
end
|
|
939
|
+
|
|
907
940
|
def video
|
|
908
941
|
return nil unless @browser_context.send(:has_record_video_option?)
|
|
909
|
-
@video ||= Video.new(self)
|
|
942
|
+
@video ||= Video.new(self, artifact: @video_artifact)
|
|
910
943
|
end
|
|
911
944
|
|
|
912
|
-
def
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
end
|
|
945
|
+
def pick_locator
|
|
946
|
+
result = @channel.send_message_to_server_result('pickLocator', {})
|
|
947
|
+
@main_frame.locator(result['selector'])
|
|
948
|
+
end
|
|
917
949
|
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
if option_mode == 'full'
|
|
925
|
-
result['full']
|
|
926
|
-
elsif option_mode == 'incremental'
|
|
927
|
-
result['incremental']
|
|
928
|
-
end
|
|
950
|
+
def snapshot_for_ai(timeout: nil, depth: nil, _track: nil)
|
|
951
|
+
aria_snapshot(mode: 'ai', timeout: timeout, depth: depth, _track: _track)
|
|
952
|
+
end
|
|
953
|
+
|
|
954
|
+
def _assertions(timeout, is_not, message)
|
|
955
|
+
PageAssertionsImpl.new(self, timeout, is_not, message)
|
|
929
956
|
end
|
|
930
957
|
|
|
931
958
|
def start_js_coverage(resetOnNavigation: nil, reportAnonymousScripts: nil)
|
|
@@ -81,6 +81,10 @@ module Playwright
|
|
|
81
81
|
end
|
|
82
82
|
end
|
|
83
83
|
|
|
84
|
+
def existing_response
|
|
85
|
+
@response
|
|
86
|
+
end
|
|
87
|
+
|
|
84
88
|
def response
|
|
85
89
|
resp = @channel.send_message_to_server('response')
|
|
86
90
|
ChannelOwners::Response.from_nullable(resp)
|
|
@@ -162,6 +166,10 @@ module Playwright
|
|
|
162
166
|
res.send(:sizes)
|
|
163
167
|
end
|
|
164
168
|
|
|
169
|
+
private def update_response(response)
|
|
170
|
+
@response = response
|
|
171
|
+
end
|
|
172
|
+
|
|
165
173
|
private def update_redirected_to(request)
|
|
166
174
|
@redirected_to = request
|
|
167
175
|
end
|
|
@@ -7,6 +7,7 @@ module Playwright
|
|
|
7
7
|
private def after_initialize
|
|
8
8
|
@provisional_headers = RawHeaders.new(@initializer['headers'])
|
|
9
9
|
@request = ChannelOwners::Request.from(@initializer['request'])
|
|
10
|
+
@request.send(:update_response, self)
|
|
10
11
|
timing = @initializer['timing']
|
|
11
12
|
@request.send(:update_timings,
|
|
12
13
|
start_time: timing["startTime"],
|
|
@@ -74,6 +75,10 @@ module Playwright
|
|
|
74
75
|
actual_headers.get_all(name)
|
|
75
76
|
end
|
|
76
77
|
|
|
78
|
+
def http_version
|
|
79
|
+
@channel.send_message_to_server('httpVersion')
|
|
80
|
+
end
|
|
81
|
+
|
|
77
82
|
def server_addr
|
|
78
83
|
@channel.send_message_to_server('serverAddr')
|
|
79
84
|
end
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
module Playwright
|
|
2
2
|
define_channel_owner :Tracing do
|
|
3
|
-
def start(name: nil, title: nil, screenshots: nil, snapshots: nil, sources: nil)
|
|
3
|
+
def start(name: nil, title: nil, screenshots: nil, snapshots: nil, sources: nil, live: nil)
|
|
4
4
|
params = {
|
|
5
5
|
name: name,
|
|
6
6
|
screenshots: screenshots,
|
|
7
7
|
snapshots: snapshots,
|
|
8
8
|
sources: sources,
|
|
9
|
+
live: live,
|
|
9
10
|
}.compact
|
|
10
11
|
@include_sources = params[:sources] || false
|
|
11
12
|
@channel.send_message_to_server('tracingStart', params)
|
|
@@ -53,9 +53,10 @@ module Playwright
|
|
|
53
53
|
# test when HAR was recorded but we'd abort it immediately.
|
|
54
54
|
return if response['status'] == -1
|
|
55
55
|
|
|
56
|
+
headers = merge_har_response_headers(response['headers'])
|
|
56
57
|
route.fulfill(
|
|
57
58
|
status: response['status'],
|
|
58
|
-
headers:
|
|
59
|
+
headers: headers,
|
|
59
60
|
body: Base64.strict_decode64(response['body']),
|
|
60
61
|
)
|
|
61
62
|
else
|
|
@@ -82,6 +83,20 @@ module Playwright
|
|
|
82
83
|
page.once(Events::Page::Close, method(:dispose))
|
|
83
84
|
end
|
|
84
85
|
|
|
86
|
+
private def merge_har_response_headers(headers)
|
|
87
|
+
headers.each_with_object({}) do |header, merged|
|
|
88
|
+
name = header['name']
|
|
89
|
+
value = header['value']
|
|
90
|
+
|
|
91
|
+
if name.casecmp('set-cookie').zero?
|
|
92
|
+
key = merged.keys.find { |existing| existing.casecmp('set-cookie').zero? } || name
|
|
93
|
+
merged[key] = merged[key] ? "#{merged[key]}\n#{value}" : value
|
|
94
|
+
else
|
|
95
|
+
merged[name] = value
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
85
100
|
def dispose
|
|
86
101
|
@local_utils.async_har_close(@har_id)
|
|
87
102
|
end
|
|
@@ -426,11 +426,27 @@ module Playwright
|
|
|
426
426
|
end
|
|
427
427
|
end
|
|
428
428
|
|
|
429
|
-
def aria_snapshot(timeout: nil)
|
|
430
|
-
|
|
429
|
+
def aria_snapshot(depth: nil, mode: nil, timeout: nil, _track: nil)
|
|
430
|
+
params = {
|
|
431
431
|
selector: @selector,
|
|
432
432
|
timeout: _timeout(timeout),
|
|
433
|
-
}
|
|
433
|
+
}
|
|
434
|
+
params[:depth] = depth if depth
|
|
435
|
+
params[:mode] = mode if mode
|
|
436
|
+
if _track
|
|
437
|
+
params.delete(:selector)
|
|
438
|
+
params[:track] = _track
|
|
439
|
+
end
|
|
440
|
+
result = @frame.channel.send_message_to_server_result('ariaSnapshot', params.compact)
|
|
441
|
+
result['snapshot']
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
def normalize
|
|
445
|
+
resolved_selector = @frame.channel.send_message_to_server('resolveSelector', { selector: @selector })
|
|
446
|
+
LocatorImpl.new(
|
|
447
|
+
frame: @frame,
|
|
448
|
+
selector: resolved_selector,
|
|
449
|
+
)
|
|
434
450
|
end
|
|
435
451
|
|
|
436
452
|
def scroll_into_view_if_needed(timeout: nil)
|
|
@@ -537,6 +553,10 @@ module Playwright
|
|
|
537
553
|
@frame.highlight(@selector)
|
|
538
554
|
end
|
|
539
555
|
|
|
556
|
+
def _assertions(timeout, is_not, message)
|
|
557
|
+
LocatorAssertionsImpl.new(self, timeout, is_not, message)
|
|
558
|
+
end
|
|
559
|
+
|
|
540
560
|
def expect(expression, options, title)
|
|
541
561
|
@frame.expect(@selector, expression, options, title)
|
|
542
562
|
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'base64'
|
|
2
|
+
|
|
3
|
+
module Playwright
|
|
4
|
+
class Screencast
|
|
5
|
+
def initialize(page)
|
|
6
|
+
@page = page
|
|
7
|
+
@started = false
|
|
8
|
+
@save_path = nil
|
|
9
|
+
@artifact = nil
|
|
10
|
+
@on_frame = nil
|
|
11
|
+
@page.send(:channel).on('screencastFrame', method(:handle_screencast_frame))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def start(path: nil, size: nil, quality: nil, &on_frame)
|
|
15
|
+
raise 'Screencast is already started' if @started
|
|
16
|
+
|
|
17
|
+
@started = true
|
|
18
|
+
@on_frame = on_frame if on_frame
|
|
19
|
+
|
|
20
|
+
params = {}
|
|
21
|
+
params[:record] = true if path
|
|
22
|
+
params[:size] = size if size
|
|
23
|
+
params[:quality] = quality if quality
|
|
24
|
+
params[:sendFrames] = true if on_frame
|
|
25
|
+
|
|
26
|
+
result = @page.send(:channel).send_message_to_server_result('screencastStart', params)
|
|
27
|
+
if result.is_a?(Hash) && result['artifact']
|
|
28
|
+
@artifact = ChannelOwners::Artifact.from(result['artifact'])
|
|
29
|
+
@save_path = path
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
DisposableStub.new { stop }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def stop
|
|
36
|
+
return unless @started
|
|
37
|
+
|
|
38
|
+
@started = false
|
|
39
|
+
@on_frame = nil
|
|
40
|
+
@page.send(:channel).send_message_to_server('screencastStop')
|
|
41
|
+
|
|
42
|
+
if @save_path && @artifact
|
|
43
|
+
@artifact.save_as(@save_path)
|
|
44
|
+
end
|
|
45
|
+
@artifact = nil
|
|
46
|
+
@save_path = nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def show_overlay(html, duration: nil)
|
|
50
|
+
params = { html: html }
|
|
51
|
+
params[:duration] = duration if duration
|
|
52
|
+
result = @page.send(:channel).send_message_to_server_result('screencastShowOverlay', params)
|
|
53
|
+
overlay_id = result['id'] if result.is_a?(Hash)
|
|
54
|
+
DisposableStub.new {
|
|
55
|
+
@page.send(:channel).send_message_to_server('screencastRemoveOverlay', id: overlay_id) if overlay_id
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def show_chapter(title, description: nil, duration: nil)
|
|
60
|
+
params = { title: title }
|
|
61
|
+
params[:description] = description if description
|
|
62
|
+
params[:duration] = duration if duration
|
|
63
|
+
@page.send(:channel).send_message_to_server('screencastChapter', params)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def show_actions(duration: nil, fontSize: nil, position: nil)
|
|
67
|
+
params = {}
|
|
68
|
+
params[:duration] = duration if duration
|
|
69
|
+
params[:fontSize] = fontSize if fontSize
|
|
70
|
+
params[:position] = position if position
|
|
71
|
+
@page.send(:channel).send_message_to_server('screencastShowActions', params)
|
|
72
|
+
DisposableStub.new { hide_actions }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def hide_actions
|
|
76
|
+
@page.send(:channel).send_message_to_server('screencastHideActions')
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def show_overlays
|
|
80
|
+
@page.send(:channel).send_message_to_server('screencastSetOverlayVisible', visible: true)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def hide_overlays
|
|
84
|
+
@page.send(:channel).send_message_to_server('screencastSetOverlayVisible', visible: false)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private def handle_screencast_frame(event)
|
|
88
|
+
@on_frame&.call(Base64.strict_decode64(event['data']))
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
data/lib/playwright/test.rb
CHANGED
|
@@ -21,37 +21,6 @@ module Playwright
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
# ref: https://github.com/microsoft/playwright-python/blob/main/playwright/sync_api/__init__.py#L90
|
|
24
|
-
class Expect
|
|
25
|
-
def initialize
|
|
26
|
-
@default_expect_timeout = ::Playwright::Test.expect_timeout
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def call(actual, is_not)
|
|
30
|
-
case actual
|
|
31
|
-
when Page
|
|
32
|
-
PageAssertions.new(
|
|
33
|
-
PageAssertionsImpl.new(
|
|
34
|
-
actual,
|
|
35
|
-
@default_expect_timeout,
|
|
36
|
-
is_not,
|
|
37
|
-
nil,
|
|
38
|
-
)
|
|
39
|
-
)
|
|
40
|
-
when Locator
|
|
41
|
-
LocatorAssertions.new(
|
|
42
|
-
LocatorAssertionsImpl.new(
|
|
43
|
-
actual,
|
|
44
|
-
@default_expect_timeout,
|
|
45
|
-
is_not,
|
|
46
|
-
nil,
|
|
47
|
-
)
|
|
48
|
-
)
|
|
49
|
-
else
|
|
50
|
-
raise NotImplementedError.new("Only locator assertions are currently implemented")
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
|
|
55
24
|
module Matchers
|
|
56
25
|
class PlaywrightMatcher
|
|
57
26
|
def initialize(expectation_method, *args, **kwargs)
|
|
@@ -61,7 +30,7 @@ module Playwright
|
|
|
61
30
|
end
|
|
62
31
|
|
|
63
32
|
def matches?(actual)
|
|
64
|
-
|
|
33
|
+
assertions_for(actual, false).send(@method, *@args, **@kwargs)
|
|
65
34
|
true
|
|
66
35
|
rescue AssertionError => e
|
|
67
36
|
@failure_message = e.full_message
|
|
@@ -69,7 +38,7 @@ module Playwright
|
|
|
69
38
|
end
|
|
70
39
|
|
|
71
40
|
def does_not_match?(actual)
|
|
72
|
-
|
|
41
|
+
assertions_for(actual, true).send(@method, *@args, **@kwargs)
|
|
73
42
|
true
|
|
74
43
|
rescue AssertionError => e
|
|
75
44
|
@failure_message = e.full_message
|
|
@@ -83,6 +52,16 @@ module Playwright
|
|
|
83
52
|
def failure_message_when_negated
|
|
84
53
|
@failure_message
|
|
85
54
|
end
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
def assertions_for(actual, is_not)
|
|
59
|
+
if actual.respond_to?(:_assertions)
|
|
60
|
+
actual._assertions(::Playwright::Test.expect_timeout, is_not, nil)
|
|
61
|
+
else
|
|
62
|
+
raise NotImplementedError.new("Only page and locator assertions are currently implemented")
|
|
63
|
+
end
|
|
64
|
+
end
|
|
86
65
|
end
|
|
87
66
|
end
|
|
88
67
|
|
data/lib/playwright/utils.rb
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
require 'base64'
|
|
2
2
|
|
|
3
3
|
module Playwright
|
|
4
|
+
class DisposableStub
|
|
5
|
+
def initialize(&block)
|
|
6
|
+
@block = block
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def dispose
|
|
10
|
+
return unless @block
|
|
11
|
+
|
|
12
|
+
block = @block
|
|
13
|
+
@block = nil
|
|
14
|
+
block.call
|
|
15
|
+
rescue TargetClosedError
|
|
16
|
+
nil
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
4
20
|
module Utils
|
|
5
21
|
module PrepareBrowserContextOptions
|
|
6
22
|
# @see https://github.com/microsoft/playwright/blob/5a2cfdbd47ed3c3deff77bb73e5fac34241f649d/src/client/browserContext.ts#L265
|
|
@@ -19,6 +35,9 @@ module Playwright
|
|
|
19
35
|
if params[:record_video_size]
|
|
20
36
|
params[:recordVideo][:size] = params.delete(:record_video_size)
|
|
21
37
|
end
|
|
38
|
+
if params[:record_video_show_actions]
|
|
39
|
+
params[:recordVideo][:showActions] = params.delete(:record_video_show_actions)
|
|
40
|
+
end
|
|
22
41
|
end
|
|
23
42
|
if params[:storageState].is_a?(String)
|
|
24
43
|
params[:storageState] = JSON.parse(File.read(params[:storageState]))
|
data/lib/playwright/version.rb
CHANGED
data/lib/playwright/video.rb
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
module Playwright
|
|
2
2
|
class Video
|
|
3
|
-
def initialize(page)
|
|
3
|
+
def initialize(page, artifact: nil)
|
|
4
4
|
@page = page
|
|
5
5
|
@artifact = Concurrent::Promises.resolvable_future
|
|
6
|
-
if
|
|
6
|
+
if artifact
|
|
7
|
+
@artifact.fulfill(artifact)
|
|
8
|
+
elsif @page.closed?
|
|
7
9
|
on_page_closed
|
|
8
10
|
else
|
|
9
11
|
page.once('close', -> { on_page_closed })
|
|
@@ -16,9 +18,9 @@ module Playwright
|
|
|
16
18
|
end
|
|
17
19
|
end
|
|
18
20
|
|
|
19
|
-
# called only from Page
|
|
21
|
+
# called only from Page with send(:set_artifact, artifact)
|
|
20
22
|
private def set_artifact(artifact)
|
|
21
|
-
@artifact.fulfill(artifact)
|
|
23
|
+
@artifact.fulfill(artifact) unless @artifact.resolved?
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
def path
|
data/lib/playwright.rb
CHANGED
|
@@ -20,6 +20,7 @@ require 'playwright/channel_owner'
|
|
|
20
20
|
require 'playwright/http_headers'
|
|
21
21
|
require 'playwright/input_files'
|
|
22
22
|
require 'playwright/connection'
|
|
23
|
+
require 'playwright/disposable'
|
|
23
24
|
require 'playwright/har_router'
|
|
24
25
|
require 'playwright/raw_headers'
|
|
25
26
|
require 'playwright/route_handler'
|
|
@@ -28,6 +29,7 @@ require 'playwright/timeout_settings'
|
|
|
28
29
|
require 'playwright/transport'
|
|
29
30
|
require 'playwright/url_matcher'
|
|
30
31
|
require 'playwright/version'
|
|
32
|
+
require 'playwright/screencast'
|
|
31
33
|
require 'playwright/video'
|
|
32
34
|
require 'playwright/waiter'
|
|
33
35
|
|
|
@@ -21,7 +21,7 @@ module Playwright
|
|
|
21
21
|
#
|
|
22
22
|
# This methods attaches Playwright to an existing Android device.
|
|
23
23
|
# Use [`method: Android.launchServer`] to launch a new Android server instance.
|
|
24
|
-
def connect(
|
|
24
|
+
def connect(endpoint, headers: nil, slowMo: nil, timeout: nil)
|
|
25
25
|
raise NotImplementedError.new('connect is not implemented yet.')
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -43,12 +43,6 @@ module Playwright
|
|
|
43
43
|
wrap_impl(@impl.set_default_navigation_timeout(unwrap_impl(timeout)))
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
# -- inherited from EventEmitter --
|
|
47
|
-
# @nodoc
|
|
48
|
-
def once(event, callback)
|
|
49
|
-
event_emitter_proxy.once(event, callback)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
46
|
# -- inherited from EventEmitter --
|
|
53
47
|
# @nodoc
|
|
54
48
|
def on(event, callback)
|
|
@@ -61,6 +55,12 @@ module Playwright
|
|
|
61
55
|
event_emitter_proxy.off(event, callback)
|
|
62
56
|
end
|
|
63
57
|
|
|
58
|
+
# -- inherited from EventEmitter --
|
|
59
|
+
# @nodoc
|
|
60
|
+
def once(event, callback)
|
|
61
|
+
event_emitter_proxy.once(event, callback)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
64
|
private def event_emitter_proxy
|
|
65
65
|
@event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
|
|
66
66
|
end
|
|
@@ -204,12 +204,6 @@ module Playwright
|
|
|
204
204
|
wrap_impl(@impl.tap_on(unwrap_impl(selector), duration: unwrap_impl(duration), timeout: unwrap_impl(timeout)))
|
|
205
205
|
end
|
|
206
206
|
|
|
207
|
-
# -- inherited from EventEmitter --
|
|
208
|
-
# @nodoc
|
|
209
|
-
def once(event, callback)
|
|
210
|
-
event_emitter_proxy.once(event, callback)
|
|
211
|
-
end
|
|
212
|
-
|
|
213
207
|
# -- inherited from EventEmitter --
|
|
214
208
|
# @nodoc
|
|
215
209
|
def on(event, callback)
|
|
@@ -222,6 +216,12 @@ module Playwright
|
|
|
222
216
|
event_emitter_proxy.off(event, callback)
|
|
223
217
|
end
|
|
224
218
|
|
|
219
|
+
# -- inherited from EventEmitter --
|
|
220
|
+
# @nodoc
|
|
221
|
+
def once(event, callback)
|
|
222
|
+
event_emitter_proxy.once(event, callback)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
225
|
private def event_emitter_proxy
|
|
226
226
|
@event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
|
|
227
227
|
end
|
|
@@ -286,12 +286,6 @@ module Playwright
|
|
|
286
286
|
raise NotImplementedError.new('storage_state is not implemented yet.')
|
|
287
287
|
end
|
|
288
288
|
|
|
289
|
-
# -- inherited from EventEmitter --
|
|
290
|
-
# @nodoc
|
|
291
|
-
def once(event, callback)
|
|
292
|
-
event_emitter_proxy.once(event, callback)
|
|
293
|
-
end
|
|
294
|
-
|
|
295
289
|
# -- inherited from EventEmitter --
|
|
296
290
|
# @nodoc
|
|
297
291
|
def on(event, callback)
|
|
@@ -304,6 +298,12 @@ module Playwright
|
|
|
304
298
|
event_emitter_proxy.off(event, callback)
|
|
305
299
|
end
|
|
306
300
|
|
|
301
|
+
# -- inherited from EventEmitter --
|
|
302
|
+
# @nodoc
|
|
303
|
+
def once(event, callback)
|
|
304
|
+
event_emitter_proxy.once(event, callback)
|
|
305
|
+
end
|
|
306
|
+
|
|
307
307
|
private def event_emitter_proxy
|
|
308
308
|
@event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
|
|
309
309
|
end
|