Parent

Object

Public Instance Methods

assert_select_rjs(*args, &block) click to toggle source

Selects content from the RJS response.

Narrowing down

With no arguments, asserts that one or more elements are updated or inserted by RJS statements.

Use the id argument to narrow down the assertion to only statements that update or insert an element with that identifier.

Use the first argument to narrow down assertions to only statements of that type. Possible values are :replace, :replace_html, :show, :hide, :toggle, :remove</tta>, <tt>:insert_html and :redirect.

Use the argument :insert followed by an insertion position to narrow down the assertion to only statements that insert elements in that position. Possible values are :top, :bottom, :before and :after.

Use the argument :redirect followed by a path to check that an statement which redirects to the specified path is generated.

Using the :remove statement, you will be able to pass a block, but it will be ignored as there is no HTML passed for this statement.

Using blocks

Without a block, assert_select_rjs merely asserts that the response contains one or more RJS statements that replace or update content.

With a block, assert_select_rjs also selects all elements used in these statements and passes them to the block. Nested assertions are supported.

Calling assert_select_rjs with no arguments and using nested asserts asserts that the HTML content is returned by one or more RJS statements. Using assert_select directly makes the same assertion on the content, but without distinguishing whether the content is returned in an HTML or JavaScript.

Examples

# Replacing the element foo.
# page.replace 'foo', ...
assert_select_rjs :replace, "foo"

# Replacing with the chained RJS proxy.
# page[:foo].replace ...
assert_select_rjs :chained_replace, 'foo'

# Inserting into the element bar, top position.
assert_select_rjs :insert, :top, "bar"

# Remove the element bar
assert_select_rjs :remove, "bar"

# Changing the element foo, with an image.
assert_select_rjs "foo" do
  assert_select "img[src=/images/logo.gif""
end

# RJS inserts or updates a list with four items.
assert_select_rjs do
  assert_select "ol>li", 4
end

# The same, but shorter.
assert_select "ol>li", 4

# Checking for a redirect.
assert_select_rjs :redirect, root_path
# File lib/prototype-rails/selector_assertions.rb, line 84
def assert_select_rjs(*args, &block)
  rjs_type = args.first.is_a?(Symbol) ? args.shift : nil
  id       = args.first.is_a?(String) ? args.shift : nil

  # If the first argument is a symbol, it's the type of RJS statement we're looking
  # for (update, replace, insertion, etc). Otherwise, we're looking for just about
  # any RJS statement.
  if rjs_type
    if rjs_type == :insert
      position  = args.shift
      id = args.shift
      insertion = "insert_#{position}".to_sym
      raise ArgumentError, "Unknown RJS insertion type #{position}" unless RJS_STATEMENTS[insertion]
      statement = "(#{RJS_STATEMENTS[insertion]})"
    else
      raise ArgumentError, "Unknown RJS statement type #{rjs_type}" unless RJS_STATEMENTS[rjs_type]
      statement = "(#{RJS_STATEMENTS[rjs_type]})"
    end
  else
    statement = "#{RJS_STATEMENTS[:any]}"
  end

  # Next argument we're looking for is the element identifier. If missing, we pick
  # any element, otherwise we replace it in the statement.
  pattern = Regexp.new(
    id ? statement.gsub(RJS_ANY_ID, "\"#{id}\"") : statement
  )

  # Duplicate the body since the next step involves destroying it.
  matches = nil
  case rjs_type
    when :remove, :show, :hide, :toggle
      matches = @response.body.match(pattern)
    else
      @response.body.gsub(pattern) do |match|
        html = unescape_rjs(match)
        matches ||= []
        matches.concat HTML::Document.new(html).root.children.select { |n| n.tag? }
        ""
      end
  end

  if matches
    assert_block("") { true } # to count the assertion
    if block_given? && !([:remove, :show, :hide, :toggle].include? rjs_type)
      begin
        @selected ||= nil
        in_scope, @selected = @selected, matches
        yield matches
      ensure
        @selected = in_scope
      end
    end
    matches
  else
    # RJS statement not found.
    case rjs_type
      when :remove, :show, :hide, :toggle
        flunk_message = "No RJS statement that #{rjs_type.to_s}s '#{id}' was rendered."
      else
        flunk_message = "No RJS statement that replaces or inserts HTML content."
    end
    flunk args.shift || flunk_message
  end
end
button_to_function(name, *args, &block) click to toggle source

Returns a button with the given name text that'll trigger a JavaScript function using the onclick handler.

The first argument name is used as the button's value or display text.

The next arguments are optional and may include the javascript function definition and a hash of html_options.

The function argument can be omitted in favor of an update_page block, which evaluates to a string when the template is rendered (instead of making an Ajax request first).

The html_options will accept a hash of html attributes for the link tag. Some examples are :class => "nav_button", :id => "articles_nav_button"

Note: if you choose to specify the javascript function in a block, but would like to pass html_options, set the function parameter to nil

Examples:

button_to_function "Greeting", "alert('Hello world!')"
button_to_function "Delete", "if (confirm('Really?')) do_delete()"
button_to_function "Details" do |page|
  page[:details].visual_effect :toggle_slide
end
button_to_function "Details", :class => "details_button" do |page|
  page[:details].visual_effect :toggle_slide
end
# File lib/prototype-rails/javascript_helper.rb, line 30
def button_to_function(name, *args, &block)
  html_options = args.extract_options!.symbolize_keys

  function = block_given? ? update_page(&block) : args[0] || ''
  onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};"

  tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick))
end
render_with_update(options = {}, locals = {}, &block) click to toggle source
# File lib/prototype-rails/rendering.rb, line 4
def render_with_update(options = {}, locals = {}, &block)
  if options == :update
    update_page(&block)
  else
    render_without_update(options, locals, &block)
  end
end
response_from_page_with_rjs() click to toggle source

assert_select and css_select call this to obtain the content in the HTML page, or from all the RJS statements, depending on the type of response.

# File lib/prototype-rails/selector_assertions.rb, line 174
def response_from_page_with_rjs
  content_type = @response.content_type

  if content_type && Mime::JS =~ content_type
    body = @response.body.dup
    root = HTML::Node.new(nil)

    while true
      next if body.sub!(RJS_STATEMENTS[:any]) do |match|
        html = unescape_rjs(match)
        matches = HTML::Document.new(html).root.children.select { |n| n.tag? }
        root.children.concat matches
        ""
      end
      break
    end

    root
  else
    response_from_page_without_rjs
  end
end
unescape_rjs(rjs_string) click to toggle source

Unescapes a RJS string.

# File lib/prototype-rails/selector_assertions.rb, line 199
def unescape_rjs(rjs_string)
  # RJS encodes double quotes and line breaks.
  unescaped= rjs_string.gsub('\"', '"')
  unescaped.gsub!(/\\\//, '/')
  unescaped.gsub!('\n', "\n")
  unescaped.gsub!('\076', '>')
  unescaped.gsub!('\074', '<')
  # RJS encodes non-ascii characters.
  unescaped.gsub!(RJS_PATTERN_UNICODE_ESCAPED_CHAR) {|u| [$1.hex].pack('U*')}
  unescaped
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.