capybara-lockstep 0.3.2 → 0.7.0
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/.github/workflows/test.yml +36 -0
 - data/.gitignore +1 -0
 - data/CHANGELOG.md +33 -0
 - data/Gemfile +6 -0
 - data/Gemfile.lock +34 -7
 - data/README.md +109 -56
 - data/Rakefile +8 -0
 - data/capybara-lockstep.gemspec +1 -0
 - data/lib/capybara-lockstep/capybara_ext.rb +62 -7
 - data/lib/capybara-lockstep/configuration.rb +44 -4
 - data/lib/capybara-lockstep/helper.js +180 -72
 - data/lib/capybara-lockstep/helper.rb +16 -1
 - data/lib/capybara-lockstep/lockstep.rb +46 -16
 - data/lib/capybara-lockstep/logging.rb +8 -2
 - data/lib/capybara-lockstep/version.rb +1 -1
 - metadata +19 -3
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 8335399770451283be7443be41f3f1e5c2b0401f16a64a7722fb6b39ec2f3143
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 601249c76c50789b44199e734a64fb039cd3b77c1db3e9f9068b1e7dea188216
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 638b0671d9f919c85b972cb2af4df763932a8c00ab21cd8387e3b483fda43448bb3c28b434aa821c0c6e75d4c67d82acb1dad0788128a5b1761bae0ae45400d6
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: eed68edd632b78dea169e208162e4a041cfc1ed2a78c6593eebf55d27d2fe54d9161e1c65f21771cb66de2ef4e2e2ce92573569118e30e8a3148368ffaaafe53
         
     | 
| 
         @@ -0,0 +1,36 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            ---
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: Tests
         
     | 
| 
      
 3 
     | 
    
         
            +
            on:
         
     | 
| 
      
 4 
     | 
    
         
            +
              push:
         
     | 
| 
      
 5 
     | 
    
         
            +
                branches:
         
     | 
| 
      
 6 
     | 
    
         
            +
                - master
         
     | 
| 
      
 7 
     | 
    
         
            +
              pull_request:
         
     | 
| 
      
 8 
     | 
    
         
            +
                branches:
         
     | 
| 
      
 9 
     | 
    
         
            +
                - master
         
     | 
| 
      
 10 
     | 
    
         
            +
            jobs:
         
     | 
| 
      
 11 
     | 
    
         
            +
              test:
         
     | 
| 
      
 12 
     | 
    
         
            +
                runs-on: ubuntu-20.04
         
     | 
| 
      
 13 
     | 
    
         
            +
                strategy:
         
     | 
| 
      
 14 
     | 
    
         
            +
                  fail-fast: false
         
     | 
| 
      
 15 
     | 
    
         
            +
                  matrix:
         
     | 
| 
      
 16 
     | 
    
         
            +
                    include:
         
     | 
| 
      
 17 
     | 
    
         
            +
                    - ruby: 2.6.6
         
     | 
| 
      
 18 
     | 
    
         
            +
                      gemfile: Gemfile
         
     | 
| 
      
 19 
     | 
    
         
            +
                    - ruby: 2.7.2
         
     | 
| 
      
 20 
     | 
    
         
            +
                      gemfile: Gemfile
         
     | 
| 
      
 21 
     | 
    
         
            +
                    - ruby: 3.0.1
         
     | 
| 
      
 22 
     | 
    
         
            +
                      gemfile: Gemfile
         
     | 
| 
      
 23 
     | 
    
         
            +
                env:
         
     | 
| 
      
 24 
     | 
    
         
            +
                  BUNDLE_GEMFILE: "${{ matrix.gemfile }}"
         
     | 
| 
      
 25 
     | 
    
         
            +
                steps:
         
     | 
| 
      
 26 
     | 
    
         
            +
                - uses: actions/checkout@v2
         
     | 
| 
      
 27 
     | 
    
         
            +
                - name: Install ruby
         
     | 
| 
      
 28 
     | 
    
         
            +
                  uses: ruby/setup-ruby@v1
         
     | 
| 
      
 29 
     | 
    
         
            +
                  with:
         
     | 
| 
      
 30 
     | 
    
         
            +
                    ruby-version: "${{ matrix.ruby }}"
         
     | 
| 
      
 31 
     | 
    
         
            +
                - name: Bundle
         
     | 
| 
      
 32 
     | 
    
         
            +
                  run: |
         
     | 
| 
      
 33 
     | 
    
         
            +
                    gem install bundler:2.2.15
         
     | 
| 
      
 34 
     | 
    
         
            +
                    bundle install --no-deployment
         
     | 
| 
      
 35 
     | 
    
         
            +
                - name: Run tests
         
     | 
| 
      
 36 
     | 
    
         
            +
                  run: bundle exec rake spec
         
     | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/CHANGELOG.md
    ADDED
    
    | 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            All notable changes to this project will be documented in this file.
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            ## Unreleased
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            ### Breaking changes
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            - 
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            ### Compatible changes
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            -
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            ## 0.7.0 - 2021-05-04
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            ### Compatible changes
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            - add changelog
         
     | 
| 
      
 21 
     | 
    
         
            +
            - add gemika for tests with github actions
         
     | 
| 
      
 22 
     | 
    
         
            +
            - add Ruby 3 support
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            ## 0.6.0 - 2021-03-10
         
     | 
