How to test for flash using cucumber - ruby-on-rails

I am writing cucumber tests for my RoR app and I need to test for a flash to appear:
<p class='flashnotice flash'>Message was successfully sent.</p>
However, I just can't find a solution that works. I've tried:
page.should have_selector('p', :class => 'flashnotice flash') do
page.should have_content fartknocker
end
But that returns an error on :class and says I can't use that. Can someone show me the right way to test for flash?

You can use this style instead
page.should have_css('.flashnotice', text: "Message was successfully sent")

Related

Capybara and remote links

I have this link in records_path page:
link_to "CLICK HERE", edit_record_path(record), remote: true
The controller:
def edit
puts request.format # Just to show you part of the issue
end
And when clicked, it executes the edit.js.coffee and renders a modal for editing the record.
It works great. The problem I have is with Capybara.
context 'when on records list page' do
before { visit records_path }
context 'when clicking on "CLICK HERE"', js: true do
before { click_link('CLICK HERE') }
it 'shows the record name' do
expect(page).to have_content record.name
end
end
end
When I run the test, it raise an error:
Capybara::ElementNotFound: Unable to find link "CLICK HERE"
But if I remove the js: true from the context, it works (It executes the edit method on the RecordsController) but the printed format is html instead of js. I don't even have an edit.html, I just have the edit.js.coffee and that is the one that should be rendered in the test.
What am I doing wrong? If the link has the remote: true prop, and the test has the js: true shouldn't be enough for make it work?
In your setup you don't actually create a record. I am assuming this is the cause of your problem. The edit_record link will not show up if you do not have records to edit. I could be wrong but from what you pasted I think this could be the cause.

Using regular expressions with Capybara

