Capybara, TestUnit: testing presence of hyperlink without label - ruby-on-rails

I'm using Capybara to perform some functional tests on a Ruby On Rails app.
(Everything seems properly configured, as other Capybara tests run as expected.)
In my home page I have a link to the sign up one, in this format:
<a href="http://www.example.com/signup" class="sign_up_1">
<div class="signUpStyle">Sign Up</div>
</a>
In my test:
page.has_link?("Sign Up", :href => '/signup')
always returns false. It shouldn't, should it?

Yes it will return false.
Since the final xpath generated would have "//a[#href='/signup']" which is not a valid xpath for your dom.
You can do
page.has_xpath?("//a[#href='#{sign_up_path}']")
capybara-docs
You can also verify
page.has_link?('Sign Up', href: "http://www.example.com/signup/company")

Related

Rails - Capybara, populate hidden field from trix-editor

I use Trix Editor to have WISIWIG in my form. I want to test with RSpec and Capybara but trix-editor put the field hidden.
<div class="form-group">
<trix-editor class="formatted_content form-control" placeholder="Description" input="annonce_ad_body_trix_input_annonce_ad"></trix-editor><input type="hidden" name="annonce_ad[body]" id="annonce_ad_body_trix_input_annonce_ad" />
</div>
I need to know how i can fill this hidden field with Capybara to make my test pass. I have try these attemp:
fill_in "annonce_ad[body]", with: "my value"
find(:css, 'trix-editor').set("New text")
find("trix-editor", visible: false).set("my value")
find(:xpath, "//input[#id='annonce_ad_body_trix_input_annonce_ad']", visible: false).set "my value"
find(:xpath, "//*[#id='annonce_ad_body_trix_input_annonce_ad']", visible: false).set("value")
first('input#annonce_ad_body_trix_input_annonce_ad.class', visible: false).set("your value")
None of these have work for me. Someone have any idea how i can fill my body(with trix) in this case?
When using Capybara the rule when dealing with non-standard controls is to mimic what the user would do. In this case that would be click on the visible field (trix-editor element) and then type the contents wanted. You should never be trying to fill in non-visible elements and in fact the visible option should rarely (if ever) be used when testing an app (makes some sense if using Capybara for scraping). So in your case that should be
find('trix-editor').click.set('New text')
It would probably work without the click, but it doesn't hurt to more fully replicate the user. Since you've stated that something very similar to that doesn't work for you (but not provided the actual error) I have to assume you're not actually using a JS capable driver. Since trix is a JS driven editor you need to use a JS capable driver when testing it - https://github.com/teamcapybara/capybara#drivers .
The following basic ruby snippet shows Capybara filling in the demo trix editor at trix-editor.org
require 'capybara/dsl'
require 'selenium-webdriver'
sess = Capybara::Session.new(:selenium_chrome, nil)
sess.visit('https://trix-editor.org/')
editor = sess.find('trix-editor')
editor.click.set('My test text')
editor.assert_text('My test text')
I make a mistake, this work for me.
find(:xpath, "//*[#id='annonce_ad_body_trix_input_annonce_ad']", visible: false).set("some value here")

Rspec/Capybara - how to target data-target attribute inside a span

