module Rails::Dom::Testing::Assertions::SelectorAssertions

Constants

PATTERN_HTML

Selects content from a JQuery response. Patterned loosely on assert_select_rjs.

Narrowing down

With no arguments, asserts that one or more method calls are made.

Use the method argument to narrow down the assertion to only statements that call that specific method.

Use the opt argument to narrow down the assertion to only statements that pass opt as the first argument.

Use the id argument to narrow down the assertion to only statements that invoke methods on the result of using that identifier as a selector.

Using blocks

Without a block, +assert_select_jquery_ merely asserts that the response contains one or more statements that match the conditions specified above

With a block +assert_select_jquery_ also asserts that the method call passes a javascript escaped string containing HTML. All such HTML fragments are selected and passed to the block. Nested assertions are supported.

Examples

# asserts that the notice element is hidden assert_select :hide, '#notice'

# asserts that the cart element is shown with a blind parameter assert_select :show, :blind, '#cart'

# asserts that cart content contains a current_item assert_select :html, '#cart' do

assert_select '#current_item'

end

# asserts that product append to a product_list assert_select_jquery :appendTo, '#product_list' do

assert_select '.product'

end

PATTERN_UNICODE_ESCAPED_CHAR
SKELETAL_PATTERN

Public Instance Methods

assert_select_jquery(*args) { || ... } click to toggle source
# File lib/jquery/assert_select.rb, line 54
def assert_select_jquery(*args, &block)
  jquery_method = args.first.is_a?(Symbol) ? args.shift : nil
  jquery_opt    = args.first.is_a?(Symbol) ? args.shift : nil
  id            = args.first.is_a?(String) ? args.shift : nil

  target_pattern   = "['\"]#{id || '.*'}['\"]"
  method_pattern   = "#{jquery_method || '\\w+'}"
  argument_pattern = jquery_opt ? "['\"]#{jquery_opt}['\"].*" : PATTERN_HTML

  # $("#id").show('blind', 1000);
  # $("#id").html("<div>something</div>");
  # $("#id").replaceWith("<div>something</div>");
  target_as_receiver_pattern = SKELETAL_PATTERN % [target_pattern, method_pattern, argument_pattern]

  # $("<div>something</div>").appendTo("#id");
  # $("<div>something</div>").prependTo("#id");
  target_as_argument_pattern = SKELETAL_PATTERN % [argument_pattern, method_pattern, target_pattern]

  # $("#id").remove();
  # $("#id").hide();
  argumentless_pattern = SKELETAL_PATTERN % [target_pattern, method_pattern, '']

  patterns = [target_as_receiver_pattern, target_as_argument_pattern]
  patterns << argumentless_pattern unless jquery_opt

  matched_pattern = nil
  patterns.each do |pattern|
    if response.body.match(Regexp.new(pattern))
      matched_pattern = pattern
      break
    end
  end

  unless matched_pattern
    opts = [jquery_method, jquery_opt, id].compact
    flunk "No JQuery call matches #{opts.inspect}"
  end

  if block_given?
    @selected ||= nil
    fragments = Nokogiri::HTML::Document.new

    if matched_pattern
      response.body.scan(Regexp.new(matched_pattern)).each do |match|
        flunk 'This function can\'t have HTML argument' if match.is_a?(String)

        doc = Nokogiri::HTML::Document.parse(unescape_js(match.first))
        doc.root.children.each do |child|
          fragments << child if child.element?
        end
      end
    end

    begin
      in_scope, @selected = @selected, fragments
      yield
    ensure
      @selected = in_scope
    end
  end
end

Private Instance Methods

unescape_js(js_string) click to toggle source

Unescapes a JS string.

# File lib/jquery/assert_select.rb, line 119
def unescape_js(js_string)
  # js encodes double quotes and line breaks.
  unescaped= js_string.gsub('\"', '"')
  unescaped.gsub!('\\\'', "'")
  unescaped.gsub!(/\\\//, '/')
  unescaped.gsub!('\n', "\n")
  unescaped.gsub!('\076', '>')
  unescaped.gsub!('\074', '<')
  # js encodes non-ascii characters.
  unescaped.gsub!(PATTERN_UNICODE_ESCAPED_CHAR) {|u| [$1.hex].pack('U*')}
  unescaped
end