module WebStepsHelpers

Public Instance Methods

assert_hidden(options) click to toggle source
# File lib/spreewald_support/web_steps_helpers.rb, line 9
def assert_hidden(options)
  visibility_test(options.merge(:expectation => :hidden))
end
assert_visible(options) click to toggle source
# File lib/spreewald_support/web_steps_helpers.rb, line 5
def assert_visible(options)
  visibility_test(options.merge(:expectation => :visible))
end
find_with_disabled(*args, **options, &optional_filter_block) click to toggle source
# File lib/spreewald_support/web_steps_helpers.rb, line 13
def find_with_disabled(*args, **options, &optional_filter_block)
  if Spreewald::Comparison.compare_versions(Capybara::VERSION, :<, "2.0")
    find(:xpath, XPath::HTML.send(args[0], args[1])) # Versions < 2.0 will find both enabled and disabled fields, nothing to do
  elsif Spreewald::Comparison.compare_versions(Capybara::VERSION, :<, "2.6")
    begin
      find(*args, **options, disabled: false, &optional_filter_block)
    rescue Capybara::ElementNotFound
      find(*args, **options, disabled: true, &optional_filter_block)
    end
  else
    options_with_disabled = { disabled: :all }.merge(options)
    find(*args, **options_with_disabled, &optional_filter_block)
  end
end

Private Instance Methods

detect_visibility_with_capybara(options) click to toggle source
# File lib/spreewald_support/web_steps_helpers.rb, line 99
def detect_visibility_with_capybara(options)
  begin
    old_ignore_hidden_elements = Capybara.ignore_hidden_elements
    Capybara.ignore_hidden_elements = false

    if options.has_key?(:selector)
      selector = options[:selector].strip
      expect(page).to have_css options[:selector]

      have_hidden_tag = have_css %(.hidden #{selector}, .invisible #{selector}, [style~="display: none"] #{selector})

      if options[:expectation] == :hidden
        expect(page).to have_hidden_tag
      else
        expect(page).not_to have_hidden_tag
      end

    else
      expect(page).to have_css('*', :text => options[:text])
      have_hidden_text = have_css('.hidden, .invisible, [style~="display: none"]', :text => options[:text])
      if options[:expectation] == :hidden
        expect(page).to have_hidden_text
      else
        expect(page).not_to have_hidden_text
      end
    end
  ensure
    Capybara.ignore_hidden_elements = old_ignore_hidden_elements
  end
end
detect_visibility_with_js(options) click to toggle source
# File lib/spreewald_support/web_steps_helpers.rb, line 38
  def detect_visibility_with_js(options)
    patiently do

      if selector = options[:selector]
        visible = page.execute_script(<<-JAVASCRIPT)
          function isVisible(element) {
             return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
          }
          
          var element = document.querySelector(#{selector.to_json});

          if (!element) {
            throw new Error("No element found for selector: "+ #{selector.to_json});
          }

          return isVisible(element);
        JAVASCRIPT
      elsif text = options[:text]
        visible = page.execute_script(<<-JAVASCRIPT)
          // This entire code block can be replaced with this single line
          // when we drop support for ancient Firefoxes (< 45):
          //
          //     return document.body.innerText.indexOf(#{text.to_json}) >= 0

          function isVisible(element) {
             return !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length);
          }

          var candidates = document.querySelectorAll('*');

          // Convert NodeList to Array so we can use #filter() and #some()
          candidates = Array.prototype.slice.call(candidates);

          // Keep only candidates that contain the given text
          candidates = candidates.filter(function(candidate) {
            var text = candidate.textContent;
            return text && text.indexOf(#{text.to_json}) >= 0;
          });

          // Keep only candidates without another candidate in its descendants.
          // If that descendant exists, it's a better match.
          candidates = candidates.filter(function(candidate) {
            return !candidates.some(function(other) {
              return candidate !== other && candidate.contains(other);
            });
          });
          
          return candidates.some(isVisible);
        JAVASCRIPT
      else
        raise "Must pass either :selector or :text option"
      end

      if options[:expectation] == :visible
        expect(visible).to eq(true)
      else
        expect(visible).to eq(false)
      end
    end
  end
visibility_test(options) click to toggle source
# File lib/spreewald_support/web_steps_helpers.rb, line 30
def visibility_test(options)
  if javascript_capable?
    detect_visibility_with_js(options)
  else
    detect_visibility_with_capybara(options)
  end
end