最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ajax - How can I test in Capybara that a page has *not* reloaded (JavaScript onClick intercept has worked)? - Stack Overflow

programmeradmin4浏览0评论

I am using Capybara, Cucumber and Poltergeist. I am testing a JavaScript function that is attached to a form submit button, which is intended to catch the submit event and prevent it (doing an AJAX request in the background). With and without AJAX, the page will end up looking the same, but the AJAX approach is much faster and does not interrupt the browsing experience etc.

What can I do to test that the form was indeed not submitted, and that the changes are the result of a dynamic AJAX call rather than a reload?

I am using Capybara, Cucumber and Poltergeist. I am testing a JavaScript function that is attached to a form submit button, which is intended to catch the submit event and prevent it (doing an AJAX request in the background). With and without AJAX, the page will end up looking the same, but the AJAX approach is much faster and does not interrupt the browsing experience etc.

What can I do to test that the form was indeed not submitted, and that the changes are the result of a dynamic AJAX call rather than a reload?

Share Improve this question asked Nov 27, 2013 at 13:00 Matt GibsonMatt Gibson 14.9k7 gold badges51 silver badges80 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 2

I had the same issue and came up with a solution, probably not the best one–but it works :)

#support/reload.rb
def init_reload_check
    page.evaluate_script "window.not_reloaded = 'not reloaded';"
end

def not_reloaded
    page.evaluate_script("window.not_reloaded") == "not reloaded"
end

#Ajax Test
it "should not reload the page", js: true do
    init_reload_check
    click_link "Ajax Link"
    expect(not_reloaded).to be_truthy
end

Modified version of @jules' answer:

describe "My page", :js do
  it "reloads when it should" do
    visit "/"

    expect_page_to_reload do
      click_link "Reload me"
    end
  end

  def expect_page_to_reload
    page.evaluate_script "$(document.body).addClass('not-reloaded')"
    yield
    expect(page).not_to have_selector("body.not-reloaded")
  end
end

EDIT 2017-01-19:

I found this old answer of mine which strangely did not seem to answer the actual question, but instead the opposite (check that the page has reloaded). This is what we do currently in our app to check that a page does not reload:

def expect_page_not_to_reload
  page.evaluate_script %{$(document.body).addClass("not-reloaded")}
  expect(page).to have_selector("body.not-reloaded")
  yield
  sleep 0.5  # Give it a chance to reload before we check.
  expect(page).to have_selector("body.not-reloaded")
end

Both answers rely on jQuery for adding the class.

And here's my version of Henrik N's answer. Doesn't rely on jQuery or whatever assertion library he's using.

def assert_page_reloads(message = "page should reload")
  page.evaluate_script "document.body.classList.add('not-reloaded')"
  yield
  if has_selector? "body.not-reloaded"
    assert false, message
  end
end

def assert_page_does_not_reload(message = "page should not reload")
  page.evaluate_script "document.body.classList.add('not-reloaded')"
  yield
  unless has_selector? "body.not-reloaded"
    assert false, message
  end
  page.evaluate_script "document.body.classList.remove('not-reloaded')"
end

Capybara is intended for user-level functional testing. There isn't an easy way to test an implementation detail such as whether a form uses AJAX or a traditional form submission. It encourages you to write your tests in terms of the end-user experience.

There are a couple of things you can do:

  • Capybara supports a wait time for finders and assertions. There are a few ways to set it, using Capybara.default_wait_time, Capybara.using_wait_time, or passing a wait option to your assertion methods. If you set a low wait time, you can be sure that the results of clicking the submit button return quickly.

  • Look into JavaScript unit and integration testing frameworks such as Jasmine. This can be used to test the JavaScript code that sets up the event binding and AJAX call. You can use a spy to ensure that the expected AJAX call is made when the button is clicked.

feature "User creates ment", do
  context "with JavaScript enabled", js: true do

    scenario "creates ment via AJAX" do

      initial_page_id = assign_page_id

      # Perform AJAX action
      ...

      page_reloaded = current_page_id != initial_page_id
      expect(page_reloaded).to eq(false)

    end

    def assign_page_id
      page_id = SecureRandom.hex
      page.evaluate_script "window.pageIdForTesting = '#{page_id}'"
    end

    def current_page_id
      page.evaluate_script("window.pageIdForTesting")
    end

  end

  context "without JavaScript" do
    # Can be used if progressively enhancing
    ...
  end
end

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论