Test a form text_field presence with capybara - ruby-on-rails

I have the following form and I want to check if the text field is present or not. How can I do that ?
<%= form_for(ownership, remote: true) do |f| %>
<div>
<%= f.text_field :confirm, value: nil %>
<%= f.hidden_field :start_date, value: Time.now %>
</div>
<%= f.submit t('button.ownership.take.confirmation'), class: "btn btn-small"%>
<% end %>
Here my test :
describe "for not confirmed ownership" do
before do
FactoryGirl.create(:agreed_ownership, user: current_user, product: product)
be_signed_in_as(current_user)
visit current_page
end
# it { should_not have_text_field(confirm) }
it { should_not have_button(t('button.ownership.take.confirmation')) }
end

You'd use a has_css? expectation:
it "should have the confirm input field" do
visit current_page
expect(page).to have_css('input[type="text"]')
end
You can use additional jQuery-style selectors to filter for other attributes on the input field, too. For example, 'input[type="text"][name*="confirm"]' would select for confirm appearing in the input field's name attribute.
To set an expectation the field isn't present, you'd use to_not on your expectation: expect(page).to_not have_css('input[type="text"]')
Bonus: Here's the older, should-style syntax:
it "should have the confirm input field" do
visit current_page
page.should have_css('input[type="text"]')
end
it "shouldn't have the confirm input field" do
visit current_page
page.should_not have_css('input[type="text"]')
end

Related

Rails: Capybara::ElementNotFound

I'm trying to solve a challenge, but I received an error message from Cabybara saying:
`Failure/Error: fill_in 'Name', with: 'Vostro 2017'
Capybara::ElementNotFound: Unable to find visible field "Name" that is not disabled`
My new.html.erb is:
<%= form_for #item, url: {action: "create"} do |f|%>
<%= f.label 'Name' %>
<%= f.text_field :name %>
<%= f.label 'Description' %>
<%= f.text_field :description %>
<%= f.label 'Features' %>
<%= f.text_field :features %>
<%= f.label 'Asset number' %>
<%= f.text_field :assetNumber %>
<%= f.submit%>
<% end %>
And my item_controller.rb is:
class ItemController < ApplicationController
def show
#items = Item.find(params[:id])
end
def new
#item = Item.new
end
def create
#item = Item.new(item_params)
#item.save
redirect_to #item
end
private
def item_params
params.require(:item).permit(:name, :description, :features, :assetNumber)
end
end
The rspec file that is being used to do the test is:
require 'rails_helper'
feature 'User creates a new inventory item' do
scenario 'successfully' do
visit new_item_path
fill_in 'Name', with: 'Vostro 2017'
fill_in 'Description', with: 'Dell Notebook'
fill_in 'Features', with: '16gb, 1Tb, 15.6"'
fill_in 'Asset number', with: '392 DLL'
click_button 'Create Item'
expect(page).to have_content 'Vostro 2017'
expect(page).to have_content 'Dell Notebook'
expect(page).to have_content '16gb, 1Tb, 15.6"'
expect(page).to have_content '392 DLL'
end
end
I'm using ruby-2.3.5 and rails 4.1.0.
I'm beginner in ruby/rails and I can't figure out what's wrong with my code.
Could somebody help me to solve that?
I appreciate in advance.
You could do this, assuming your input has an id of name:
find("input[id$='name']").set "Vostro 2017"
or:
find("#name").set "Vostro 2017"
You might also try lower-casing Name:
fill_in 'name', with: "Vostro 2017"
Capybara will target the name or the id attribute, so the second example should work.
Rails generates form input names with using form object.
fill_in 'item[name]', with: "Vostro 2017"
fill_in 'item[description]', with: 'Dell Notebook'
fill_in 'item[features]', with: '16gb, 1Tb, 15.6"'
fill_in 'item[assetNumber]', with: '392 DLL'
If you look at the actual HTML of the page instead of the erb template (always better to include the HTML unless your question is specifically about the erb) you'll notice your labels aren't actually associated with the input elements (no matching for attribute to the id of the input). Obviously for Capybara to find the element by label text ('Name' in your case) the label would have to be correctly associated with the element. To fix that you need to use f.label - http://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html#method-i-label - correctly. If you want to specify the text of the element (vs using text extracted from i18n translation) that would be
f.label :name, 'Name'
I realized what I was doing wrong, so let's go:
I changed the instance variable items inside def show action to item (not pluralized) and I changed an atribute from assetNumber to asset_number, so this way the Cabybara test could understand correctly.
Thanks guys.

Find an element without an id for Capybara testing

