capybara-lockstep 0.2.2 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 58ff0d51fafccaca566a89722c750b18db169331d57070c5db7d5de32620d648
4
- data.tar.gz: f6f859ded650d9b2dba0c43bbb7b19333e505ed57aa0d883b0a2981e5928f1a8
3
+ metadata.gz: aa8ccde381bb125f66222689d93c93008ec2137cfabc664a6ce83ff0701cd7a8
4
+ data.tar.gz: 7485b88104f0c4b43387f252e600ad7dc23a917eac28914249b8f279d5ab9df3
5
5
  SHA512:
6
- metadata.gz: 4c1ba4546483509650a7423d04e0acffaf286db556ae431152076478e5d2ca7611a915e9f666c077d9c9c205cb4703d2cf29341e52a0b39493c4b11b78e6a883
7
- data.tar.gz: 1e890d3d985af8ce4d623778781cfc06a1242d83d1c93b98bc550997e3044066544dc15100ccdb28e89090e1b865d7720200a84f8461984655b0f87fcf795281
6
+ metadata.gz: 19f52ab1ca0e9f30fe8be0e791b66bcefe9992d958a104a30c602987e310363587f075f7af19bebf8248e76836a008601c700092bc3b1d53fff3fda5b764dcdc
7
+ data.tar.gz: e6380494b6940092842f87e54c898e6a2da9311aa2fd1951a602fb193fb44c7ee6f96907704d80382bd1cc2ccc31a7e0b433e27da8906f889aa6f7178fcd2dff
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- capybara-lockstep (0.2.2)
4
+ capybara-lockstep (0.2.3)
5
5
  activesupport (>= 3.2)
6
6
  capybara (>= 2.0)
7
7
  selenium-webdriver (>= 3)
@@ -9,11 +9,12 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
- activesupport (5.2.4.3)
12
+ activesupport (6.1.3)
13
13
  concurrent-ruby (~> 1.0, >= 1.0.2)
14
- i18n (>= 0.7, < 2)
15
- minitest (~> 5.1)
16
- tzinfo (~> 1.1)
14
+ i18n (>= 1.6, < 2)
15
+ minitest (>= 5.1)
16
+ tzinfo (~> 2.0)
17
+ zeitwerk (~> 2.3)
17
18
  addressable (2.7.0)
18
19
  public_suffix (>= 2.0.2, < 5.0)
19
20
  capybara (3.35.3)
@@ -25,13 +26,15 @@ GEM
25
26
  regexp_parser (>= 1.5, < 3.0)
26
27
  xpath (~> 3.2)
27
28
  childprocess (3.0.0)
28
- concurrent-ruby (1.1.7)
29
+ concurrent-ruby (1.1.8)
29
30
  diff-lcs (1.3)
30
- i18n (1.8.2)
31
+ i18n (1.8.9)
31
32
  concurrent-ruby (~> 1.0)
32
33
  mini_mime (1.0.2)
33
- minitest (5.14.1)
34
- nokogiri (1.11.1-x86_64-linux)
34
+ mini_portile2 (2.5.0)
35
+ minitest (5.14.4)
36
+ nokogiri (1.11.1)
37
+ mini_portile2 (~> 2.5.0)
35
38
  racc (~> 1.4)
36
39
  public_suffix (4.0.6)
37
40
  racc (1.5.2)
@@ -53,15 +56,15 @@ GEM
53
56
  diff-lcs (>= 1.2.0, < 2.0)
54
57
  rspec-support (~> 3.7.0)
55
58
  rspec-support (3.7.0)
56
- rubyzip (1.3.0)
59
+ rubyzip (2.3.0)
57
60
  selenium-webdriver (3.142.7)
58
61
  childprocess (>= 0.5, < 4.0)
59
62
  rubyzip (>= 1.2.2)
60
- thread_safe (0.3.6)
61
- tzinfo (1.2.7)
62
- thread_safe (~> 0.1)
63
+ tzinfo (2.0.4)
64
+ concurrent-ruby (~> 1.0)
63
65
  xpath (3.2.0)
64
66
  nokogiri (~> 1.8)
67
+ zeitwerk (2.4.2)
65
68
 
66
69
  PLATFORMS
67
70
  ruby
data/README.md CHANGED
@@ -59,7 +59,7 @@ Installation
59
59
  Check if your application satisfies all requirements for capybara-lockstep:
