Skip to content

Commit

Permalink
Fix spec type inferrence.
Browse files Browse the repository at this point in the history
- In #970 we added `infer_spec_type_from_file_location!` but forgot
  to remove the code in `lib/rspec/rails/configuration.rb` that
  made it always infer - so the opt-in API was there but it
  was always enabled. Here I've made it truly opt-in.
- The logic of `infer_spec_type_from_file_location!` also setup
  the helper module inclusion via explicit `:type` metadata but
  was only intended to setup the implicit mapping of spec file
  location to type.  Here I've made the module inclusion via
  `:type` always work w/o an explicit config option needed to
  enable it.
- We used to mutate the `:type` metadata on inclusion of the helper
  module, but this caused bugs such as #825. The problem is that
  rspec-core uses a raw hash for the metadata and doesn't re-apply
  filtering/inclusion logic when the metadata hash is mutated.
  Instead, we use a new explicit `define_derived_metadata` API.

Fixes #825 and closes #829.
  • Loading branch information
myronmarston committed Apr 21, 2014
1 parent fd3f5ea commit e135076
Show file tree
Hide file tree
Showing 23 changed files with 134 additions and 242 deletions.
14 changes: 14 additions & 0 deletions features/directory_structure.feature
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ Feature: Directory Structure
"""ruby
require "spec_helper"
RSpec.configure do |config|
config.before(:context, :type => :controller) do
puts "Running a controller example group"
end
end
describe WidgetsController do
it "responds successfully" do
get :index
Expand All @@ -33,12 +39,19 @@ Feature: Directory Structure
"""
When I run `rspec spec`
Then the example should pass
And the output should contain "Running a controller example group"

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"
RSpec.configure do |config|
config.before(:context, :type => :controller) do
puts "Running a controller example group"
end
end
describe WidgetsController, :type => :controller do
it "responds successfully" do
get :index
Expand All @@ -48,6 +61,7 @@ Feature: Directory Structure
"""
When I run `rspec spec`
Then the example should pass
And the output should contain "Running a controller example group"

Scenario: Specs in canonical directories can override their types
Given a file named "spec/routing/duckduck_routing_spec.rb" with:
Expand Down
47 changes: 45 additions & 2 deletions lib/rspec/rails.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,45 @@
require 'rspec/rails/without_filetype_infer'
require 'rspec/rails/configuration'
require 'rspec/core'
require 'rspec/collection_matchers'
require 'rails/version'
require 'rspec/rails/extensions'
require 'rspec/rails/view_rendering'
require 'rspec/rails/adapters'
require 'rspec/rails/matchers'
require 'rspec/rails/fixture_support'
require 'rspec/rails/example'
require 'rspec/rails/vendor/capybara'

RSpec.configure do |c|
c.backtrace_exclusion_patterns << /vendor\//
c.backtrace_exclusion_patterns << /lib\/rspec\/rails/

c.include RSpec::Rails::ControllerExampleGroup, :type => :controller
c.include RSpec::Rails::HelperExampleGroup, :type => :helper
c.include RSpec::Rails::ModelExampleGroup, :type => :model
c.include RSpec::Rails::RequestExampleGroup, :type => :request
c.include RSpec::Rails::RoutingExampleGroup, :type => :routing
c.include RSpec::Rails::ViewExampleGroup, :type => :view
c.include RSpec::Rails::FeatureExampleGroup, :type => :feature

if defined?(RSpec::Rails::MailerExampleGroup)
c.include RSpec::Rails::MailerExampleGroup, :type => :mailer
end

def c.infer_spec_type_from_file_location!
{
:controller => %w[spec controllers],
:helper => %w[spec helpers],
:mailer => %w[spec mailers],
:model => %w[spec models],
:request => %w[spec (requests|integration|api)],
:routing => %w[spec routing],
:view => %w[spec views],
:feature => %w[spec features]
}.each do |type, dir_parts|
escaped_path = Regexp.compile(dir_parts.join('[\\\/]') + '[\\\/]')
define_derived_metadata(:file_path => escaped_path) do |metadata|
metadata[:type] ||= type
end
end
end
end
63 changes: 0 additions & 63 deletions lib/rspec/rails/configuration.rb

This file was deleted.

2 changes: 0 additions & 2 deletions lib/rspec/rails/example.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,3 @@
require 'rspec/rails/example/routing_example_group'
require 'rspec/rails/example/model_example_group'
require 'rspec/rails/example/feature_example_group'

require 'rspec/rails/infer_type_configuration'
2 changes: 0 additions & 2 deletions lib/rspec/rails/example/controller_example_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,6 @@ def method_missing(method, *args, &block)
included do
subject { controller }

metadata[:type] = :controller

before do
self.routes = ::Rails.application.routes
end
Expand Down
2 changes: 0 additions & 2 deletions lib/rspec/rails/example/feature_example_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ module FeatureExampleGroup
DEFAULT_HOST = "www.example.com"

included do
metadata[:type] = :feature

app = ::Rails.application
if app.respond_to?(:routes)
include app.routes.url_helpers if app.routes.respond_to?(:url_helpers)
Expand Down
2 changes: 0 additions & 2 deletions lib/rspec/rails/example/helper_example_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ def _controller_path(example)
end

included do
metadata[:type] = :helper

before do |example|
controller.controller_path = _controller_path(example)
end
Expand Down
1 change: 0 additions & 1 deletion lib/rspec/rails/example/mailer_example_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ module MailerExampleGroup
include ActionMailer::TestCase::Behavior

included do
metadata[:type] = :mailer
include ::Rails.application.routes.url_helpers
options = ::Rails.configuration.action_mailer.default_url_options
options.each { |key, value| default_url_options[key] = value } if options
Expand Down
4 changes: 0 additions & 4 deletions lib/rspec/rails/example/model_example_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,5 @@ module RSpec::Rails
module ModelExampleGroup
extend ActiveSupport::Concern
include RSpec::Rails::RailsExampleGroup

included do
metadata[:type] = :model
end
end
end
2 changes: 0 additions & 2 deletions lib/rspec/rails/example/request_example_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ def app
end

included do
metadata[:type] = :request

before do
@routes = ::Rails.application.routes
end
Expand Down
2 changes: 0 additions & 2 deletions lib/rspec/rails/example/routing_example_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ def routes(&blk)
end

included do
metadata[:type] = :routing

before do
self.routes = ::Rails.application.routes
end
Expand Down
1 change: 0 additions & 1 deletion lib/rspec/rails/example/view_example_group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ def _include_controller_helpers
included do
include ExampleMethods

metadata[:type] = :view
helper(*_default_helpers)

before do
Expand Down
65 changes: 0 additions & 65 deletions lib/rspec/rails/infer_type_configuration.rb

This file was deleted.

16 changes: 0 additions & 16 deletions lib/rspec/rails/without_filetype_infer.rb

This file was deleted.

8 changes: 2 additions & 6 deletions spec/rspec/rails/example/controller_example_group_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ def self.abstract?; false; end

module RSpec::Rails
describe ControllerExampleGroup do
it { is_expected.to be_included_in_files_in('./spec/controllers/') }
it { is_expected.to be_included_in_files_in('.\\spec\\controllers\\') }
it { is_expected.to be_included_in_files_in('./spec/controllers/').or_tagged_with_type(:controller) }
it { is_expected.to be_included_in_files_in('.\\spec\\controllers\\').or_tagged_with_type(:controller) }

let(:group) do
RSpec::Core::ExampleGroup.describe do
Expand All @@ -19,10 +19,6 @@ module RSpec::Rails
expect(group.included_modules).to include(RSpec::Rails::Matchers::RoutingMatchers)
end

it "adds :type => :controller to the metadata" do
expect(group.metadata[:type]).to eq(:controller)
end

context "with implicit subject" do
it "uses the controller as the subject" do
controller = double('controller')
Expand Down
12 changes: 2 additions & 10 deletions spec/rspec/rails/example/feature_example_group_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,8 @@

module RSpec::Rails
describe FeatureExampleGroup do
it { is_expected.to be_included_in_files_in('./spec/features/') }
it { is_expected.to be_included_in_files_in('.\\spec\\features\\') }

it "adds :type => :feature to the metadata" do
group = RSpec::Core::ExampleGroup.describe do
include FeatureExampleGroup
end

expect(group.metadata[:type]).to eq(:feature)
end
it { is_expected.to be_included_in_files_in('./spec/features/').or_tagged_with_type(:feature) }
it { is_expected.to be_included_in_files_in('.\\spec\\features\\').or_tagged_with_type(:feature) }

it "includes Rails route helpers" do
with_isolated_stderr do
Expand Down
11 changes: 2 additions & 9 deletions spec/rspec/rails/example/helper_example_group_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ module RSpec::Rails
module ::FoosHelper; end
subject { HelperExampleGroup }

it { is_expected.to be_included_in_files_in('./spec/helpers/') }
it { is_expected.to be_included_in_files_in('.\\spec\\helpers\\') }
it { is_expected.to be_included_in_files_in('./spec/helpers/').or_tagged_with_type(:helper) }
it { is_expected.to be_included_in_files_in('.\\spec\\helpers\\').or_tagged_with_type(:helper) }

it "provides a controller_path based on the helper module's name" do
example = double
Expand All @@ -16,13 +16,6 @@ module ::FoosHelper; end
expect(helper_spec.__send__(:_controller_path, example)).to eq("foos")
end

it "adds :type => :helper to the metadata" do
group = RSpec::Core::ExampleGroup.describe do
include HelperExampleGroup
end
expect(group.metadata[:type]).to eq(:helper)
end

describe "#helper" do
it "returns the instance of AV::Base provided by AV::TC::Behavior" do
helper_spec = Object.new.extend HelperExampleGroup
Expand Down
Loading

0 comments on commit e135076

Please sign in to comment.