I'm using RSpec, Spork, Capybara and Capybara Mechanic to write integration tests for a registration path that uses Facebook connect. It correctly navigates through registration, but the new users are created in my development database instead of the test database.
RSpec is setup to use the test environment and I've confirmed that any model methods I run in my spec all hit the test database, but all of the UI actions hit development.
Here's my test:
it "go through registration path" do
print "RAILS_ENV: #{Rails.env}\n" # correctly prints 'test'
print "1) #{User.count}\n" # correctly shows the user count in my test database (zero)
Capybara.current_driver = :mechanize
visit root_path
click_link "register"
# Fill in Facebook Connect form
fill_in 'email', :with => "bob#example.com"
fill_in 'pass', :with => "password"
click_button "Log In"
print "2) #{User.count}\n" # still shows zero users in the test database
end
After that test I can look at my development database and the new user has been created there.
I've tried setting up database_cleaner as well and that hasn't helped.
Anyone know what I need to do so that capybara will hit the test database?
rails 3.1.3
rspec 2.7.0
spork 0.9.0
capybara 1.1.0
capybara-mechanize 0.3.0.rc3
The problem was that I had a separate development server running in parallel with the tests and the tests were defaulting to a the same address/port. I resolved this by adding the following to spec_helper.rb so Capybara would use a different port.
Capybara.run_server = true
Capybara.server_port = 7000
Capybara.app_host = "http://localhost:#{Capybara.server_port}"
Related
This question already has answers here:
Cucumber / Capybara -- how to get the host and port of the current execution
(3 answers)
Closed 4 years ago.
I have a test program that mimics a user's iOS device by sending chunks of data to a rails server. This program works fine outside of testing. Inside of testing, the program immediately times out since it cannot find the server.
My configuration, in env.rb:
require 'capybara/poltergeist'
Capybara.javascript_driver = :poltergeist
Capybara.server_port = 3123
Capybara.app_host = "http://0.0.0.0:3123"
Inside the test, I've tried things like
puts Capybara.current_session.current_host
puts Capybara.current_session.current_url
and so forth, but those are all blank. Doing:
puts Capybara.current_session
produces a memory address, so I know that the current session is working.
This is with Capybara set up like so in the gemfile:
gem 'capybara', '~> 2.0.2
I've seen several questions based on this, but their answers just don't work for me. Specifically, Capybara does not appear to be setting the current host or url as I've specified, nor is it actually allowing me to see the contents of the current session. So how can I fix this and specify a particular port and url?
For capybara < 2.0:
Capybara.current_session.driver.rack_server.host
Capybara.current_session.driver.rack_server.port
Capybara 2.0:
Capybara.current_session.server.host
Capybara.current_session.server.port
I found the answer here: Cucumber / Capybara -- how to get the host and port of the current execution
Capybara.current_session.driver.server.port
I have some Ruby on Rails applications that are using Active Admin gem. Rails version is 3.2.6, Active Admin version is 0.4.4.
I am pushing these applications to Heroku, then doing migrations and everything is working fine. But after some time (when application restarts) i'm starting to get 404 error when trying to open admin page (like myapp/admin). In logs there is an error:
ActionController::RoutingError (uninitialized constant Admin::DashboardController)
Moreover, if i'm trying to open some other admin page (like myapp/admin/videos - to administer videos) everything is still working fine, but error 404 persists when opening Dashboard page.
I have tried to put
config.cache_classes = true
config.assets.compile = true
to my config files, but all the same.
Basically the scheme is as follows:
I make some changes to the app, commit the changes with "git add .", "git commit" and push it to Heroku
I open the /admin page on Heroku and it works fine
After application restarts i get 404 error when visiting /admin, but everything still works when accessing other admin pages, not dashboard
GoTo 1
I'm still unsure if the error appears when the app is restarted by itself (not by "heroku restart").
Any ideas why this is happening? Maybe someone can advice how to switch off this Dashboard and use my myapp/admin/videos as the default admin page?
I had this very same problem, and since it complaints about the ActiveAdmin Dashboard, and it is now deprecated I proceeded to update my dashboard.rb file to the new Dashboard style and that solved the problem.
(I got that file from here).
Hope it helps.
I got the same issue.
Check whether you have to upgrade ActiveAdmin to new version
When upgrading to a new version of ActiveAdmin you may need to run
rails generate active_admin:assets
If you get:
uninitialized constant Admin::DashboardController
Use the New default page for admin/dashboard.rb
which is like following,
ActiveAdmin.register_page "Dashboard" do
menu :priority => 1, :label => proc{ I18n.t("active_admin.dashboard") }
content :title => proc{ I18n.t("active_admin.dashboard") } do
div :class => "blank_slate_container", :id => "dashboard_default_message" do
span :class => "blank_slate" do
span I18n.t("active_admin.dashboard_welcome.welcome")
small I18n.t("active_admin.dashboard_welcome.call_to_action")
end
end
# Here is an example of a simple dashboard with columns and panels.
#
# columns do
# column do
# panel "Recent Posts" do
# ul do
# Post.recent(5).map do |post|
# li link_to(post.title, admin_post_path(post))
# end
# end
# end
# end
# column do
# panel "Info" do
# para "Welcome to ActiveAdmin."
# end
# end
# end
end # content
end
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.
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__
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.