Skip to content

Commit

Permalink
Allows metadata to override the type of Rails spec
Browse files Browse the repository at this point in the history
[Fixes #801]
  • Loading branch information
alindeman committed Oct 27, 2013
1 parent 2c4b2ae commit 3c8d163
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 24 deletions.
1 change: 1 addition & 0 deletions features/.nav
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- Changelog.md
- Upgrade.md
- RailsVersions.md (Rails versions)
- directory_structure.feature
- model_specs:
- errors_on.feature
- records.feature
Expand Down
71 changes: 71 additions & 0 deletions features/directory_structure.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
Feature: Directory Structure

Specs are usually placed in a canonical directory structure that describes
their purpose.

* Model specs reside in the `spec/models` directory
* Controller specs reside in the `spec/controllers` directory
* Request specs reside in the `spec/requests` directory
* Feature specs reside in the `spec/features` directory
* View specs reside in the `spec/views` directory
* Helper specs reside in the `spec/helpers` directory
* Mailer specs reside in the `spec/mailers` directory
* Routing specs reside in the `spec/routing` directory

If you follow this directory structure, RSpec will automatically include the
correct test support functions for each type of test.

Application developers are free to use a different directory structure, but
will need to specify the types manually by adding a `:type` metadata key (for
example, `describe WidgetsController, :type => :controller`)

Scenario: Specs in the `spec/controllers` directory automatically tagged as controller specs
Given a file named "spec/controllers/widgets_controller_spec.rb" with:
"""ruby
require "spec_helper"
describe WidgetsController do
it "responds successfully" do
get :index
expect(response.status).to eq(200)
end
end
"""
When I run `rspec spec`
Then the example should pass

Scenario: Specs in other directories must have their types specified manually
Given a file named "spec/functional/widgets_controller_spec.rb" with:
"""ruby
require "spec_helper"
describe WidgetsController, :type => :controller do
it "responds successfully" do
get :index
expect(response.status).to eq(200)
end
end
"""
When I run `rspec spec`
Then the example should pass

Scenario: Specs in canonical directories can override their types
Given a file named "spec/routing/duckduck_routing_spec.rb" with:
"""ruby
require "spec_helper"
Rails.application.routes.draw do
get "/example" => redirect("http://example.com")
end
# Due to limitations in the Rails routing test framework, routes that
# perform redirects must actually be tested via request specs
describe "/example", :type => :request do
it "redirects to example.com" do
get "/example"
expect(response).to redirect_to("http://example.com")
end
end
"""
When I run `rspec spec`
Then the example should pass
71 changes: 47 additions & 24 deletions lib/rspec/rails/example.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,53 @@ def c.escaped_path(*parts)
Regexp.compile(parts.join('[\\\/]') + '[\\\/]')
end

c.include RSpec::Rails::ControllerExampleGroup, :type => :controller, :example_group => {
:file_path => c.escaped_path(%w[spec controllers])
}
c.include RSpec::Rails::HelperExampleGroup, :type => :helper, :example_group => {
:file_path => c.escaped_path(%w[spec helpers])
}
if defined?(RSpec::Rails::MailerExampleGroup)
c.include RSpec::Rails::MailerExampleGroup, :type => :mailer, :example_group => {
:file_path => c.escaped_path(%w[spec mailers])
c.include RSpec::Rails::ControllerExampleGroup,
:type => :controller,
:example_group => lambda { |example_group, metadata|
metadata[:type].nil? && c.escaped_path(%w[spec controllers]) =~ example_group[:file_path]
}

c.include RSpec::Rails::HelperExampleGroup,
:type => :helper,
:example_group => lambda { |example_group, metadata|
metadata[:type].nil? && c.escaped_path(%w[spec helpers]) =~ example_group[:file_path]
}

if defined?(RSpec::Rails::MailerExampleGroup)
c.include RSpec::Rails::MailerExampleGroup,
:type => :mailer,
:example_group => lambda { |example_group, metadata|
metadata[:type].nil? && c.escaped_path(%w[spec mailers]) =~ example_group[:file_path]
}
end
c.include RSpec::Rails::ModelExampleGroup, :type => :model, :example_group => {
:file_path => c.escaped_path(%w[spec models])
}
c.include RSpec::Rails::RequestExampleGroup, :type => :request, :example_group => {
:file_path => c.escaped_path(%w[spec (requests|integration|api)])
}
c.include RSpec::Rails::RoutingExampleGroup, :type => :routing, :example_group => {
:file_path => c.escaped_path(%w[spec routing])
}
c.include RSpec::Rails::ViewExampleGroup, :type => :view, :example_group => {
:file_path => c.escaped_path(%w[spec views])
}
c.include RSpec::Rails::FeatureExampleGroup, :type => :feature, :example_group => {
:file_path => c.escaped_path(%w[spec features])
}

c.include RSpec::Rails::ModelExampleGroup,
:type => :model,
:example_group => lambda { |example_group, metadata|
metadata[:type].nil? && c.escaped_path(%w[spec models]) =~ example_group[:file_path]
}

c.include RSpec::Rails::RequestExampleGroup,
:type => :request,
:example_group => lambda { |example_group, metadata|
metadata[:type].nil? && c.escaped_path(%w[spec (requests|integration|api)]) =~ example_group[:file_path]
}

c.include RSpec::Rails::RoutingExampleGroup,
:type => :routing,
:example_group => lambda { |example_group, metadata|
metadata[:type].nil? && c.escaped_path(%w[spec routing]) =~ example_group[:file_path]
}

c.include RSpec::Rails::ViewExampleGroup,
:type => :view,
:example_group => lambda { |example_group, metadata|
metadata[:type].nil? && c.escaped_path(%w[spec views]) =~ example_group[:file_path]
}

c.include RSpec::Rails::FeatureExampleGroup,
:type => :feature,
:example_group => lambda { |example_group, metadata|
metadata[:type].nil? && c.escaped_path(%w[spec features]) =~ example_group[:file_path]
}
end

0 comments on commit 3c8d163

Please sign in to comment.