Ruby
Datetime select
Sometimes, default Date and DateTime Rails selects might be hard to use from your Cucumber tests. Luckily, we can always build some custom steps to work around this problem.
Consider a trivial user registration form with a birthday field:
= form_for User.new do |form|
= form.label :birthday
= form.date_select :birthday
It typically generates HTML similar to this:
<form accept-charset="UTF-8" action="/users" method="post">
<label for="user_birthdate">Birthdate</label>
<select id="user_birthdate_3i" name="user[birthday(3i)]"><option>Day</option>
<select id="user_birthdate_2i" name="user[birthday(2i)]"><option>Month</option>
<select id="user_birthdate_1i" name="user[birthday(1i)]"><option>Year</option>
</form>
There are two problems with this code:
- The label does not actually point to any of the selects. Select ids are
different from labels
for
attribute. - There are 3 separate selects for a single database field that could go in any arbitrary order.
Both problems make these types of fields super inconvenient to access from
Capybara/Cucumber tests. Your usual select "1986/08/25", from: "Birthday"
is not
going to work here.
Custom Cucumber step to the rescue:
When /^I fill in "(.*?)" date field with "(.*?)"$/ do |field_name, date_components|
label = find("label", text: field_name)
select_base_id = label[:for]
date_components.split(",").each_with_index do |value, index|
select value.strip, from: "#{select_base_id}_#{index+1}i"
end
end
Now you can fill in date selects like this:
When I fill in "Birthdate" date field with "1986, Aug, 25"
This step could also easily be adopted to work with DateTime select fields. Notice that you have to pass date and time components in the order Rails expects it: year goes first, followed by month and then day.