I have multiple email fields in a form. None of them have an id on them intentionally. How can I differentiate each element in the test if they don't have an id? I'll show code for clarity.
TEST
it "sends an invitation to multiple users" do
click_on "Invite"
click_link "Invite Another Team Member"
fill_in "", with: "user#example.com"
fill_in "", with: "user2#example.com"
expect { click_button "Invite" }
.to change(ActionMailer::Base.deliveries, :count).by(1)
.and change(Invitation, :count).by(2)
expect(current_path).to eq(account_users_path)
expect(page).to have_content("user#example.com")
expect(page).to have_content("user2#example.com")
end
This actually creates one object, the bottom field. How can I give the text fields individuality?
FORM
<%= form_tag account_invitations_url do %>
<label class="email-label">
<%= email_field_tag "emails[]", "", placeholder: "Email Address", data: { invitation_modal_email: "" }, id: "" %>
</label>
<%= link_to '✚ Invite Another Team Member', "#email", data: { invitation_modal_add: "" } %>
<div class="form-actions invitation">
<span class="button-text"><%= link_to 'Cancel', account_users_path %></span>
<%= submit_tag "Invite", class: "button button--invitation" %>
</div>
<% end %>
## Browser HTML
I think you can use Capybara's method all for finding all elements with same name:
emails = ["user#example.com", "user2#example.com"]
all('input[name="emails[]"]').each_with_index do |field, i|
field.set(emails[i])
end
Or:
all('input[name="emails[]"]')[0].set("user#example.com")
all('input[name="emails[]"]')[1].set("user2#example.com")

Uncheck check_box only not working with rspec / capybara tests

I have a nested form that has 4 checkboxes. Currently, everything is working in browser, but I can't get the capybara tests to uncheck the checkbox and save.
Using Rails 4.2.2 and latest versions of capaybara-webkit and rspec
settings.html.erb
<%= f.fields_for :preferences do |f| %>
<div class="email-notifications-holder">
<div class="email-holder">
<%= f.label :new_match, "Getting a new match each week" %>
<%= f.check_box :new_match, class: "checkbox new_match_email" %>
</div>
<div class="email-holder">
<%= f.label :match_reminder, "New matches Thursday reminder", class: "match_reminder_email" %>
<%= f.check_box :match_reminder, default: true, class: "checkbox" %>
</div>
<div class="email-holder">
<%= f.label :accepted_match, "A Glassbreakers accepted a match", class: "accepted_match_email" %>
<%= f.check_box :accepted_match, default: true, class: "checkbox" %>
</div>
<div class="email-holder">
<%= f.label :new_message, "Received a new message", class: "new_message_email" %>
<%= f.check_box :new_message, default: true, class: "checkbox" %>
</div>
</div>
<% end %>
edit_account_spec.rb
it "allows the user to opt out of new match email", :js do
user = create(:user)
preferences = create(:preference, user: user)
sign_in(user)
visit edit_user_path(user)
click_tab(t("edit_user.tabs.settings"))
find(:css, "#user_preferences_attributes_0_new_match").set(false)
within "#button-container" do
page.find('.save.main-save-button-edit').trigger('click')
end
visit edit_user_path(user)
click_tab(t("edit_user.tabs.settings"))
user.preferences.reload
new_match_email_checkbox = find(".new_match_email")
expect(new_match_email_checkbox.checked?).to be_falsey
end
I've tried clicking it, unchecking it, checking it, trigger clicking it, wrapping it around a within block, reloading the db, etc.
new_match_email_checkbox = find(".new_match_email")
within(".email-notifications-holder") do
page.uncheck('Getting a new match each week')
end
new_match_email_checkbox.set(false)
Right now when you save a user's profile, you must have onboard skills saved or else it will throw an error message when you're trying to click the save button.
part of the user controller
def update
if update_current_user?(user_params)
redirect_to user_path(current_user)
else
flash["notice"] =
"Please choose 3 industries, fields and years of experience."
redirect_to edit_user_path(current_user)
end
end
private
def update_current_user?(update_params)
skills_chosen?(update_params[:user_onboard_skills_attributes]) &&
current_user.update(update_params)
end
Using save_and_open_page, the error alert wasn't appearing so it was unclear what was happening. I was able to debug this by trailing the logs while running the tests using:
tail -f log/test.log
Just using this will uncheck the checkbox
within(".email-notifications-holder") do
page.uncheck('Getting a new match each week')
end
But you then have to grab the element to test it.
new_match_email_checkbox = find(".new_match_email")
expect(new_match_email_checkbox.checked?).to be_falsey
Note:
One thing I am unclear about. Are you trying to make this line work?:
find(:css, "#user_preferences_attributes_0_new_match").set(false)
or are you trying to uncheck the checkbox after you call user.preferences.reload ?

