using webmock with cucumber - ruby-on-rails-3

I am using webmock and it is not working for cucumber tests
In my Gemfile
gem 'vcr'
gem 'webmock'
And in my features/support.env.rb, I have
require 'webmock/cucumber'
WebMock.allow_net_connect!
When I run my cucumber tests I am getting this error.
Real HTTP connections are disabled. Unregistered request:
GET http://127.0.0.1:9887/__identify__ with headers
{'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Ruby'}
Am I doing anything wrong or is sth missing?

First off, if you're using VCR, you don't need to configure webmock with the require 'webmock/cucumber' line and the WebMock.allow_net_connect! line. VCR takes care of any necessary WebMock configuration for you.
The request that is triggering the error looks like it's coming from Capybara. When you use one of the javascript drivers, capybara boots your app using a simple rack server, and then polls the special __identify__ path so it knows when it has finished booting.
VCR includes support for ignoring localhost requests so that it won't interfere with this. The relish docs have the full story but the short version is that you need to add VCR configuration like this:
VCR.config do |c|
c.ignore_localhost = true
end

I had the same error though do not use VCR. I was able to resolve this by adding:
require 'webmock/cucumber'
WebMock.disable_net_connect!(:allow_localhost => true)
to my env.rb file.

Expanding on Myron Marston's answer. If you need to keep localhost for something else, such as a Rack App, that you might want VCR to capture request for, you will need to create a custom matcher rather than ignore all localhost requests.
require 'vcr'
VCR.configure do |c|
c.hook_into :webmock
c.ignore_localhost = false
c.ignore_request do |request|
localhost_has_identify?(request)
end
end
private
def localhost_has_identify?(request)
if(request.uri =~ /127.0.0.1:\d{5}\/__identify__/)
true
else
false
end
end

If you use both RSpec and Cucumber, you might need to create two config files for WebMock (when using with VCR):
# spec/support/webmock.rb
# Config for RSpec
require 'webmock/rspec'
WebMock.disable_net_connect!(allow_localhost: true)
# features/support/webmock.rb
# Config for Cucumber
require 'webmock/cucumber'
WebMock.disable_net_connect!(allow_localhost: true)
Documenting this here for people to find when googling for __identify__. Errors look like...
Real HTTP connections are disabled.
Unregistered request: GET http://127.0.0.1:59005/__identify__

Related

ActionMailer sending real emails in test mode! - How to turn off?

Newly signed up users to my little app must be approved by the admin (me) before they can gain access to the site. I've succeeded in generating such emails in development with an after_create :send_admin_email in my user model which works great. My problem is that I'm generating multiple users during my tests (using FactoryGirl) and each test user created sends off a real email. Running my tests is like pouring molasses in January and I've got to delete hundreds of emails sent to my inbox. How do I turn that off?
Action Mailer Basics in the Rails Guides tells me that "By default Action Mailer does not send emails in the test environment. They are just added to the ActionMailer::Base.deliveries array."
Moreover, in config/environments/test.rb I've got:
config.action_mailer.delivery_method = :test
That's in addition to in config/environment.rb having:
# Configuration for using SendGrid on Heroku
ActionMailer::Base.smtp_settings = {
:address => 'smtp.sendgrid.net',
:port => '587',
:authentication => :plain,
:user_name => 'app[my app number]#heroku.com',
:password => '[something super secret]',
:domain => '[let's get this party started!.com]',
:enable_starttls_auto => true
}
ActionMailer::Base.delivery_method = :smtp
I'm sure that I'm missing something simple and basic. I've searched around and related questions and posts deal with how to test that ActionMailer actually sent email.
Humble gratitude in advance for any thoughts or help.
Addendum: Following answer to similar question found at Is it possible to turn off ActionMailer emails when cucumber testing is happening on development? I was able to stop the email sending madness. Still, I had to add ActionMailer::Base.delivery_method = :test to several rspec files. Is there a way I can shut this down globally? Anyone have any thoughts on what's going on?
So I've figured it out. Having the line ActionMailer::Base.delivery_method = :smtp in config/environment.rb overrides ActionMailer::Base.delivery_method = :test in config/environments/test.rb.
So, delete that line, ActionMailer::Base.delivery_method = :smtp'
from config/environment.rb and place it in config/environments/production.rb.
That allows you to place ActionMailer::Base.delivery_method = :test in config/environments/test.rb and the version you want in config/environments/development.rb. I made development.rb :test as I populated my database using Faker and changed it to smtp so I was sure that real emails were sent as an additional check.
Note: You must restart your server for these changes to take effect.
Another note: Heroku's current SendGrid Instructions put the SendGrid Heroku configuration code in a new config/initializers/mail.rb file which will likely require removing its last line and placing the desired version in each config/environments/[production.rb, development.rb, test.rb]
Perhaps useful...
My config/environment.rb did not contain ActionMailer::Base.delivery_method = :smtp and my config/environments/test.rb did contain ActionMailer::Base.delivery_method = :test but Rails still delivered mailers while testing.
I simply added the following to config/environments/test.rb to fix:
config.action_mailer.perform_deliveries = false
I faced the similar situation in Rails4.2 (ActiveJob integration with ActionMailer) even if I didn't write delivery_method = :smtp in config/environment.rb.
In my case, The issue here happened after using "resque" as background worker. Finally, I found out that the following config was WRONG:
config/initializers/active_job.rb:
Rails.application.config.active_job.queue_adapter = :resque # here is WRONG
...because it effected to test mode as well.
So, I set "queue_adapter = :resque" only in config/environments/{development,production.rb}. Now, that works as I expect.

