I'm trying to write a controller test which tests a subdomain constraint. However, I'm unable to get RSpec to set the subdomain and return an error if the subdomain isn't accurate.
I'm using Rails 4.2.6 and RSpec ~3.4
routes.rb
namespace :frontend_api do
constraints subdomain: 'frontend-api' do
resources :events, only: [:index]
end
end
events_controller.rb
module FrontendAPI
class EventsController < FrontendAPI::BaseController
def index
render json: []
end
end
end
spec
RSpec.describe FrontendAPI::EventsController do
describe 'GET #index' do
context 'wrong subdomain' do
before do
#request.host = 'foo.example.com'
end
it 'responds with 404' do
get :index
expect(response).to have_http_status(:not_found)
end
end
end
end
Is there some other way of doing this?
You can accomplish this by using the full URL in your tests instead of setting the host in a before block.
Try:
RSpec.describe FrontendAPI::EventsController do
describe 'GET #index' do
let(:url) { 'http://subdomain.example.com' }
let(:bad_url) { 'http://foo.example.com' }
context 'wrong subdomain' do
it 'responds with 404' do
get "#{bad_url}/route"
expect(response).to have_http_status(:not_found)
end
end
end
end
There is a similar question and answer here testing routes with subdomain constraints using rspec
Related
I am writing a controller spec to verify this private method and I get the error Module::DelegationError: ActionController::RackDelegation but I am lost as how to fix this. The best example I have found has been http://owowthathurts.blogspot.com/2013/08/rspec-response-delegation-error-fix.html.
How can I get the unverified spec to pass? I want to make sure the 401 is returned.
Method
def validate_api_request
return four_oh_one unless api_request_verified?(request)
end
Current Spec
describe Api::ApiController, type: :controller do
describe '#validate_api_request' do
it 'verified' do
allow_any_instance_of(described_class).to receive(:api_request_verified?).and_return(true)
expect(subject.send(:validate_api_request)).to be_nil
end
it 'unverified' do
allow_any_instance_of(described_class).to receive(:api_request_verified?).and_return(false)
allow(controller).to receive(:redirect_to)
binding.pry
end
end
end
I'm using Rails 4.
If anyone is working on a similar issue writing controller specs, here is how I solved this based on these 2 guides: http://codegur.com/22603728/test-user-authentication-with-rspec and https://gayleforce.wordpress.com/2012/12/01/testing-rails-before_filter-method/.
describe Api::ApiController, type: :controller do
describe '#validate_api_request' do
controller(Api::ApiController) do
before_filter :validate_api_request
def fake
render text: 'TESTME'
end
end
before do
routes.draw { get 'fake', to: 'api/api#fake' }
end
it 'verified' do
allow_any_instance_of(described_class).to receive(:api_request_verified?).and_return(true)
expect(subject.send(:validate_api_request)).to be_nil
end
it 'unverified' do
allow_any_instance_of(described_class).to receive(:api_request_verified?).and_return(false)
get 'fake'
expect(response.status).to be(401)
end
end
end
I am trying to test that on the creation of a post, the user is redirected to deployments path. I have added in
config.include Rails.application.routes.url_helpers
to extend rails routes to rspec. But my test still fails with the following error
1) Failure/Error: expect(response).to redirect_to(path)
Expected response to be a redirect to <http://test.host/deployments/new> but was a redirect to <http://test.host/deployments/new.1473>.
Expected "http://test.host/deployments/new" to be === "http://test.host/deployments/new.1473".
# -e:1:in `<main>'
Here is the test:
describe "post create" do
before do
allow(model).to receive(:new).and_return(instance)
end
context "where all is not well" do
before do
allow(instance).to receive(:save).and_return(false)
post :create, params_new_instance
end
sets_flash(:error)
it "should render the new form" do
expect(response).to render_template("projects/new")
end
end
context "where all is well" do
before do
allow(instance).to receive(:save).and_return(true)
post :create, params_new_instance
end
sets_flash(:notice)
it "redirects to new_deployments_path" do
expect(controller.controller_path).to eq(new_deployment_path)
end
end
end
project controller
def create
#project=Project.new(params_project)
if #project.save
record_saved
return redirect_to(new_deployment_path(#project))
else
check_for_errors
return render('/projects/new')
end
end
why is this failing? am i approaching this in the right way?
thanks in advance
Are you sure that new_deployments_path instead of new_deployment_path
This is my first suggestion. Them can be more but not enough information: routes.rb and deployments controller for example
I've got some routes that look like this:
constraints ClientCodeConstraint.new do
get 'share/:client_code', to: redirect('/%{client_code}')
get 'share/:client_code/:id', to: redirect('/%{client_code}/%{id}')
get ':client_code', to: 'share#index', as: :shares
get ':client_code/:id', to: 'share#show', as: :share
get ':client_code/:document_id/more/:component_id', to: 'share#more', as: :more
end
My constraint looks like this:
class ClientCodeConstraint
def matches?(request)
users.each do |user|
return true if request.path_parameters[:client_code] == user.client_code
end
end
def users
#users ||= User.all
end
end
I've got tests like this but I'm having no luck:
context 'not logged in' do
let!(:user) { create(:user) }
let!(:document) { create(:document) }
specify 'renders the :index view' do
get :index
expect(response.code).to eq '302'
expect(response).to redirect_to("/#{assigns(:user).client_code}")
end
specify 'renders the :show view' do
get :show
expect(response).to redirect_to("/#{assigns(:user).client_code}/#{assigns(:document).id}")
end
end
How do I test with Rspec these redirects? I just get a bunch of these errors:
ActionController::RoutingError: No route matches {:controller=>"share"}
And the controller and routes of course exist.
UPDATE
Relevant rake routes output is here:
GET /share/:client_code(.:format) :controller#:action
GET /share/:client_code/:id(.:format) :controller#:action
shares GET /:client_code(.:format) share#index
share GET /:client_code/:id(.:format) share#show
more GET /:client_code/:document_id/more/:component_id(.:format) share#more
The tests pass like this:
specify 'renders the :index view' do
get :index, client_code: user.client_code
expect(response.status).to eq(200)
end
That feels though like I'm testing only that the response is correct. I want to test more thoroughly, i.e., it doesn't render an error message, etc.
I'm writing tests with rspec for my application controller in my rails app (written in Rails 4) and I'm running into a problem where it doesn't recognize the route for the HTTP request I'm sending. I know there's a way to do this using MyApp::Application.routes but I'm not able to get it working.
#application_controller_spec.rb
require 'spec_helper'
class TestController < ApplicationController
def index; end
end
describe TestController do
before(:each) do
#first_user = FactoryGirl.create(:user)
# this is to ensure that all before_filters are run
controller.stub(:first_time_user)
controller.stub(:current_user)
end
describe 'first_time_user' do
before(:each) do
controller.unstub(:first_time_user)
end
context 'is in db' do
before(:each) do
#user = FactoryGirl.create(:user)
controller.stub(:current_user).and_return(#user)
end
it 'should not redirect' do
get :index
response.should_not be_redirect
end
end
context 'is not in db' do
context 'session[:cas_user] does not exist' do
it 'should return nil' do
get :index
expect(assigns(:current_user)).to eq(nil)
end
end
it "should redirect_to new_user_path" do
controller.stub(:current_user, redirect: true).and_return(nil)
get :index
response.should be_redirect
end
end
end
The error I'm getting right now is
No route matches {:action=>"index", :controller=>"test"}
I would add the test#index route to config/routes.rb, but it doesn't recognize the Test Controller, so I want to do something like
MyApp::Application.routes.append do
controller :test do
get 'test/index' => :index
end
end
but I'm not sure where to add this or if this even works in rspec. Any help would be great!
If you are trying to test your ApplicationController, see this RSpec documentation about it. You will need to define methods like index inside the test, but it works well.
I am attempting to create a RSpec controller test for a namespaced controller, but rspec doesn't seem able to detect the nesting and generate the proper path for the post :create action.
This is my spec code:
# for: /app/controllers/admin/crm/report_adjustments_controller.rb
require 'spec_helper'
describe Admin::Crm::ReportAdjustmentsController do
render_views
before(:each) do
signin
end
describe "GET 'index'" do
it "returns http success" do
get :index
response.should be_success
end
end
describe "POST 'create'" do
it "creates with right parameters" do
expect {
post :create, report_adjustment: {distributor_id: #ole_distributor.id, amount: "30.0", date: Date.today }
}.to change(Crm::ReportAdjustment, :count).by(1)
response.should be_success
end
end
end
# routes.rb
namespace :admin do
namespace :crm do
resources :report_adjustments
end
end
For this code, the get :index works just fine, but when post :create is called, the following error is generated: undefined method 'crm_report_adjustment_url'
Why would RSpec be smart enough to figure things out with get :index, but not with post :create? How do I get RSpec to properly load the right route, which is admin_crm_report_adjustments_url?
Thanks in advance.
Try posting to the url instead:
post admin_crm_report_adjustments_url
# or
post "/admin/crm/report_adjustments"