ruby rails test case failing but real app works - ruby-on-rails-4

So here's a strange problem: When I start my local rails app and browse to http://localhost:3000/static_pages/help I can see the page I created there.
However, the test case that I wrote says otherwise.
static_pages_controller_test.rb
require 'test_helper'
class StaticPagesControllerTest < ActionController::TestCase
test "should get home" do
get :home
assert_response :success
end
test "should get help" do
puts static_pages_help_url
puts static_pages_help_path
get static_pages_help_url
assert_response :success
end
end
It fails with this error, Output of $bin/rake test:
Running:
..http://test.host/static_pages/help
/static_pages/help
E
Finished in 0.466745s, 8.5700 runs/s, 4.2850 assertions/s.
1) Error.
StaticPagesControllerTest#test_should_get_help:
ActionController::UrlGenerationError: No route matches {:action=>"http://test.host/static_pages/help", :controller=>"static_pages"}
test/controllers/static_pages_controller_test.rb:12:in `block in <class:StaticPagesControllerTest>'
Here is routes.rb
Rails.application.routes.draw do
get 'static_pages/home'
get "static_pages/help"
end
and here is the static_pages_controller.rb
class StaticPagesController < ApplicationController
def home
end
def help
end
end
and these two files
app/views/static_pages/home.html.erb
app/views/static_pages/help.html.erb
exist, as I can also see them when navigating to /static_pages/help in my browser. I've searched the web for hours, no clue.
$ rails --version
Rails 4.2.7.1
$ ruby --version
ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux]
I must be missing something. Please help.

Since you're writing a controller spec, the parameter to a GET should be the action(controller method). But you're passing a URL. If you look at the error message, you can find that "http://test.host/static_pages/help" was passed into action. So, pass the name of the controller method as a symbol rather than the URL. Try
get :help
Note that help is the controller action.
However if you're interested in writing an integration test, you should inherit from ActionDispatch::IntegrationTest rather than ActionController::TestCase. So, your spec should look aomething like this.
class StaticPagesControllerTest < ActionDispatch::IntegrationTest
test "should get home" do
get static_pages_home_url
assert_response :success
end
test "should get help" do
get static_pages_help_url
assert_response :success
end
end
To learn more about integration and controller tests, see http://weblog.jamisbuck.org/2007/1/30/unit-vs-functional-vs-integration.html
Hope this helps!

Related

undefined method 'document' for nil:NilClass while running Rails-tutorial with rspec

I am following the railstutorial by Michael Hartl, and I don't understand the reason for failing tests in Chapter 5. The book used the minitest framework but I decided to use RSpec. To do this, I deleted the test folder and included rspec-rails in my Gemfile then ran bundle install and rails g rspec:install to generate my spec folders. However, there are some tests that I feel convenient running with minitest syntax such as assert_select in static_pages_controller_spec.rb file. Here is how my spec file looks like:
require "rails_helper"
RSpec.describe StaticPagesController, type: :controller do
describe "GET #home" do
it "returns http success" do
get :home
expect(response).to have_http_status(:success)
end
it "should have the right title" do
get :home
assert_select "title", "Ruby on Rails Tutorial Sample App"
end
end
describe "GET #help" do
it "returns http success" do
get :help
expect(response).to have_http_status(:success)
end
it "should have the right title" do
get :help
assert_select "title", "Help | Ruby on Rails Tutorial Sample App"
end
end
describe "GET #about" do
it "returns http success" do
get :about
expect(response).to have_http_status(:success)
end
it "should have the right title" do
get "about"
assert_select "title", "About | Ruby on Rails Tutorial Sample App"
end
end
end
When I run the tests with RSpec, this is what I get as the failure error:
StaticPagesController GET #home should have the right title
Failure/Error: assert_select "title", "Ruby on Rails Tutorial Sample App"
NoMethodError:
undefined method `document' for nil:NilClass
# ./spec/controllers/static_pages_controller_spec.rb:11:in `block (3 levels)
in <top (required)>'
The same error message (No Method error) appears in each of the failing tests.
How can I fix it? Is there something I am doing wrong.
The reason for this error is that RSpec doesn't render views for controller specs by default. You can enable view rendering for a particular group of specs like this:
describe FooController, type: :controller do
render_views
# write your specs
end
or you can enable it globally by adding this somewhere in your RSpec config:
RSpec.configure do |config|
config.render_views
end
See https://www.relishapp.com/rspec/rspec-rails/v/2-6/docs/controller-specs/render-views for more information.
The problem is that assert_selected is a MiniTest construct whereas you are using RSpec. You will need to use RSpec mechanisms for expecting view content https://relishapp.com/rspec/rspec-rails/v/3-4/docs/view-specs/view-spec or add capybara to your Gemfile and use the capybara matchers: https://gist.github.com/them0nk/2166525