Using VCR with Cucumber via tags

I have some Cucumber features which need to interact with the Google Maps Routing API. I'm trying to stub out these interactions using VCR.
I have added a VCR tag to my features like so:
#google_routing_api #javascript
Scenario: Creating a bus
Given I am on the buses page
When I follow "Get Started Now"
And then added my VCR configuration in features/support/vcr.rb
require 'vcr'
VCR.config do |c|
# INFO: This is relative to the Rails.root
c.cassette_library_dir = 'features/fixtures/vcr_cassettes'
c.stub_with :fakeweb
end
# INFO: https://github.com/myronmarston/vcr/wiki/Usage-with-Cucumber
VCR.cucumber_tags do |t|
t.tag '#google_routing_api'
end
But when I run my cukes, I am told..
Real HTTP connections are disabled. Unregistered request: GET http://127.0.0.1:54181/__identify__
You have to set VCR to ignore localhost requests. Otherwise, when capybara tries to request any page from your website, VCR will block it.
Add c.ignore_localhost = true to your VCR config block.
VCR.config do |c|
c.cassette_library_dir = 'features/fixtures/vcr_cassettes'
c.stub_with :fakeweb
c.ignore_localhost = true
end

Deploying rails 3.1 app in subdirectory

I'm trying to deploy my rails 3.1.3 app in a subdirectory on the server:
Apache (reverse proxy) => unicorn (listening on localhost:5000)
The problem is with url_helper.
via the --path switch in unicorn I'm setting my /subdir
It gets picked up by rails; DashboardController.config.relative_url_root gives me that subdir.
But when I use something like 'members_path' in my view it gives me '/members' and not '/subdir/members'
what am I missing?
I had exactly the same problem. Two things were missing/faulty in my setup.
My web-server had an superflous, faiulty rewrite-rule, rewriting /prefix/<controller> to just /controller.
It seems Rails3 routing are by default ignoring relative_url_root. (Stupid IMHO) There's a good tip in https://stackoverflow.com/a/5457484/103192 that shows a trick to make it work again.
Otherwise, you can wrap the run statement in your config.ru with the
following block:
map ActionController::Base.config.relative_url_root || "/" do
run FooApp::Application
end
I now have it working much like one would want it to work.

Rails console log - how to customize what is printed in the console

When I run rails s it loads up and everything works. When I browse to a page several lines of information are printed. Mostly this is the webpage getting the assets for the page. I really don't need to see this and have it clutter my screen. Is there a way to customize what gets printed in console?
Thanks
For assets pipeline messages it seems that you can't (yet). See How to disable logging of asset pipeline (sprockets) messages in Rails 3.1? and the rails issue on Github
You can do it in part by using these lines (credits) in your development.rb file
config.after_initialize do |app|
app.assets.logger = Logger.new('/dev/null')
end
For Rails 3.1, inside config/environments/development.rb, set the following to false:
config.assets.debug = false
Your logs will show you everything you want to see minus the assets.
You can configure the logging detail of the rails dev server by setting config.log_level in environments/development.rb. Setting it to :warn will get rid of most of the logging (you can always send your own messages with whatever log level you want so they still get printed).
http://guides.rubyonrails.org/debugging_rails_applications.html#log-levels
http://guides.rubyonrails.org/debugging_rails_applications.html#log-levels

