如何测试导轨4确认与Capybara和Poltergeist的对话?

时间:2014-08-13 17:40:46

标签: ruby-on-rails rspec capybara poltergeist

我正在尝试测试指向destroy操作的链接是否会使用正确的消息抛出本机浏览器confirm框。

使用rails {link_to

生成链接
link_to 'Delete', user_path, method: :delete, data: { confirm: "Are you sure?" }

并生成以下html:

<a data-confirm="Are you sure?" data-method="delete" href="/users/6" rel="nofollow">Delete</a>

该功能在浏览器中正常运行,但我想在我的rspec功能规范中对其进行测试。

我正在尝试按照herethis gist中描述的浏览器的confirm功能进行存根,但我无法让它发挥作用。

it 'requests confirmation', js: true do
  visit user_path(user)
  page.execute_script "
    window.confirmMsg = null;
    window.confirm = function(msg) { window.confirmMsg = msg; return true; };"
  click_link 'Delete'
  expect(page.evaluate_script('window.confirmMsg')).to eq('Are you sure?')
end

rspec发出以下错误:

Failure/Error: expect(page.evaluate_script('window.confirmMsg')).to eq('Are you sure?')

       expected: "Are you sure?"
            got: nil

       (compared using ==)

但是,如果我通过confirm直接致电page.execute_script

it 'requests confirmation', js: true do
  visit user_path(user)
  page.execute_script "
    window.confirmMsg = null;
    window.confirm = function(msg) { window.confirmMsg = msg; return true; };
    window.confirm('Are you sure?');"
  expect(page.evaluate_script('window.confirmMsg')).to eq('Are you sure?')
end

然后测试通过。

即使直接为confirm调用page.execute_script,点击删除链接也会导致测试失败:

it 'requests confirmation', js: true do
  visit user_path(user)
  page.execute_script "
    window.confirmMsg = null;
    window.confirm = function(msg) { window.confirmMsg = msg; return true; };
    window.confirm('Are you sure?');"
  click_link 'Delete'
  expect(page.evaluate_script('window.confirmMsg')).to eq('Are you sure?')
end

rspec发出相同的错误:

Failure/Error: expect(page.evaluate_script('window.confirmMsg')).to eq('Are you sure?')

       expected: "Are you sure?"
            got: nil

       (compared using ==)

为什么测试失败?而且,我如何正确测试确认对话?


上下文

我正在使用Vagrant虚拟机运行我的测试,该虚拟机为Ubuntu 12.04.4 LTS并且正在运行ruby 2.1.2p95

我的Gemfile.lock表明我有以下版本:

rails (4.1.4)
poltergeist (1.5.1)
capybara (2.4.1)

6 个答案:

答案 0 :(得分:27)

page.driver.browser.accept_js_confirms已弃用。而是使用

page.accept_confirm do
  click_link 'Delete'
end

答案 1 :(得分:6)

不幸的是,你cannot do this,因为Poltergeist只能在一个窗口中工作。

对于该特定测试,您需要使用Selenium和此API:

page.driver.browser.switch_to.alert.accept

如果您担心想要无头运行测试,可以像这样使用Xvfb(X Virtual Framebuffer):

Xvfb :1 -screen 0 1024x768x24+32

或者您也可以使用capybara-webkit:

page.driver.browser.accept_js_confirms
page.driver.browser.reject_js_confirms

然而,在必要的情况下,我使用了(主要是)Poltergeist和Selenium的混合物,获得了最好的体验。

答案 2 :(得分:1)

为了扩展上述内容,使用Selenium时,您可以使用以下方法测试确认对话框的实际文本:

    click_link 'Delete'
    a = page.driver.browser.switch_to.alert
    expect(a.text).to eq("Are you sure?")
    a.accept

另外,刚刚找到了一个关于警报是否存在的良好测试:selenium 2.4.0, how to check for presence of an alert我稍微修改了它,将我的spec_helper文件放入:

def alert_present?
  begin
    page.driver.browser.switch_to.alert
    return true
  rescue
    return false
  end
end

然后在你的测试中做:

click_link 'Delete'
expect(alert_present?).to eq(true)

答案 3 :(得分:0)

测试JavaScript行为很难。但是如果你想检查确认消息,可以在没有Poltergeist的情况下测试链接属性:

it 'requests confirmation' do
  visit user_path(user)
  delete_link = find_link 'Delete', href: user_path(user)
  expect(delete_link['data-confirm']).to eq 'Are you sure?'
end

以下是替代方案:

it 'requests confirmation' do
  visit user_path(user)
  expect(page).to have_selector "a[data-confirm='Are you sure?'][href='#{user_path(user)}']", text: 'Delete'
end

此测试无法检查JS是否正常工作,但在大多数情况下可能已足够。 (快点!)

答案 4 :(得分:0)

鉴于此Javascript:

confirm('You have unsaved changes, do you want to continue?')

对于Poltergiest,我发现以下内容有效:

expect(page.driver.browser.modal_message).eq 'You have unsaved changes, do you want to contine?'

page.driver.browser.dismiss_confirm
page.driver.browser.accept_confirm

答案 5 :(得分:0)

这就是我在Rails 3.2和capybara (~> 2.18.0)

中的工作方式
context 'when `All listing` overlaps with listing 1' do
  it 'displays warning' do
    set_weekday_times('.show_window','10:00 AM', '02:00 PM', listing1.address)
    set_weekday_times('.show_window:last-child', '11:00 AM', '03:00 PM', 'All Listing')

    # button click event that triggers the confirm to appear
    submit_weekdays_form

    # Get the message in the confirm dialog
    confirm_text = page.driver.browser.switch_to.alert.text
    expect(confirm_text).to include('overlapping show windows on Sunday')
  end
end