Can't find element in Capybara even though it exists - ruby-on-rails

I am writing some Capybara tests, and am failing at what seemed to be quite straight forward search. I have HTML:
<div id="divId">
<div class="unimportantClass">
</div>
<form id="formId">
<div>
</div>
<h2>Irrelevant text</h2>
<p>Equally irrelevant</p>
<span class="remarkableSpan">
<i class="whatever"> </i>
Some text
<input id="targetTag">
</input>
</span>
</form>
</div>
I am trying to confirm existence of "targetTag"
Everything goes well in
expect(page).to have_css('div#divId form#formId span.remarkableSpan')
but with
expect(page).to have_css('div#divId form#formId span.remarkableSpan input')
or
expect(page).to have_css('div#divId form#formId span.remarkableSpan input#targetTag')
it fails to find it. Any ideas what is causing it?

Related

Capybara can't find element

I can't get Capybara to find an element here;
<div class="block__body">
<div class="programme-list">
<div class="programme-item">
<div class="programme-item__header">
<svg class="icon icon--type">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icons-flexi"></use>
</svg>
<h3 class="programme-item__title">Flexi programmes</h3>
</div>
<div class="programme-item__body">
<ul class="list-style-none">
<div class="progress">
<div class="progress__status">
<div class="progress__total">
<span class="progress__label">
Total <strong>£265000</strong>
</span>
</div>
<a class="action action--link action--understate" href="/sponsors/1/programmes/sport-fit-scheme-1">
<span class="action__label">Sport Fit Scheme</span>
<!--<svg class="icon icon--arrow">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#icons-chevron-right"></use>
</svg>-->
</a>
This is my code in my rspec file.
scenario 'Update programme' do
programme = create(
:programme,
id: 2,
name: 'Acme Two Programme',
description: 'The description for the Acme Two Programme',
account: create(:account)
)
sign_in_as(admin)
click_link 'Programmes'
within(:css, '.programme-list') do
within(:css, '.programme-item') do # this does not work...
end
end
The error I get is;
Capybara::ElementNotFound: Unable to find css ".programme-item"
Why can't it find the element? Is it because I have several of these elements in theory with the same name? If so, how can I specify just one?

Rspec, testing AJAX, count list items

