Using RSpec2 to test a controller's show action - ruby

I have a fairly simple Rails 3 project where I've defined a custom route:
get 'factions/:name' => 'factions#show', :as => :factions
get 'factions' => 'factions#index'
... which when running rails s gives me the expected page (http://localhost:3000/factions/xyz is HTTP 200 with the app/views/factions/show.html.haml being displayed). However I've tried multiple different ways of expressing a spec that will work, below is my latest incarnation:
require 'spec_helper'
describe FactionsController do
render_views
describe "GET 'show'" do
before { get '/xyz' }
subject { controller }
it { should respond_with(:success) }
it { should render_template(:show) }
end
describe "GET 'index'" do
it "should be successful" do
get 'index'
response.should be_success
end
end
end
The GET 'index' spec passes without complaint but no matter what I do the GET 'show' specs cannot pass - even if they do succeed when I am browsing to them locally.
1) FactionsController GET 'show'
Failure/Error: before { get '/xyz' }
ActionController::RoutingError:
No route matches {:controller=>"factions", :action=>"/xyz"}
# ./spec/controllers/factions_controller_spec.rb:7:in `block (3 levels) in <top (required)>'
The action really should be show but my routes.rb configuration must be incorrect or something. What gives?
(Additional context: I am using bundle exec spork for speeding up my specs and I have restarted the spork server multiple times just to make sure I'm not completely insane.)

Change:
before { get '/xyz' }
To:
before { get :show, :name => 'xyz' }

Related

How to simulate a POST request in Ruby with the webmock gem?

I am trying to simulate a POST request with rspec. I thought about using the webmock gem, after searching how it worked, my code looks like this:
Gist_Request_spec.rb:
require_relative '../Gist_Request.rb'
require 'spec_helper'
require 'webmock'
include WebMock::API
WebMock.enable!
RSpec.describe GistRequest do
describe "#post" do
it "crear gist" do
stub_request(:post, "https://api.github.com/gists").
with(
body: {"description" => "description","public" => true,"files" => { "file.txt" => { "content" => "content" }}},
headers: {
'Accept'=>'*/*',
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
'Authorization'=>'Basic Sm9lbEFsYXlvbjEyMzo0NzVmYjI1ZWU0MGQyNGQzZGM1NWQ0MzQ5YjI4MTU3MjM1ZjdmZDBk',
'Host'=>'api.github.com',
'User-Agent'=>'Ruby'}).to_return(status: 201, body: "", headers: {})
expect(WebMock).to have_requested(:post, "https://api.github.com/gists").with { |req| req.status == 201 }
end
end
end
I added code to my file spec_helper.rb and now it looks like this:
The first lines spec_helper.rb:
require 'webmock/rspec'
WebMock.disable_net_connect!(allow_localhost: true)
But when I run rspec spec/Gist_Request_spec.rb, it returns the following error:
GistRequest
#post
crear gist (FAILED - 1)
Failures:
1) GistRequest#post crear gist
Failure/Error: expect(WebMock).to have_requested(:post, "https://api.github.com/gists").with { |req| req.status == 201 }
The request POST https://api.github.com/gists with given block was expected to execute 1 time but it executed 0 times
The following requests were made:
No requests were made.
============================================================
# ./spec/Gist_Request_spec.rb:21:in `block (3 levels) in <top (required)>'

Rspec is different from the app

I'm currently working on a Ruby/Sinatra App and now I'm stuck because my rspec testing is not working properly on the controller. But when I tried my API using curl or web the code just works!.
Here are my file, spesificly on that line of code
listproduct_controller.rb
get '/' do
products = Product.all
payload = []
products.each do |product|
payload.push({ :exhibit_name => product.exhibit_name, :icon => product.icon })
end
return {
:status => 'SUCCESS',
:message => 200,
:payload => payload
}.to_json
end
and here are my spec file
listproduct_controller_spec.rb
context "GET to /products" do
before { allow(Product).to receive(:all) }
before { allow(Product).to receive(:find_by) }
it "returns status 200 OK" do
get '/'
puts(last_response)
expect(last_response).to be_ok
end
it "show a list of product's name and its icon" do
get '/'
#products = Product.all.to_a
expect(last_response.body).to include_json(#products)
end
end
When I puts the last_response on spec it shows this
500
{"Content-Type"=>"text/html", "Content-Length"=>"212150"}
#<Rack::BodyProxy:0x0000000480b1d8>
but when im using curl or apps it just works and return
200 status code with the payload
Can anyone help me what I did wrong?
UPDATE :
I solved it, it was the problem on the database, where all the product in the development database were not on the test database so it returns 500 of empty database.

hartl chapter 5 full_title not found

I'm in the Hartl tutorial in Chapter 5.
I'm getting the following error when running the test file:
Failures:
1) User pages Signup page
Failure/Error: it { should have_selector('title', text: full_title('Sign up')) }
NoMethodError:
undefined method `full_title' for #<RSpec::Core::ExampleGroup::Nested_2::Nested_1:0xaeb792c>
# ./spec/requests/user_pages_spec.rb:12:in `block (3 levels) in <top (required)>'
For brevity, I've commented out the other "full_title not found" errors while troubleshooting.
I've confirmed that the method is in the app/helpers/application_helper.rb file.
Any ideas why it's not being found? It's most definitely in the helper file.
My user pages spec file:
require 'spec_helper'
describe "User pages" do
subject { page }
describe "Signup page" do
before { visit signup_path }
it { should have_selector('h1', text: 'Sign Up') }
it { should have_selector('title', text: full_title('Sign up')) }
end
end
and my application_helper.rb file
module ApplicationHelper
# Returns the full title on a per-page basis.
def full_title(page_title)
base_title = "Ruby on Rails Tutorial Sample App"
if page_title.empty?
base_title
else
"#{base_title} | #{page_title}"
end
end
end
The Tutorial seems to add that in a different place that yours. The full_title used on the spec was defined on spec/support/utilities.rb. The one defined on the application_helper.rb was used in app/views/layouts/application.html.erb.

