Routing Test Fails with Matched Route - ruby-on-rails

I have this line of code in my routes
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
match '/auth/:provider/callback', to: 'sign_in#authenticate'
end
end
And my test as
require 'spec_helper'
describe "Routing" do
it "should route to sign_in#authenticate" do
expect(post: 'api/v1/auth/:provider/callback').to route_to({ controller: 'api/v1/sign_in', action: 'authenticate', format: 'json' })
end
end
However, no matter what I do I keep getting the error
No route matches "/api/v1/auth/:provider/callback"
What am I missing here in order to make this test pass?

I believe the error you're getting is because match defaults to a GET request, but you are testing a POST request in your spec. You should be able to fix the issue by changing the route to:
match '/auth/:provider/callback', to: 'sign_in#authenticate', via: :post
My personal preference is to use the post method instead of match, it just reads better to me:
post '/auth/:provider/callback' => 'sign_in#authenticate'

Related

ActionController::UrlGenerationError: No route matches {:action=>"index", :controller=>"api/v1/topics", :format=>:json}

I have my topics_controller inside the folder (api/v1/) as
class Api::V1::TopicsController < ApplicationController
def index
#topics = Topic.all
render json: #topics
end
end
When I try to write rspec for above code as :
require 'rails_helper'
require 'spec_helper'
RSpec.describe Api::V1::TopicsController do
describe "GET #index" do
it "should return a successful response" do
get :index, format: :json
expect(response).to be_success
end
end
end
I'm getting error:
ActionController::UrlGenerationError: No route matches {:action=>"index", :controller=>"api/v1/topics", :format=>:json}.
But I have correct route I don't know why it is showing like that. Any solution are most welcomed.
I have my route as:
Rails.application.routes.draw do
namespace :api, defaluts: {format: :json} do
namespace :v1 do
resources :topics
end
end
end
Typo in routes:
namespace :api, defaluts: {format: :json} => defaults
You have a typo. defaluts: {format: :json} should be defaults: {format: :json}
Okay guys i had a typo in 'defaults'. Everyone will make typo mistakes so you need not downvote my question.

No route matches [POST] "/users"

I'm new to rails, and I'm trying to build API following Code School tutorial.
I get this error while trying to post to '/users' path.
routes file code :
Rails.application.routes.draw do
namespace :api,constraints: {subdomain: 'api'}, path: '/' do
resources :users, except: :delete
end
end
and the test code is :
require 'test_helper'
class CreatingUsersTest < ActionDispatch::IntegrationTest
test 'create users' do
post api_users_path,
{user: {name: 'test', email:'test#test.com'}}.to_json,
{'Accept' => Mime::JSON, 'Content-Type': Mime::JSON.to_s}
assert_equal response.status, 201
assert_equal response.content_type, Mime::JSON
user = json(response.body)
assert_equal api_user_url(user[:id]), response.location
end
end
And when I use rake routes :
api_users GET /users(.:format) api/users#index {:subdomain=>"api"}
POST /users(.:format) api/users#create {:subdomain=>"api"}
....
In the route you constraint the subdomain to be api
namespace :api,constraints: {subdomain: 'api'}, path: '/' do
but then in the test you call api_user_path
post api_users_path
that uses a generic hostname (test.host), and not the api hostname. The solution is to pass a specific host to the helper that satisfies the requirement.
post api_users_path(host: "api.test.host")

Redirect /api/* to /api/v1/*

In a Rails project, there's a namespace called api. I'm looking into making the API versioned so that api/v1 would be the preferred namespace.
For the routing, I was thinking of doing this:
namespace :api do
redirect_api_path_to_api_v1_path
namespace :v1 do
...
end
end
Its a large project, so I was thinking that I would still support the v1 endpoint and just redirect people to v1. Then slowly add v2 and at a point in time, do a v2 redirect.
What I've tried:
namespace :api do
namespace :v1 do
...
resources :countries
...
end
match "*", to: redirect(-> (params, request) {
"https://#{request.host_with_port}/api/v1#{request.path.split("/api").last}"
}), via: [:get, :post, :put, :post]
end
Specs return:
it "should redirect to v1" do
get "/api/countries"
expect(response).to have_http_status 302
end
Failures:
1) Version /api should redirect to v1
Failure/Error: get "/api/countries"
ActionController::RoutingError:
No route matches [GET] "/api/countries"

Test custom route error handling with rspec

I have a rails 4 api application in which I capture all missing routes like this:
namespace :api, defaults: {format: :json} do
namespace :v1 do
# matchers ...
end
# catch all undefined paths and redirect them to the errors controller
match "*path", to: "errors#routing_error", via: :all
end
With a simple click through test, this seems to work like a charm, however I'd like to write
an rspec test for this behaviour.
In my Rspec spec I try the following:
it "should capture non existing action" do
get '/api/non-existing-action', format: :json #Note that non-existing-action is not defined in the routes.rb
#expectations come here
end
The problem is that Rspec seem to catch the routing error before the router and raises a default error like this one
ActionController::UrlGenerationError:
No route matches {:action=>"/api/non-existing-action", :controller=>"api/api", :format=>:json}
So my question is: Is there a way to tell Rspec that it should let my router handle the non existing path, so that I can expect the error response from my errors controller?

Creating an API namespaced controller in Rails

I'm trying to test my namespaced controller and not having much luck. I have the following route setup:
namespace :api do
get 'organization/:id/questions/:number', controller: 'questions', action: 'index', as: 'organization_questions'
end
which produces the following route:
api_organization_questions GET /api/organization/:id/questions/:number(.:format) {:controller=>"api/questions", :action=>"index"}
that route works, and I'm able to successfully make a request to it with the following url: http://localhost:3000/api/organization/1/questions/1234567890
However when I try to make a get request to it in my unit test I get the following error:
No route matches {:controller=>"api/questions", :action=>"/api/organization/1/questions/1234567890"}
my get request looks like this:
get api_organization_questions_path(#organization.id, '1234567890')
Not sure what I'm doing wrong!?
What are you using for testing ? RSpec? The first parameter for the get method is the action. The code below should make the request you want:
describe Api::QuestionsController do
it "should do something" do
get :index, :id => #organization.id, :number => '1234567890'
end
end

Resources