1

我有两个失败的规范,似乎有些相关。他们是这样的:

describe "exclude from navigation button" do
  before do
      within "#page_#{pages[1].id}" do
      click_link I18n.t 'pages.exclude'
    end
    pages[1].reload
  end
  specify { pages[1].menu_order.should == -1 }
  it "should add an excluded css class to the pages control" do
    page.should have_selector "li.excluded#page_#{pages[1].id}"
  end
end

describe "include in navigation button" do
  before do
    within "#page_#{pages[2].id}" do
      click_link I18n.t 'pages.include'
    end
    pages[2].reload
  end
  specify { pages[2].menu_order.should == 1 }
  it "should remove the excluded css class from the pages control" do
    page.should_not have_selector "li.excluded#page_#{pages[2].id}"
  end
end

两个 describe 块在使用expected css "..." (not) to return (any|some)thing.

这是 click_link 操作的控制器代码:

def exclude_page
  page = Page.find params[:page_id]
  Hierarchy::PageHierarchy.exclude! page
  redirect_to admin_pages_path
end

def include_page
  page = Page.find params[:page_id]
  Hierarchy::PageHierarchy.include! page
  redirect_to admin_pages_path
end

这些是模块方法排除!并包括!:

def self.exclude! page
  page.update_attribute :menu_order, -1
end


def self.include! page
  page.update_attribute :menu_order, 1
  menu_order = 2
  page.siblings.each do |p|
    p.update_attribute :menu_order, menu_order unless p.menu_order == -1
    menu_order += 1
  end
end

这是重定向目标的控制器代码(admin_pages_path):

def index
  @pages = Page.roots
end

其中 Page.roots 是where parent_id: nil.

第一个示例块很容易修复。我只需要重新访问页面和 CSS 匹配。但是 afaik Capybara 应该只遵循重定向。那我为什么要重温?

第二个块更难(如果这值得自己提出问题,请打我,我只是想避免重复发布所有代码。)

这次重新访问该页面将无法解决问题。事实上重访似乎改变了数据库:

    69:       end
    70:       pages[2].reload
    71:     end
    72:     its(:menu_order) { should == 1}
    73:     it "should add an excluded css class to the pages control" do
 => 74:       binding.pry
    75:       page.should_not have_selector "li.excluded#page_#{pages[2].id}"
    76:     end
    77:   end
    78: end

[1] pry(#<RSpec::Core::ExampleGroup::Nested_1::Nested_2>)> pages[2].id
=> 9
[2] ... > Page.find(9).menu_order
=> 1
[3] ... > visit admin_pages_path
=> nil
[4] ... > Page.find(9).menu_order
=> -1

这是我感到困惑的地方。所以我不明白的是: - 为什么我必须在第一个示例块中重新访问?- 为什么这个技巧在第二个示例块中不起作用?- 为什么重新访问页面会改变数据库?

请注意,所有这些仅适用于 Capybara/RSpec。使用浏览器手动执行此操作时,一切正常。

更新:

页面定义:

let(:pages) { bunch_of_pages.sort { |a, b| a.menu_order <=> b.menu_order } }

# bunch_of_pages:
def bunch_of_pages
  pages = []
  roots << root1 = FactoryGirl.create(:public_page, menu_order: (rand*1000).to_i)
  child1 = FactoryGirl.create :public_page, parent: root1, menu_order: (rand*1000).to_i
  child2 = FactoryGirl.create :public_page, parent: root1, menu_order: (rand*1000).to_i
  subchild1 = FactoryGirl.create :public_page, parent: child2, menu_order: (rand*1000).to_i

  pages << root2 = FactoryGirl.create(:public_page, menu_order: (rand*1000).to_i)
  child3 = FactoryGirl.create :public_page, parent: root2, menu_order: (rand*1000).to_i
  .
  .
  .

  pages
end
4

1 回答 1

0

不知道为什么您的测试在不重新加载页面的情况下无法通过。但是,编写第二个示例的正确方法是:

page.should have_no_selector "li.excluded#page_#{pages[2].id}"

Capybara 的断言有一个内置机制,可以在匹配失败之前重试特定次数。它仅在您使用should而不是should_not.

于 2012-07-29T07:44:46.320 回答