My app has a dashboard with 3 columns.
All three columns represent a different state(field of model) of that object.
When in the first column it's 'pending', when you approve it, it goes to the 'accepted' column.
I start off by creating 3 objects, 1 in each column.
Then I want to be able to press the approve button of the first column and test if it moved to column 2.
This is the structure of the code currently:
<div class="col-xs-3 pending-candidates">
<div class="collection-menu">
<h1>Candidates</h1>
<div class="icon-menu"></div>
<i class="material-icons">done</i>
</div>
<ul id="applied-desktop-dashboard-ajax">
<li class="collection-item applied-candidate" id="pending_8"> <=== NEED TO COUNT THIS
<div class="first-content">
<div class="candidate-details">
<a href="/employees/8">
<h1>Patrick M.</h1>
</a>
</div>
</div>
<div class="second-content" style="display: none;">
<a data-remote="true" rel="nofollow" data-method="patch" href="/matchings/216?state=denied">
<i class="material-icons close-deny">close</i>
</a>
<a data-remote="true" rel="nofollow" data-method="patch" href="/matchings/216?state=accepted">
<i class="material-icons close-accept">done</i>
</a>
</div>
</li>
</ul>
I try to accessing it like following:
expect(page).to have_selector('applied-desktop-dashboard-ajax li', count: 1)
expect(page).to have_css('applied-desktop-dashboard-ajax li', count: 1)
and it returns following error message:
expected to find css "applied-desktop-dashboard-ajax li" 1 time
but there were no matches
same goes for when I only want to check if it has the ul (its always there even if it has no objects loaded in).
Anyone has an idea how to count the list items?
I think you just forgot the ID prefix (#) in your selector, it should be:
expect(page).to have_css('#applied-desktop-dashboard-ajax li', count: 1)

ng-model not working for certain attributes in angularJS

Hi I encountered a problem with ng-model. I want to create an edit page for admin user to edit the rest of the user's permission level.
So, I listed out all the user's attributes in the edit page, and these attributes should display the current values.
I can update all the attributes correctly, however, the problem is that when visiting the edit page, only certain attributes are displayed while some are not. I think it is the problem with ng-model.
code snippets from my _form.html.erb
<div class="col-md-12 space-1" ng-class="{ 'has-error' : form['email'].$invalid }">
<label class="control-label">Email</label>
<div class="input-icon right">
<i ng-show="form['email'].$invalid" class="fa fa-warning tooltips" data-original-title="{{errors['email']}}" data-container="body"></i>
<input ng-model= "user.email" name="email" type="text" class="form-control">
</div>
</div>
<br>
<div class="col-md-12 space-1" ng-class="{ 'has-error' : form['events'].$invalid }">
<label class="control-label">Event Permission Level : {{user.activities.events}}</label>
<div class="input-icon right">
<i ng-show="form['events'].$invalid" class="fa fa-warning tooltips" data-original-title="{{errors['events']}}" data-container="body"></i>
<input ng-model= "user.activities.events" name="activities.events" type="range" max="2" min="0" class="form-control">
</div>
</div>
<br>
<div class="col-md-12 space-1" ng-class="{ 'has-error' : form['admin_events'].$invalid }">
<label class="control-label">Admin Event Permission Level : {{user.activities.admin_events}}</label>
<div class="input-icon right">
<i ng-show="form['admin_events'].$invalid" class="fa fa-warning tooltips" data-original-title="{{errors['admin_events']}}" data-container="body"></i>
<input ng-model= "user.activities.admin_events" name="activities.admin_events" type="range" max="2" min="0" class="form-control">
</div>
</div>
<br>
The code above shows 3 different ng-models, 1.user.email, 2.user.activities.events 3.user.activities.admin_events
The way I process them is the same, but when visiting the edit page, only email and events attributes displayed the current value, but not admin_events. I can update their values alright, but I cannot get admin_events to display its current value when visiting the edit page. This is weird isn't it. I mean if I can see the value of events, why can't I see the value of admin_event since they all belong to the user variable.
Can anyone explain why is it like this? It is very confusing for me. Thank you very much.
As it solved the problem, I quote myself from the comments :
If only user.activities.admin_events is not working, it may be related to the _ notation. Try camel case user.activities.adminEvents or user.activities['admin_events'].

How "assert_select" works in Rails

I was trying the following test in my Rails app:
test "markup need for store.js.coffee is in place" do
get :index
assert_select '.store .entry > img', 3
assert_select '.entry input[type=submit]', 3
end
The test is all ok, I haven't failures or errors, but I can't understand what assert_selects are looking for in my HTML.
I will try to explain myself in a better way: is assert_select '.entry input[type=submit]', 3 looking for exact 3 fields of input type=submit inside the .entry element? and What is the first asser_select looking for?
This is the HTML where assert_selects act
<body class="store">
<div id="columns">
<div id="main">
<h1>Your Pragmatic Catalog</h1>
<div class="entry">
<img height="95px" src="/assets/cs.jpg" alt="Cs">
<h3>CoffeeScript</h3>
<p> CoffeeScript is JavaScript done right. It provides all of JavaScript's functionality wrapped in a cleaner, more succinct syntax. In the first book on this exciting new language, CoffeeScript guru Trevor Burnham shows you how to hold onto all the power and flexibility of JavaScript while writing clearer, cleaner, and safer code. </p>
<div class="price_line">
<span class="price">$36.00</span>
<form class="button_to" method="post" data-remote="true" action="/line_items?product_id=2">
<div>
<input type="submit" value="Add to Cart">
<input type="hidden" value="H5APP93C0onJsfliaMRqww+ER0u/hTZAjvGIeMluHIo=" name="authenticity_token">
</div>
</form>
</div>
</div>
<div class="entry">
<img height="95px" src="/assets/hp.jpg" alt="Hp">
<h3>Harry Potter</h3>
<p>Mago</p>
<div class="price_line">
<span class="price">$15.00</span>
<form class="button_to" method="post" data-remote="true" action="/line_items?product_id=5">
<div>
<input type="submit" value="Add to Cart">
<input type="hidden" value="H5APP93C0onJsfliaMRqww+ER0u/hTZAjvGIeMluHIo=" name="authenticity_token">
</div>
</form>
</div>
</div>
<div class="entry">
<img height="95px" src="/assets/ruby.jpg" alt="Ruby">
<h3>Programming Ruby 1.9 & 2.0</h3>
<p> Ruby is the fastest growing and most exciting dynamic language out there. If you need to get working programs delivered fast, you should add Ruby to your toolbox. </p>
<div class="price_line">
<span class="price">$49.95</span>
<form class="button_to" method="post" data-remote="true" action="/line_items?product_id=3">
<div>
<input type="submit" value="Add to Cart">
<input type="hidden" value="H5APP93C0onJsfliaMRqww+ER0u/hTZAjvGIeMluHIo=" name="authenticity_token">
</div>
</form>
</div>
</div>
<div class="entry">
<img height="95px" src="/assets/rtp.jpg" alt="Rtp">
<h3>Rails Test Prescriptions</h3>
<p>
<em>Rails Test Prescriptions</em>
is a comprehensive guide to testing Rails applications, covering Test-Driven Development from both a theoretical perspective (why to test) and from a practical perspective (how to test effectively). It covers the core Rails testing tools and procedures for Rails 2 and Rails 3, and introduces popular add-ons, including Cucumber, Shoulda, Machinist, Mocha, and Rcov.
</p>
<div class="price_line">
<span class="price">$34.95</span>
<form class="button_to" method="post" data-remote="true" action="/line_items?product_id=4">
<div>
<input type="submit" value="Add to Cart">
<input type="hidden" value="H5APP93C0onJsfliaMRqww+ER0u/hTZAjvGIeMluHIo=" name="authenticity_token">
</div>
</form>
</div>
</div>
</div>
</div>
</body>
Good question. I'm working through the same book - Agile Web Development with Rails 4. It's good stuff.
To answer your question:
The first assert_select is looking for exactly 3 image elements that are direct children of the .entry element which is below the .store element on the dom tree.
The second is, as you suggest, looking for 3 inputs fields of the type submit that are below the .entry element on the dom tree.
First select is looking for img placed as first child of element with .entry class, which is descendant of element with class .store
http://css-tricks.com/child-and-sibling-selectors/

Click on element with capybara

I have a yes/no slider on a web page that i need to interact with. I need to click on one of the elements so that the value changes from true to false or false to true. Using the id i can get the value of the element with
find_field('passcode_policies__allow_simple').find('option[selected]').value
But i have tried over and over to simulate a click on this object to change the value and have been unsuccessful.
<div class="control-group">
<select class="toggle" id="passcode_policies__allow_simple" name="passcode_policies[][allow_simple]" style="display: none; " tabindex="-1">
<option value="true" selected="selected">Yes</option>
<option value="false">No</option>
</select>
<div class="ui-switch off" tabindex="0">
<div class="ui-switch-mask">
<div class="ui-switch-master" style="left: -38px; ">
<div class="ui-switch-upper">
<span class="ui-switch-handle" style="left: 33px; "></span>
</div>
<div class="ui-switch-lower">
<div class="ui-switch-labels">
Yes
No
</div>
</div>
</div>
</div>
<div class="ui-switch-middle" style="width: 60px; ">
</div>
</div>
<label class="inline">Allow simple value</label>
<span class="help-block">Permit the use of repeating, ascending, and descending character sequences</span>
</div>
If you're using Selenium, headless webkit or phantomjs (poltergeist gem) you should be able to call the simple
click_link 'Yes'
but if you're just using straight up capybara you will have to interact with the select element with something like
select('Yes', :from => 'passcode_policies__allow_simple')
and you can check the visibility and whatnot with this capybara: page.should have_no_content doesn't work correctly for display:none element
Working solution:
within(:css, '#passcode_policies__allow_simple + .ui-switch') do
click_link 'No'
end

Resources