Rails, Capybara and subdomains: how to visit certain subdomain

Rails 3, Cucumber 0.9.4, Capybara 0.4.0
I want to test my features with subdomain. I found that solution:
Given /^I visit subdomain "(.+)"$/ do |sub|
Capybara.default_host = "#{sub}.example.com" #for Rack::Test
Capybara.app_host = "http://#{sub}.example.com:9887" if Capybara.current_driver == :culerity
end
It works if I run cucumber features/subdomain.feature but it fails if I run cucumber features! It's unbelievable, but it's true. I logged current urls and it is subdomain.example.com for cucumber features/subdomain.feature and www.example.com for cucumber features for one scenario with
Scenario: subdomain scenario
Given I visit subdomain "subdomain"
in both cases!
I don't know the reason...
Is there best way for testing subdomains with capybara?
Okay, here is what should be a fairly straightforward and easy to understand hack of Capybara that yields the desired behavior, namely to be able to create a new session each time you switch subdomains. This is useful for sites where a user registers on one domain (which results in a subdomain being created for his account) and then ends up needing to navigate over to that subdomain.
First of all (and this part is fairly common to the other solutions out there) go ahead and give yourself a way to change Capybara.default_host in a Cucumber step. I did it like this:
Then /^I switch the subdomain to (\w+)$/ do |s|
Capybara.default_host = "#{s}.smackaho.st"
end
Stick this step into your Cucumber feature at the point where you want the new subdomain to be used. For example:
When I open the email
Then I should see "http://acme.rightbonus.com/users/confirmation" in the email body
Given I switch the subdomain to acme
When I follow "Click here to finish setting up your account" in the email
Then I should be on the user confirmation page for acme
Now for the magical monkeypatching that makes this work. Basically, you want Capybara to be smart enough to detect when the subdomain has changed and reset its RackTest session object.
# features/support/capybara.rb
class Capybara::Driver::RackTest
# keep track of the default host you started with
def initialize(app)
raise ArgumentError,
"rack-test requires a rack application, but none was given" unless app
#app = app
#default_host = Capybara.default_host
end
def process(method, path, attributes = {})
reset_if_host_has_changed
path = ["http://", #default_host, path].join
return if path.gsub(/^#{request_path}/, '') =~ /^#/
path = request_path + path if path =~ /^\?/
send(method, to_binary(path), to_binary( attributes ), env)
follow_redirects!
end
private
def build_rack_mock_session # :nodoc:
puts "building a new Rack::MockSession for " + Capybara.default_host
Rack::MockSession.new(app, Capybara.default_host || "www.example.com")
end
def reset_if_host_has_changed
if #default_host != Capybara.default_host
reset! # clears the existing MockSession
#default_host = Capybara.default_host
end
end
end
This patch works with Capybara 0.4.1.1 and will probably not work with different versions unless modified. Good luck.
If your needs don't include anything to do with sessions, and all you're after is visiting a different subdomain, I wrote this function:
def visit_with_subdomain(uri, options = {})
domain = Capybara.default_host
port = Capybara.server_port
subdomain = options[:subdomain]
visit "http://#{subdomain}.#{domain}:#{port}#{uri}"
end
You can call it like this:
visit_with_subdomain some_path, subdomain: some_subdomain
Had the same problem for a bit with and my test had to sometimes switch or redirect back and forth between subdomains.
given this step:
When /^(?:|I )go to "(.+)"$/ do |url|
visit url
end
When I go to "http://mysubdomain.example.org" works in rack test, but if you are redirected by the app or follow a link to some other path the host reverts to the default_host.
There's a fork of rack-test by hassox that ensures that rack-test keeps track of the host used in the previous request.
So, in my Gemfile, before requiring capybara:
gem 'rack-test', :git => "https://github.com/hassox/rack-test.git"
Now if I need to hit a particular subdomain (or the app redirects me to one, like secure.myapp.com/sign_in) I'm sure that the feature can read more like a browser would behave: it will allow me to stay on the current subdomain until I go–using capybara's visit("somesubdomain.example.org")–or am redirected by the app to a different host.