Rails:assert_select在使用数值测试属性时会出现nokogiri错误

时间:2018-03-06 23:33:01

标签: ruby-on-rails integration-testing nokogiri

在我的rails集成测试中,我试图测试是否存在具有给定值的复选框(这是对象的ID,整数)。

此行:assert_select "input[type=checkbox][value=#{c.id.to_s}]"生成以下错误:

  

Nokogiri :: CSS :: SyntaxError:unexpected' 283557850'等于'

     

(283557850是对象的ID)。

令人困惑的是,我在测试数值时只会遇到此错误。如果我输入一些字母,例如assert_select "input[type=checkbox][value=test#{c.id.to_s}]",我就不会再出现错误了(显然测试失败,因为我的复选框的值实际上不是" test283557850")。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

问题是input[type=checkbox][value=123]不是有效的CSS选择器。查询属性时,值必须以字母开头或引用。

assert_select "input[type=checkbox][value='#{c.id.to_s}']"

使用浏览器控制台和document.querySelectorAll()可以解决这类问题。

答案 1 :(得分:0)

附件是我的assert_xpath。它比assert_select好,因为XPath将XML视为一个可以进行任意复杂查询的数据库。

您的查询将是assert_xpath "//input[@type='checkbox' and @value='#{c.id.to_s}']",或者更好assert_xpath '//input[@type="checkbox" and @value=$value]', value: c.id.to_s

assert_xpath也可以嵌套。例如:

assert_xpath '//label[ contains(text(), "Group:") ]' do
  assert_xpath 'select[ "group_id" = @name ]' do
    assert_xpath 'option[ "Anonymous users" = text() and "13" = @value ]'
    assert_xpath 'option[ "B Team" = text() and "11" = @value and "selected" = @selected ]'
  end
end

将其粘贴到您的test_helper.rb文件中:

class ActiveSupport::TestCase

  def assert_xml(xml)
    @xdoc = Nokogiri::XML(xml, nil, nil, Nokogiri::XML::ParseOptions::STRICT)
    refute_nil @xdoc
    return @xdoc
  end

  def assert_html(html=nil)
    html ||= @response.body
    @xdoc = Nokogiri::HTML(html, nil, nil, Nokogiri::XML::ParseOptions::STRICT)
    refute_nil @xdoc
    return @xdoc
  end

  def assert_xpath(path, replacements={}, &block)
    @xdoc ||= nil  #  Avoid a dumb warning
    @xdoc or assert_html  #  Because assert_html snags @response.body for us
    element = @xdoc.at_xpath(path, nil, replacements)

    unless element
      complaint = "Element expected in:\n`#{@xdoc}`\nat:\n`#{path}`"
      replacements.any? and complaint += "\nwith: " + replacements.pretty_inspect
      raise Minitest::Assertion, complaint
    end

    if block
      begin
        waz_xdoc = @xdoc
        @xdoc = element
        block.call(element)
      ensure
        @xdoc = waz_xdoc
      end
    end

    return element
  end

  def refute_xpath(path, replacements={}, &block)
    @xdoc ||= nil  #  Avoid a dumb warning
    @xdoc or assert_html  #  Because assert_html snags @response.body for us
    element = @xdoc.at_xpath(path, nil, replacements)

    if element
      complaint = "Element not expected in:\n`#{@xdoc}`\nat:\n`#{path}`"
      replacements.any? and complaint += "\nwith: " + replacements.pretty_inspect
      raise Minitest::Assertion, complaint
    end
  end

end