Using capybara to select radio button value that's in another field? - ruby-on-rails

I have a multiple choice quiz game written in Rails. I am trying to write an integration test that clicks through the quiz, selecting the correct answers. Here is my view:
<h2>The word is: <%= #question %> <br> </h2>
<h2>Your score is <%= session[:score] %> </h2>
<h2><%= #questions_remaining %> questions left!</h2>
<% answers = #quiz_words.shuffle %>
<%= form_tag("answer", method: "get") do %>
<%= radio_button_tag(:answer, "#{answers.first.id}")%><%= answers.first.definition %><br>
<%= radio_button_tag(:answer, "#{answers.second.id}")%><%= answers.second.definition %><br>
<%= radio_button_tag(:answer, "#{answers.third.id}")%><%= answers.third.definition %><br>
<%= radio_button_tag(:answer, "#{answers.fourth.id}")%><%= answers.fourth.definition %> <br>
<%= hidden_field_tag :orig, "#{#quiz_words.first.id}" %>
<%= submit_tag("Submit") %>
<% end %>
<%= link_to 'Back to Index', root_path %> <br>
The correct answer is being generated in the html source as a hidden field id = 'orig' with the value as the answer.
I want Capybara to look for the hidden field and it's value ("13"), then in the next step, select the radio button that has the same value as the hidden field. Here is the html source that gets generated
I am new to Capybara and wasn't able to find if its possible looking through it's docs.
Is this possible, if so can someone show me how to do it or point me to the docs for this?
Is this the best way to test the quiz functionality? or would I be better testing it in another way? (unit tests?)

Yes, this is possible, and you likely want to use an integration test here.
Find the hidden input
Get it's value
Choose the radio with the value returned in step 2.

The only slightly complicated thing here is that you want to look for a non-visible element, which you can do with the visible: false option.
orig_value = find('#orig', visible: false).value
choose(option: orig_value)

Related

Replacing button_to with dynamic Select form

