I am trying to test an ajax request in rspec, but am not quite sure how to do it at this point It doesnt matter if it is rspec or capybara, I am just trying to get the test to pass, any advice is greatly appreciated
describe "Cart", js: true, search: true do
let(:product) { create(:product) }
let(:variant) { create(:variant, :product => product, :count_on_hand => 1, :sku=>"YIG01276") }
let(:flash_sale) { create(:flash_sale) }
let(:user) { create(:user) }
before do
flash_sale.variants << variant
flash_sale.save
product.reload
end
it "displays expiring time in cart" do
login_user user
visit spree.product_path(product)
click_button 'Add To Cart'
user.last_incomplete_spree_order.expires_in.should > 0
end
end
if you want to check behavior after ajax call, like update view. You need use capybara https://github.com/jnicklas/capybara with driver which support javascript, like selenium, webkit
if you just want to test the request, you can use rack-test directly
Related
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.
For some application I am using Paperclip for file upload (actually the dm-paperclip flavour), and Factory Girl, Rspec, Capybara for testing.
I have a very simple Factory for the "Picture" model, where I am stubbing my file properties as suggested in this post:
FactoryGirl.define do
factory :picture do
title "My Picasso"
description "It's like looking in a mirror."
picture_file_file_name { 'spec/resources/img_1.jpg' }
picture_file_content_type { 'image/jpg' }
picture_file_file_size { 1024 }
end
end
In diverse feature tests with Capybara, I visit pages in which the templates feature thumbnails of the Picture instances:
feature "List of Pictures", :js => true do
scenario "displays appropriately the index page of the pictures with pagination" do
FactoryGirl.create_list(:picture, 21)
visit '/pictures'
# And more testing...
end
end
An example of partial used in one of the templates:
= content_tag_for(:li, picture, :class => 'listed_picture') do
= link_to picture_path(picture) do
- if picture.picture_file?
= image_tag picture.picture_file.url(:thumb)
The problem I have now, is whenever I run the specs, the test fails because there is no matching route for the thumbnail url:
No route matches [GET] "/system/picture_files/1/thumb/img_1.jpg"
Is there any way to stub Paperclip's helper methods to make the test pass?
Thanks in advance for any help!
I just went through this process. Here's how I solved the issue.
First, I created a single method on the object to reference the image URL, both to abide by the law of Demeter and to make for an easier test. For you, that might look like:
#picture.rb
class Picture
...
def picture_file_url(size = nil)
picture_file.url(size)
end
...
end
Now we're ready to stub the Paperclip attachment URL in the spec:
describe "List of Pictures", :js => true do
it "displays appropriately the index page of the pictures with pagination" do
let(:picture) { create(:picture) }
allow(Picture).to receive(:picture_file_url) { "url" }
visit '/pictures'
# And more testing...
end
end
Hope this helps you or someone.
I'm trying to set up a RESTful API to a database of redirect links. I have set up a lot of tests in cucumber one of which is when a user does a GET on /links/:id. This is supposed to redirect the user to the link. It works in the browser but I'm having some trouble setting up this test in cucumber.
Given /^The link id part of the URL matches an existing entry in the links table$/ do
FactoryGirl.create(:users)
FactoryGirl.create(:links, :OWNER_USERID => Users.first.id)
Users.count.should==1
Links.count.should==1
end
When /^you use GET on link$/ do
visit link_path(Links.first.id)
end
The link_path specified sends me to this show method:
def show
redir=Links.find_by_id(params[:id])
redirect_to redir.target, :status=>307
end
The problem is just that cucumber fails on the When part complaining that I doesn't have a template for application/index. For some reason it does not redirect me but rather goes to root_path of my own site. Anyone knows how to check if such a redirect actually works?
Have you tried testing it in RSpec instead of Cucumber? Try something like this and see if it works:
describe "testing links" do
subject { page }
describe "use GET on link" do
let(:links) { Links.first }
before { get link_path(Links.first.id) }
specify { response.should redirect_to("http://example.com") }
end
end
Also make sure your test database if properly configured and populated before doing the tests.
rake db:migrate and rake db:test:prepare
Using Rspec and Capybara, I'm trying to test a failing validation for a form, where a "required" input is not filled in, so it fails. New navigators understanding HTML5 provide built-in validations, and I understand Capybara is using that as well. Before, I was using
page.should have_error
which doesn't work for me anymore.
Someone knows how to test this now?
Many thanks!
David
HTML5 client side validations are tricky to find. I found this post with a great answer.
The code is:
describe "when I leave required field empty" do
it "I get an the correct html5 validation error" do
#Leave the field empty
click_on "Save" # or whichever button triggers the submit
message = page.find("#field_id_attr").native.attribute("validationMessage")
expect(message).to eq "Please fill out this field."
end
end
Basically the way it works is that the field element has an attribute called "validationMessage" and the process is:
Click submit - this triggers the error message
Get a reference to the native(html) attribute(as opposed to the Capybara page object attribute) called "validationMessage". This will give you the value or the message itself.
Assert that the value is as expected.
I am not familiar with RSpec so I am not sure about what does have_error.
You should think about what you want to test exactly.
You surely don't want to test the exact behavior (what message is displayed, and how) as it is specific to each browser. What you want to test, because this is not specific to the browser, is the fact that the form is not submitted.
For instance, for a basic html form at root, with a required radio button "My value".
# Check form can not be submitted without the radio button
visit '/'
click_button 'Submit'
assert_equal '/', current_path
# Check form can be submitted with the radio button
visit '/'
choose 'My value'
click_button 'Submit'
assert_equal '/next', current_path
You should also consider to test only the presence of required in your html code, as the browser is supposed to work as expected (test only your code, not other's code)
If there is an error message, you can something along the lines of
page.should have_content("error")
This depends on how you handle the errors, and whether you use javascript or not.
This is an old post, however I will try to answer it
have_error is a method provided by webkit, to check e.g. if ajax requests or javascript in general running fine
I use to test my validations in my model specs:
describe 'validations' do
it { is_expected.to validate_presence_of :competitor_name }
it { is_expected.to validate_presence_of :chassi }
it { is_expected.to validate_presence_of :auction }
it { is_expected.to validate_presence_of :car_template_id }
end
or like
expect(FactoryGirl.create(:customer)).to be_valid
to check if my Factory is valid.
If you need to check your notices by targeting invalid inputs, you could test the html of your notice by capybara with the following:
it 'searches for specific order_car by chassi and model' do
visit order_cars_search_detailed_path
fill_in 'order_car_chassi', with: '123456'
select 'Octavia', from: 'order_car_car_template_car_template_id'
click_button 'Search Order'
expect(page).to have_content('THIS IS MY NOTICE')
expect(page).to have_content('123456')
end
Hope I could help some others running into this question.
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')