My HTML/ERB looks like this
<fieldset class="row notifications">
<legend>
<hr class="dash blue inline">
<%= t :my_notifications %>
</legend>
<label>
<%= f.check_box(:subscribed_to_news) %>
<span></span>
<span class="checkbox-text"><%= t :accepts_to_receive_news %></span>
<br>
</label>
</fieldset>
When I debug my Cucumber test with Capybara, I do find the notification checkbox f.check_box(:subscribed_to_news) in this mess
page.find('.notifications label')['innerHTML']
# => "\n\t\t<input name=\"user[subscribed_to_news]\" type=\"hidden\" value=\"0\"><input type=\"checkbox\" value=\"1\" checked=\"checked\" name=\"user[subscribed_to_news]\" id=\"user_subscribed_to_news\">\n\t\t<span></span>\n\t\t<span class=\"checkbox-text\">blahblahblah</span>\n\t\t<br>\n\t"
But for some reason I cannot find the nested inputs nor find them by ID
page.find('.notifications label input')
# => Capybara::ElementNotFound Exception: Unable to find css ".notifications label input"
page.find('.notifications label #user_subscribed_to_news') # => Capybara::ElementNotFound Exception: Unable to find css ".notifications label #user_subscribed_to_news"
Selecting the label does work though
page.find('.notifications label')
# => #<Capybara::Node::Element tag="label" path="//HTML[1]/BODY[1]/DIV[1]/MAIN[1]/SECTION[1]/FORM[1]/FIELDSET[3]/LABEL[1]">
What am I doing wrong ? I just want to check the damn checkbox :'(
Most likely reason is the checkbox is actually hidden by CSS and then replaced with images to enable identical styling of checkboxes across different browsers. If you're using the latest Capybara you can have it click it the label when the checkbox is hidden by calling
page.check('user_subscribed_to_news', allow_label_click: true) # you can also set Capybara.automatic_label_click = true to default to this behavior
or if using an older capybara you would need to click the label yourself
page.find(:label, "blahblahblah").click #match on labels text
or
page.find(:label, for: 'user_subscribed_to_news').click #match on labels for attribute if set
It would seem that the checkbox is unreachable via normal css /xpath...
I got away using some javascript
page.execute_script(%Q{document.querySelector('#{area} input##{selector}').click()})
Related
I have an input that looks like this:
<%= f.input :email %>
The output I get from formtastic(v3.1.5) and rails(v4.2) looks like this.
<li class="email input required stringish" id="applicant_email_input">
<label for="applicant_email" class="label">Email<abbr title="required">*</abbr></label>
<input maxlength="255" id="applicant_email" type="email" value="davedave#gmail.com" name="applicant[email]">
</li>
What I really want is for formtastic to emit:
<div class="email input required stringish form-group" id="applicant_email_input">
<label for="applicant_email" class=" control-label">Email<abbr title="required">*</abbr></label>
<span class="form-wrapper">
<input maxlength="255" id="applicant_email" type="email" value="davedave#gmail.com" name="applicant[email]" class="form-control">
</span>
</div>
This is what this app emmitted with formtastic(v2.3.1) and formtastic-bootstrap(v3.0.0) and rails(v4.1).
I'd love to just include the gem for formtastic-bootstrap and get that old behavior back, but near as I can tell, formtastic-bootstrap dropped out around formtastic 3.
Now I have an app with a couple thousand calls to f.input, and I need to massage the output coming from formtastic. What's the best way to do that?
Maybe you could use formtastic's custom input? Also, these links might help: https://github.com/justinfrench/formtastic/blob/master/lib/formtastic/helpers/input_helper.rb and https://github.com/justinfrench/formtastic/issues/625.
Specifically, Justin French recommends that you monkey patch your app with an initializer in config/initializers/formtastic_patches.rb that would look something like this:
module Formtastic
module Inputs
module Base
module Wrapping
def input_wrapping(&block)
template.content_tag(:li,
[template.capture(&block), error_html, hint_html].join("\n").html_safe,
wrapper_html_options
)
end
end
end
end
end
And then switch the :li for a :div.
Here is a hacked version of formtastic I have named boomtastic which will do what you want.
(This actually includes all that you require except for the form-wrapper. However, the form-wrapper seems to be an element of bootstrap-formtastic only and not part of formtastic or standard bootstrap. If you really want to have the <span class="form-wrapper">, I think you can add this by editing boomtastic/lib/formtastic/inputs/base/wrapping.rb.)
What about a solution that uses jquery to change your form at page reload?
var ready = function () {
var $input = $('#applicant_email');
var input_html = $input.html();
$input.html('<span class="form-wrapper">' + input_html + '</span>');
}
$(document).on('turbolinks:load', ready);
You need to tell me how you want to select those fields, because in your example you did not include the full html and any explanation of the real problem.
I also see that the other divs have some other classes, that can be done with some easy jquery
Otherwise you can edit that gem
I'm using a cucumber/ruby/capybara/siteprism framework and I'm having problems identifying elements as either we're missing the ids, names, etc or they create them with a in real time.
I was mainly trying to define some of those elements in a siteprism page object model. For example, I was trying to enter some data in the 'input' field for 'First Name' below:
<div class="control-group">
<label class="control-label" for="input_field_dec_<random_number>">
First Name
<span class="required"></span>
</label>
<div class="controls">
<input id="input_field_dec_<random_number>" class=" span5" type="text" value="" scripttofire="SetUserFirstName('input_field_dec_<random_number>')" required="required" name="input_field_dec_<random_number>" data-val-required="First Name is required" data-val-regex-pattern="^[a-zA-Z0-9_ \-\']*$" data-val-regex="Only alphabetic and numeric characters allowed" data-val="true">
<span class="field-validation-valid help-inline" data-valmsg-for="input_field_dec_<random_number>" data-valmsg-replace="true"></span>
</div>
</div>
Is there a way to pass the label text (eg: 'First Name' - ignoring the spaces around, something like - contains='First Name') and then find the input element inside to set it up?
I was thinking something along the lines of:
element :first_name_field, :xpath, "//label[contains(text()='Continue'])/<and here something to find the input field?>" but cannot figure it out...
Capybara provides a bunch of built-in "selectors" that can be used for this, and you can add your own if you find it necessary. You can see the provided selectors by either building the Capybara docs yourself (rubydocs doesn't run the custom yard code used to generate that part of the docs) or by browsing the file where they are implemented - https://github.com/teamcapybara/capybara/blob/master/lib/capybara/selector.rb#L47
For your original example you can use the :field selector
element :first_name_field, :field, 'First Name'
which will match on the inputs associated label text. For you second example (from the comments) where the input and label have no connection (wrapped or for attribute) you should be able to do something like
element :some_field, :xpath, ".//label[contains(normalize-space(string(.)), 'label text')]/following-sibling::*[1]/self::input"
If you wanted to make that reusable you could add your own "selector" like
Capybara.add_selector(:sibling_input) do
label "Label adjacent sibling input"
xpath do |locator|
XPath.descendant(:label)[XPath.string.n.is(locator)].next_sibling(:input)
end
end
which could then be used as
element :some_field, :sibling_input, 'label text'
I want to retrieve the value of Test Services code
<p>
<span class="floatLeft w30p">Test Services code:</span>
<span> <strong>F603YPW</strong> </span>
</p>
The rest of the page will really affect what selector(s) you would need to use to get that text, however given only the HTML specified you can use the css adjacent sibling selector to get the element
value = find(:css, 'span.floatLeft.w30p + span').text
if there are a bunch of other elements with the floatLeft and w30p classes then you could get more complicated using xpath selectors and do something along the lines of
value = find(:xpath, XPath.descendant(:span)[XPath.string.n.is('Test Services code:')].next_sibling).text
or with multiple finds
value = find(:css, 'span', text: 'Test Services code:').find(:xpath, XPath.next_sibling).text
If you are able to edit the HTML to
<p>
<span class="floatLeft w30p">Test Services:</span>
<span class="your_class"> <strong>F603YPW</strong> </span>
</p>
(so by adding a class to the span),
you will be able to find its value doing
value = page.find('.your_class').text
If you are not able to edit the HTML, do
value = find(:css, 'the css selector').text
I am writing the test automaton code for a system and the dev team presented me the following html:
<div id="someId">
<div class="classA">
<button class="classB">
</div>
<div class="classA">
<button class="classB">
</div>
</div>
Now the question is: Is it possible to click exclusively on the SECOND button? If so - how?
If I understand you right, you're click on links styled as buttons. You can use this step definition
Then(/^I click the (\d+) instance of link "(.*?)"$/) do |instance, link|
page.all('a', :text => "#{link}")[instance.to_i - 1].click
end
I would not rely on the order of elements returned by all. I remember running into issues with it in the past, see e.g. this issue. Instead I'd use a selector, something like this:
find("#someId div.classA:nth-child(1) button.classB").click
(IIRC they are zero-indexed)
this is my view code where i have make multiple 'a' tag and want to test third element from li. and we can uniquely identified with offer id as per below code ...
<div class="search_data_outer_div">
<ul>
<li class="small_preview">
<div class="image_area">
<a href="/offer/show/334">
</div>
<span>
<span class="artist_name">Artist 1</span>
<span class="remaining_time">Remaining Time: 7 days</span>
<i id="334" class="icon-remove pointer" style="position:absolute;right:0;display:none;"></i>
</span>
</li>
and i have tried make one step defination ... it is working fine with cucumber but when execute with selenium (WebDriver) then page not open after click.
Scenario:
When I press third offer
Then I should see "YOUR OFFER"
and its step defination file
When /^I press third offer$/ do
page.execute_script %Q{ $(".search_data_outer_div ul li .image_area a").eq(2).click(); }
end
let me know right solution if anybody can help
thanks
IIRC CSS style selectors have issues with some version of Web Driver. Ideally you'd have PageObject variables set up for this so you're not using raw webdriver code in your steps but something like this should work:
browser.div( :class => 'search_data_outer_div').div( :class => 'image_area').links.first.click