Rails 4.1.12 and routes - ruby-on-rails

I'm updating from Rails 4.1.8 to 4.1.12, and one spec is failing because of a route:
expected: "https://test.host/en/name-3/activities/3-activity-around-name-3/bookings/new?booking%5Bstart_date%5D=2015-07-03+08%3A38%3A39+UTC"
got: "https://test.host/en/name-3/activities/3-activity-around-name-3/bookings/new.name-3?booking%5Bstart_date%5D=2015-07-03+08%3A38%3A39+UTC" (using ==)
config/routes.rb:
get '*destination/activities/:id/bookings/new', to: 'bookings#new', as: :new_destination_activity_booking, constraints: DestinationConstraint.new
app/controllers/public/bookings_controller.rb:
def new
session[:traveler_return_to] = new_destination_activity_booking_url(#activity.destination, #activity, params)
spec/controllers/public/bookings_controller_spec.rb:
session[:traveler_return_to].should == new_destination_activity_booking_url(activity.destination, activity, booking: { start_date: start_date })
I tested that route in Rails console and it behaves fine. How can it add ".name-3" in specs?

Related

Set headers before request in Rails Minitest

In Ruby on Rails Minitest, is there any way to set the headers before calling the request, within an ActionDispatch::IntegrationTest test?
Inside the before/setup is not a solution at the moment.
# Default way
test 'foo' do
get '/home', headers: { foo: "bar" }
end
# How I wish
test 'foo' do
#request.headers['foo'] = "bar"
get '/home'
end
# I already tried and it did not work...
test 'foo' do
request.headers['foo'] = 'bar'
#request.headers['foo'] = 'bar'
request.env['foo'] = 'bar'
#request.env['foo'] = 'bar'
request.env['HTTP_FOO'] = 'bar'
#request.env['HTTP_FOO'] = 'bar'
get '/home'
end
Ruby version: ruby 2.5.1p57
Rails version: 5.2.0
Minitest version: 5.1
The default way is good, but according to naming of headers custom header you should start with "X-" prefix.
test 'foo' do
get '/home', headers: { "X-Foo": "bar" }
end

Running minitest controller get ActionController::UrlGenerationError: No route matches

I know, that with this topic more questions asket, but i don't found what i need.
Currently i'm updating rails app from 3.2.13 to 4.2.0 and after upgrading rails naturally fails tests. These tests are passed in 3.2.13
So, i have this route:
get '/catalogs/:article_id/get_applicability_by_brand/:brand_id', :to => 'catalogs#get_applicability_by_brand', constrains: { format: 'js' }, as: :catalog_get_applicability_by_brand
Result of rake routes like this:
catalog_get_applicability_by_brand GET /catalogs/:article_id/get_applicability_by_brand/:brand_id(.:format) catalogs#get_applicability_by_brand {:constrains=>{:format=>"js"}}
Controller action, it only render js.erb template:
def get_applicability_by_brand
#applicability = CatalogAccess::TecDoc.get_applicability_by_brand(params[:article_id], params[:brand_id])
end
Minitest controller test:
def test_get_applicability_by_brand_action
expected_applicability = [
{ 'model_name' => 'Model 1',
'name' => 'fake name',
'year_of_construct_from' => '2000',
'year_of_construct_to' => '2010',
'construction_type' => 'fake type' },
{ 'model_name' => 'Model 1',
'name' => 'fake name 2',
'year_of_construct_from' => '1991',
'year_of_construct_to' => '2005',
'construction_type' => 'fake type' }
]
CatalogAccess::TecDoc.expects(:get_applicability_by_brand).with('12', '23').returns expected_applicability
xhr :get, :get_applicability_by_brand, :article_id => '12', :brand_id => '23', :format => "js"
assert_response 200
assert_template 'get_applicability_by_brand'
assert_template :partial => '_tecdoc2_applicability'
end
Test error message is:
ActionController::UrlGenerationError: ActionController::UrlGenerationError: No route matches {:action=>"get_applicability_by_brand", :article_id=>"12", :brand_id=>"23", :controller=>"catalogs", :format=>"js"}
I found that if append to my test option 'use_route', it will be pass, but get warning that seems not good solution
xhr :get, :get_applicability_by_brand, :article_id => '12', :brand_id => '23', :format => "js", :use_route => 'catalogs'
Warning message:
DEPRECATION WARNING: You are trying to generate the URL for a named route called "catalogs" but no such route was found. In the future, this will result in an `ActionController::UrlGenerationError` exception. (called from test_get_applicability_by_brand_action at /home/sdilshod/webapp/ps_base/apps/www/test/controllers/catalogs_controller_test.rb:627)
DEPRECATION WARNING: Passing the `use_route` option in functional tests are deprecated. Support for this option in the `process` method (and the related `get`, `head`, `post`, `patch`, `put` and `delete` helpers) will be removed in the next version without replacement. Functional tests are essentially unit tests for controllers and they should not require knowledge to how the application's routes are configured. Instead, you should explicitly pass the appropiate params to the `process` method. Previously the engines guide also contained an incorrect example that recommended using this option to test an engine's controllers within the dummy application. That recommendation was incorrect and has since been corrected. Instead, you should override the `#routes` variable in the test case with `Foo::Engine.routes`. See the updated engines guide for details. (called from test_get_applicability_by_brand_action at /home/sdilshod/webapp/ps_base/apps/www/test/controllers/catalogs_controller_test.rb:627)
DEPRECATION WARNING: You are trying to generate the URL for a named route called "catalogs" but no such route was found. In the future, this will result in an `ActionController::UrlGenerationError` exception. (called from test_get_applicability_by_brand_action at /home/sdilshod/webapp/ps_base/apps/www/test/controllers/catalogs_controller_test.rb:627)
Advise me please correct solution.
I'll hope your help, thanks!

Rails 4 rspec UrlGenerationError

I am testing a Rails app that has been upgraded to Rails 4.2 using rspec 3.4.1. In this app I have the following route (as printed by rake routes):
contact_g GET /foo/contact/:legs_trip_id/:user_id(.:format)
foo#find_edit { :trip_type_id=>"123", :user_id=>"0", :locale=>"en", :format=>/html|js|json/, :legs_trip_id=>/\d+/}
In my app, in development and production modes, this route works fine. But in tests I get the following error when trying to use the route. Example spec:
describe "#find_edit, logged in:" do
before do
#c1 = mock_model(Foo, :id => 1059)
# mock a User, set up session and expectations to mimick a logged in user
#u = pseudo_login
end
it "..." do
expect(#u).to receive # ...
get :find_edit, :legs_trip_id => "123", :pn_id => 252, :sa_id => 1923, :email => 1, :ee_id => "bla", :trip_type_id => "123", user_id: #u.id
expect(response).to redirect_to(...)
end
As a controller test, at the "get" line rspec throws this error:
ActionController::UrlGenerationError:
No route matches { :action=>"find_edit", :controller=>"foo", :ee_id=>"bla", :email=>"1", :legs_trip_id=>"123", :pn_id=>"252", :sa_id=>"1923", :trip_type_id=>"123", :user_id=>"19" }
As a feature or integration specI can't access request.session to login my mocked user and thus can't get the tests to start at all:
undefined local variable or method `request' for #<RSpec::ExampleGroups::FindingByLTAndUserIDFindEditLoggedIn:...>
in this helper code that is called during spec setup:
request.session[:user_id] = mocked_user.id
How can I run these specs? It used to work in Rails 3.x.

Rspec: add some header requests inside routing specs

I'm working on a Rails application having a REST API in JSON format and versioned (according to this excellent Ryan's cast: http://railscasts.com/episodes/350-rest-api-versioning).
For instance, there is a spec/requests spec:
require 'spec_helper'
describe "My Friends" do
describe "GET /my/friends.json" do
it "should get my_friends_path" do
get v1_my_friends_path, {}, {'HTTP_ACCEPT' => 'application/vnd.myapp+json; level=1'}
response.status.should be(401)
end
end
end
And it works well. But (keeping this example) how can we write the routing spec? For instance this spec isn't correct:
require 'spec_helper'
describe "friends routing" do
it "routes to #index" do
get("/my/friends.json", nil, {'HTTP_ACCEPT' => 'application/vnd.myapp+json; level=1'}).
should route_to({ action: "index",
controller: "api/v1/private/my/friends",
format: "json" })
end
end
I tried different ways (such as request.headers['Accept'] and #request.headers['Accept'], where request is undefined and #request is nil); I really don't see how to do.
I'm on Ruby 1.9.3, Rails 3.2.6 and rspec-rails 2.11.0. Thanks.
By combining the ideas from Cristophe's and Piotr's answers, I came up with a solution that worked for me. I'm using rspec and rails 3.0.
it 'should route like i want it to' do
Rack::MockRequest::DEFAULT_ENV["HTTP_ACCEPT"] = "*/*"
{get: "/foo/bar"}.
should route_to(
controller: 'foo',
action: 'bar',
)
Rack::MockRequest::DEFAULT_ENV.delete "HTTP_ACCEPT"
end
Currently you can't send addititional Headers in Routing specs, this is due to line 608 in actionpack-3.2.5/lib/action_dispatch/routing/route_set.rb where it says:
env = Rack::MockRequest.env_for(path, {:method => method})
path is your requested path "/my/friends.json" and method is :get
The resulting env contains something like the following:
{
"rack.version"=>[1, 1],
"rack.input"=>#<StringIO:0xb908f5c>,
"rack.errors"=>#<StringIO:0xb908fac>,
"rack.multithread"=>true,
"rack.multiprocess"=>true,
"rack.run_once"=>false,
"REQUEST_METHOD"=>"GET",
"SERVER_NAME"=>"your-url.com", # if path was http://your-url.com/
"SERVER_PORT"=>"80",
"QUERY_STRING"=>"",
"PATH_INFO"=>"/",
"rack.url_scheme"=>"http",
"HTTPS"=>"off",
"SCRIPT_NAME"=>"",
"CONTENT_LENGTH"=>"0"
}
If you are able to mock Rack::MockRequest::env_for it should be possible to inject other headers than the ones generated by env_for (see Hash above).
Other than that you are currently using the route_to matcher wrong, you should call it on a Hash where you specify the method and the path like this:
{ get: '/' }.should route_to(controller: 'main', action: 'index')
Let us know if you were able to Mock out that env_for and let it return your headers, would be nice to know.
Regards
Christoph
before do
ActionDispatch::TestRequest::DEFAULT_ENV["action_dispatch.request.accepts"] = "application/vnd.application-v1+json"
end
after do
ActionDispatch::TestRequest::DEFAULT_ENV.delete("action_dispatch.request.accepts")
end
You can using rspec's and_wrap_original to mock the Rack::MockRequest.env_for method:
expect(Rack::MockRequest).to receive(:env_for).and_wrap_original do |original_method, *args, &block|
original_method.call(*args, &block).tap { |hash| hash['HTTP_ACCEPT'] = 'application/vnd.myapp+json; level=1' }
end
For Rails 3 and 4 I had done the following in an RSpec around hook:
around do |example|
Rack::MockRequest::DEFAULT_ENV['HTTP_ACCEPT'] = 'application/vnd.vendor+json; version=1'
example.run
Rack::MockRequest::DEFAULT_ENV.delete 'HTTP_ACCEPT'
end
Since Rack >= 2.0.3 (used by Rails 5) the Rack::MockRequest::DEFAULT_ENV hash is frozen.
You can redefine the constant and use Kernel.silence_warnings to silence the Ruby warnings:
around do |example|
silence_warnings do
Rack::MockRequest::DEFAULT_ENV = Rack::MockRequest::DEFAULT_ENV.dup
end
Rack::MockRequest::DEFAULT_ENV['HTTP_ACCEPT'] = 'application/vnd.vendor+json; version=1'
example.run
Rack::MockRequest::DEFAULT_ENV.delete 'HTTP_ACCEPT'
end
It's a bit of hack but it works like a charm.

Rails 3 & Sinatra integration issue

I am trying to set up a sinatra app inside my Rails 3 (v3.0.1) application, but having no success. Sinatra gem (v1.1.0) is setup using bundle install.
Here's what i have.
customer_app.rb class in lib directory -
class CustomerApp < Sinatra::Base
get "/test" do
"Hello World"
end
end
my routes.rb file contains -
CustomerService::Application.routes.draw do
root :to => CustomerApp
end
The URL i am trying is - http://localhost:3000/test
I get this error (on the browser) - Routing Error. No route matches "/test"
and this error in the log - ActionController::RoutingError (No route matches "/test"):
Is there anything I am missing??
Also I just noticed, even a simple rack route is not working -
root :to => proc { |env| [200, {}, ["Welcome!"]]}
The root keyword by default maps only the path /.
So you are trying to say, forward any request for / to CustomerApp which can handle requests for /test.
You should change the match filter.
CustomerService::Application.routes.draw do
match "/test" :to => CustomerApp
end

Resources