Ruby on Rails App Testing with Rspec and Capybara

when i create a feature test for my application get the following error:
ActionController::RoutingError:
No route matches [GET] "/example"
My application uses subdomains and sub-applications(engines/modules) within these subdomains. Now when i set for Capybara the app_host or default_host through an feature_subdomain_helper like
Capybara.app_host = "example.lvh.me" or
Capybara.default_host = "example.lvh.me"
and into my rails_helper.rb i add the following code line
config.extend SubdomainHelpers, type: :feature
I get the same error. Now i think the configured subdomain are not considered by my feature test.
My Rspec Version is: 3.2
and Capybara Version is: 2.4.4
My sample feature test looks like:
require 'rails_helper'
feature 'Example Page' do
scenario 'visit example page' do
visit "/example"
expect(page).to have_content 'Example'
end
end
Have someone an idea what i do wrong?
Edit:
Mainapp routes:
constraints(Subdomain) do
mount Example::Engine => '/', as: 'example'
end
Engine routes:
Example::Engine.routes.draw do
scope '/example', nav_scope: 'example' do
end
end
The names of Capybara.default_host and Capybara.app_host are slightly misleading since they both need to be set as URLs to function properly
Capybara.default_host = "http://example.lvh.me"
If that doesn't fix your issue check rake routes and make sure the action you think is mounted at '/example' really is.

Why are there 2 kinds of controller tests in MiniTest?

I'm converting over to MiniTest from RSpec, and having a couple of difficulties doing so. I have been following some examples I have found:
class ArticlesControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:articles)
end
end
So that's a class that inherits from ActionController::TestCase, that makes sense.
But then there are other examples like this:
require 'test_helper'
describe ThingsController do
describe "#create" do
it do "valid"
login_user
post :create, { catalog: { name: "My Thing", description: "Description of my thing."}}
assert_redirected_to thing_path(Thing.last)
end
end
end
Why are these two styles different? I'm using the second example, and none of my redirects are working like they do in my dev system. Trying to get to the bottom of it.
First one is Minitest::Unit test syntax explained here
Second is more like Rspec syntax, you can use minitest-spec-rails gem for that

Rails 4 Rspec test session when assigned in spec

In my test i assign session to a specific value but when i run the test and print from my app controller, the session is nil. Any idea how should i do this ?
Here is my spec :
RSpec.describe "welcome/index.html.haml", type: :view do
before(:each) do
session[:followed_repos] = ["rails/rails"]
end
context "when visitor tracked repositories" do
it "should see tracked repository list" do
visit root_path
expect(page).to have_no_content("You are tracking 0 repositories. Search for more here")
expect(page).to render_template(:partial => "_tracked_repo")
end
end
end
Here is my controller where i print the value :
def index
puts session[:followed_repos].inspect
end
Thx for your help.
I found 2 answers that might help people trying to use session in type: :view :
You can use that gem: rack_session_access
You have no other choice then reproduce all the needed steps to get the session you need

Rspec assigns equivalent in unit test/minitest

Is there rspec assigns equivalent in MiniTest::Test? If not how can I check the instant controller instant variable in tests. I am using sinatra
The assigns method comes from Rails, not RSpec or Minitest. It works just the same.
The following example is from the Rails Testing Guide:
class PostsControllerTest < ActionController::TestCase
test "should get index" do
get :index
assert_response :success
assert_not_nil assigns(:posts)
end
end