ruby-on-rails-4capybararspec2poltergeist

Capybara: Test for Content in CSS PsuedoElements


I'm working on an app where text conditionally appears in a ::before pseudo element's content property and is rendered on the page. After a code change caused this important text to accidentally disappear, I wanted to be able to write tests that would capture that error if it happened again, but there are challenges grabbing the content from pseudo-selectors. I was looking for something like:

#scss
.content-div {
  &.condition-true {
    &:before {
      content: "conditional text";
    }
  }
}

#coffeescript
if @someCondition
  $('content-div').addClass('condition-true')
else
  $('content-div').removeClass('condition-true')

#spec
context "when true" do
  it "should have the conditional text" do
    # do thing that makes it true
    expect( page ).to have_content("conditional text")
  end
end

The solution wasn't so easy, and I thought I'd share here and let others comment, or provide other solutions.

I'm using Capybara 2.3.0 and Poltergeist 1.5.1.


Solution

  • The key was passing a block of code to page.evaluate_script, as well as Javascript's getComputedStyle() function.

    content_array = page.evaluate_script <<-SCRIPT.strip.gsub(/\s+/,' ')
      (function () {
        var elementArray = $('.desired-css-selector');
        var contentArray = [];
        for (var i = 0, tot=elementArray.length; i < tot; i++) {
          var content = window.getComputedStyle( elementArray[i], ':before' ).getPropertyValue('content');
          contentArray.push(content);
        }
        return contentArray;
      })()
    SCRIPT
    content_array.each { |c| c.gsub!(/\A'|'\Z/, '') }
    
    expect( content_array ).to include("conditional text")
    

    UPDATE - SIMPLE EXAMPLE:

    I've recently had to do a much simpler version of this:

    color = page.evaluate_script <<-SCRIPT
      (function () {
        var element = document.getElementById('hoverme');
        var color = window.getComputedStyle( element, ':hover' ).getPropertyValue('color');
    
        return color;
       })()
    SCRIPT