Capybara API
Capybara提供了许多API对网页元素进行操作,如果使用Cucumber做BDD那么要在env.rb文件中加入语句:
require 'cucumber/formatter/unicode' #在Windows下可以显示中文 require 'rubygems' require 'capybara' require 'capybara/cucumber' require 'capybara/dsl' #When using capybara/dsl, the Session is initialized automatically for you
The DSL
A complete reference is available at rubydoc.info.
Note: All searches in Capybara are case sensitive. This is because Capybara heavily uses XPath, which doesn't support case insensitivity.
Navigating
You can use the #visit method to navigate to other pages:
visit('/projects') visit(post_comments_path(post))
The visit method only takes a single parameter, the request method is always GET.
You can get the current path of the browsing session for test assertions:
current_path.should == post_comments_path(post)
Clicking links and buttons
Full reference: Capybara::Node::Actions
You can interact with the webapp by following links and buttons. Capybara automatically follows any redirects, and submits forms associated with buttons.
click_link('id-of-link') click_link('Link Text') click_button('Save') click_on('Link Text') # clicks on either links or buttons click_on('Button Value')
Interacting with forms
Full reference: Capybara::Node::Actions
There are a number of tools for interacting with form elements:
fill_in('First Name', :with => 'John') fill_in('Password', :with => 'Seekrit') fill_in('Description', :with => 'Really Long Text...') choose('A Radio Button') check('A Checkbox') uncheck('A Checkbox') attach_file('Image', '/path/to/image.jpg') select('Option', :from => 'Select Box')
Querying
Full reference: Capybara::Node::Matchers
Capybara has a rich set of options for querying the page for the existence of certain elements, and working with and manipulating those elements.
page.has_selector?('table tr') page.has_selector?(:xpath, '//table/tr') page.has_no_selector?(:content) page.has_xpath?('//table/tr') page.has_css?('table tr.foo') page.has_content?('foo')
Note: The negative forms like has_no_selector?
are different from not has_selector?
. Read the section on asynchronous JavaScript for an explanation.
You can use these with RSpec's magic matchers:
page.should have_selector('table tr') page.should have_selector(:xpath, '//table/tr') page.should have_no_selector(:content) page.should have_xpath('//table/tr') page.should have_css('table tr.foo') page.should have_content('foo')
Finding
Full reference: Capybara::Node::Finders
You can also find specific elements, in order to manipulate them:
find_field('First Name').value find_link('Hello').visible? find_button('Send').click find(:xpath, "//table/tr").click find("#overlay").find("h1").click all('a').each { |a| a[:href] }
Note: find
will wait for an element to appear on the page, as explained in the Ajax section. If the element does not appear it will raise an error.
These elements all have all the Capybara DSL methods available, so you can restrict them to specific parts of the page:
find('#navigation').click_link('Home') find('#navigation').should have_button('Sign out')
Scoping
Capybara makes it possible to restrict certain actions, such as interacting with forms or clicking links and buttons, to within a specific area of the page. For this purpose you can use the generic within method. Optionally you can specify which kind of selector to use.
within("li#employee") do fill_in 'Name', :with => 'Jimmy' end within(:xpath, "//li[@id='employee']") do fill_in 'Name', :with => 'Jimmy' end
Note: within
will scope the actions to the first (not any) element that matches the selector.
There are special methods for restricting the scope to a specific fieldset, identified by either an id or the text of the fieldset's legend tag, and to a specific table, identified by either id or text of the table's caption tag.
within_fieldset('Employee') do fill_in 'Name', :with => 'Jimmy' end within_table('Employee') do fill_in 'Name', :with => 'Jimmy' end
Scripting
In drivers which support it, you can easily execute JavaScript:
page.execute_script("$('body').empty()")
For simple expressions, you can return the result of the script. Note that this may break with more complicated expressions:
result = page.evaluate_script('4 + 4');
Debugging
It can be useful to take a snapshot of the page as it currently is and take a look at it:
save_and_open_page
You can also retrieve the current state of the DOM as a string using page.html.
print page.html
This is mostly useful for debugging. You should avoid testing against the contents of page.html
and use the more expressive finder methods instead.
Finally, in drivers that support it, you can save a screenshot:
page.save_screenshot('screenshot.png')
参考资料