| 
      
 25 
     | 
    
         
            +
            ## 0.5.0 - 2021-03-09
         
     | 
| 
      
 26 
     | 
    
         
            +
            ## 0.4.0 - 2021-03-05
         
     | 
| 
      
 27 
     | 
    
         
            +
            ## 0.3.3 - 2021-03-05
         
     | 
| 
      
 28 
     | 
    
         
            +
            ## 0.3.2 - 2021-03-04 
         
     | 
| 
      
 29 
     | 
    
         
            +
            ## 0.3.1 - 2021-03-04
         
     | 
| 
      
 30 
     | 
    
         
            +
            ## 0.3.0 - 2021-03-04
         
     | 
| 
      
 31 
     | 
    
         
            +
            ## 0.2.3 - 2021-03-03
         
     | 
| 
      
 32 
     | 
    
         
            +
            ## 0.2.2 - 2021-03-03
         
     | 
| 
      
 33 
     | 
    
         
            +
            ## 0.2.1 - 2021-03-03 
         
     | 
    
        data/Gemfile
    CHANGED
    
    
    
        data/Gemfile.lock
    CHANGED
    
    | 
         @@ -1,15 +1,16 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            PATH
         
     | 
| 
       2 
2 
     | 
    
         
             
              remote: .
         
     | 
| 
       3 
3 
     | 
    
         
             
              specs:
         
     | 
