I'm trying to write a test for a Bootstrap form using rspec. I have the following code:
<div id="published" class="col-sm-auto">
<div class="custom-control custom-radio custom-control-inline">
<%= form.radio_button :published, true, checked: page.published?, class: 'custom-control-input' %>
<%= form.label :published, 'Published', value: true, class: 'custom-control-label' %>
</div>
<div class="custom-control custom-radio custom-control-inline">
<%= form.radio_button :published, false, checked: !page.published?, class: 'custom-control-input' %>
<%= form.label :published, 'Hidden', value: false, class: 'custom-control-label' %>
</div>
</div>
which generates the following HTML:
<div id="published" class="col-sm-auto">
<div class="custom-control custom-radio custom-control-inline">
<input class="custom-control-input" type="radio" value="true" name="page[published]" id="page_published_true" />
<label class="custom-control-label" for="page_published_true">Published</label>
</div>
<div class="custom-control custom-radio custom-control-inline">
<input class="custom-control-input" type="radio" value="false" checked="checked" name="page[published]" id="page_published_false" />
<label class="custom-control-label" for="page_published_false">Hidden</label>
</div>
</div>
When I run this test, it fails with the message
it 'should default to unpublished' do
expect(page).to have_checked_field('Hidden')
end
giving the message expected to find visible field "page[published]" that is checked and not disabled but there were no matches. Also found "", "", which matched the selector but not all filters.
Looking at the HTML in the inspector, the field is visible and not disabled, and there is a label that matches the text. I have no idea what the two empty strings are about.
Please could somebody tell me why have_checked_field isn't matching? I'm really not keen on writing a more brittle test that uses has_css or has_xpath to look for an input tag with a specific ID — the whole point is that the user should see a field labelled "Hidden" and it should be checked, regardless of what's happening behind the scenes!
I'll 99.9% guarantee you the radio input isn't actually visible and has been replaced by an image using CSS (and maybe some JS). You could do
expect(page).to have_checked_field('Hidden', visible: false)
or you could do something slightly more complicated that verifies the label is actually visible like
expect(page).to have_css('input:checked + label', exact_text: 'Hidden')
Another solution if you're dealing with a lot of these radio buttons is to write a custom selector type something like
Capybara.add_selector(:bootstrap_radio) do
xpath do |locator|
XPath.descendant(:input)[XPath.attr(:type) == 'radio'].following_sibling(:label)[XPath.string.n.is(locator)]
end
filter(:checked) do |node, value|
node.sibling('input[type="radio"]', visible: :hidden).checked? == value
end
end
which would then allow you to do
expect(page).to have_selector(:bootstrap_radio, 'Hidden', checked: true)
and then you could write helper methods like have_checked_bootstrap_radio if wanted. Note: this code was off the cuff so the XPath/CSS expressions may not be 100% correct but the general idea is sound :)
Related
Current result: In deadline filter, it is considering the first box as "from date " and the second as "to date" and on applying the filter same tickets are repeating
Expected result: The deadline filter should work properly and on applying the filter tickets should not repeat
View:-
<div>
<div class="row">
<div class="col">
<label>Deadline Date</label>
<div class="d-flex">
<%= f.date_field :developers_deadline_date_gteq, class:"fa fa-calendar form-control", id: "todate-form" %>
<%= image_tag("datepickerArrow.svg", alt: "image is not loaded", class:"date-img") %>
<%= f.date_field :developers_deadline_date_lteq, class:"fa fa-calendar form-control", id: "fromdate-form" %>
</div>
</div>
</div>
</div>
Controller:-
#q = ClientRequest.with_resource_info_and_developer.page(params[:page]).per(params[:per_page]).ransack(params[:q])
#client_requests = #q.result
What am I doing wrong? I suspect it's got something to do with the way I'm passing params to Ransack but I don't see why it wouldn't work.
Any help is appreciated.
Database JOINs can lead to duplicate results, depending on the type of relation between both tables and the conditions run.
Just add distinct to your query to tell Ruby on Rails to only return unique records:
#q = ClientRequest
.with_resource_info_and_developer
.page(params[:page])
.per(params[:per_page])
.ransack(params[:q])
.distinct
I'm using sinatra as my web framework and right now I have
<p><%= #sentence %></p>
<form action='/' method='POST'>
<button type='submit'>Save Story</button>
</form>
in my erb file. The variable at #sentence changes at refresh. When I hit the save Story button I want it to create a param in the post method that is equal to #sentence so that I can save #sentence to the main page. Is there anyway to do this without javascript?
ANSWERED
I used
`<div class="row">
<form action='/' method='POST'>
<input id="sentence" type="hidden" name="sentence" value= "<%= #sentence %>" >
<button type='submit'>Save Story</button>
</form>
</div>`
its still only taking the first word on one of the 4 pages but there must be something else going on there.
You need to create a hidden input field with the value set to w.e #sentence is
<p><%= #sentence %></p>
<form action='/' method='POST'>
<input type="hidden" name="sentence" value="<%= #sentence %>" />
<button type='submit'>Save Story</button>
</form>
This will give the form something to pass that you can grab with post elsewhere, hope that helps, just put your variable where the ... is and be sure to tell it the language, here is a php example on how to add a varaible to a value.
value="<?php echo $state; ?>"
Here I'm basically telling the browser to echo(print) the state variable between the " and " using php start and end to initiate the language and end it, The hidden type input field is invisible to users and they cannot edit it, its a background trick you can use to pass information, it acts as a text field.
Information on hidden fields:
http://www.blooberry.com/indexdot/html/tagpages/i/inputhidden.htm
When you select an answer, please edit your main post to display ANSWERED and the updated code so users can see what you decide to use.
In sinatra you can do this:
<p><%= #sentence %></p>
<form action='/' method='POST'>
<input type="hidden" name="sentence" value="<%= #sentence %>" />
<button type='submit'>Save Story</button>
</form>
I'd like to reproduce this html sequence of radio buttons with simple_form in order to make simple_form work with http://semantic-ui.com/ syntax :
<div class="grouped inline fields">
<div class="field">
<div class="ui radio checkbox">
<input type="radio" name="fruit" checked="">
<label>Apples</label>
</div>
</div>
<div class="field">
<div class="ui radio checkbox">
<input type="radio" name="fruit">
<label>Oranges</label>
</div>
</div>
<div class="field">
<div class="ui radio checkbox">
<input type="radio" name="fruit">
<label>Pears</label>
</div>
</div>
<div class="field">
<div class="ui radio checkbox">
<input type="radio" name="fruit">
<label>Grapefruit</label>
</div>
</div>
</div>
So I prepared a custom wrapper :
config.wrappers :semantic_radios, tag: 'div', class: "grouped fields", error_class: 'error', hint_class: 'with_hint' do |b|
b.use :html5
b.use :label
b.use :input
end
Set some options :
config.item_wrapper_tag = :div
config.item_wrapper_class = 'ui radio checkbox'
And call this code in my form :
=f.input :child_care_type, collection: [["option 1", 1],["option 2", 2]], as: :radio_buttons, wrapper: :semantic_radios
I don't know where to customize the div.field encapsulation :
<div class="field">
<div class="ui radio checkbox">
<input type="radio" name="fruit" checked="">
<label>Apples</label>
</div>
</div>
My code only render this :
<div class="ui radio checkbox">
<input type="radio" name="fruit" checked="">
<label>Apples</label>
</div>
Can you help me ? I didn't find more wrapper's customization for collection :s
Summary:
I had done something similar to this before by creating a custom input that inherits from SimpleForm::Inputs::CollectionRadioButtonsInput and overloading just a few methods. For more on custom input components, see https://github.com/plataformatec/simple_form/wiki/Adding-custom-input-components.
In any case, the code below produces your desired html markup almost exactly using simple_form v2.1.0 and rails v3.2.15.
Code:
# File: app/inputs/semantic_ui_radio_buttons_input.rb
class SemanticUiRadioButtonsInput < SimpleForm::Inputs::CollectionRadioButtonsInput
# Creates a radio button set for use with Semantic UI
def input
label_method, value_method = detect_collection_methods
iopts = {
:checked => 1,
:item_wrapper_tag => 'div',
:item_wrapper_class => 'field',
:collection_wrapper_tag => 'div',
:collection_wrapper_class => 'grouped inline fields'
}
return #builder.send(
"collection_radio_buttons",
attribute_name,
collection,
value_method,
label_method,
iopts,
input_html_options,
&collection_block_for_nested_boolean_style
)
end # method
protected
def build_nested_boolean_style_item_tag(collection_builder)
tag = String.new
tag << '<div class="ui radio checkbox">'.html_safe
tag << collection_builder.radio_button + collection_builder.label
tag << '</div>'.html_safe
return tag.html_safe
end # method
end # class
Then, in your form, just do:
-# File: app/views/<resource>/_form.html.haml
-# Define the collection
- child_care_coll = %w( Infant Toddler Preschool Kindergarten ).map!.with_index(1).to_a
-# Render the radio inputs
= f.input :child_care_type,
:collection => child_care_coll,
:label_method => :first,
:value_method => :last,
:as => :semantic_ui_radio_buttons
Results:
<div class="input semantic_ui_radio_buttons optional childcare_child_care_type">
<label class="semantic_ui_radio_buttons optional control-label">
Child care type
</label>
<div class="grouped inline fields">
<div class="field">
<div class="ui radio checkbox">
<input checked="checked" class="semantic_ui_radio_buttons optional" id="childcare_child_care_type_1" name="childcare[child_care_type]" type="radio" value="1">
<label for="childcare_child_care_type_1">Infant</label>
</div>
</div>
...
<div class="field">
<div class="ui radio checkbox">
<input class="semantic_ui_radio_buttons optional" id="childcare_child_care_type_4" name="childcare[child_care_type]" type="radio" value="4">
<label for="childcare_child_care_type_4">Kindergarten</label>
</div>
</div>
</div>
</div>
I was having trouble with the same problem until I looked through config/initializers/simple_form.rb.
Turns out you can set the option here (line ~51):
# Define the way to render check boxes / radio buttons with labels.
# Defaults to :nested for bootstrap config.
# inline: input + label
# nested: label > input
config.boolean_style = :inline
A bit further down you can also define the default wrapper tag and wrapper tag class for the collection (line ~81):
# You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none.
config.collection_wrapper_tag = :div
# You can define the class to use on all collection wrappers. Defaulting to none.
config.collection_wrapper_class = 'styled-radios'
Hope this helps someone :)
*using gem 'simple_form'
With updated versions 'simple_form', '~> 3.0.2' and Semantic UI 0.19.3, I achieved it with following code.
class SemanticCheckBoxesInput < SimpleForm::Inputs::CollectionCheckBoxesInput
def input
label_method, value_method = detect_collection_methods
options[:collection_wrapper_tag] = 'div'
options[:collection_wrapper_class] = 'grouped inline fields'
#builder.send("collection_check_boxes",
attribute_name, collection, value_method, label_method,
input_options, input_html_options, &collection_block_for_nested_boolean_style
)
end
protected
def item_wrapper_class
"ui checkbox field"
end
end
and in the view
= f.association :branches, as: :semantic_check_boxes
Here is the output:
Using Simple_form 2.0.2
The simple form code using HAML:
= f.input :remember_me, as: :boolean, inline_label: 'Remember me'
But it renders this:
<div class="control-group boolean optional">
<label class="boolean optional control-label" for="admin_remember_me">Remember me</label>
<div class="controls">
<input name="admin[remember_me]" type="hidden" value="0" />
<label class="checkbox"><input class="boolean optional" id="admin_remember_me" name="admin[remember_me]" type="checkbox" value="1" />Remember me</label>
</div>
</div>
How do I remove that first label that's rendered, so that I only have the inline label?
You can use:
= f.input :remember_me, as: :boolean, inline_label: 'Remember me', label: false
Found a solution after much Google fu.
Use input_field instead of input which won't automatically generate a label.
= f.input_field :remember_me, as: :boolean, inline_label: 'Remember me'
For whom it doesn't work
= f.input_field ...
Use this way
= f.check_box ...
With simple_form 2.1.0 and rails 3.0.20, none of the solutions listed here worked (I don't want to use f.input_field because it's an admission of defeat).
The missing part is the boolean_style option:
options.merge!({label: false, boolean_style: :inline})
I suggest you create a custom input for this (e.g.: inline_checkbox)
boolean_style is configured as :nested by default, I think:
# Defaults to :nested for bootstrap config.
# :inline => input + label
# :nested => label > input
config.boolean_style = :nested
.control-group.error .help-inline {
display: none;
}
This should work, it works for me on rails 3.2 and simple_form 2.x+
Maybe too late, but inspired by gamov answer I have made this a custom wrapper from inline bootstrap checkbox in the initializer file 'config/simple_form_bootstrap.rb':
config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
b.use :html5
b.optional :readonly
b.use :label, class: 'col-sm-3 control-label'
b.use :input
b.use :error, wrap_with: { tag: 'span', class: 'help-block' }
b.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
end
which generates this html:
<div class="form-group boolean optional user_admin">
<label class="boolean optional col-sm-3 control-label" for="user_admin">Admin</label>
<div class="col-sm-9 checkbox-inline">
<input name="user[admin]" value="0" type="hidden">
<input class="boolean optional" id="user_admin" name="user[admin]" value="1" type="checkbox">
</div>
I have a haml like ;
= form_for #company, :html => {:multipart => true}, :url => update_user_company_path do |f|
.field
Title:#{f.text_field :name}
= f.fields_for :attachments do |builder|
- if builder.object.new_record?
.field
= builder.hidden_field :name, :value => 'logo'
= builder.file_field :file
- elsif builder.object.name.eql?('logo') && !builder.object.file.url.eql?('/files/original/missing.png')
.field
%span.thumbnail
= link_to "Delete", delete_company_attachment_path(#company, builder.object), :method => :delete, :class => "remove_image"
= image_tag builder.object.file.url, :style => "height:86px;width:125px"
= f.submit 'Ok'
Chrome renders this code as intended, but in Firefox it is like;
<form method="post" id="edit_company_29" enctype="multipart/form-data" class="edit_company" action="/users/25/company" accept-charset="UTF-8"><div style="margin:0;padding:0;display:inline"><input type="hidden" value="✓" name="utf8"><input type="hidden" value="put" name="_method"><input type="hidden" value="thisismytokenvalue=" name="authenticity_token"></div>
<div class="field">
Title:<input type="text" value="sdgdfgghjh" size="30" name="company[name]" id="company_name">
</div>
<input id="company_attachments_attributes_0_id" name="company[attachments_attributes][0][id]" type="hidden" value="114" /><input id="company_attachments_attributes_1_id" name="company[attachments_attributes][1][id]" type="hidden" value="115" /><div class="field">
<input type="hidden" value="logo" name="company[attachments_attributes][2][name]" id="company_attachments_attributes_2_name">
<input type="file" name="company[attachments_attributes][2][file]" id="company_attachments_attributes_2_file">
</div>
<input type="submit" value="Ok" name="commit">
</form>
Why is an element escaped. If you check haml, you can see I didn't put them.
Where did it come from?
Why is it happening?
Wow ... I've just had a similar issue. My guess is that if you pass nil to the form_builder's fields_for the hidden_input isn't returned with html_safe. To quickly fix that add a
-else
=""
after the whole elsif block
You must return something other than nil in the fields_for block.
This issue has been fixed in Haml 4.0.4 by mattwildig, with the help of #lulalala. Here is an explanation of the problem:
The #fields_for helper generates a hidden input field for each record, which it adds to the result of capturing the block. Normally the return value of capture will be a SafeBuffer, so this won’t be escaped. However if the block doesn’t write anything to the buffer then Haml returns a literal empty String from capture. The hidden input element is concatted to this string, and when it is combined with the rest of the entries, since it is a String being added to a SafeBuffer, it gets escaped.