in my Rails4/rspec app, I need to male Capybara click on a zone that has no formal "link" , using data-target attribute.
html
<div class="info-zone">
<span data-target="#myInfoZone1" class="City" data-toggle="modal">
</span>
</div>
My current attempt at using capyabar fails
describe "modal loads with the right content" do
it "has right text" do
visit actual_page_path(:id => #deal.id)
find("span[data-target='#myInfoZone1']").click
end
I currently get this error
Capybara::ElementNotFound:
Unable to find css "span[data-target='#myInfoZone1']"
How can I make capybara "find" and click on the zone ?
Thanks for your help
EDIT
I found out why capybara is not finding it!
for a reason I can't understand, that is the html output code capybara finds
<!-- city zone -->
<div id="city-zone">
<!--
We gather here the various types of <spans> and load it via javascript
we append it to the the div id=city-zone
-->
</div>
I am using javascript to load inside this div. so when I load the 'page source' i see what's above
but when I go on chrome dev tools, then I see:
<!-- city zone -->
<div id="city-zone">
<div class="info-zone">
<!--
We gather here the various types of <spans> and load it via javascript
we append it to the the div id=city-zone
-->
<span data-target="#myInfoZone1" class="City" data-toggle="modal">
</span>
</div>
</div>
So i guess capybara sees the same thing as I see when I load the page source: no .
how come my javascript which I append does not appear in the html code source?
what to do about it to make capybara work
Capybara's default driver only tests html rendered by your back-end application server. If you want to test pages with front-end javascript as well, you should use a javascript-enabled driver with Capybara.
Luckily, the folks at thoughtbot made a Capybara extension just for that Capybara-webkit You can easily install it in your Gemfile. Follow the instructions here on how to install the gem.
Finally, once you install it, you can enable javascript tests in your feature specs by adding js: true in your features/scenarios as following:
RSpec.feature "test my new feature", js: true do
# my test
end

How to test for a target="_blank" attribute with Capybara?

I'm trying something which I thought would be simple. I need to modify a link to have the target="_blank" attribute and I would like to have a test to confirm that it's actually on the page. I've tried a ton of variations, the closest I can get is:
it { should have_link('change', href: 'url', target: '_blank') }
but that just throws an error saying that 'target:' is an invalid key. Is there a way to test for this attribute? Moreover, is there a general method for testing for HTML element attributes? The information I've found isn't clear.
Using Capybara 2.1.0, Rails 4.0.5.
Thanks
You can do what you want, or test for any attribute value, using have_selector and the CSS selector syntax for specifying attribute values, like this:
it { should have_selector('a[href="url"][target="_blank"]') }
It can't be done with have_link, since have_link
doesn't take any HTML attribute as an option (it takes the options that have_selector takes, plus :href), and
doesn't let you specify the entire selector.

Rspec view test not working out, help me troubleshoot

I'm writing Rspec view tests, and the tests are not passing, but I'm not sure why. In other words there are no errors in the way the test is written, it's just that the expectation is not meeting the result. Would love help troubleshooting here.
In the test below, I initially thought the problem was that the link I'm looking for is in the navbar in the application layout. So following advice from this post: getting Rspec view specs to render application layout, I explicitly called which template and layout to render. However, the right link still cannot be found.
The href tag that I've written is copied directly from the inspect element on the actual page. I have also tried to write the new_request_path that the routes gives me, and that didn't work either.
Thanks for any help!
RSpec View test code:
describe 'signups/new.html.erb' do
it 'displays link to request pages not signup page' do
assign(:signup, FactoryGirl.build(:signup))
render template: "signups/new", layout: "layouts/application"
rendered.should have_link(href: "/new")
end
end
FYI, Inspect Element:
<a class="navbar-brand" href="/new">Make a new request</a>
FYI, Routes:
get 'new', to: 'requests#new', as: 'new_request'
FYI, the application layout being rendered:
<nav class="navbar navbar-inverse navbar-static-top" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="<%= root_path %>">Home</a>
<a class="navbar-brand" href="<%= new_request_path %>">Make a new request</a>
I don't see the need to post anything from the new template being rendered since hte test is looking only inside the application layout. (But it's not a layout based view test, because 1) I'm testing pages as a whole and there are different flash messages triggered in the layout and because 2) other tests that I'm writing [similarly stuck but I think I can figure them out if I get help on one] look at the actual new template)
Somewhat figured this out, here are some short hand notes:
Render_view in controller never worked, I just removed it
completely (at least controller tests pass!)
So terrible, but reason view tests weren't passing is because my
model is named Request so my variables were #request, which
apparently is a class already, so there was a name conflict. I
basically had to change every instance of #request to #requestrecord
There were indeed some syntax errors in the tests. have_selector('csstag') MUST be prefixed with either a . for css class or # for css id. As well, have_link MUST take a name of link, e.g., have_link("Home", href: root_path). If latter can be changed, that'd be great, because I think it's worrisome to have a hard written title of the link, which can easily change.
In two views that were tested, the first lines of code in the actual view were if/then statements testing for errors in form submission (and then flashing up an appropriate message) of a certain variable. This tripped up the view because in isolation, these variables were never defined. So in the tests, I had to always add a before block that just passed through some arbitrary data for the variable.

Why is Rspec/Capybara giving me a expected css ... to return something error?

The test I am using is:
it { should have_link('Logout', href: logout_url) }
I am just testing for the existence of a <a> tag with Logout as the text, and the href to be logout_url path. Should I be using another syntax for this?
Gems:
rails 3.2.6
rspec-rails 2.10.1
capybara 1.1.2
There are a number of ways you can do this. I'd recommend (if you haven't already) familiarizing yourself with the overall capybara dsl as well as some of the specific sections such as the capybara matchers.
I believe your test is fine written as:
it { should have_link('Logout', href: logout_url) }
as long as the link text really is 'Logout' and the href is specified correctly (see below).
According to the capybara docs, the first parameter to have_link is what's called the locator. In your case it's 'Logout'. This can be either the text in the link itself, or it can be the #id of the dom element. So in your case you need to have the text 'Logout' in the link that has the logout_url link.
Note that locaters in capybara are case sensitive, so make sure you match on case.
You might also want to consider whether you should be using logout_url and not logout_path. By default, rails doesn't always generate the full url for most links. It just generates paths. Here's the difference:
users_url: http://localhost/users
users_path: /users
Check your page to see which of these types of url's are being generated by your app.
Probably it should be logout_path.
Also you can try to use save_and_open_page to understand what's going wrong.

Resources