I am complete beginner with forms, just trying to tame it but hopeless atm.
I have this following button_to setup:
<% #product.variants.each do |variant| %>
<div><%= variant.asin %></div>
<div><%= variant.price %></div>
<div><%= button_to "Add to cart", shopping_cart_path(:variant_id => variant) %></div>
<% end %>
This works quite fine, the problem with it is, it creates a several buttons for each product.
What I want to achieve is to have only one button and select, as shown below. Which directions do I need to take to pass this hash dynamically.
You could use select_tag and use it nested inside a form_tag. You will have a form containing a select tag inside.
Your code should look similar to this:
<%= form_tag shopping_cart_path do %>
<%= select_tag('variant', options_from_collection_for_select(#product.variants, "id", "asin")) %>
<%= submit_tag "Create" %>
<% end %>
Note: The code above is not tested, but it should give you an idea on how you should approach this.

How to send one or the other attribute in the form

I have a form for which I am using checkboxes (Not using radio buttons for my purpose). The problem I run into is when I submit a form, I get an error saying params is missing or value is empty:checkup. I am trying to use hidden filed but get the same error. HOw to have an option of sending only one if selected?
def checkup_params
params.require(:checkup).permit(:eye, :heart)
end
my form:
<%= form_for(#checkup) do |f| %>
<%= hidden_field_tag "checkup[eye]", nil %>
<%= check_box_tag :eye, "eye" %>
<%= hidden_field_tag "checkup[heart]", nil %>
<%= check_box_tag :heart, "heart" %>
<%= f.submit %>
<% end %>
I suggest reading this guide http://guides.rubyonrails.org/form_helpers.html#dealing-with-model-objects
Most specifically section 2.2. You really shouldn't be using tag helpers here.

disable button if user has previously performed that action

Tried to figure this out for a while without being able to crack the nut.
What I am trying to do is this.
I have a user model, it has_many answers. I would like to restrict the ability for one user to answer the same answer more than once. I've been able to block this in the model, however not in the view.
I would like the submit button to see if the current_user.id is present in the current answer id (the one it's thinking about filling out), if so disable the submit button saying "already applied".
My answers#new
<%= form_for #answer do |f| %>
<%= f.hidden_field :application_id, value: #application.id %>
<% if #application.question_2.length && #application.question_3.length >= 1 %>
<p>Question 1: <%= #application.question_1 %></p>
<%= f.text_area :answer_1 %><br/>
<p>Question 2: <%= #application.question_2 %></p>
<%= f.text_area :answer_2 %><br/>
<p>Question 3: <%= #application.question_3 %></p>
<%= f.text_area :answer_3 %>
<% elsif #application.question_2.length >= 1 %>
<p>Question 1: <%= #application.question_1 %></p>
<%= f.text_area :answer_1 %><br/>
<p>Question 2: <%= #application.question_2 %></p>
<%= f.text_area :answer_2 %><br/>
<% else %>
<p>Question 1: <%= #application.question_1 %></p>
<%= f.text_area :answer_1 %><br/>
<% end %>
<%= f.submit "Submit answers", data: { disable_with: "Please wait..." } %>
<% end %>
I see a couple different pieces of this. When I write similar functionality, I think about the following questions:
What should happen on page load / reload?
Should anything happen without page reload (ie. via AJAX / JS)?
Should the action be disabled server-side, client-side, or both?
First of all, if the user has already submitted an answer by the time the page loads, the template should display the button differently. Usually it makes sense to not display a form at all in that case, but if you want the form with the button disabled, the following code comes to mind (see html example):
<% if #user_has_answered %>
<%= f.submit "Submit answers", disabled: true %>
<% else %>
<%= ... normal button ... %>
<% end %>
If you're concerned about preventing the user from clicking the button twice when they submit the form from the page, some simple Jquery can easily handle that, or you can use disable_with as in your example twice. This has nothing to do with the state of the database; it merely sets up a Javascript listener that disables the button as soon as it's clicked (and changes its text) to prevent the user from accidentally double-submitting when pages load slowly.
You mentioned that you have prevented double answers in the model. How does the controller handle this? If a user somehow manages to fill out the form a second time and submit it (perhaps Javascript is disabled and they had multiple tabs open on the same page? If it's possible, users do it), what do you want to happen to the data they've submitted? Show them a rejection message? Preserve their data on the same page? This functionality should be 80% automatic in Rails, if you want it, as long as you handle the request and rejection in the same way that form validation errors are handled.
I'm happy to be more specific if you share more detail about what you're looking for or having trouble with.
Assuming that Answer belongs_to Application, you could do...
<% if current_user.answers.collect(&:application).include?(#application) %>
<%= f.submit "already applied", disabled: true %>
<% else %>
<%= f.submit "Submit answers", data: { disable_with: "Please wait..." } %>
<% end %>

Replacing drop down search menu with multiple links for form submission

This is what I'm hoping to do. Currently I have a drop down list of characteristics from which user can choose and search does certain element holds that characteristic. He picks a characteristic from drop down menu and clicks search button. Now I am trying to make a list of links for those characteristics so user can immediately click on certain characteristic.
I will have a couple of links separated with |:
characteristic1_link | characteristic2_link | characteristic3_link
Currently I have the following for drop down search which works:
<%= form_for(#element, method: 'get', url: 'query') do |f| %>
<%= f.collection_select :characteristic_id, Characteristic.all, :id, :name, :include_blank => true %>
<%= f.submit "Search" %>
<% end %>
I am trying to do that with links which I generate like this:
<% #characteristics.each do |characteristic| %>
<%= link_to (characteristic.name), '#' %>
<% end %>
How can I pass :characteristic_id parameter with link and somehow make f.submit to trigger when user clicks on link?
EDIT:
This seems to be working:
<% #characteristics.each do |characteristic| %>
<%= link_to (characteristic.name), query_path(:element => {:characteristic_id => characteristic.id}) %>
<% end %>
Opinions about this method? :)
if i understand your question like that clicking and link_to-anchor selects the option with the same name as the anchors label and submits the form then you might want to...
<%= link_to characteristic.name, '#', class: 'trigger_select' %>
and let your JS do the rest. (untested.)
$('.trigger_select').click( function() {
var href = $(this).attr('href');
$('#select_field').val(href);
$('#form').submit();
});
hope i understood you correcly.

Custom form processing

I have some custom form (user reputation) that doesn't link with any model directly.
I have several reputation criteria which affects final returation value
Here is code of the form
<%= form_tag("/add_reputing",:method => "POST") do%>
<div class="reputing_column">
<p>
<b>Your feedback:</b>
</p>
<p>
<%= text_area_tag :comment,"",{:class=>"or-form-textarea"} %>
</p>
<%= submit_tag("Submit",:class=>"or-button")%>
</div>
<div class="reputing_column">
<p>
<b>Recomendation:</b>
</p>
<% #criterias.each do |c| %>
<div class="reputing_row">
<label><%= c.name%>:</label>
<div>
<% (c.rating_from .. c.rating_to).each do |i| %>
<%= radio_button_tag "reputing_#{c.id}", i%><%= (i<1)? i : "+#{i}"%>
<% end %>
</div>
</div>
<% end %>
</div>
<% end %>
In controller I need to summirize a values of "reputing_#{c.id}" fields. And then add a record to user reputation table.
How it will be better and properly to process data from this form in controller? I tried to google that problem, but found nothing.
No answers, so I'll try to clarify the dealing with, as you called them, custom forms.
Here's the form for selecting a preferred color via radio buttons.
= form_for :preferences, url: '', method: :post do |f|
- %w[black blue white green red yellow].each do |color|
= f.radio_button :color, color
= f.label :color, color.capitalize, value: color
= f.submit
The cool thing about forms in Rails that they can be used with or without a model. If you have an instance variable called #preferences then this form will respect that and will call the color method on it to determine the "current" color. This color will be selected on the generated form. If this variable doesn't exist it won't be a big deal.
In any case, after submitting the form you'll be able to access the selected color via:
params[:preferences][:color]

Resources