23

I have a test using Cucumber, capybara and selenium driver. This test should go to a form and submit it. The normal text would be

  Scenario: Fill form
    Given I am on the Form page
    When I fill in "field1" with "value1"
    And I fill in "field2" with "value2"
    And I press "OK"
    Then I should see "Form submited"

The problem is that I don't have the OK button in the form I need a way to do the "form.submit", without clicking any button or link - the same as happens when you press ENTER when you are in a form field using the browser.

I don't know how to tell capybara to submit a form. How can I do it?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Daniel Cukier
  • 11,502
  • 15
  • 68
  • 123

12 Answers12

31

You can access the selenium send_keys method to invoke a return event like

 find_field('field2').native.send_key(:enter)
Brian Dunn
  • 840
  • 2
  • 9
  • 10
19

A simple solution:

When /^I submit the form$/ do
  page.evaluate_script("document.forms[0].submit()")
end

Worked for me with capybara-envjs. Should work with selenium as well.

Hakan Ensari
  • 1,969
  • 1
  • 18
  • 32
  • There is another similar solution: [page.execute_script("$('form#your-form').submit()")](http://stackoverflow.com/a/13712246/664833) -- also, check out the note regarding [Capybara::Session#execute_script](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Session:execute_script) (it says *`execute_script` should be used over `evaluate_script` whenever possible*) -- this is just a piece of information to consider. – user664833 Jun 24 '14 at 02:39
10

I just had to solve this problem myself. In webrat I had something like this:

Then /^I submit the "([^\"]*)" form$/ do |form_id|
  submit_form form_id
end

I was able to achieve the same thing with this in Capybara:

  Then /^I submit the "([^\"]*)" form$/ do |form_id|
    element = find_by_id(form_id)
    Capybara::RackTest::Form.new(page.driver, element.native).submit :name => nil
  end
siannopollo
  • 1,464
  • 11
  • 24
  • 1
    This is _awesome_ because it doesn't even require javascript! So it shouldn't depend on the driver's implementation (like everything else in the world...) In particular, it works with no js at all. – bchurchill May 13 '13 at 13:49
5

With the capybara Selenium driver you can do something like this:

within(:xpath, "//form[@id='the_form']") do
  locate(:xpath, "//input[@name='the_input']").set(value)
  locate(:xpath, "//input[@name='the_input']").node.send_keys(:return)
end
Aaron Gibralter
  • 4,773
  • 3
  • 35
  • 50
3

Simply put: you can't.

Some browsers will not allow you to submit a form without a submit button at all (most notably Internet Explorer <= 6). So this kind of form is a bad idea to begin with. Add a submit button and position it off the screen with CSS.

jnicklas
  • 2,155
  • 2
  • 16
  • 14
1

You can try sending a newline:

find_field('field2').native.send_key("\n")
SztupY
  • 10,291
  • 8
  • 64
  • 87
vijay chouhan
  • 1,012
  • 8
  • 25
1

You may probably roll your own step (And I submit the form with the link "Ok", for example), and emulate the submit functionality yourself.

Here it is the javascript emulation dropped in Rails 3 to support "unobtrusive" (emphasis on the quotes) Javascript. The line

Capybara::Driver::RackTest::Form.new(driver, js_form(self[:href], emulated_method)).submit(self)

is probably the clue to answer your problem. The full code is here

Chubas
  • 17,823
  • 4
  • 48
  • 48
  • I think it does. I'm using form submission with confirmation dialogs without problem in an application right now, and they work correctly. – Chubas May 15 '10 at 23:33
1

I'd recommend you add a submit button, then hide it with CSS. Then you can test the form submission, but still get the user behavior you want.

nakajima
  • 1,862
  • 12
  • 12
1

With Webrat you can just:

When /^I submit the form$/ do
  submit_form "form_id"
end

p. 307, The RSpec Book

Sai Perchard
  • 853
  • 1
  • 10
  • 12
1

The display:none solution does not work with capybara using selenium driver because selenium complains about interacting with invisible elements. If you try the above solution you may end up seeing the following error message:

Element is not currently visible and so may not be interacted with (Selenium::WebDriver::Error::ElementNotVisibleError)
Pikachu
  • 774
  • 13
  • 15
0

Try this..

find(:css, "input[name$='login']").native.send_keys :enter
Abhisek
  • 103
  • 1
  • 6
0

This is a bit hackish, but it filled a need. I monkey-patched Capybara to support a #submit method on elements.

It is not robust because it naively creates the POST parameters from every input elements's name and value attributes. (In my case, all my <input> elements were of type hidden, so it works fine).

class Capybara::Node::Element
  # If self is a form element, submit the form by building a
  # parameters from all 'input' tags within this form.
  def submit
    raise "Can only submit form, not #{tag_name}" unless tag_name =~ /form/i

    method = self['method'].to_sym
    url = self['action']
    params = all(:css, 'input').reduce({}) do |acc, input|
      acc.store(input['name'], input['value'])
      acc
    end

    session.driver.submit(method, url, params)
  end
end

...

form = find('#my_form_with_no_submit_button')
form.submit
Patrick
  • 5,714
  • 4
  • 31
  • 36