3
3
module Capybara
4
4
module Lockstep
5
5
module SynchronizeMacros
6
+ def self . extended ( by )
7
+ by . instance_eval do
8
+ prepend ( @synchronize_before_module = Module . new )
9
+ prepend ( @synchronize_after_module = Module . new )
10
+ prepend ( @unsynchronize_after_module = Module . new )
11
+ end
12
+ end
6
13
7
14
def synchronize_before ( meth , lazy :)
8
- mod = Module . new do
15
+ @synchronize_before_module . module_eval do
9
16
define_method meth do |*args , &block |
10
- Lockstep . auto_synchronize ( lazy : lazy , log : "Synchronizing before ##{ meth } " )
17
+ @synchronize_before_count ||= 0
18
+ @synchronize_before_count += 1
19
+ Lockstep . auto_synchronize ( lazy : lazy , log : "Synchronizing before ##{ meth } " ) if @synchronize_before_count == 1
11
20
super ( *args , &block )
21
+ ensure
22
+ @synchronize_before_count -= 1
12
23
end
13
24
14
25
ruby2_keywords meth
15
26
end
16
-
17
- prepend ( mod )
18
27
end
19
28
20
29
def synchronize_after ( meth )
21
- mod = Module . new do
30
+ @synchronize_after_module . module_eval do
22
31
define_method meth do |*args , &block |
32
+ @synchronize_after_count ||= 0
33
+ @synchronize_after_count += 1
23
34
super ( *args , &block )
24
35
ensure
25
- Lockstep . auto_synchronize
36
+ Lockstep . auto_synchronize ( log : "Synchronizing after ##{ meth } " ) if @synchronize_after_count == 1
37
+ @synchronize_after_count -= 1
26
38
end
27
39
28
40
ruby2_keywords meth
29
41
end
30
-
31
- prepend ( mod )
32
42
end
33
43
34
44
def unsynchronize_after ( meth )
35
- mod = Module . new do
45
+ @unsynchronize_after_module . module_eval do
36
46
define_method meth do |*args , &block |
37
47
super ( *args , &block )
38
48
ensure
@@ -41,10 +51,7 @@ def unsynchronize_after(meth)
41
51
42
52
ruby2_keywords meth
43
53
end
44
-
45
- prepend ( mod )
46
54
end
47
-
48
55
end
49
56
end
50
57
end
@@ -158,23 +165,23 @@ def synchronize_around_script_method(meth)
158
165
synchronize_around_script_method :evaluate_async_script
159
166
end
160
167
161
- # Capybara 3 has driver-specific Node classes which sometimes
162
- # super to Capybara::Selenium::Node, but not always .
163
- node_classes = [
168
+ # In Capybara 3 there are the specialized classes for nodes for most browers.
169
+ # We need to patch relevant methods on all of these .
170
+ driver_specific_node_classes = [
164
171
( Capybara ::Selenium ::ChromeNode if defined? ( Capybara ::Selenium ::ChromeNode ) ) ,
165
172
( Capybara ::Selenium ::FirefoxNode if defined? ( Capybara ::Selenium ::FirefoxNode ) ) ,
166
173
( Capybara ::Selenium ::SafariNode if defined? ( Capybara ::Selenium ::SafariNode ) ) ,
167
174
( Capybara ::Selenium ::EdgeNode if defined? ( Capybara ::Selenium ::EdgeNode ) ) ,
168
175
( Capybara ::Selenium ::IENode if defined? ( Capybara ::Selenium ::IENode ) ) ,
169
- ] . compact
176
+ ] . compact . freeze
170
177
171
- if node_classes . empty?
172
- # Capybara 2 has no driver-specific Node implementations,
173
- # so we patch the shared base class.
174
- node_classes = [ Capybara ::Selenium ::Node ]
175
- end
178
+ # For other browsers (like the :remote browser) we instead get a generic node class.
179
+ # This is also the case for Capybara 2.
180
+ generic_node_classes = [
181
+ Capybara ::Selenium ::Node ,
182
+ ] . freeze
176
183
177
- node_classes . each do |node_class |
184
+ [ * driver_specific_node_classes , * generic_node_classes ] . each do |node_class |
178
185
node_class . class_eval do
179
186
extend Capybara ::Lockstep ::SynchronizeMacros
180
187
0 commit comments