Checkboxes in Rails - Value chosen not displaying in 'Show', undefined method `merge' for "a":String

I'm having a set of problems that are doing my head in! Kind of a Rails newb so I'm having trouble figuring this out.
I've got a field for my 'Question' model that's called 'Answers_expected', which I want to have two options for, 'One' or 'Multiple', rather than just a normal text input.
My Questions_controller.rb (relevant lines):
before_action :set_answers_expected
private
# Use callbacks to share common setup or constraints between actions.
def set_question
#question = Question.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def question_params
params.require(:question).permit(:title, :brief, :idea_id, :user_id, :answers_expected)
end
def set_answers_expected
#answers_expected = [
"One",
"Multiple"
]
end
Questions.rb (relevant line):
validates :answers_expected, presence: true
_form.html.erb:
<%= form_for(#question) do |f| %>
<% if #question.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#question.errors.count, "error") %> prohibited this question from being saved:</h2>
<ul>
<% #question.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field form-group">
<%= f.label :title, "Question" %><br>
<%= f.text_area :title, class:"form-control" %>
</div>
<div class="field form-group">
<%= f.label :brief, "Description" %><br>
<%= f.text_area :brief, class:"form-control" %>
</div>
<div class="field form-group">
<%= f.label :answers_expected %><br>
<% #answers_expected.each do |a| %>
<%= f.label :a, class: 'checkbox' do %>
<%= f.check_box :answers_expected, "a" %>
<%= a %>
<% end %>
<% end %>
</div>
My Questions show.html.erb:
div class="question">
<p>
<strong>Question:</strong>
<%= #question.title %>
</p>
<p>
<strong>Brief:</strong>
<%= #question.brief %>
</p>
<p>
<strong>Answers expected:</strong>
<%= #question.answers_expected %>
</p>
For some reason on my server, I get an error undefined methodmerge' for "a":Stringpointing to line<%= f.check_box :answers_expected, "a" %>in _form.html.erb, but it works when I changef.check_boxtof.radio_button`; why?
Even with radio_button, however, the Answers Expected display on the server continuously shows zero, despite what I click, which I also don't understand.
Also wrote specs hoping to point me in the right direction here:
question_spec.rb:
scenario 'with valid params' do
click_link 'Create a question'
fill_in 'Question', with: 'Valid question'
fill_in 'Description', with: 'This is valid description for the question.'
check 'One'
click_button 'Create Question'
page.should have_content 'One'
expect(page).to have_content('Question was successfully created.')
end
With my session_helper.rb having:
def submit_question(title = 'valid title', brief = 'valid brief')
click_link 'Create a question'
fill_in 'Question', with: title
fill_in 'Description', with: brief
check 'One'
click_button 'Create Question'
end
And my failed spec:
1) Visitor submits a question with valid params
Failure/Error: page.should have_content 'One'
expected to find text "One" in "Toggle navigation Labthi.ng Home Explore Recent Activity Example User Sign out × Question was successfully created. 0 Title: Valid Title Phase: 1 Brief: Valid brief for an idea Image: Active: true Components: App Categories: Other User: Example User Direct Define Reputation Activity Question was successfully created. Question: Valid question Brief: This is valid description for the question. Answers expected: 0 Idea: Valid brief for an idea User: Example User No comments. Add comment No answers yet. Why don't you add one ? Add answer Edit | Back"
# ./spec/features/question_spec.rb:16:in `block (2 levels) in <top (required)>'
Very confused! This is messing with my understanding of Rails a bit.
Thanks.
Edit:
Changed the syntax to <%= f.check_box :answers_expected, value: "a" %> , but the answers expected on the show page is still displaying as zero?
The correct way to set a value with the the check_box form helper is:
<%= f.check_box :answers, {}, "a" %>
:answers is the field name
{} is where you would put html attributes like class or id
"a" will be the value :)

Selecting a radio button with Rspec

I'm currently writing a test for a form using RSpec, and I was wondering how I'd go about selecting a radio button, given the form below:
<%=form_for(#whatever) do|f|%>
<%=f.label :option, "TRUE" %>
<%=f.radio_button :option, true %>
<%=f.label :option, "FALSE" %>
<%=f.radio_button :morning, false %>
<%=f.submit "SAVE" %>
<% end %>
I want my test to look something like:
describe "with valid options selected" do
before do
#CODE TO SELECT A RADIO BUTTON
click_button "SAVE"
end
end
describe "with valid info" do
before do
choose('True')
click_button "Create Setlist"
end
...
end
I had to assign an ID to the radio button for this to work as well
Doc for additional reference: http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Actions

Resources