capybara-playwright-driver 0.0.0.pre.r1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,180 @@
1
+ require 'fileutils'
2
+
3
+ module Capybara
4
+ module Playwright
5
+ module PageExtension
6
+ def initialize(*args, **kwargs)
7
+ super
8
+ capybara_initialize
9
+ end
10
+
11
+ private def capybara_initialize
12
+ @capybara_all_responses = {}
13
+ @capybara_last_response = nil
14
+ @capybara_frames = []
15
+
16
+ on('dialog', -> (dialog) {
17
+ capybara_dialog_event_handler.handle_dialog(dialog)
18
+ })
19
+ on('download', -> (download) {
20
+ FileUtils.mkdir_p(Capybara.save_path)
21
+ dest = File.join(Capybara.save_path, download.suggested_filename)
22
+ # download.save_as blocks main thread until download completes.
23
+ Thread.new(dest) { |_dest| download.save_as(_dest) }
24
+ })
25
+ on('response', -> (response) {
26
+ @capybara_all_responses[response.url] = response
27
+ })
28
+ on('framenavigated', -> (frame) {
29
+ @capybara_last_response = @capybara_all_responses[frame.url]
30
+ @capybara_all_responses.clear
31
+ })
32
+ end
33
+
34
+ private def capybara_dialog_event_handler
35
+ @capybara_dialog_event_handler ||= DialogEventHandler.new.tap do |h|
36
+ h.default_handler = method(:capybara_on_unexpected_modal)
37
+ end
38
+ end
39
+
40
+ private def capybara_on_unexpected_modal(dialog)
41
+ puts "[WARNING] Unexpected modal - \"#{dialog.message}\""
42
+ if dialog.type == 'beforeunload'
43
+ dialog.accept_async
44
+ else
45
+ dialog.dismiss
46
+ end
47
+ end
48
+
49
+ class DialogAcceptor
50
+ def initialize(dialog_type, options)
51
+ @dialog_type = dialog_type
52
+ @options = options
53
+ end
54
+
55
+ def handle(dialog)
56
+ if @dialog_type == :prompt
57
+ dialog.accept_async(promptText: @options[:with] || dialog.default_value)
58
+ else
59
+ dialog.accept_async
60
+ end
61
+ end
62
+ end
63
+
64
+ class DialogMessageMatcher
65
+ def initialize(text_or_regex_or_nil)
66
+ if [NilClass, Regexp, String].none? { |k| text_or_regex_or_nil.is_a?(k) }
67
+ raise ArgumentError.new("invalid type: #{text_or_regex_or_nil.inspect}")
68
+ end
69
+
70
+ @filter = text_or_regex_or_nil
71
+ end
72
+
73
+ def matches?(message)
74
+ case @filter
75
+ when nil
76
+ true
77
+ when Regexp
78
+ message =~ @filter
79
+ when String
80
+ message&.include?(@filter)
81
+ end
82
+ end
83
+ end
84
+
85
+ def capybara_accept_modal(dialog_type, **options, &block)
86
+ timeout_sec = options[:wait]
87
+ acceptor = DialogAcceptor.new(dialog_type, options)
88
+ matcher = DialogMessageMatcher.new(options[:text])
89
+ message_promise = Concurrent::Promises.resolvable_future
90
+ handler = -> (dialog) {
91
+ message = dialog.message
92
+ if matcher.matches?(message)
93
+ message_promise.fulfill(message)
94
+ acceptor.handle(dialog)
95
+ else
96
+ message_promise.reject(Capybara::ModalNotFound.new("Dialog message=\"#{message}\" dowsn't match"))
97
+ dialog.dismiss
98
+ end
99
+ }
100
+ capybara_dialog_event_handler.with_handler(handler) do
101
+ block.call
102
+
103
+ message = message_promise.value!(timeout_sec)
104
+ if message_promise.fulfilled?
105
+ message
106
+ else
107
+ # timed out
108
+ raise Capybara::ModalNotFound
109
+ end
110
+ end
111
+ end
112
+
113
+ def capybara_dismiss_modal(dialog_type, **options, &block)
114
+ timeout_sec = options[:wait]
115
+ matcher = DialogMessageMatcher.new(options[:text])
116
+ message_promise = Concurrent::Promises.resolvable_future
117
+ handler = -> (dialog) {
118
+ message = dialog.message
119
+ if matcher.matches?(message)
120
+ message_promise.fulfill(message)
121
+ else
122
+ message_promise.reject(Capybara::ModalNotFound.new("Dialog message=\"#{message}\" dowsn't match"))
123
+ end
124
+ dialog.dismiss
125
+ }
126
+ capybara_dialog_event_handler.with_handler(handler) do
127
+ block.call
128
+
129
+ message = message_promise.value!(timeout_sec)
130
+ if message_promise.fulfilled?
131
+ message
132
+ else
133
+ # timed out
134
+ raise Capybara::ModalNotFound
135
+ end
136
+ end
137
+ end
138
+
139
+ class Headers < Hash
140
+ def [](key)
141
+ # Playwright accepts lower-cased keys.
142
+ # However allow users to specify "Content-Type" or "User-Agent".
143
+ super(key.downcase)
144
+ end
145
+ end
146
+
147
+ def capybara_response_headers
148
+ headers = @capybara_last_response&.headers || {}
149
+
150
+ Headers.new.tap do |h|
151
+ headers.each do |key, value|
152
+ h[key] = value
153
+ end
154
+ end
155
+ end
156
+
157
+ def capybara_status_code
158
+ @capybara_last_response&.status.to_i
159
+ end
160
+
161
+ def capybara_reset_frames
162
+ @capybara_frames.clear
163
+ end
164
+
165
+ # @param frame [Playwright::Frame]
166
+ def capybara_push_frame(frame)
167
+ @capybara_frames << frame
168
+ end
169
+
170
+ def capybara_pop_frame
171
+ @capybara_frames.pop
172
+ end
173
+
174
+ def capybara_current_frame
175
+ @capybara_frames.last || main_frame
176
+ end
177
+ end
178
+ ::Playwright::Page.prepend(PageExtension)
179
+ end
180
+ end
@@ -0,0 +1,44 @@
1
+ module Capybara
2
+ module Playwright
3
+ class PageOptions
4
+ def initialize(options)
5
+ @options = options
6
+ end
7
+
8
+ NEW_PAGE_PARAMS = {
9
+ acceptDownloads: nil,
10
+ bypassCSP: nil,
11
+ colorScheme: nil,
12
+ deviceScaleFactor: nil,
13
+ extraHTTPHeaders: nil,
14
+ geolocation: nil,
15
+ hasTouch: nil,
16
+ httpCredentials: nil,
17
+ ignoreHTTPSErrors: nil,
18
+ isMobile: nil,
19
+ javaScriptEnabled: nil,
20
+ locale: nil,
21
+ noViewport: nil,
22
+ offline: nil,
23
+ permissions: nil,
24
+ proxy: nil,
25
+ record_har_omit_content: nil,
26
+ record_har_path: nil,
27
+ record_video_dir: nil,
28
+ record_video_size: nil,
29
+ screen: nil,
30
+ storageState: nil,
31
+ timezoneId: nil,
32
+ userAgent: nil,
33
+ viewport: nil,
34
+ }.keys
35
+
36
+ def value
37
+ @options.select { |k, _| NEW_PAGE_PARAMS.include?(k) }.tap do |options|
38
+ # Set default value
39
+ options[:acceptDownloads] = true
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capybara
4
+ module Playwright
5
+ VERSION = '0.0.0-r1'
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,216 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capybara-playwright-driver
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0.pre.r1
5
+ platform: ruby
6
+ authors:
7
+ - YusukeIwaki
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-05-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: capybara
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: playwright-ruby-client
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.5.9
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.5.9
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 2.2.3
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 2.2.3
55
+ - !ruby/object:Gem::Dependency
56
+ name: launchy
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 2.0.4
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 2.0.4
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 13.0.3
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 13.0.3
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 3.10.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 3.10.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 1.7.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 1.7.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: sinatra
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: 1.4.0
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: 1.4.0
153
+ - !ruby/object:Gem::Dependency
154
+ name: webrick
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description:
168
+ email:
169
+ - q7w8e9w8q7w8e9@yahoo.co.jp
170
+ executables: []
171
+ extensions: []
172
+ extra_rdoc_files: []
173
+ files:
174
+ - ".rspec"
175
+ - CODE_OF_CONDUCT.md
176
+ - Gemfile
177
+ - LICENSE.txt
178
+ - README.md
179
+ - Rakefile
180
+ - bin/console
181
+ - bin/setup
182
+ - capybara-playwright.gemspec
183
+ - lib/capybara-playwright-driver.rb
184
+ - lib/capybara/playwright.rb
185
+ - lib/capybara/playwright/browser.rb
186
+ - lib/capybara/playwright/browser_options.rb
187
+ - lib/capybara/playwright/dialog_event_handler.rb
188
+ - lib/capybara/playwright/driver.rb
189
+ - lib/capybara/playwright/node.rb
190
+ - lib/capybara/playwright/page.rb
191
+ - lib/capybara/playwright/page_options.rb
192
+ - lib/capybara/playwright/version.rb
193
+ homepage: https://github.com/YusukeIwaki/capybara-playwright-driver
194
+ licenses:
195
+ - MIT
196
+ metadata: {}
197
+ post_install_message:
198
+ rdoc_options: []
199
+ require_paths:
200
+ - lib
201
+ required_ruby_version: !ruby/object:Gem::Requirement
202
+ requirements:
203
+ - - ">="
204
+ - !ruby/object:Gem::Version
205
+ version: '0'
206
+ required_rubygems_version: !ruby/object:Gem::Requirement
207
+ requirements:
208
+ - - ">"
209
+ - !ruby/object:Gem::Version
210
+ version: 1.3.1
211
+ requirements: []
212
+ rubygems_version: 3.1.4
213
+ signing_key:
214
+ specification_version: 4
215
+ summary: Playwright driver for Capybara
216
+ test_files: []