jquerycssruby-on-railscapybaracapybara-webkit

Capybara Webkit not detecting CSS updates when DOM changes


I have a floating menu that pops up when a user clicks on a menu button (button is hidden behind the floating menu in the image below).

enter image description here

The functionality works fine in a live browser (tried it on Firefox, Safari, and Chrome).

However it doesn't seem to work when testing with Capybara-Webkit - the menu never becomes visible on click

Here's the basic implementation:

HTML

The menu is a <ul> that sits inside a <div>

<div class="location-card">
  ...

  <div class="location-card__menu-btn">
    <%= inline_svg("icons/menu-btn-icon.svg", height: "20px", width: "20px") %>

    <ul class="location-card__menu">
      <li>Delete</li>
      <li>Open</li>
      <li>Share</li>
      ...
    </ul>
  </div>
</div>

JS

Simple javascript/jquery sets a toggle class (location-card--menu-open) on the top-level <div> whenever the button is clicked.

$(".location-card").on("click", ".location-card__menu-btn", function(e) {
  // Find the card element top-level div
  var card = $(e.currentTarget).parents(".location-card");

  // Set the toggle class 
  $(card).addClass("location-card--menu-open");
});

CSS

Finally, the CSS for the menu defaults to display: none, but is changed to display: flex when the toggle class is present on the parent.

.location-card__menu {
  display: none;
  ...
}

.location-card--menu-open .location-card__menu {
  display: flex;
  ...
}

RSpec / Capybara

When testing I do the following:

// Click the menu button
find(".location-card__menu-btn").click

// Verify that the menu opened and is visible
expect(page).to have_selector(".location-card__menu", visible: true)

to which Capybara throws the errror:

expected to find visible css ".location-card__menu" within #<Capybara::Node::Element ... > but there were no matches. Also found "", which matched the selector but not all filters.

As the error says, the element is found but is not visible even though the toggle class is added correctly. The CSS rule that adds the display: flex is not being applied even though the toggle class exists on the parent.

I can verify this is the issue by removing the display: none to have the menu displayed by default and then everything works great and the test passes.

Any idea why Capybara or the underlying browser might be failing to re-apply the CSS logic once the DOM changes?

I'm using:

Thanks!


Solution

  • capybara-webkit is basically equivalent to a 7 year old version of Safari (due to QtWebkit, which it is built on, not having been updated in a long time). As such it doesn't support a lot of modern JS/CSS, which happens to include flex box. Because of this display: flex will be considered invalid and ignored.

    You're going to have a much easier time testing your app if you swap from using capybara-webkit to selenium with headless chrome or firefox for your headless testing.