Obtaining a render Argument Error: What is the correct syntax or usage?

I am new to Ruby, Sinatra and Pusher so this is a basic question. I am attempting to authenticate a Pusher Client (using iOS demo code https://github.com/lukeredpath/libPusher). The server code below fails with error when the iOS client attempts to join a presence channel:
ArgumentError - wrong number of arguments (1 for 2):
/Users/waveocean/.rvm/gems/ruby-1.9.3-p327/gems/sinatra-1.3.3/lib/sinatra/base.rb:665:in `render'
web.rb:13:in `auth'
web.rb:26:in `block in <main>'
/Users/waveocean/.rvm/gems/ruby-1.9.3-p327/gems/sinatra-1.3.3/lib/sinatra/base.rb:1265:in `call'
... snipped for brevity ...
Here is the code:
require 'sinatra'
require 'pusher'
require 'thin'
Thin::HTTP_STATUS_CODES[403] = "FORBIDDEN"
Pusher.app_id = 'MY-APP-ID'
Pusher.key = 'MY-KEY'
Pusher.secret = 'MY-SECRET'
def auth
response = Pusher[params[:channel_name]].authenticate(params[:socket_id], {:user_id => 101})
render :json => response
end
use Rack::Auth::Basic, "Protected Area" do |username, password|
username == 'foo' && password == 'bar'
end
post '/presence/auth' do
if params[:channel_name] == 'presence-demo'
auth
else
# render :text => "Forbidden", :status => '403'
response.status = 403
end
end
Can someone provide a suggestion or correct usage of render?
Here's is what I discovered. render is associated with Rails, and not strictly Ruby. To respond to the Sinatra route, use the following in the auth method:
def auth
response = Pusher[params[:channel_name]].authenticate(params[:socket_id], {:user_id => 101})
[200, {"Content-Type" => "application/json"}, response.to_json]
end
As it turns out, the Pusher iOS project demo provides a Scripts/auth_server.rb file with the required implementation. It is documented with the installation instructions here: https://github.com/lukeredpath/libPusher/wiki/Adding-libPusher-to-your-project .

Rspec validation test fails on 'put' update

I have this factory: #host = FactoryGirl.create(:host)
This test passes:
it 'should update and redirect to the show page' do
new_attr = #host.attributes.merge("hostname" => "New_name")
put 'update', id: #host, host: new_attr
response.should redirect_to(host_path(#host))
endĀ¬
But this one fails:
it 'should fail on validation for empty hostname and redirect to edit' do
bad_attr = #host.attributes.merge("hostname" => "")
put 'update', id: #host, host: bad_attr
response.should redirect_to(edit_host_path(#host))
end
With this error:
1) HostsController POST update failure should redirect to edit
Failure/Error: response.should redirect_to(edit_host_path(#host))
Expected response to be a redirect to <http://test.host/hosts/1/edit> but was a redirect to <http://test.host/hosts/1>
# ./spec/controllers/hosts_controller_spec.rb:127:in `block (4 levels) in <top (required)>'
In the #update of my HostsController, host objects that fail validation with empty hostnames are supposed to redirect_to edit_host_path(#host). Here is my HostsController#update
def update
#host = Host.find(params[:id])
if #host.save
flash[:notice] = 'Host was successfully updated.'
redirect_to host_path(#host)
elseĀ¬
redirect_to edit_host_path(#host)
end
end
I've played with saving and updating attributes in the console and my validations work. So why this error? Any ideas? Rspec seems to be saying that my factory objects with bad attributes are passing validation, but my model validates fine. Thank you.
/me does a face-palm.
In HostsController#update, this:
#host = Host.find(params[:id])
#host.save
Should be this:
#host = Host.find(params[:id])
#host.update_attributes(params[:host])

Resources