Read more

Nested Spreewald patiently blocks are now patient

Henning Koch
February 09, 2018Software engineer at makandra GmbH

In Spreewald 1.10.4+, nested patiently blocks are now patient.

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

Here is an example:

patiently do
  outer_code
  patiently do
    inner_code
  end
end

On spreewald 1.11.2+ the inner block will wait for the full configured wait time (by default 5 seconds). The outer patiently block would now be out of time, but it will always be retried at least a second time. This behavior allows with_scope to be patient, and it must be patient, as explained below.

In versions 1.10.4 - 1.11.1, inner blocks would keep giving the outer block additional time to finish, which solves the same issues, but as a downside can cause the whole step to take extremely long if it was actually supposed to fail.

In even earlier versions of Spreewald the outer patiently would wait for 5 seconds and all inner patientlys would not wait at all.

with_scope must be patient

Since 90% of the time you will have nested patiently block is when using with_scope (Cucumber: ... within ...), here is some information about this issue:

Using with_scope without patiently will sometimes break:

with_scope('.container') do  # => this caches the container element
                             # => here JavaScript swaps the container element
  page.find('.child')        # => tries to find a child of the previously cached container
                             # => Selenium explodes because the container is detached from the DOM
end

Unfortunately we cannot fix this by making sure that the element exists before we enter with_scope:

patiently do
  expect(page).to have_css('.container') # => asserts that a container element is on the page
end

with_scope('.container') do  # => this caches the container element
                             # => here JavaScript swaps the container element
  page.find('.child')        # => tries to find a child of the previously cached container
                             # => Selenium explodes because the container is detached from the DOM
end

The only way to make this work is wrap it in patiently:

patiently do
  with_scope('.container') do
    page.find('.child')
  end  
end

This used to be an issue with how nested patiently blocks worked in the past.

In Spreewald 1.10.4+ the ... within ... step is patient again.

Posted by Henning Koch to makandra dev (2018-02-09 12:33)