capybara-playwright-driver 0.5.7 → 0.5.8
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 +18 -1
- data/capybara-playwright.gemspec +0 -2
- data/lib/capybara/playwright/browser.rb +6 -3
- data/lib/capybara/playwright/driver.rb +2 -2
- data/lib/capybara/playwright/node.rb +74 -0
- data/lib/capybara/playwright/page.rb +12 -10
- data/lib/capybara/playwright/shadow_root_node.rb +3 -3
- data/lib/capybara/playwright/version.rb +1 -1
- metadata +4 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fe14f82e64d08efc962dda883c9c4a6b54b794c75bb5458c522fbf88e839267a
|
|
4
|
+
data.tar.gz: 59156f6e1a5db3dd787b1342cafd5c9f8aca74df33042013304cdd029875e64c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3bbf39026f4bc9dfdce2c319510c709e00b6eb5a890e8057566f57a2b804e2890ff3ee97d67a8ba5da3fe7ede58c526f4b239cd425fe6ac47f049075a83a0a7d
|
|
7
|
+
data.tar.gz: 813ccb3ce551cb1a3484d261096d8847d045cd694b6dc8275ba27f4012fab798ed23ad2bf36f2996818b653bf6ed4d0213d8f7c9f131cccf1c242450ea86327c
|
data/README.md
CHANGED
|
@@ -43,10 +43,27 @@ end
|
|
|
43
43
|
|
|
44
44
|
Refer the [documentation](https://playwright-ruby-client.vercel.app/docs/article/guides/rails_integration) for more detailed configuration.
|
|
45
45
|
|
|
46
|
+
## Development
|
|
47
|
+
|
|
48
|
+
Prepare to run tests:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
bundle install
|
|
52
|
+
export PLAYWRIGHT_CLI_VERSION=$(bundle exec ruby -e 'require "playwright"; puts Playwright::COMPATIBLE_PLAYWRIGHT_VERSION.strip')
|
|
53
|
+
npm install playwright@${PLAYWRIGHT_CLI_VERSION}
|
|
54
|
+
./node_modules/.bin/playwright install --with-deps
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Now, run tests: note that they are run in a virtual framebuffer (Xvfb).
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
PLAYWRIGHT_CLI_EXECUTABLE_PATH=./node_modules/.bin/playwright xvfb-run bundle exec rspec
|
|
61
|
+
```
|
|
62
|
+
|
|
46
63
|
## License
|
|
47
64
|
|
|
48
65
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
49
66
|
|
|
50
67
|
## Code of Conduct
|
|
51
68
|
|
|
52
|
-
Everyone interacting in the Capybara::Playwright project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
|
69
|
+
Everyone interacting in the Capybara::Playwright project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/YusukeIwaki/capybara-playwright-driver/blob/main/CODE_OF_CONDUCT.md).
|
data/capybara-playwright.gemspec
CHANGED
|
@@ -20,8 +20,6 @@ Gem::Specification.new do |spec|
|
|
|
20
20
|
f.match(%r{^(test|spec|features)/}) || f.include?('.git')
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
|
-
spec.bindir = 'exe'
|
|
24
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
25
23
|
spec.require_paths = ['lib']
|
|
26
24
|
|
|
27
25
|
spec.required_ruby_version = '>= 2.4'
|
|
@@ -84,7 +84,8 @@ module Capybara
|
|
|
84
84
|
path
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
-
@playwright_page.capybara_current_frame.goto(url)
|
|
87
|
+
response = @playwright_page.capybara_current_frame.goto(url)
|
|
88
|
+
@playwright_page.capybara_set_last_response(response)
|
|
88
89
|
}
|
|
89
90
|
end
|
|
90
91
|
|
|
@@ -144,13 +145,15 @@ module Capybara
|
|
|
144
145
|
|
|
145
146
|
def go_back
|
|
146
147
|
assert_page_alive {
|
|
147
|
-
@playwright_page.go_back
|
|
148
|
+
response = @playwright_page.go_back
|
|
149
|
+
@playwright_page.capybara_set_last_response(response)
|
|
148
150
|
}
|
|
149
151
|
end
|
|
150
152
|
|
|
151
153
|
def go_forward
|
|
152
154
|
assert_page_alive {
|
|
153
|
-
@playwright_page.go_forward
|
|
155
|
+
response = @playwright_page.go_forward
|
|
156
|
+
@playwright_page.capybara_set_last_response(response)
|
|
154
157
|
}
|
|
155
158
|
end
|
|
156
159
|
|
|
@@ -90,8 +90,8 @@ module Capybara
|
|
|
90
90
|
end
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
-
# video path can be
|
|
94
|
-
# video is
|
|
93
|
+
# video path can be acquired only before closing context.
|
|
94
|
+
# video is completely saved only after closing context.
|
|
95
95
|
video_path = @browser&.video_path
|
|
96
96
|
|
|
97
97
|
# [NOTE] @playwright_browser should keep alive for better performance.
|
|
@@ -30,6 +30,75 @@ module Capybara
|
|
|
30
30
|
end
|
|
31
31
|
Node::Element.prepend(WithElementHandlePatch)
|
|
32
32
|
|
|
33
|
+
module NodeActionsAllowLabelClickPatch
|
|
34
|
+
def choose(locator = nil, **options)
|
|
35
|
+
_playwright_check_via_get_by_label(locator, checked: true, **options) { super }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def check(locator = nil, **options)
|
|
39
|
+
_playwright_check_via_get_by_label(locator, checked: true, **options) { super }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def uncheck(locator = nil, **options)
|
|
43
|
+
_playwright_check_via_get_by_label(locator, checked: false, **options) { super }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private def _playwright_check_via_get_by_label(locator, checked:, allow_label_click: session_options.automatic_label_click, **options)
|
|
47
|
+
unless _playwright_use_get_by_label?(locator, allow_label_click, options)
|
|
48
|
+
return yield
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
return self if _playwright_try_get_by_label(locator, checked: checked)
|
|
52
|
+
|
|
53
|
+
yield
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private def _playwright_use_get_by_label?(locator, allow_label_click, options)
|
|
57
|
+
return false if locator.nil?
|
|
58
|
+
return false unless allow_label_click
|
|
59
|
+
return false unless driver.is_a?(Capybara::Playwright::Driver)
|
|
60
|
+
return false if Hash.try_convert(allow_label_click)
|
|
61
|
+
return false unless options.empty?
|
|
62
|
+
|
|
63
|
+
true
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private def _playwright_try_get_by_label(locator, checked:)
|
|
67
|
+
handled = false
|
|
68
|
+
driver.with_playwright_page do |playwright_page|
|
|
69
|
+
begin
|
|
70
|
+
control_locator = playwright_page.get_by_label(locator.to_s)
|
|
71
|
+
control = control_locator
|
|
72
|
+
|
|
73
|
+
if control.evaluate('el => !!el.checked') != checked
|
|
74
|
+
label = control.evaluate_handle('(el) => (el.labels && el.labels[0]) || el.closest("label") || null')
|
|
75
|
+
next unless label.is_a?(::Playwright::ElementHandle)
|
|
76
|
+
|
|
77
|
+
label.click
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
next unless control.evaluate('el => !!el.checked') == checked
|
|
81
|
+
|
|
82
|
+
handled = true
|
|
83
|
+
rescue ::Playwright::Error
|
|
84
|
+
handled = false
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
handled
|
|
89
|
+
rescue StandardError
|
|
90
|
+
false
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7')
|
|
94
|
+
# Prepend to Node::Base instead of Node::Actions because Ruby < 3.1
|
|
95
|
+
# does not propagate Module#prepend to classes that have already
|
|
96
|
+
# included the target module. Node::Base includes Node::Actions at
|
|
97
|
+
# load time, so prepending to Node::Actions afterwards has no effect
|
|
98
|
+
# on Node::Document / Node::Element in older Rubies.
|
|
99
|
+
Node::Base.prepend(NodeActionsAllowLabelClickPatch)
|
|
100
|
+
end
|
|
101
|
+
|
|
33
102
|
module CapybaraObscuredPatch
|
|
34
103
|
# ref: https://github.com/teamcapybara/capybara/blob/f7ab0b5cd5da86185816c2d5c30d58145fe654ed/lib/capybara/selenium/node.rb#L523
|
|
35
104
|
OBSCURED_OR_OFFSET_SCRIPT = <<~JAVASCRIPT
|
|
@@ -97,6 +166,8 @@ module Capybara
|
|
|
97
166
|
raise StaleReferenceError.new(err)
|
|
98
167
|
when /error in channel "content::page": exception while running method "adoptNode"/ # for Firefox
|
|
99
168
|
raise StaleReferenceError.new(err)
|
|
169
|
+
when /(: Shadow DOM element - no XPath :)/
|
|
170
|
+
raise StaleReferenceError.new(err)
|
|
100
171
|
else
|
|
101
172
|
raise
|
|
102
173
|
end
|
|
@@ -905,6 +976,9 @@ module Capybara
|
|
|
905
976
|
xpath = el.nodeName.toUpperCase()+"["+pos+"]/"+xpath;
|
|
906
977
|
}
|
|
907
978
|
el = el.parentNode;
|
|
979
|
+
if (!el) {
|
|
980
|
+
throw "(: Shadow DOM element - no XPath :)";
|
|
981
|
+
}
|
|
908
982
|
}
|
|
909
983
|
xpath = '/'+xml.documentElement.nodeName.toUpperCase()+'/'+xpath;
|
|
910
984
|
xpath = xpath.replace(/\\/$/, '');
|
|
@@ -17,7 +17,7 @@ module Capybara
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
private def capybara_initialize
|
|
20
|
-
@
|
|
20
|
+
@capybara_response_mutex = Mutex.new
|
|
21
21
|
@capybara_last_response = nil
|
|
22
22
|
@capybara_frames = []
|
|
23
23
|
|
|
@@ -31,13 +31,9 @@ module Capybara
|
|
|
31
31
|
Thread.new(dest) { |_dest| download.save_as(_dest) }
|
|
32
32
|
})
|
|
33
33
|
on('response', -> (response) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
@capybara_last_response = @capybara_all_responses[frame.url]
|
|
38
|
-
})
|
|
39
|
-
on('load', -> (page) {
|
|
40
|
-
@capybara_all_responses.clear
|
|
34
|
+
if response.request.navigation_request?
|
|
35
|
+
capybara_set_last_response(response)
|
|
36
|
+
end
|
|
41
37
|
})
|
|
42
38
|
end
|
|
43
39
|
|
|
@@ -146,6 +142,12 @@ module Capybara
|
|
|
146
142
|
end
|
|
147
143
|
end
|
|
148
144
|
|
|
145
|
+
def capybara_set_last_response(response)
|
|
146
|
+
@capybara_response_mutex.synchronize do
|
|
147
|
+
@capybara_last_response = response
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
149
151
|
class Headers < Hash
|
|
150
152
|
def [](key)
|
|
151
153
|
# Playwright accepts lower-cased keys.
|
|
@@ -155,7 +157,7 @@ module Capybara
|
|
|
155
157
|
end
|
|
156
158
|
|
|
157
159
|
def capybara_response_headers
|
|
158
|
-
headers = @capybara_last_response&.headers || {}
|
|
160
|
+
headers = @capybara_response_mutex.synchronize { @capybara_last_response&.headers || {} }
|
|
159
161
|
|
|
160
162
|
Headers.new.tap do |h|
|
|
161
163
|
headers.each do |key, value|
|
|
@@ -165,7 +167,7 @@ module Capybara
|
|
|
165
167
|
end
|
|
166
168
|
|
|
167
169
|
def capybara_status_code
|
|
168
|
-
@capybara_last_response&.status.to_i
|
|
170
|
+
@capybara_response_mutex.synchronize { @capybara_last_response&.status.to_i }
|
|
169
171
|
end
|
|
170
172
|
|
|
171
173
|
def capybara_reset_frames
|
|
@@ -5,12 +5,12 @@ module Capybara
|
|
|
5
5
|
class ShadowRootNode < Node
|
|
6
6
|
def initialize(driver, internal_logger, page, element)
|
|
7
7
|
super
|
|
8
|
-
@
|
|
8
|
+
@shadow_root_element = element.evaluate_handle('el => el.shadowRoot')
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def all_text
|
|
12
12
|
assert_element_not_stale {
|
|
13
|
-
text = @
|
|
13
|
+
text = @shadow_root_element.text_content
|
|
14
14
|
text.to_s.gsub(/[\u200b\u200e\u200f]/, '')
|
|
15
15
|
.gsub(/[\ \n\f\t\v\u2028\u2029]+/, ' ')
|
|
16
16
|
.gsub(/\A[[:space:]&&[^\u00a0]]+/, '')
|
|
@@ -25,7 +25,7 @@ module Capybara
|
|
|
25
25
|
return '' unless visible?
|
|
26
26
|
|
|
27
27
|
# https://github.com/teamcapybara/capybara/blob/1c164b608fa6452418ec13795b293655f8a0102a/lib/capybara/rack_test/node.rb#L18
|
|
28
|
-
displayed_text = @
|
|
28
|
+
displayed_text = @shadow_root_element.text_content.to_s.
|
|
29
29
|
gsub(/[\u200b\u200e\u200f]/, '').
|
|
30
30
|
gsub(/[\ \n\f\t\v\u2028\u2029]+/, ' ')
|
|
31
31
|
displayed_text.squeeze(' ')
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: capybara-playwright-driver
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- YusukeIwaki
|
|
8
|
-
|
|
9
|
-
bindir: exe
|
|
8
|
+
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: addressable
|
|
@@ -52,7 +51,6 @@ dependencies:
|
|
|
52
51
|
- - ">="
|
|
53
52
|
- !ruby/object:Gem::Version
|
|
54
53
|
version: 1.16.0
|
|
55
|
-
description:
|
|
56
54
|
email:
|
|
57
55
|
- q7w8e9w8q7w8e9@yahoo.co.jp
|
|
58
56
|
executables: []
|
|
@@ -86,7 +84,6 @@ homepage: https://github.com/YusukeIwaki/capybara-playwright-driver
|
|
|
86
84
|
licenses:
|
|
87
85
|
- MIT
|
|
88
86
|
metadata: {}
|
|
89
|
-
post_install_message:
|
|
90
87
|
rdoc_options: []
|
|
91
88
|
require_paths:
|
|
92
89
|
- lib
|
|
@@ -101,8 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
101
98
|
- !ruby/object:Gem::Version
|
|
102
99
|
version: '0'
|
|
103
100
|
requirements: []
|
|
104
|
-
rubygems_version: 3.
|
|
105
|
-
signing_key:
|
|
101
|
+
rubygems_version: 3.6.9
|
|
106
102
|
specification_version: 4
|
|
107
103
|
summary: Playwright driver for Capybara
|
|
108
104
|
test_files: []
|