Rspec using test, Capybara using development database - ruby-on-rails

I have an interesting problem. I'm using Rspec for test driven development and Capybara with Poltergeist for acceptance testing. Oh, and FactoryGirl, too. Rspec and FactoryGirl is operating against the test database, which is what I want. The problem is that acceptance tests are operating against the development database.
This causes simple tests like the following to fail:
my_class = FactoryGirl.create(:my_class)
visit my_classes_path
expect(page).to have_content(my_class.title)
I've even checked screenshots along the way using:
page.save_screenshot("screenshot#{__FILE__}_#{__LINE__}.png")
SOLUTION
So apparently Capybara was attempting to use the same URL and port that is initialized in my local environment when I kickoff "rails server". Specifying a different port in my Capybara configuration did the trick as seen below:
Capybara.configure do |c|
c.run_server = true
c.javascript_driver = :poltergeist
c.default_driver = :poltergeist
c.server_port = 7000
c.app_host = "http://localhost:#{c.server_port}"
end

For normal use you shouldn't have to lock to a specific port or set app_host. If app_host isn't set then Capybara defaults to http://#{Capybara.server_host}:#{Capybara.server_port} which by default is http://127.0.0.1:<the port capybara runs the server on> . If you need to use localhost instead of 127.0.0.1 (because of IPv6 or something) then just set
Capybara.server_host = 'localhost'
instead of app host and fixing the port. app_host is really for when you're trying to test an external site, or you need to access subdomains to test your app - and fixing the port is really intended for issues with firewalls, etc.

Related

Capybara error on HTTP.get: HTTP::ConnectionError Exception: failed to connect: Connection refused - connect(2) for "localhost" port 3000

My app is set to use Capybara and minitest with RackTest driver. This is the main config in test_helper.rb:
require 'capybara/rails'
require 'capybara/minitest'
class ActionDispatch::IntegrationTest
include Capybara::DSL
include Capybara::Minitest::Assertions
fixtures :all
...
Capybara.app_host = "http://localhost:3000"
Capybara.run_server = true
Capybara.server_port = 3000
Capybara.register_driver :rack_test do |app|
Capybara::RackTest::Driver.new app,
follow_redirects:false
end
...
end
Now, when I perform request directly on my tests they work fine. Such as:
post '/api/v4/login', params: {"email": u.email, "password": u.password }
But in one test I'm calling a class (inside /app) that performs the following method:
HTTP.get(url,params).body
For which i appear to have no server running and get the following Error message in response:
HTTP::ConnectionError Exception: failed to connect: Connection refused - connect(2) for "localhost" port 3000
First, you should not be using post or get in tests that use Capybara (feature/system tests). They should only be used in request/raw integration tests, which don't use Capybara or the server it starts (lazily when the need is detected through a visit call) and are generally used for API tests.
Second, you should not be setting the port (to 3000), or app_host (generally) when having Capybara run the AUT. Port 3000 is generally the port your development server gets run on (rails s) so having Capybara run on the same port in test mode would conflict. If you don't have a really specific need for Capybara to be on a specific port (firewall forwarding, etc) then just let it pick a random port.
Capybara.run_server = true
Capybara.register_driver :rack_test do |app|
Capybara::RackTest::Driver.new app, follow_redirects:false
end
That will then have Capybara start the app on 127.0.0.1:<random_port>, if you want it specifically on localhost (due to special networking needs, IPv6, etc) then you can set Capybara.server_host = 'localhost'. Also the use of follow_redirects: false is questionable since your tests that use Capybara really shouldn't be checking status codes, but rather what the user sees.
Beyond all that, if you are running a request test that ends up calling app code that does a HTTP::get you'll either need to change that test to be a feature/system test (uses Capybara, starts its own server, uses visit, etc) or mock/stub the request.

Cannot specify no_proxy for Capybara with poltergeist

I there, I am a bit stuck with this...
I can't find documentation on how to tell Capybara/Poltergeist with phantomjs to avoid the proxy and go directly to the specified IP.
Host machine (Fedora 20) config? Already tried setting no_proxy
Or, Application config?
A bit of context:
I am making a few web tests using Capybara with Poltergeist/PhantomJS. Unfortunately, my company decided that any request for an internal network that hits the proxy won't be forwarded anymore. So, since I am testing between two different machines in the company's intranet, putting the env variable no_proxy should be enough. But no...
Well... after digging a bit more on the PhantomJS github API Reference page I found the answer.
There is an option --proxy-type=[http|socks5|none] that can be passed to phantomjs command line or in the initialization of Capybara with poltergeist like this:
Capybara.run_server = false
Capybara.javascript_driver = :poltergeist
Capybara.default_wait_time = 60
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, { :phantomjs_options => ['--ignore-ssl-errors=yes', '--proxy-type=none'] })
end

What should I default_url_options[:host] for integration testing, if using Pow?

I'm using Pow to serve up my development environment. In my config/environments/development.rb and test.rb files, I had this line:
Rails.application.routes.default_url_options[:host] = "myapp.dev"
But of course that doesn't work, because then my RSpec/Capy integration test run against the development database and don't match the factory data.
Why does this even matter? I thought the testing suite spun up its own Rack server. Since it does appear to matter, to what do I set it?
Change the port in your spec_helper.rb for starters, as you're apparently running tests in your development environment.
Capybara.run_server = true
Capybara.server_port = 7000
Capybara.app_host = "http://localhost:#{Capybara.server_port}"

Port of the Rails app when running Cucumber tests

Is there a way to get, in the test, the port in which the rails app is running during cucumber test? I tried Capybara.server_port but that's nil.
Thanks.
When using the selenium driver, the port can be found on:
Capybara.current_session.driver.rack_server.port
and when using the webkit driver, it can be found on:
Capybara.current_session.driver.server_port
Alternative, you can set
Capybara.server_port
to a known value and use that.
My understanding is that if you're using rack-test, the default Capybara driver, then there's isn't actually any real web server running to make requests to.
If you want to view your app as Cucumber/Capybara would, then you'd need to start it up manually on a chosen port:
$ RAILS_ENV=test rails s -p 4000
And then have something like this in env.rb:
Capybara.configure do |config|
config.run_server = false
config.app_host = "http://localhost:4000"
end

Running capybara with nginx

Is is possible to run capybara with nginx and passenger? instead or webrick? Capybara is installed with cucumber in a rails app.
It is easy - the only thing you have to do is to switch your mind - neither capybara nor cucumber are not tied to local environment you can test application that is located in internet and it will not care about it - you can even test google.com if you want.
For your particular problem you'll have to set
Capybara.run_server = false
Capybara.server_port = 8000 # or whatever port is your instance of nginx is configured to serve
Capybara.app_host = 'http://www.google.com' # if your instance is running on remote machine, else just drop it and capybara will use localhost
You can easily control restarting of your application using cucumber hooks, you can configure it to restart before each test or before test suite. (See cucumber wiki) Within hook you'll have to issue FileUtils.touch tmp/restart.txt command. The same with database - you can manually setup hook to truncate it whenever it is needed (See database_cleaner gem)

Resources