In the below capybara test I want to check that a user can see any number after 'Temperature:' when they visit the root path of my rails application. The value which is stored in the instance variable #temperature is retrieved from an API and is displayed to the user when the page is refreshed.
How can i put a ruby regular expression like 'Temperature: \d' into my spec below?
Spec:
require "rails_helper"
feature "user sees temperature" do
scenario "success" do
visit root_path
expect(page).to have_css 'p', text: 'Temperature: \d'
end
end
View:
<p>Temperature: <%= #temperature %></p>
This is about right, you just have to use regex syntax (//) instead of string one (''):
expect(page).to have_css('p', text: /Temperature: \d/)

hashes, flash and assert_not - how do I assert_not a hash

I'm trying to finish the exercises in the Mhartl RoR tutorial.
The question asks you to complete the following integration test
assert_not 'flash.FILLIN'
assert_select 'div#FILLIN'
assert_select 'div.FILLIN'
And I have a flash that shows either
{:success => "success message here"}
or upon error,
<% flash.each do |message_type, message| %>
taking the standard #user.errors.fullmessages.
My questions are:
How would I go about finding the list of #users.errors.fullmessages, and how do assert_not error?
assert_not 'flash.errors'
yields no exit:success... :(
any help appreciated, the link to the exercise is here: https://draft.railstutorial.org/book/sign_up#sec-signup_exercises
Turns out that it is
assert_not flash.nil?
and some helpful places to look: Check for array not empty: any?
:)
assert_not flash.empty?
Michael Hartl says "I prefer only to test that the flash isn’t empty" at
http://3rd-edition.railstutorial.org/book/sign_up#sec-signup_exercises
And he writes the same test at
http://3rd-edition.railstutorial.org/book/updating_and_deleting_users#code-successful_edit_test
To assert that there is no flash message of a particular type set (:error in this example), you can do:
assert_predicate flash[:error], :nil?

Capybara matcher for presence of button or link

Users on web page don't distinguish between "button" and "link styled as button".
Is there a way to add check whether a "button or link" is present on page?
For example Capybara has step:
page.should have_button('Click me')
which does not find links styled as buttons.
Updated answer (should matcher is deprecated in RSpec 3.0+):
expect(page).to have_selector(:link_or_button, 'Click me')
Before:
page.should have_selector(:link_or_button, 'Click me')
Followed from click_link_or_button which is defined here: https://github.com/jnicklas/capybara/blob/master/lib/capybara/node/actions.rb#L12
def click_link_or_button(locator)
find(:link_or_button, locator).click
end
alias_method :click_on, :click_link_or_button
It calls a selector :link_or_button. This selector is defined here: https://github.com/jnicklas/capybara/blob/master/lib/capybara/selector.rb#L143
Capybara.add_selector(:link_or_button) do
label "link or button"
xpath { |locator| XPath::HTML.link_or_button(locator) }
end
It calls this method: http://rdoc.info/github/jnicklas/xpath/XPath/HTML#link_or_button-instance_method
# File 'lib/xpath/html.rb', line 33
def link_or_button(locator)
link(locator) + button(locator)
end
So i tried to check the presence of the selector and it worked:
page.should have_selector(:link_or_button, 'Click me')
Using the expect syntax
expect(page).to have_selector(:link_or_button, 'Click me')
This works without needing to define a custom matcher.
You can also use a custom matcher
RSpec::Matchers::define :have_link_or_button do |text|
match do |page|
Capybara.string(page.body).has_selector?(:link_or_button, text: text)
end
end
Then do
expect(page).to have_link_or_button('Login')
Personally I would give your button or link an id and look for that using
page.should have_css('#foo')
This way you can refer to the link or button without worrying about its implementation.
I always find this useful: https://gist.github.com/428105
I think you can use the find button instance method:
(Capybara::Element) find_button(locator)
Using id, name, value.
Or if you want a link
(Capybara::Element) find_link(locator)
From: http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Finders#find_button-instance_method
I had an odd case where some smoke tests marched across various customer-centric login pages that had slight variations on doing the login submit button... Driven by a Cucumber table of user, org, etc.
# A bit of a hack, org_name is normally a subdomain, but sometimes it is the complete domain
def login(user, org_name)
# Use the below to automatically hit each user's org's server
if org_name.include? '.com'
Capybara.app_host = "http://#{org_name}"
else
Capybara.app_host = "http://#{org_name}.mydomain.com"
end
visit '/'
fill_in 'username', :with => user
fill_in 'userpwd', :with => '***'
begin
page.find(:link_or_button, 'submit')
click_on 'submit'
rescue Capybara::ElementNotFound
page.find(:link_or_button, 'Log In')
click_on 'Log In'
rescue Capybara::ElementNotFound
pending "Need to determine how to invoke the Login button for #{org_name} near Line ##{__LINE__} of #{__method__} in #{__FILE__} "
end
# -----------------------
# Work-around for modal popup saying SSL is mismatched if you are using actual production URLs
# The rescue is for cases that do not exhibit the modal pop-up
page.driver.browser.switch_to.alert.accept rescue Selenium::WebDriver::Error::NoAlertPresentError
# Ensure that login was successful
page.should_not have_content 'Login failed'
end
if html:
<a class="top-menu__item">text123
<span class="label">
<span class="label">86</span>
</span>
</a>
not work:
assert page.has_selector?(:link_or_button, text: 'text123')
assert page.should have_selector(:link_or_button, text: 'text123')

How to test css property in rspec?

I'm using tabnav plugin for Rails and I want to use rpsec to make sure it highlights properly.
describe 'account navigation links' do
it 'should have account settings link' do
get '/account/settings'
response.should have_tag("li", :text => "Account Settings")
end
it 'should be highlighted' do
get '/account/settings'
response.should have_tag("li", :color => "Account Settings")
end
end
However the above code doesn't seem to work. I'm using webrat with rspec btw. Any help? Thanks.
The only real thing to be testing here is whether or not a particular class name is applied, if highlighting comes from a class name. If so, you could do have_tag("li.highlighted", :text => "Account Settings").
Otherwise, you probably should not be automating your testing for whether or not the CSS selectors themselves are applied correctly. This is a purely presentational detail, and it isn't really what a test suite is designed to test. I suspect that Webrat doesn't bother to go through and apply your stylesheet for you, so testing that detail isn't feasible, not to mention that you could check with just one page load whether or not it's working - after all, you are arguably testing your stylesheet as you design it.
Anyway. Your question doesn't really make clear what you're really trying to test for, but you shouldn't be testing presentation, anyway. Testing the structure of the HTML document is good, but confirming how the client program interprets the document is the role of a designer, not a programmer. (If you wear both hats, so be it, but don't go mixing your foods.)
describe 'highlighting' do
it 'should highlight account/settings' do
get '/account/settings'
response.should have_tag("a.active[href=?]", account_settings_path, /Account Settings/i)
end
it 'should highlight account/profile' do
get '/account/profile'
response.should have_tag("a.active[href=?]", account_profile_path, /Profile Information/i)
end
it 'should highlight account/picture' do
get '/account/picture'
response.should have_tag("a.active[href=?]", account_picture_path, /Profile Picture/i)
end
it 'should highlight account/notifications' do
get '/account/notifications'
response.should have_tag("a.active[href=?]", account_notifications_path, /Notifications/i)
end
it 'should not highlight Profile' do
get '/account/profile'
response.should_not have_tag("a.active[href=?]", account_settings_path, /Account Settings/i)
end
it 'should not highlight Notifications' do
get '/account/profile'
response.should_not have_tag("a.active[href=?]", account_notifications_path, /Notifications/i)
end
it 'should not highlight Picture' do
get '/account/profile'
response.should_not have_tag("a.active[href=?]", account_picture_path, /Profile Picture/i)
end
end
You could write more test, especially for "doesn't highlight on wrong action" scenarios, but I think this is good enough.
If you're using Sass you can parse it with the Sass parser:
root = Sass::SCSS::Parser.new('.error { color: red; }', 'example.scss').parse
It returns a parse tree you could test by diving into it. For example:
prop = root.children.select {|child| child.rule.flatten.include?('.error')}.first
prop_strings = prop.children.map {|p| [p.name.flatten.first, p.value].join(':')}
prop_strings.should include?('color:red')

Resources