| 
       4 
     | 
    
         
            -
                capybara-lockstep (0. 
     | 
| 
      
 4 
     | 
    
         
            +
                capybara-lockstep (0.7.0)
         
     | 
| 
       5 
5 
     | 
    
         
             
                  activesupport (>= 3.2)
         
     | 
| 
       6 
6 
     | 
    
         
             
                  capybara (>= 2.0)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  ruby2_keywords
         
     | 
| 
       7 
8 
     | 
    
         
             
                  selenium-webdriver (>= 3)
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
10 
     | 
    
         
             
            GEM
         
     | 
| 
       10 
11 
     | 
    
         
             
              remote: https://rubygems.org/
         
     | 
| 
       11 
12 
     | 
    
         
             
              specs:
         
     | 
| 
       12 
     | 
    
         
            -
                activesupport (6.1.3)
         
     | 
| 
      
 13 
     | 
    
         
            +
                activesupport (6.1.3.1)
         
     | 
| 
       13 
14 
     | 
    
         
             
                  concurrent-ruby (~> 1.0, >= 1.0.2)
         
     | 
| 
       14 
15 
     | 
    
         
             
                  i18n (>= 1.6, < 2)
         
     | 
| 
       15 
16 
     | 
    
         
             
                  minitest (>= 5.1)
         
     | 
| 
         @@ -17,6 +18,7 @@ GEM 
     | 
|
| 
       17 
18 
     | 
    
         
             
                  zeitwerk (~> 2.3)
         
     | 
| 
       18 
19 
     | 
    
         
             
                addressable (2.7.0)
         
     | 
| 
       19 
20 
     | 
    
         
             
                  public_suffix (>= 2.0.2, < 5.0)
         
     | 
| 
      
 21 
     | 
    
         
            +
                byebug (11.1.3)
         
     | 
| 
       20 
22 
     | 
    
         
             
                capybara (3.35.3)
         
     | 
| 
       21 
23 
     | 
    
         
             
                  addressable
         
     | 
| 
       22 
24 
     | 
    
         
             
                  mini_mime (>= 0.1.3)
         
     | 
| 
         @@ -26,16 +28,28 @@ GEM 
     | 
|
| 
       26 
28 
     | 
    
         
             
                  regexp_parser (>= 1.5, < 3.0)
         
     | 
| 
       27 
29 
     | 
    
         
             
                  xpath (~> 3.2)
         
     | 
| 
       28 
30 
     | 
    
         
             
                childprocess (3.0.0)
         
     | 
| 
      
 31 
     | 
    
         
            +
                chrome_remote (0.3.0)
         
     | 
| 
      
 32 
     | 
    
         
            +
                  websocket-driver (~> 0.6)
         
     | 
| 
       29 
33 
     | 
    
         
             
                concurrent-ruby (1.1.8)
         
     | 
| 
      
 34 
     | 
    
         
            +
                daemons (1.3.1)
         
     | 
| 
       30 
35 
     | 
    
         
             
                diff-lcs (1.3)
         
     | 
| 
       31 
     | 
    
         
            -
                 
     | 
| 
      
 36 
     | 
    
         
            +
                eventmachine (1.2.7)
         
     | 
| 
      
 37 
     | 
    
         
            +
                gemika (0.6.0)
         
     | 
| 
      
 38 
     | 
    
         
            +
                i18n (1.8.10)
         
     | 
| 
       32 
39 
     | 
    
         
             
                  concurrent-ruby (~> 1.0)
         
     | 
| 
       33 
     | 
    
         
            -
                 
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
      
 40 
     | 
    
         
            +
                jasmine (3.6.0)
         
     | 
| 
      
 41 
     | 
    
         
            +
                  jasmine-core (~> 3.6.0)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  phantomjs
         
     | 
| 
      
 43 
     | 
    
         
            +
                  rack (>= 1.2.1)
         
     | 
| 
      
 44 
     | 
    
         
            +
                  rake
         
     | 
| 
      
 45 
     | 
    
         
            +
                jasmine-core (3.6.0)
         
     | 
| 
      
 46 
     | 
    
         
            +
                mini_mime (1.1.0)
         
     | 
| 
      
 47 
     | 
    
         
            +
                mini_portile2 (2.5.1)
         
     | 
| 
       35 
48 
     | 
    
         
             
                minitest (5.14.4)
         
     | 
| 
       36 
     | 
    
         
            -
                nokogiri (1.11. 
     | 
| 
      
 49 
     | 
    
         
            +
                nokogiri (1.11.3)
         
     | 
| 
       37 
50 
     | 
    
         
             
                  mini_portile2 (~> 2.5.0)
         
     | 
| 
       38 
51 
     | 
    
         
             
                  racc (~> 1.4)
         
     | 
| 
      
 52 
     | 
    
         
            +
                phantomjs (2.1.1.0)
         
     | 
| 
       39 
53 
     | 
    
         
             
                public_suffix (4.0.6)
         
     | 
| 
       40 
54 
     | 
    
         
             
                racc (1.5.2)
         
     | 
| 
       41 
55 
     | 
    
         
             
                rack (2.2.3)
         
     | 
| 
         @@ -56,12 +70,20 @@ GEM 
     | 
|
| 
       56 
70 
     | 
    
         
             
                  diff-lcs (>= 1.2.0, < 2.0)
         
     | 
| 
       57 
71 
     | 
    
         
             
                  rspec-support (~> 3.7.0)
         
     | 
| 
       58 
72 
     | 
    
         
             
                rspec-support (3.7.0)
         
     | 
| 
      
 73 
     | 
    
         
            +
                ruby2_keywords (0.0.4)
         
     | 
| 
       59 
74 
     | 
    
         
             
                rubyzip (2.3.0)
         
     | 
| 
       60 
75 
     | 
    
         
             
                selenium-webdriver (3.142.7)
         
     | 
| 
       61 
76 
     | 
    
         
             
                  childprocess (>= 0.5, < 4.0)
         
     | 
| 
       62 
77 
     | 
    
         
             
                  rubyzip (>= 1.2.2)
         
     | 
| 
      
 78 
     | 
    
         
            +
                thin (1.8.0)
         
     | 
| 
      
 79 
     | 
    
         
            +
                  daemons (~> 1.0, >= 1.0.9)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  eventmachine (~> 1.0, >= 1.0.4)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  rack (>= 1, < 3)
         
     | 
| 
       63 
82 
     | 
    
         
             
                tzinfo (2.0.4)
         
     | 
| 
       64 
83 
     | 
    
         
             
                  concurrent-ruby (~> 1.0)
         
     | 
| 
      
 84 
     | 
    
         
            +
                websocket-driver (0.7.3)
         
     | 
| 
      
 85 
     | 
    
         
            +
                  websocket-extensions (>= 0.1.0)
         
     | 
| 
      
 86 
     | 
    
         
            +
                websocket-extensions (0.1.5)
         
     | 
| 
       65 
87 
     | 
    
         
             
                xpath (3.2.0)
         
     | 
| 
       66 
88 
     | 
    
         
             
                  nokogiri (~> 1.8)
         
     | 
| 
       67 
89 
     | 
    
         
             
                zeitwerk (2.4.2)
         
     | 
| 
         @@ -70,9 +92,14 @@ PLATFORMS 
     | 
|
| 
       70 
92 
     | 
    
         
             
              ruby
         
     | 
| 
       71 
93 
     | 
    
         | 
| 
       72 
94 
     | 
    
         
             
            DEPENDENCIES
         
     | 
| 
      
 95 
     | 
    
         
            +
              byebug
         
     | 
| 
       73 
96 
     | 
    
         
             
              capybara-lockstep!
         
     | 
| 
      
 97 
     | 
    
         
            +
              chrome_remote
         
     | 
| 
      
 98 
     | 
    
         
            +
              gemika
         
     | 
| 
      
 99 
     | 
    
         
            +
              jasmine
         
     | 
| 
       74 
100 
     | 
    
         
             
              rake (~> 13.0)
         
     | 
| 
       75 
101 
     | 
    
         
             
              rspec (~> 3.0)
         
     | 
| 
      
 102 
     | 
    
         
            +
              thin
         
     | 
| 
       76 
103 
     | 
    
         | 
| 
       77 
104 
     | 
    
         
             
            BUNDLED WITH
         
     | 
| 
       78 
     | 
    
         
            -
               2.2. 
     | 
| 
      
 105 
     | 
    
         
            +
               2.2.15
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -38,17 +38,13 @@ How capybara-lockstep helps 
     | 
|
| 
       38 
38 
     | 
    
         | 
| 
       39 
39 
     | 
    
         
             
            capybara-lockstep waits until the browser is idle before moving on to the next Capybara command. This greatly relieves the pressure on Capybara's retry logic.
         
     | 
| 
       40 
40 
     | 
    
         | 
| 
       41 
     | 
    
         
            -
            Whenever Capybara visits a new URL:
         
     | 
| 
      
 41 
     | 
    
         
            +
            Whenever Capybara visits a new URL or simulates a user interaction (clicking, typing, etc.):
         
     | 
| 
       42 
42 
     | 
    
         | 
| 
       43 
43 
     | 
    
         
             
            - capybara-lockstep waits for all document resources to load.
         
     | 
| 
       44 
44 
     | 
    
         
             
            - capybara-lockstep waits for client-side JavaScript to render or hydrate DOM elements.
         
     | 
| 
       45 
45 
     | 
    
         
             
            - capybara-lockstep waits for any AJAX requests.
         
     | 
| 
       46 
46 
     | 
    
         
             
            - capybara-lockstep waits for dynamically inserted `<script>`s to load (e.g. from [dynamic imports](https://webpack.js.org/guides/code-splitting/#dynamic-imports) or Analytics snippets).
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
            Whenever Capybara simulates a user interaction (clicking, typing, etc.):
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
            - capybara-lockstep waits for any AJAX requests.
         
     | 
| 
       51 
     | 
    
         
            -
            - capybara-lockstep waits for dynamically inserted `<script>`s to load (e.g. from [dynamic imports](https://webpack.js.org/guides/code-splitting/#dynamic-imports) or Analytics snippets).
         
     | 
| 
      
 47 
     | 
    
         
            +
            - capybara-lockstep waits for dynamically `<img>` or `<iframe>` elements to load.
         
     | 
| 
       52 
48 
     | 
    
         | 
| 
       53 
49 
     | 
    
         | 
| 
       54 
50 
     | 
    
         
             
            Installation
         
     | 
| 
         @@ -102,9 +98,9 @@ If you're not using Rails you can `include Capybara::Lockstep::Helper` and acces 
     | 
|
| 
       102 
98 
     | 
    
         | 
| 
       103 
99 
     | 
    
         
             
            ### Signaling the end of page initialization
         
     | 
| 
       104 
100 
     | 
    
         | 
| 
       105 
     | 
    
         
            -
            Most web applications run some JavaScript after  
     | 
| 
      
 101 
     | 
    
         
            +
            Most web applications run some JavaScript after a document has initially loaded. Such JavaScript usually enhances existing DOM elements ("hydration") or renders additional element into the DOM.
         
     | 
| 
       106 
102 
     | 
    
         | 
| 
       107 
     | 
    
         
            -
            capybara-lockstep  
     | 
| 
      
 103 
     | 
    
         
            +
            capybara-lockstep will synchronize more reliably if you signal when your JavaScript is done rendering the initial document. After the initial rendering, capybara-lockstep will automatically detect when the browser is busy, even if content is changed dynamically later.
         
     | 
| 
       108 
104 
     | 
    
         | 
| 
       109 
105 
     | 
    
         
             
            To signal that JavaScript is still initializing, your application layouts should render the `<body>` element with an `[data-initializing]` attribute:
         
     | 
| 
       110 
106 
     | 
    
         | 
| 
         @@ -112,10 +108,14 @@ To signal that JavaScript is still initializing, your application layouts should 
     | 
|
| 
       112 
108 
     | 
    
         
             
            <body data-initializing>
         
     | 
| 
       113 
109 
     | 
    
         
             
            ```
         
     | 
| 
       114 
110 
     | 
    
         | 
| 
       115 
     | 
    
         
            -
            Your application JavaScript should remove the `[data-initializing]` attribute when it is done  
     | 
| 
      
 111 
     | 
    
         
            +
            Your application JavaScript should remove the `[data-initializing]` attribute when it is done rendering the initial page.
         
     | 
| 
       116 
112 
     | 
    
         | 
| 
       117 
113 
     | 
    
         
             
            More precisely, the attribute should be removed in the same [JavaScript task](https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/) ("tick") that will finish initializing. capybara-lockstep will assume that the page will be initialized by the end of this task.
         
     | 
| 
       118 
114 
     | 
    
         | 
| 
      
 115 
     | 
    
         
            +
            **After the initial rendering, capybara-lockstep will automatically detect when the browser is busy, even if content is changed dynamically later. After the initial page load you no longer need to add or remove the `[data-initializing]` attribute.**
         
     | 
| 
      
 116 
     | 
    
         
            +
             
     | 
| 
      
 117 
     | 
    
         
            +
            #### Example: Vanilla JS
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
       119 
119 
     | 
    
         
             
            If all your initializing JavaScript runs synchronously on `DOMContentLoaded`, you can remove `[data-initializing]` in an event handler:
         
     | 
| 
       120 
120 
     | 
    
         | 
| 
       121 
121 
     | 
    
         
             
            ```js
         
     | 
| 
         @@ -125,26 +125,41 @@ document.addEventListener('DOMContentLoaded', function() { 
     | 
|
| 
       125 
125 
     | 
    
         
             
            })
         
     | 
| 
       126 
126 
     | 
    
         
             
            ```
         
     | 
| 
       127 
127 
     | 
    
         | 
| 
       128 
     | 
    
         
            -
            If you  
     | 
| 
      
 128 
     | 
    
         
            +
            If you call libraries during initialization, you may need to check the library code to see whether it finishes synchronously or asynchronously. Ideally a library offers a callback to notify you when it is done rendering:
         
     | 
| 
       129 
129 
     | 
    
         | 
| 
       130 
130 
     | 
    
         
             
            ```js
         
     | 
| 
       131 
131 
     | 
    
         
             
            document.addEventListener('DOMContentLoaded', function() {
         
     | 
| 
       132 
     | 
    
         
            -
               
     | 
| 
       133 
     | 
    
         
            -
                 
     | 
| 
       134 
     | 
    
         
            -
             
     | 
| 
      
 132 
     | 
    
         
            +
              Libary.initialize({
         
     | 
| 
      
 133 
     | 
    
         
            +
                onFinished: function() {
         
     | 
| 
      
 134 
     | 
    
         
            +
                  document.body.removeAttribute('data-initializing')
         
     | 
| 
      
 135 
     | 
    
         
            +
                }
         
     | 
| 
       135 
136 
     | 
    
         
             
              })
         
     | 
| 
       136 
137 
     | 
    
         
             
            })
         
     | 
| 
       137 
138 
     | 
    
         
             
            ```
         
     | 
| 
       138 
139 
     | 
    
         | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
      
 140 
     | 
    
         
            +
            When a library offers no such callback, but you see in its code that the library delays work for a task, you must also wait another task to remove `[data-initializing]`:
         
     | 
| 
       140 
141 
     | 
    
         | 
| 
       141 
142 
     | 
    
         
             
            ```js
         
     | 
| 
       142 
143 
     | 
    
         
             
            document.addEventListener('DOMContentLoaded', function() {
         
     | 
| 
       143 
     | 
    
         
            -
              Libary. 
     | 
| 
      
 144 
     | 
    
         
            +
              Libary.initialize()
         
     | 
| 
       144 
145 
     | 
    
         
             
              setTimeout(function() { document.body.removeAttribute('data-initializing') })
         
     | 
| 
       145 
146 
     | 
    
         
             
            })
         
     | 
| 
       146 
147 
     | 
    
         
             
            ```
         
     | 
| 
       147 
148 
     | 
    
         | 
| 
      
 149 
     | 
    
         
            +
            If your initialization code lazy-loads another script, you should only remove `[data-initializing]` once that is done:
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
            ```js
         
     | 
| 
      
 152 
     | 
    
         
            +
            document.addEventListener('DOMContentLoaded', function() {
         
     | 
| 
      
 153 
     | 
    
         
            +
              import('huge-library').then(function({ HugeLibrary }) {
         
     | 
| 
      
 154 
     | 
    
         
            +
                HugeLibrary.initialize()
         
     | 
| 
      
 155 
     | 
    
         
            +
                document.body.removeAttribute('data-initializing')
         
     | 
| 
      
 156 
     | 
    
         
            +
              })
         
     | 
| 
      
 157 
     | 
    
         
            +
            })
         
     | 
| 
      
 158 
     | 
    
         
            +
            ```
         
     | 
| 
      
 159 
     | 
    
         
            +
             
     | 
| 
      
 160 
     | 
    
         
            +
             
     | 
| 
      
 161 
     | 
    
         
            +
            #### Example: Unpoly
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
       148 
163 
     | 
    
         
             
            When you're using [Unpoly](https://unpoly.com/) initializing will usually happen synchronously in [compilers](https://unpoly.com/up.compiler). Hence a compiler is a good place to remove `[data-initializing]`:
         
     | 
| 
       149 
164 
     | 
    
         | 
| 
       150 
165 
     | 
    
         
             
            ```js
         
     | 
| 
         @@ -153,6 +168,8 @@ up.compiler('body', function(body) { 
     | 
|
| 
       153 
168 
     | 
    
         
             
            })
         
     | 
| 
       154 
169 
     | 
    
         
             
            ```
         
     | 
| 
       155 
170 
     | 
    
         | 
| 
      
 171 
     | 
    
         
            +
            #### Example: AngularJS 1
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
       156 
173 
     | 
    
         
             
            When you're using [AngularJS 1](https://unpoly.com/) initializing will usually happen synchronously in [directives](https://docs.angularjs.org/guide/directive). Hence a directive is a good place to remove `[data-initializing]`:
         
     | 
| 
       157 
174 
     | 
    
         | 
| 
       158 
175 
     | 
    
         
             
            ```js
         
     | 
| 
         @@ -173,9 +190,9 @@ capybara-lockstep will automatically patch Capybara to wait for the browser afte 
     | 
|
| 
       173 
190 
     | 
    
         
             
            Run your test suite to see if integration was successful and whether stability improves. During validation we recommend to activate `Capybara::Lockstep.debug = true` in your `spec_helper.rb` (RSpec) or `env.rb` (Cucumber). You should see messages like this in your console:
         
     | 
| 
       174 
191 
     | 
    
         | 
| 
       175 
192 
     | 
    
         
             
            ```text
         
     | 
| 
       176 
     | 
    
         
            -
            [ 
     | 
| 
       177 
     | 
    
         
            -
            [ 
     | 
| 
       178 
     | 
    
         
            -
            [ 
     | 
| 
      
 193 
     | 
    
         
            +
            [capybara-lockstep] Synchronizing
         
     | 
| 
      
 194 
     | 
    
         
            +
            [capybara-lockstep] Finished waiting for JavaScript
         
     | 
| 
      
 195 
     | 
    
         
            +
            [capybara-lockstep] Synchronized successfully
         
     | 
| 
       179 
196 
     | 
    
         
             
            ```
         
     | 
| 
       180 
197 
     | 
    
         | 
| 
       181 
198 
     | 
    
         
             
            Note that you may see some failures from tests with wrong assertions, which sometimes passed due to lucky timing.
         
     | 
| 
         @@ -192,30 +209,52 @@ In casual testing I experienced a performance impact between +/- 10%. 
     | 
|
| 
       192 
209 
     | 
    
         | 
| 
       193 
210 
     | 
    
         
             
            ## Debugging log
         
     | 
| 
       194 
211 
     | 
    
         | 
| 
       195 
     | 
    
         
            -
            capybara-lockstep  
     | 
| 
      
 212 
     | 
    
         
            +
            You can enable extensive logging. This is useful to see whether capybara-lockstep has an effect on your tests, or to debug why synchronization is taking too long.
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
            To enable the log, say this before or during a test:
         
     | 
| 
       196 
215 
     | 
    
         | 
| 
       197 
216 
     | 
    
         
             
            ```ruby
         
     | 
| 
       198 
217 
     | 
    
         
             
            Capybara::Lockstep.debug = true
         
     | 
| 
       199 
218 
     | 
    
         
             
            ```
         
     | 
| 
       200 
219 
     | 
    
         | 
| 
       201 
     | 
    
         
            -
            You should now see messages like this  
     | 
| 
      
 220 
     | 
    
         
            +
            You should now see messages like this on your standard output:
         
     | 
| 
       202 
221 
     | 
    
         | 
| 
       203 
222 
     | 
    
         
             
            ```
         
     | 
| 
       204 
     | 
    
         
            -
            [ 
     | 
| 
       205 
     | 
    
         
            -
            [ 
     | 
| 
       206 
     | 
    
         
            -
            [ 
     | 
| 
      
 223 
     | 
    
         
            +
            [capybara-lockstep] Synchronizing
         
     | 
| 
      
 224 
     | 
    
         
            +
            [capybara-lockstep] Finished waiting for JavaScript
         
     | 
| 
      
 225 
     | 
    
         
            +
            [capybara-lockstep] Synchronized successfully
         
     | 
| 
       207 
226 
     | 
    
         
             
            ```
         
     | 
| 
       208 
227 
     | 
    
         | 
| 
      
 228 
     | 
    
         
            +
            You should also see messages like this in your browser's JavaScript console:
         
     | 
| 
      
 229 
     | 
    
         
            +
             
     | 
| 
      
 230 
     | 
    
         
            +
            ```
         
     | 
| 
      
 231 
     | 
    
         
            +
            [capybara-lockstep] Started work: fetch /path [3 jobs]
         
     | 
| 
      
 232 
     | 
    
         
            +
            [capybara-lockstep] Finished work: fetch /path [2 jobs]
         
     | 
| 
      
 233 
     | 
    
         
            +
            ```
         
     | 
| 
      
 234 
     | 
    
         
            +
             
     | 
| 
      
 235 
     | 
    
         
            +
             
     | 
| 
      
 236 
     | 
    
         
            +
            ### Using a logger
         
     | 
| 
      
 237 
     | 
    
         
            +
             
     | 
| 
       209 
238 
     | 
    
         
             
            You may also configure logging to an existing logger object:
         
     | 
| 
       210 
239 
     | 
    
         | 
| 
       211 
240 
     | 
    
         
             
            ```ruby
         
     | 
| 
       212 
241 
     | 
    
         
             
            Capybara::Lockstep.debug = Rails.logger
         
     | 
| 
       213 
242 
     | 
    
         
             
            ```
         
     | 
| 
       214 
243 
     | 
    
         | 
| 
      
 244 
     | 
    
         
            +
            ### Logging in the browser only
         
     | 
| 
      
 245 
     | 
    
         
            +
             
     | 
| 
      
 246 
     | 
    
         
            +
            To enable logging in the browser console (but not STDOUT), include the snippet with `{ debug: true }`:
         
     | 
| 
      
 247 
     | 
    
         
            +
             
     | 
| 
      
 248 
     | 
    
         
            +
            ```
         
     | 
| 
      
 249 
     | 
    
         
            +
            capybara_lockstep(debug: true)
         
     | 
| 
      
 250 
     | 
    
         
            +
            ```
         
     | 
| 
      
 251 
     | 
    
         
            +
             
     | 
| 
       215 
252 
     | 
    
         | 
| 
       216 
253 
     | 
    
         
             
            ## Disabling synchronization
         
     | 
| 
       217 
254 
     | 
    
         | 
| 
       218 
     | 
    
         
            -
             
     | 
| 
      
 255 
     | 
    
         
            +
            Sometimes you want to disable browser synchronization, e.g. to observe a loading spinner during a long-running request.
         
     | 
| 
      
 256 
     | 
    
         
            +
             
     | 
| 
      
 257 
     | 
    
         
            +
            To disable synchronization:
         
     | 
| 
       219 
258 
     | 
    
         | 
| 
       220 
259 
     | 
    
         
             
            ```ruby
         
     | 
| 
       221 
260 
     | 
    
         
             
            begin
         
     | 
| 
         @@ -226,9 +265,11 @@ ensure 
     | 
|
| 
       226 
265 
     | 
    
         
             
            end
         
     | 
| 
       227 
266 
     | 
    
         
             
            ```
         
     | 
| 
       228 
267 
     | 
    
         | 
| 
       229 
     | 
    
         
            -
            ##  
     | 
| 
      
 268 
     | 
    
         
            +
            ## Synchronization timeout
         
     | 
| 
      
 269 
     | 
    
         
            +
             
     | 
| 
      
 270 
     | 
    
         
            +
            By default capybara-lockstep will wait `Capybara.default_max_wait_time` seconds for the page initialize and for JavaScript and AJAX request to finish.
         
     | 
| 
       230 
271 
     | 
    
         | 
| 
       231 
     | 
    
         
            -
             
     | 
| 
      
 272 
     | 
    
         
            +
            When synchronization times out, capybara-lockstep will log but not raise an error.
         
     | 
| 
       232 
273 
     | 
    
         | 
| 
       233 
274 
     | 
    
         
             
            You can configure a different timeout:
         
     | 
| 
       234 
275 
     | 
    
         | 
| 
         @@ -236,70 +277,82 @@ You can configure a different timeout: 
     | 
|
| 
       236 
277 
     | 
    
         
             
            Capybara::Lockstep.timeout = 5 # seconds
         
     | 
| 
       237 
278 
     | 
    
         
             
            ```
         
     | 
| 
       238 
279 
     | 
    
         | 
| 
       239 
     | 
    
         
            -
             
     | 
| 
      
 280 
     | 
    
         
            +
            To revert to defaulting to `Capybara.default_max_wait_time`, set the timeout to `nil`:
         
     | 
| 
       240 
281 
     | 
    
         | 
| 
       241 
     | 
    
         
            -
             
     | 
| 
      
 282 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 283 
     | 
    
         
            +
            Capybara::Lockstep.timeout = nil
         
     | 
| 
      
 284 
     | 
    
         
            +
            ```
         
     | 
| 
       242 
285 
     | 
    
         | 
| 
       243 
     | 
    
         
            -
            For additional edge cases you may interact with capybara-lockstep from your Ruby code.
         
     | 
| 
       244 
286 
     | 
    
         | 
| 
      
 287 
     | 
    
         
            +
            ## Manual synchronization
         
     | 
| 
       245 
288 
     | 
    
         | 
| 
       246 
     | 
    
         
            -
             
     | 
| 
      
 289 
     | 
    
         
            +
            capybara-lockstep will automatically patch Capybara to wait for the browser after every command. **This should be enough for most test suites**.
         
     | 
| 
       247 
290 
     | 
    
         | 
| 
       248 
     | 
    
         
            -
             
     | 
| 
      
 291 
     | 
    
         
            +
            For additional edge cases you may manually tell capybara-lockstep to wait. The following Ruby method will block until the browser is idle:
         
     | 
| 
       249 
292 
     | 
    
         | 
| 
       250 
293 
     | 
    
         
             
            ```ruby
         
     | 
| 
       251 
294 
     | 
    
         
             
            Capybara::Lockstep.synchronize
         
     | 
| 
       252 
295 
     | 
    
         
             
            ```
         
     | 
| 
       253 
296 
     | 
    
         | 
| 
       254 
     | 
    
         
            -
             
     | 
| 
      
 297 
     | 
    
         
            +
            You may also synchronize from your client-side JavaScript. The following will run the given callback once the browser is idle:
         
     | 
| 
       255 
298 
     | 
    
         | 
| 
       256 
     | 
    
         
            -
            ``` 
     | 
| 
       257 
     | 
    
         
            -
             
     | 
| 
       258 
     | 
    
         
            -
             
     | 
| 
       259 
     | 
    
         
            -
             
     | 
| 
      
 299 
     | 
    
         
            +
            ```js
         
     | 
| 
      
 300 
     | 
    
         
            +
            CapybaraLockstep.synchronize(callback)
         
     | 
| 
      
 301 
     | 
    
         
            +
            ```
         
     | 
| 
      
 302 
     | 
    
         
            +
             
     | 
| 
      
 303 
     | 
    
         
            +
            ## Signaling asynchronous work
         
     | 
| 
      
 304 
     | 
    
         
            +
             
     | 
| 
      
 305 
     | 
    
         
            +
            If for some reason you want capybara-lockstep to consider additional asynchronous work as "busy", you can do so:
         
     | 
| 
      
 306 
     | 
    
         
            +
             
     | 
| 
      
 307 
     | 
    
         
            +
            ```js
         
     | 
| 
      
 308 
     | 
    
         
            +
            CapybaraLockstep.startWork('Eject warp core')
         
     | 
| 
      
 309 
     | 
    
         
            +
            doAsynchronousWork().then(function() {
         
     | 
| 
      
 310 
     | 
    
         
            +
              CapybaraLockstep.stopWork('Eject warp core')
         
     | 
| 
      
 311 
     | 
    
         
            +
            })
         
     | 
| 
      
 312 
     | 
    
         
            +
            ```
         
     | 
| 
      
 313 
     | 
    
         
            +
             
     | 
| 
      
 314 
     | 
    
         
            +
            The string argument is used for logging (when logging is enabled). It does **not** need to be unique per job. In this case you should see messages like this in your browser's JavaScript console:
         
     | 
| 
      
 315 
     | 
    
         
            +
             
     | 
| 
      
 316 
     | 
    
         
            +
            ```text
         
     | 
| 
      
 317 
     | 
    
         
            +
            [capybara-lockstep] Started work: Eject warp core [1 jobs]
         
     | 
| 
      
 318 
     | 
    
         
            +
            [capybara-lockstep] Finished work: Eject warp core [0 jobs]
         
     | 
| 
       260 
319 
     | 
    
         
             
            ```
         
     | 
| 
       261 
320 
     | 
    
         | 
| 
       262 
     | 
    
         
            -
             
     | 
| 
      
 321 
     | 
    
         
            +
            You may omit the string argument, in which case nothing will be logged, but the work will still be tracked.
         
     | 
| 
       263 
322 
     | 
    
         | 
| 
       264 
     | 
    
         
            -
            capybara-lockstep already hooks into [many JavaScript APIs](#how-capybara-lockstep-helps) like `XMLHttpRequest` or `fetch()` to mark the browser as "busy" until their work finishes. **This should be enough for most test suites**.
         
     | 
| 
       265 
323 
     | 
    
         | 
| 
       266 
     | 
    
         
            -
             
     | 
| 
      
 324 
     | 
    
         
            +
            ## Note on interacting with the JavaScript API
         
     | 
| 
       267 
325 
     | 
    
         | 
| 
       268 
     | 
    
         
            -
             
     | 
| 
      
 326 
     | 
    
         
            +
            If you only load capybara-lockstep in tests you, should check for the `CapybaraLockstep` global to be defined before you interact with the JavaScript API.
         
     | 
| 
       269 
327 
     | 
    
         | 
| 
       270 
328 
     | 
    
         
             
            ```js
         
     | 
| 
       271 
329 
     | 
    
         
             
            if (window.CapybaraLockstep) {
         
     | 
| 
       272 
     | 
    
         
            -
              CapybaraLockstep 
     | 
| 
      
 330 
     | 
    
         
            +
              // interact with CapybaraLockstep
         
     | 
| 
       273 
331 
     | 
    
         
             
            }
         
     | 
| 
       274 
332 
     | 
    
         
             
            ```
         
     | 
| 
       275 
333 
     | 
    
         | 
| 
       276 
     | 
    
         
            -
             
     | 
| 
      
 334 
     | 
    
         
            +
            ## Handling legacy promises
         
     | 
| 
       277 
335 
     | 
    
         | 
| 
       278 
     | 
    
         
            -
             
     | 
| 
      
 336 
     | 
    
         
            +
            Legacy promise implementations (like jQuery's `$.Deferred` and AngularJS' `$q`) work using tasks instead of microtasks. Their AJAX implementations (like `$.ajax()` and `$http`) use these promises to signal that a request is done.
         
     | 
| 
      
 337 
     | 
    
         
            +
             
     | 
| 
      
 338 
     | 
    
         
            +
            This means there is a time window in which all AJAX requests have finished, but their callbacks have not yet run:
         
     | 
| 
       279 
339 
     | 
    
         | 
| 
       280 
340 
     | 
    
         
             
            ```js
         
     | 
| 
       281 
     | 
    
         
            -
             
     | 
| 
       282 
     | 
    
         
            -
             
     | 
| 
       283 
     | 
    
         
            -
              CapybaraLockstep.stopWork()
         
     | 
| 
      
 341 
     | 
    
         
            +
            $.ajax('/foo').then(function() {
         
     | 
| 
      
 342 
     | 
    
         
            +
              // This callback runs one task after the response was received
         
     | 
| 
       284 
343 
     | 
    
         
             
            })
         
     | 
| 
       285 
344 
     | 
    
         
             
            ```
         
     | 
| 
       286 
345 
     | 
    
         | 
| 
       287 
     | 
    
         
            -
             
     | 
| 
       288 
     | 
    
         
            -
             
     | 
| 
       289 
     | 
    
         
            -
            You can query capybara-lockstep whether it considers the browser to be busy or idle:
         
     | 
| 
      
 346 
     | 
    
         
            +
            It is theoretically possible that your test will observe the browser in that window, and expect content that has not been rendered yet. This will usually be mitigated by Capybara's retry logic. **If** you think that this is an issue for your test suite, you can configure capybara-headless to wait additional tasks before it considers the browser to be idle:
         
     | 
| 
       290 
347 
     | 
    
         | 
| 
       291 
348 
     | 
    
         
             
            ```js
         
     | 
| 
       292 
     | 
    
         
            -
             
     | 
| 
       293 
     | 
    
         
            -
            CapybaraLockstep.isIdle() // => true
         
     | 
| 
      
 349 
     | 
    
         
            +
            Capybara:Lockstep.wait_tasks = 1
         
     | 
| 
       294 
350 
     | 
    
         
             
            ```
         
     | 
| 
       295 
351 
     | 
    
         | 
| 
       296 
     | 
    
         
            -
             
     | 
| 
      
 352 
     | 
    
         
            +
            If you see longer `then()` chains in your code, you may need to configure a higher number of tasks to wait.
         
     | 
| 
       297 
353 
     | 
    
         | 
| 
       298 
     | 
    
         
            -
            This will  
     | 
| 
      
 354 
     | 
    
         
            +
            This will have a negative performance impact on your test suite.
         
     | 
| 
       299 
355 
     | 
    
         | 
| 
       300 
     | 
    
         
            -
            ```js
         
     | 
| 
       301 
     | 
    
         
            -
            CapybaraLockstep.synchronize(callback)
         
     | 
| 
       302 
     | 
    
         
            -
            ```
         
     | 
| 
       303 
356 
     | 
    
         | 
| 
       304 
357 
     | 
    
         
             
            ## Development
         
     | 
| 
       305 
358 
     | 
    
         |