rpsec-rails with apartment Gem and Grape cannot set host with subdomain - ruby-on-rails

I am using Rails 4.2.6, Ruby 2.2.1, rspec-rails 3.4.2, Grape 0.16.2, grape_token_auth 0.1.0. I installed apartment gem (1.0.2) for multitenancy and trying to write rspec tests for grape requests.
But I am getting the following error from rspec-rails response method every time irrespective of whatever solutions I tried.
#buf=["<!DOCTYPE html>\n<html>\n<head>\n <title>Apartment::TenantNotFound at /content/api/v1/questions</title>\n</head>\n<body>\n
The request is taking the host as 'www.example.com' all time. I tried so many solutions by googling it. But nothing works. you can see that in spec where I commented these lines. I want the url as 'http://g_m.lvh.me:3000' with the subdomain 'g_m'.
I tried this one:
https://github.com/influitive/apartment/wiki/Testing-Your-Application
But not works. I don't know why.
I tried this, but not working:
Rails: Wrong hostname for url helpers in rspec
and tried to set the host by:
host! "g_m.lvh.me:3000"
#request.host = 'g_m.lvh.me:3000'
request.host = 'g_m.lvh.me:3000'
Nothing works!
I created a test case like the following grape link says:
https://github.com/dblock/grape/commit/99bf4b44c511541c0e10f4506bf34ae9abcccd75
require 'rails_helper'
RSpec.describe ContentManager::QuestionAPI, :type => :request do
#before(:each) { Apartment::Tenant.switch!("g_m") }
#after(:each) { Apartment::Tenant.switch!("public") }
#before(:each) do
#begin
#client = FactoryGirl.create(:client, title: 'Sample title', subdomain: 'g_m')
#rescue
#client = Client.create!(title: 'Sample title', subdomain: 'g_m')
#end
#default_url_options[:host] = 'http://g_m.lvh.me:3000'
# request.host = "#{'g_m'}.lvh.me"
#end
#end
#before(:each) do
# if respond_to?(:default_url_options)
# default_url_options[:host] = 'http://g_m.lvh.me:3000'
# end
#end
describe "GET /content/api/v1/questions" do
it "returns an empty array of questions" do
get "/content/api/v1/questions"
#puts "response.inspect: #{response.inspect}"
response.status.should == 200
JSON.parse(response.body).should == []
end
end
end
My configurations:
in spec/rails_helper.rb
config.include RSpec::Rails::RequestExampleGroup, type: :request, file_path: /spec\/requests/
All time this request sent by rspec-rails with
url: '/content/api/v1/questions'
host: 'www.example.com'
My test result shows:
$ rspec spec/requests/
F
Failures:
1) ContentManager::QuestionAPI GET /content/api/v1/questions returns an empty array of questions
Failure/Error: response.status.should == 200
expected: 200
got: 500 (using ==)
# ./spec/requests/question_spec.rb:30:in `block (3 levels) in <top (required)>'
Deprecation Warnings:
Using `should` from rspec-expectations' old `:should` syntax without explicitly enabling the syntax is deprecated. Use the new `:expect` syntax or explicitly enable `:should` with `config.expect_with(:rspec) { |c| c.syntax = :should }` instead. Called from /home/vagrant/gauge-slcsl/spec/requests/question_spec.rb:30:in `block (3 levels) in <top (required)>'.
If you need more of the backtrace for any of these deprecations to
identify where to make the necessary changes, you can configure
`config.raise_errors_for_deprecations!`, and it will turn the
deprecation warnings into errors, giving you the full backtrace.
1 deprecation warning total
Finished in 6.19 seconds (files took 1.93 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/requests/question_spec.rb:26 # ContentManager::QuestionAPI GET /content/api/v1/questions returns an empty array of questions
abhi#ubuntu-trusty-64:~/my-app$
If anyone knows about the error and what I am doing wrong here, please reply/answer.

The error was because of, we have to say the apartment subdomain configuration that just exclude the 'www' word considering as a sub domain.
Add the following:
# config/initializers/apartment/subdomain_exclusions.rb
Apartment::Elevators::Subdomain.excluded_subdomains = ['www']
I was using the better_errors gem in my development and test environment. This causes the rspec output as an better error generated html codes and difficult to understand the rspec failure reason.
I removed better errors from 'test' environment and I got the clue of this error where we have to exclude the 'www' considering as a subdomain.

Related

Gettting undefined method `empty?' for nil:NilClass in my test suite when I try to call a Rails path helper (*_path) using Rails, Rspec

Rails 6.1.3.1
Rspec
basic behavior spec code:
describe "index" do
it "should show me the list" do
visit dashboard_targets_path
end
end
the routes file
namespace :dashboard do
resources :targets
end
error shows me the exception, but strangely it appears as if it isn't calling through to the app, just fails right in my test code:
1) interaction for Dashboard::TargetsController index should show me the list
Failure/Error: visit dashboard_targets_path
NoMethodError:
undefined method `empty?' for nil:NilClass
# ./spec/system/dashboard/targets_behavior_spec.rb:16:in `block (3 levels) in <top (required)>'
# /Users/jason/.rvm/gems/ruby-2.6.6/gems/webmock-3.12.2/lib/webmock/rspec.rb:37:in `block (2 levels) in <main>'
# /Users/jason/.rvm/gems/ruby-2.6.6/gems/rspec-wait-0.0.9/lib/rspec/wait.rb:46:in `block (2 levels) in <main>'
it seems to be failing inside the test code, if I drop into the debugger there and run dashboard_targets_path directly I also get the same exception, so the problem is just using the helper within the TEST ENVIRONMENT
within the dev environment, this function works
the problem here was the the config/environments/test.rb file does have default_url_options.
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
when you hit errors that disappear into the Rails gems, a good way to debug them is like so:
begin
// your failing code here
rescue StandardError => e
puts e.backtrace
byebug
puts e.inspect
raise (e)
end
WARNING: do not leave this code in your app or check it in unless you explicitly want to use exception handling for flow control (not recommended!). This is recommended ONLY for debugging purposes.
here you will see the full backtrace to the line number in the Gem where it is failing. when debugging Gems be careful— remember to un-do any changes you make and know that your monkey-patching inside of the Gem code doesn't affect your production code.

undefined method `get?' for 302:Integer

I like to upgrade the ruby version from 2.4.2 to 2.5.0 in my rails application.
All specs/tests fail where I use turbolinks.
Is there a known issue with turbolinks and ruby 2.5.0?
Here is the output on the terminal.
Failure/Error: expect(request).to redirect_to company_salesmen_path(salesman.company)
NoMethodError:
undefined method `get?' for 302:Integer
# /Users/dennish/.rvm/gems/ruby-2.5.0/gems/turbolinks-5.1.0/lib/turbolinks/assertions.rb:37:in `turbolinks_request?'
# /Users/dennish/.rvm/gems/ruby-2.5.0/gems/turbolinks-5.1.0/lib/turbolinks/assertions.rb:6:in `assert_redirected_to'
# ./spec/requests/salesmen_spec.rb:206:in `block (3 levels) in <top (required)>'
This is the spec:
describe 'DELETE /salesman/:id' do
subject(:request) do
delete salesman_path(salesman), headers: auth_headers
end
let!(:salesman) { create :salesman }
it 'destroys salesman' do
expect { request }.to change { Salesman.count }.by(-1)
end
it 'redirects to index' do
expect(request).to redirect_to company_salesmen_path(salesman.company)
end
end
The root cause of this error is:
subject(:request)
By assigning :request we are overwriting rails internals - hence it breaks and the tests fail wierdly.
The Solution
Just go with the default (no name)
subject { delete salesman_path(salesman) }
Or you can rename the subject:
subject(:http_request) { delete salesman_path(salesman) }
Both solutions will make the tests succeed.
I had this same issue it seems to be a compatibility issue with Turbolinks 5.1 and Rails 5.0.x. Downgrading to Turbolinks 5.0.1 solved it for me.
By renaming the request to http_request is solving this.

capybara have_title NoMethodError

At the moment, this is a simple project - just a couple of static pages. I'm developing a generic test framework but am struggling to differentiate between the different test options. I have added Rspec, Capybara, Faker, Factory Girl, Spring, and shoulda (though I'm not using the shoulda matchers at the moment).
I have this controller test file:
require 'rails_helper'
RSpec.describe StaticPagesController, type: :controller do
describe "GET #a_page" do
before(:each) { get :a_page }
it "returns http success" do
expect(response).to have_http_status(:success)
end
it "has a page title Static Site" do
expect(response).to have_title('Static Site')
end
end
end
When this runs through guard, it throws an error stack:
23:13:39 - INFO - Run all
23:13:39 - INFO - Running all specs
Running via Spring preloader in process 4498
Running via Spring preloader in process 4506
/home/steve/workspaces/static_site/db/schema.rb doesn't exist yet. Run `rake db:migrate` to create it, then try again. If you do not intend to use a database, you should instead alter /home/steve/workspaces/static_site/config/application.rb to limit the frameworks that will be loaded.
.F
Failures:
1) StaticPagesController GET #a_page has a page title Static Site
Failure/Error: expect(response).to have_title('Static Site')
NoMethodError:
undefined method `match' for nil:NilClass
Did you mean? catch
# /home/steve/.rvm/gems/ruby-2.3.1/gems/capybara-2.7.1/lib/capybara/queries/title_query.rb:18:in `resolves_for?'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/capybara-2.7.1/lib/capybara/node/document_matchers.rb:20:in `block in assert_title'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/capybara-2.7.1/lib/capybara/node/simple.rb:144:in `synchronize'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/capybara-2.7.1/lib/capybara/node/document_matchers.rb:19:in `assert_title'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/capybara-2.7.1/lib/capybara/rspec/matchers.rb:105:in `matches?'
# ./spec/controllers/static_pages_controller_spec.rb:34:in `block (3 levels) in <top (required)>'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-commands-rspec-1.0.4/lib/spring/commands/rspec.rb:18:in `call'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/command_wrapper.rb:38:in `call'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/application.rb:191:in `block in serve'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/application.rb:161:in `fork'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/application.rb:161:in `serve'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/application.rb:131:in `block in run'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/application.rb:125:in `loop'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/application.rb:125:in `run'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/application/boot.rb:19:in `<top (required)>'
# -e:1:in `<main>'
Finished in 0.029 seconds (files took 2.54 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/controllers/static_pages_controller_spec.rb:33 # StaticPagesController GET #a_page has a page title Static Site
The first test runs OK and, without the second, I get a clean result. I've spent a lot of time going over my config and it looks OK. I have also looked at the docs and some support sites.
Can anybody help out?
Capybara matchers need to be called against a html/xml document element (or a string that parses into a document), not against a response object. By default Capybaras matchers are normally only available in feature and view specs (not controller) was there a particular reason you included them into controller specs? Verifying a pages title really should lean more towards being a view spec than controller (by default views aren't rendered in controller specs - https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs).
As #Thomas Walpole pointed out, Capybara is not enabled in controller specs by default. One option is to change the type of the test to feature (type: :feature).
To make Capybara's built-in matcher have_title work, you need to use visit from Capybara's API, not get from ActionDispatch::IntegrationTest.

capybara, rspec - Address already in use - bind(2) for 127.0.0.1:3000

I'm running a feature spec to test some Rails code. The spec runs fine however, there is some js that needs to be tested.
As per the documentation, I've added the :js => true flag to the scenario. However, when I do this, I get the following error:
Failures:
1) User can check off items as being owned user can check off an item on the checklist
Failure/Error: Unable to find matching line from backtrace
Errno::EADDRINUSE:
Address already in use - bind(2) for 127.0.0.1:3000
# /Users/agazoom/.rvm/gems/ruby-2.2.1#kollista/gems/rack-1.6.0/lib/rack/handler/webrick.rb:32:in `new'
# /Users/agazoom/.rvm/gems/ruby-2.2.1#kollista/gems/rack-1.6.0/lib/rack/handler/webrick.rb:32:in `run'
# /Users/agazoom/.rvm/gems/ruby-2.2.1#kollista/gems/capybara-2.4.4/lib/capybara.rb:173:in `run_default_server'
# /Users/agazoom/.rvm/gems/ruby-2.2.1#kollista/gems/capybara-2.4.4/lib/capybara.rb:359:in `block (2 levels) in <top (required)>'
# /Users/agazoom/.rvm/gems/ruby-2.2.1#kollista/gems/capybara-2.4.4/lib/capybara/server.rb:70:in `call'
# /Users/agazoom/.rvm/gems/ruby-2.2.1#kollista/gems/capybara-2.4.4/lib/capybara/server.rb:70:in `block in boot'
The test is listed below. This is strange because the thing runs fine when I remove the js flag:
scenario "user can check off an item on the checklist", :js => true do
visit root_path
expect(page).to have_title("agazoom")
end
I did some experimenting and discovered that when I turn off webkit, the tests work. Basically, it looks like Capybara was trying to use the same port as webkit and failing when using js. Don't ask me the details as to why or how.
So, I just changed the port on which Capybara runs in 'rails_helper':
Capybara.configure do |config|
.
.
config.server_port = 3001
end

ActionMailer fails when testing mailer

Rails 4.1.4 and Rspec 3
I'm doing a VERY basic email test with Rspec. If I call the mailer from rails console, it works perfectly. If I call it from the mailer spec I get:
wrong number of arguments (0 for 1..2)
The mailer is very basic:
def create_team_invite(org, email)
#organization = org
mail(:to=>email, :subject=>'Test Subject')
end
The Test is pretty basic too:
it 'can send out emails to invite others to create teams' do
UserMailer.create_team_invite(#org, 'test#test.com').deliver
expect(ActionMailer::Base.deliveries.count).to eq 1
mail = ActionMailer::Base.deliveries.first
expect(mail.subject).to eq 'Test Subject'
expect(mail.from).to eq 'test#test.com'
end
Its failing in the "mail(:to..." line in the mailer. Seems like maybe its some configuration issue in my environment, but I have Test setup exactly the same as Dev, using SMTP and sending it to a Mailcatcher port. I caught the exception and looked at the Backtrace, but don't see anything unusual...
Anyone seen this before?
Update: providing additional info that was requested.
My test.rb, minus comments:
Rails.application.configure do
config.cache_classes = true
config.eager_load = false
config.serve_static_assets = true
config.static_cache_control = 'public, max-age=3600'
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
config.action_dispatch.show_exceptions = false
config.action_controller.allow_forgery_protection = false
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.active_support.deprecation = :stderr
config.action_mailer.default_url_options = { :host => 'lvh.me:3000', :only_path=>false }
end
The entire rspec failure is:
UserMailer
Team Joining Email
can send out emails to invite others to create teams (FAILED - 1)
Failures:
1) UserMailer Team Joining Email can send out emails to invite others to create teams
Failure/Error: UserMailer.create_team_invite(#team, 'test#test.com').deliver
ArgumentError:
wrong number of arguments (0 for 1..2)
# ./app/mailers/user_mailer.rb:11:in `create_team_invite'
# ./spec/mailers/user_mailer_spec.rb:36:in `block (3 levels) in <top (required)>'
Finished in 0.25858 seconds (files took 29 minutes 48 seconds to load)
1 example, 1 failure
The way I configure my email is via an initializer that loads an email.yml file from my config, per environment. Exact same process used by both test and dev, with the same settings. (Again, I'm sending to Mailcatcher, instead of just to mail_delivery :test)
Update 2
I have narrowed it down to the Mailer missing the "request" object. If I dig through where the error is occurring (AbstractController rendering.rb, line 109) it tries to reference the request object:
if defined?(request) && request && request.variant.present?
This is calling over to Rack test.rb line 121:
def request(uri, env = {}, &block)
env = env_for(uri, env)
process_request(uri, env, &block)
end
So its like the Rack Test.rb class is being seen as the request method in that abstractcontroller... but I dont know how, or why, or why this is happening in this particular project...
I get this same exact error, and it seems that it's trying to call rack-test request code, when I'm just trying to test a mailer object. So what I did is just not include all the stuff that I put in the spec_helper for the mailer spec. That fixed the problem for me.
# require 'spec_helper' -> I removed this line,
# and manually require the files that's needed to just test the mailer object:
require 'rubygems'
require './config/environment'
require './app/mailers/your_mailer'
Note: I'm just doing a rack project using action_mailer, no rails stuff. So your solution will be different, but you get the idea.
Update:
After doing some more troubleshooting. I found this problem in my spec_helper.rb file
RSpec.configure do |config|
config.include include RackSpecHelper # notice the double include
...
end
# where RackSpecHelper is a custom module
module RackSpecHelper
include Rack::Test::Methods
# a bunch of other helper methods
end
Notice the double include on this line
config.include include RackSpecHelper
At first I tried just removing the line and my mailer test is running just fine. Suspicious with the double include, I remove the include so it's just like this
config.include RackSpecHelper
Now my mailer test runs just fine without having to do manual require like I posted earlier above (and it can run together with the other test that uses rack test stuff).
The double include is basically doing
config.include(include(RackSpecHelper))
which include the RackSpecHelper in the configure block, which loads all the methods in the top level namespace! (very bad thing). It works, but that means all the methods from Rack::Test::Methods are in the global namespace.
So I'm guessing in your case, you might have a line in the spec_helper that include Rack::Test::Methods in the global namespace like this
include Rack::Test::Methods
remove it and instead put it in the RSpec config like this
RSpec.configure do |config|
config.include RackSpecHelper
end

Resources