All notable changes to this project will be documented in this file.
This project adheres to Semantic Versioning.
- We now only wait for
<script>
elements with a JavaScript type - We only wait for
<iframe>
elements with a[src]
attribute - We no longer wait for
<video>
and<audio>
elements to load their metadata. This did not work consistently, and would sometimes cause capybara-lockstep to wait indefinitely.
- Fixed a bug that disabled most functionality for drivers with
browser: :remote
.
- We now wait for
<video>
and<audio>
elements to load their metadata. This addresses a race condition where a media element is inserted into the DOM, but another user action deletes or renames the source before the browser could load the initial metadata frames. - We now wait for
<script type="module">
. - We no longer wait for
<img loading="lazy">
or<iframe loading="lazy">
. This prevents a deadlock where we would wait forever for an element that defers loading until it is scrolled into the viewport.
- We now synchronize for an additional JavaScript task after
history.pushState()
,history.replaceState()
,history.forward()
,history.back()
andhistory.go()
. - We now synchronize for an additional JavaScript task after
popstate
andhashchange
events. - We now synchronize for an additional JavaScript task when the window is resized.
- You can now disable automatic synchronization for the duration of a block:
Capybara::Lockstep.with_mode(:manual) { ... }
.
- Fix a bug where we wouldn't wait for an additional JavaScript task after a tracked event or async job.
- Fix a bug where the
Capybara::Lockstep.wait_tasks
configuration would be ignored. - Fix a bug where the
capybara_lockstep_js
helper (for use without Rails) would not include the current configuration.
- Fix a bug where setting a logger object with
Capybara::Lockstep.debug = logger
would crash (by @dorianmarie).
- Don't crash when an interaction closes the window (tab).
This major release detects many additional sources of flaky tests:
- We now synchronize before a user interaction. Previously we only synchronized before an observation. This could lead to race conditions when a test chained multiple interactions without making an observation in between.
- We now synchronize after a user interaction (e.g. after a click). Previously we only synchronized before an observation. This could lead to race conditions when a test made assertions without going through Capybara, e.g. by accessing the database or global state variables.
- When a job ends (e.g. an AJAX request finishes) we now wait for one JavaScript task. This gives event listeners more time to schedule new async work.
- We now wait one JavaScript task after
touchstart
,mousedown
,click
andkeydown
events. This gives event listeners more time to schedule async work after a user interaction. - You can now wait while the backend server is busy, by using
Capybara::Lockstep::Middleware
in your Rails or Rack app. We previously only waited for AJAX requests on the client, but using the middleware addresses some additional edge cases. For example, the middleware detects requests that were aborted on the frontend, but are still being processed by the backend. - You can signal async work from the backend, e.g. for background jobs. Note that you don't need to signal work for the regular request/response cycle, as this is detected automatically.
Although we now cover a lot more edge cases, this releases will not slow down your test suite considerably.
Now synchronizes before and after evaluate_script
.
Previously we only synchronized around execute_script
and evaluate_async_script
.
You can configure a proc to run after successful synchronization:
Capybara::Lockstep.after_synchronize do
puts "Synchronized!"
end
- Synchronize with pages constructed from non-empty data URLs
We now synchronize before and after history navigation using the following Capybara methods:
page.refresh
page.go_back
page.go_forward
We also synchronize before current_url
in case running a JavaScript task wants to update the URL when done.
capybara-lockstep now supports test that work with multiple frames or multiple tabs or windows. We now synchronize before and after the following Capybara methods:
switch_to_frame
within_frame
switch_to_window
within_window
- Only log when we're actually synchronizing
- Log the reason why we're synchronizing (e.g. before node access)
- Log which browser work we're waiting for (e.g. XHR request, image load)
- Synchronize before accessing
page.html
.
- Activate rubygems MFA
- Stop handling of
[data-initializing]
attribute. Apps that have late initialization after theload
event can just useCapybaraLockstep.startWork()
. - Remove useless tracking of interaction events like
"click"
or"focus"
. If such an event handler would start an AJAX request, it is already tracked. - On apps with Unpoly 0.x, wait for one more task after
DOMContentLoaded
. Please upgrade to Unpoly 1.x or 2.x, as this logic will be removed in a year or so.
- First stable release.
- Replace option
Capybara::Lockstep.config
(true
,false
) with a more refined option.mode
(:auto
,:manual
,:off
)
- Ruby 3 compatibility.
- Fix logging.
- Synchronize around
evaluate_script
andexecute_script
. - Improve logging.
- Allow developer to signal custom async work.
- Option to wait additional tasks, to handle legacy promise implementations.
- Debugging log can be enabled during a running test.
- Also wait for images and iframes.
- Don't fail the test when synchronization times out.
- Capybara::Lockstep.debug = true will now also enable client-side logging on the browser's JavaScript console.
- Always wait at least for
Capybara.default_max_wait_time
.
- Delay synchronization when an alert is open (instead of failing)
- Fix typo in log message
- Rework entire waiting logic to be lazy.
- There is now a single method
Capybara::Lockstep.synchronize
(no distinction between awaiting "initialization" and "idle").
- When we cannot wait for browser idle due to an open alert, wait before the next Capybara synchronize
- Fix incorrect data in gemspec.
- Internal changes.
- Initial release.