60
60
 
61
61
  - Capybara 2 or higher.
62
- - Your Capybara driver must use [selenium-webdriver](https://rubygems.org/gems/selenium-webdriver/). capybara-headless deactivates itself for any other driver.
62
+ - Your Capybara driver must use [selenium-webdriver](https://rubygems.org/gems/selenium-webdriver/). capybara-lockstep deactivates itself for any other driver.
63
63
  - This gem was only tested with a Selenium-controlled Chrome browser. [Chrome in headless mode](https://makandracards.com/makandra/492109-running-capybara-tests-in-headless-chrome) is recommended, but not required.
64
64
  - This gem was only tested with Rails, but there's no Rails dependency.
65
65
 
@@ -1,24 +1,38 @@
1
1
  module Capybara
2
2
  module Lockstep
3
3
  module VisitWithWaiting
4
- def visit(*args, **kwargs, &block)
5
- super(*args, **kwargs, &block).tap do
4
+ def visit(*args, &block)
5
+ visiting_remote_url = !args[0].start_with?('data:')
6
+
7
+ Capybara::Lockstep.catch_up
8
+
9
+ super(*args, &block).tap do
6
10
  # There is a step that changes drivers mid-scenario.
7
11
  # It works by creating a new Capybara session and re-visits the
8
12
  # URL from the previous session. If this happens before a URL is ever
9
13
  # loaded, it re-visits the URL "data:", which will never "finish"
10
14
  # initializing.
11
- unless args[0].start_with?('data:')
15
+ if visiting_remote_url
12
16
  Capybara::Lockstep.await_initialized
13
17
  end
14
18
  end
15
19
  end
16
20
  end
21
+ end
22
+ end
17
23
 
24
+
25
+ Capybara::Session.class_eval do
26
+ prepend Capybara::Lockstep::VisitWithWaiting
27
+ end
28
+
29
+ module Capybara
30
+ module Lockstep
18
31
  module AwaitIdle
19
32
  def await_idle(meth)
20
33
  mod = Module.new do
21
34
  define_method meth do |*args, &block|
35
+ Capybara::Lockstep.catch_up
22
36
  super(*args, &block).tap do
23
37
  Capybara::Lockstep.await_idle
24
38
  end
@@ -30,10 +44,6 @@ module Capybara
30
44
  end
31
45
  end
32
46
 
33
- Capybara::Session.class_eval do
34
- prepend Capybara::Lockstep::VisitWithWaiting
35
- end
36
-
37
47
  # Capybara 3 has driver-specific Node classes which sometimes
38
48
  # super to Capybara::Selenium::Node, but not always.
39
49
  node_classes = [
@@ -69,3 +79,19 @@ node_classes.each do |node_class|
69
79
  await_idle :trigger
70
80
  end
71
81
  end
82
+
83
+ module Capybara
84
+ module Lockstep
85
+ module SynchronizeWithCatchUp
86
+ def synchronize(*args, &block)
87
+ Capybara::Lockstep.catch_up
88
+
89
+ super(*args, &block)
90
+ end
91
+ end
92
+ end
93
+ end
94
+
95
+ Capybara::Node::Base.class_eval do
96
+ prepend Capybara::Lockstep::SynchronizeWithCatchUp
97
+ end
@@ -5,25 +5,28 @@ module Capybara
5
5
  include Configuration
6
6
 
7
7
  def await_idle
8
+ @delay_await_idle = false
8
9
  return unless enabled?
9
10
 
10
- ignoring_alerts do
11
- # evaluate_async_script also times out after Capybara.default_max_wait_time
12
- with_max_wait_time(timeout) do
13
- message_from_js = evaluate_async_script(<<~JS)
14
- let done = arguments[0]
15
- if (window.CapybaraLockstep) {
16
- CapybaraLockstep.awaitIdle(done)
17
- } else {
18
- done('Cannot synchronize: Capybara::Lockstep was not included in page')
19
- }
20
- JS
21
- log(message_from_js)
22
- end
11
+ with_max_wait_time(timeout) do
12
+ message_from_js = evaluate_async_script(<<~JS)
13
+ let done = arguments[0]
14
+ if (window.CapybaraLockstep) {
15
+ CapybaraLockstep.awaitIdle(done)
16
+ } else {
17
+ done('Cannot synchronize: Capybara::Lockstep was not included in page')
18
+ }
19
+ JS
20
+ log(message_from_js)
23
21
  end
22
+ rescue ::Selenium::WebDriver::Error::UnexpectedAlertOpenError
23
+ log 'Cannot synchronize: Alert is open'
24
+ @delay_await_idle = true
24
25
  end
25
26
 
26
27
  def await_initialized
28
+ @delay_await_initialized = false
29
+ @delay_await_idle = false # since we're also waiting for idle
27
30
  return unless enabled?
28
31
 
29
32
  # We're retrying the initialize check every few ms.
@@ -41,6 +44,29 @@ module Capybara
41
44
  raise Busy, reason
42
45
  end
43
46
  end
47
+ rescue ::Selenium::WebDriver::Error::UnexpectedAlertOpenError
48
+ log 'Cannot synchronize: Alert is open'
49
+ @delay_await_initialized = true
50
+ end
51
+
52
+ def catch_up
53
+ return if @catching_up
54
+
55
+ begin
56
+ @catching_up = true
57
+ if @delay_await_initialized
58
+ log 'Retrying synchronization'
59
+ await_initialized
60
+ # elsif browser_made_full_page_load?
61
+ # log 'Browser loaded new page'
62
+ # await_initialized
63
+ elsif @delay_await_idle
64
+ log 'Retrying synchronization'
65
+ await_idle
66
+ end
67
+ ensure
68
+ @catching_up = false
69
+ end
44
70
  end
45
71
 
46
72
  def idle?
@@ -72,31 +98,34 @@ module Capybara
72
98
 
73
99
  private
74
100
 
101
+ def browser_made_full_page_load?
102
+ # Page change without visit()
103
+ page.has_css?('body[data-hydrating]')
104
+ end
105
+
75
106
  def initialize_reason
76
- ignoring_alerts do
77
- execute_script(<<~JS)
78
- if (location.href.indexOf('data:') == 0) {
79
- return 'Requesting initial page'
80
- }
107
+ execute_script(<<~JS)
108
+ if (location.href.indexOf('data:') == 0) {
109
+ return 'Requesting initial page'
110
+ }
81
111
 
82
- if (document.readyState !== "complete") {
83
- return 'Document is loading'
84
- }
112
+ if (document.readyState !== "complete") {
113
+ return 'Document is loading'
114
+ }
85
115
 
86
- // The application layouts render a <body data-initializing>.
87
- // The [data-initializing] attribute is removed by an Angular directive or Unpoly compiler (frontend).
88
- // to signal that all elements have been activated.
89
- if (document.querySelector('body[data-initializing]')) {
90
- return 'DOM is being hydrated'
91
- }
116
+ // The application layouts render a <body data-initializing>.
117
+ // The [data-initializing] attribute is removed by an Angular directive or Unpoly compiler (frontend).
118
+ // to signal that all elements have been activated.
119
+ if (document.querySelector('body[data-initializing]')) {
120
+ return 'DOM is being hydrated'
121
+ }
92
122
 
93
- if (window.CapybaraLockstep && CapybaraLockstep.isBusy()) {
94
- return 'JavaScript or AJAX requests are running'
95
- }
123
+ if (window.CapybaraLockstep && CapybaraLockstep.isBusy()) {
124
+ return 'JavaScript or AJAX requests are running'
125
+ }
96
126
 
97
- return false
98
- JS
99
- end
127
+ return false
128
+ JS
100
129
  end
101
130
 
102
131
  def page
@@ -105,12 +134,6 @@ module Capybara
105
134
 
106
135
  delegate :evaluate_script, :evaluate_async_script, :execute_script, :driver, to: :page
107
136
 
108
- def ignoring_alerts(&block)
109
- block.call
110
- rescue ::Selenium::WebDriver::Error::UnexpectedAlertOpenError
111
- # noop
112
- end
113
-
114
137
  def with_max_wait_time(seconds, &block)
115
138
  old_max_wait_time = Capybara.default_max_wait_time
116
139
  Capybara.default_max_wait_time = seconds
@@ -1,5 +1,5 @@
1
1
  module Capybara
2
2
  module Lockstep
3
- VERSION = "0.2.2"
3
+ VERSION = "0.2.3"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capybara-lockstep
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henning Koch