A weird Capybara error in `within` block

Andrea Longhi

26 Jun 2019 Development, Solidus, Open Source

Andrea Longhi

3 mins
A weird Capybara error in `within` block

At Nebulab we are encouraged in [spending Fridays][playbook-friday] on open source projects, and I simply love it.

[Solidus eCommerce ecosystem][solidusio] and [its extensions][solidusio-contrib] is where I usually hang out, you never get bored with so many different projects and things to do.

A few Fridays ago I started working on a [flaky spec][flaky-spec] that failed often on Solidus CI builds. This is pretty annoying as flaky failures mean the test suite must be run again with the usual consequences of uncertainty of results, wasted time, longer queues, wasted CPU time, CO2 buildup, seven years of famine and hordes of locusts (not necessarily in this order).

Most of the times flaky specs happen on Selenium tests, where JS interactions may take a bit more time to complete and some parts of the HTML may not be yet present or visible (want another example from Solidus codebase? [Here you are][another-flaky-spec]). But this time it was different: the spec failed with Rack::Test, which is usually very deterministic by nature, no javascript interaction was involved, so I was quite puzzled about it.

The error

This is the relevant code of the tentative spec:

it "can sort desc" do
  within_table(table_id) do
    click_link sort_link, exact: false
    expect(page).to have_selector '.sort_link.desc'
  end
end

It basically clicks on the sorting triangle icon visible in this screenshot:

solidus admin sorting before click

and checks that the triangle sorting direction has changed (this happens with a page refresh, no JS involved):

solidus admin sorting after click

Quite surprisingly, this spec fails with the current version of Capybara (3.13.2):

expected to find css ".sort_link.desc" within #<Capybara::Node::Element tag="table" path="/html/body/div[5]/div/div/fieldset/table"> but there were no matches

If you change Capybara driver to Firefox or Chrome, for example by changing the first line to:

it "can sort desc”, :js do

then the spec passes without errors, so it must be an issue with Rack::Test. After digging a bit inside Capybara source code I confirmed that what happens here is that the Capybara node that represents the HTML of the selected table is not refreshed after the page reload, so changes that happen within that block are not visible.

The fix

There’s an easy workaround that solves this issue: you just need to close the within block after clicking the link and reopening it before checking the page, actively forcing Capybara to reload the HTML block from the table:

it "can sort desc" do
  within_table(table_id) do
    click_link sort_link, exact: false
  end
  within_table(table_id) do
    expect(page).to have_selector '.sort_link.desc'
  end
end

OSS Collaboration

I won't claim to be the first man on earth that encountered this issue, but I think it's quite rare as nobody here at Nebulab had seen this before, and also a few internet searches did not bring any results to me. This bug is barely worth noticing, the fix is very simple and makes perfect sense: if you need the node to be updated, just close and reopen the block. Still, I decided it was worth digging a bit deeper and notify the [Capybara team][capybara-issue] about the issue. After a few days they fixed it. I think this is a good example of [OSS][oss] cooperation between different projects, this kind of interactions are good for the community as they lead to improvements that will benefit everybody. Years ago I was amazed by the simple truth of this quote from (or [maybe not?][maybe-not]) [George Bernard Shaw][gb-shaw]:

If you have an apple and I have an apple and we exchange these apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. I think that software is more like ideas than apples, as it's much easier to do good to others while still pursuing your (selfish) interest: if I share my apple with you, we both have only half an apple. But if I write some software and share it with you, then we both can benefit from the code. Happy coding! [flaky-spec]: https://github.com/solidusio/solidus/pull/3089 [another-flaky-spec]: https://github.com/solidusio/solidus/pull/3110#issuecomment-466177067 [playbook-friday]: https://playbook.nebulab.com/personal-growth/fridays/ [solidusio]: https://github.com/solidusio [solidusio-contrib]: https://github.com/solidusio-contrib [capybara-issue]: https://github.com/teamcapybara/capybara/issues/2157 [oss]: https://en.wikipedia.org/wiki/Open-source_software [maybe-not]: https://quoteinvestigator.com/2011/12/13/swap-ideas/ [gb-shaw]: https://en.wikipedia.org/wiki/George_Bernard_Shaw

You may also like

Let’s redefine
eCommerce together.