Skip to content

Commit

Permalink
Support conversion of implicit spec types in rspec-rails
Browse files Browse the repository at this point in the history
This closes #57.
  • Loading branch information
yujinakayama committed May 16, 2014
1 parent 8ae29f7 commit bc6847c
Show file tree
Hide file tree
Showing 11 changed files with 186 additions and 4 deletions.
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ The one-liner (implicit receiver) `should`:
* [Pending examples](#pending-examples)
* [Current example object](#current-example-object)
* [Custom matcher DSL](#custom-matcher-dsl)
* [Implicit spec types in rspec-rails](#implicit-spec-types-in-rspec-rails)
* [Example groups](#example-groups)
* [Hook scope aliases](#hook-scope-aliases)

Expand Down Expand Up @@ -1241,6 +1242,55 @@ end
* Deprecation: deprecated since RSpec 3.0
* See also: [Expectations: Matcher protocol and custom matcher API changes - The Plan for RSpec 3](http://myronmars.to/n/dev-blog/2013/07/the-plan-for-rspec-3#expectations_matcher_protocol_and_custom_matcher_api_changes)

### Implicit spec types in rspec-rails

**This conversion is available only if `rspec-rails` is loaded in your spec and your project's RSpec is `2.99.0.rc1` or later.**

Targets:

```ruby
# In spec/models/some_model_spec.rb
RSpec.configure do |rspec|
end

describe SomeModel do
end
```

Will be converted to:

```ruby
RSpec.configure do |rspec|
end

describe SomeModel, :type => :model do
end

# With `--no-explicit-spec-type`
RSpec.configure do |rspec|
rspec.infer_spec_type_from_file_location!
end

describe SomeModel do
end
```

Here's an excerpt from [the warning](https://github.com/rspec/rspec-rails/blob/ab6313b/lib/rspec/rails/infer_type_configuration.rb#L13-L22) in RSpec 2.99:

> rspec-rails 3 will no longer automatically infer an example group's spec type from the file location. You can explicitly opt-in to this feature using this snippet:
>
> ```ruby
> RSpec.configure do |config|
> config.infer_spec_type_from_file_location!
> end
> ```
>
> If you wish to manually label spec types via metadata you can safely ignore this warning and continue upgrading to RSpec 3 without addressing it.
* This conversion can be disabled by: `--keep deprecated`
* Deprecation: deprecated since RSpec 2.99, removed in RSpec 3.0
* See also: [Consider making example group mixins more explicit · rspec/rspec-rails](https://github.com/rspec/rspec-rails/issues/662)
### Example groups
**This conversion is disabled by default and available only if your project's RSpec is `3.0.0.beta2` or later.**
Expand Down
44 changes: 44 additions & 0 deletions README.md.erb
Original file line number Diff line number Diff line change
Expand Up @@ -1276,6 +1276,50 @@ Will be converted to:
* Deprecation: deprecated since RSpec 3.0
* See also: [Expectations: Matcher protocol and custom matcher API changes - The Plan for RSpec 3](http://myronmars.to/n/dev-blog/2013/07/the-plan-for-rspec-3#expectations_matcher_protocol_and_custom_matcher_api_changes)

### Implicit spec types in rspec-rails

**This conversion is available only if `rspec-rails` is loaded in your spec and your project's RSpec is `<%= rspec_version = Transpec::RSpecVersion.implicit_spec_type_disablement_available_version %>` or later.**

Targets:

```ruby
# In spec/models/some_model_spec.rb
<%=
example = <<END
RSpec.configure do |rspec|
end
describe SomeModel do
end
END
-%>
```

Will be converted to:

```ruby
<%= convert(example, rspec_version: rspec_version, path: 'spec/models/some_model_spec.rb') -%>

# With `--no-explicit-spec-type`
<%= convert(example, rspec_version: rspec_version, path: 'spec/models/some_model_spec.rb', cli: ['--no-explicit-spec-type']) -%>
```

Here's an excerpt from [the warning](https://github.com/rspec/rspec-rails/blob/ab6313b/lib/rspec/rails/infer_type_configuration.rb#L13-L22) in RSpec 2.99:

> rspec-rails 3 will no longer automatically infer an example group's spec type from the file location. You can explicitly opt-in to this feature using this snippet:
>
> ```ruby
> RSpec.configure do |config|
> config.infer_spec_type_from_file_location!
> end
> ```
>
> If you wish to manually label spec types via metadata you can safely ignore this warning and continue upgrading to RSpec 3 without addressing it.

* This conversion can be disabled by: `--keep deprecated`
* Deprecation: deprecated since RSpec 2.99, removed in RSpec 3.0
* See also: [Consider making example group mixins more explicit · rspec/rspec-rails](https://github.com/rspec/rspec-rails/issues/662)

### Example groups

**This conversion is disabled by default and available only if your project's RSpec is `<%= rspec_version = Transpec::RSpecVersion.non_monkey_patch_example_group_available_version %>` or later.**
Expand Down
1 change: 1 addition & 0 deletions lib/transpec/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Config
[:convert_stub_with_hash_to_allow_to_receive_and_return, false],
[:skip_dynamic_analysis, false],
[:add_receiver_arg_to_any_instance_implementation_block, true],
[:add_explicit_type_metadata_to_example_group, true],
[:parenthesize_matcher_arg, true]
].freeze

Expand Down
15 changes: 13 additions & 2 deletions lib/transpec/converter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,14 @@ def process_matcher_definition(matcher_definition)
end

def process_example_group(example_group)
return unless rspec_version.non_monkey_patch_example_group_available?
example_group.convert_to_non_monkey_patch! if config.convert_example_group?
if rspec_version.non_monkey_patch_example_group_available? && config.convert_example_group?
example_group.convert_to_non_monkey_patch!
end

if rspec_version.implicit_spec_type_disablement_available? &&
config.add_explicit_type_metadata_to_example_group?
example_group.add_explicit_type_metadata!
end
end

def process_rspec_configure(rspec_configure)
Expand All @@ -171,6 +177,11 @@ def process_rspec_configure(rspec_configure)
should_yield = config.add_receiver_arg_to_any_instance_implementation_block?
rspec_configure.mocks.yield_receiver_to_any_instance_implementation_blocks = should_yield
end

if rspec_version.implicit_spec_type_disablement_available? &&
!config.add_explicit_type_metadata_to_example_group?
rspec_configure.infer_spec_type_from_file_location!
end
end

def process_have(have)
Expand Down
8 changes: 8 additions & 0 deletions lib/transpec/option_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ def setup_parser # rubocop:disable MethodLength
config.add_receiver_arg_to_any_instance_implementation_block = false
end

define_option('-t', '--no-explicit-spec-type') do
config.add_explicit_type_metadata_to_example_group = false
end

define_option('-p', '--no-parentheses-matcher-arg') do
config.parenthesize_matcher_arg = false
end
Expand Down Expand Up @@ -172,6 +176,10 @@ def descriptions # rubocop:disable MethodLength
'Suppress yielding receiver instances to `any_instance`',
'implementation blocks as the first block argument.'
],
'-t' => [
'Suppress adding explicit `:type` metadata to example groups in a',
'project using rspec-rails.'
],
'-p' => [
'Suppress parenthesizing arguments of matchers when converting',
'`should` with operator matcher to `expect` with non-operator matcher.',
Expand Down
6 changes: 6 additions & 0 deletions lib/transpec/rspec_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,15 @@ def to_s
define_feature :be_truthy, '2.99.0.beta1'
define_feature :yielded_example, '2.99.0.beta1'
define_feature :yielding_receiver_to_any_instance_implementation_block, '2.99.0.beta1'

define_feature :oneliner_is_expected, '2.99.0.beta2', except: '3.0.0.beta1'
define_feature :skip, '2.99.0.beta2', except: '3.0.0.beta1'

define_feature :implicit_spec_type_disablement, '2.99.0.rc1',
except: ['3.0.0.beta1', '3.0.0.beta2']

define_feature :receive_messages, '3.0.0.beta1'

define_feature :receive_message_chain, '3.0.0.beta2'
define_feature :non_should_matcher_protocol, '3.0.0.beta2'
define_feature :non_monkey_patch_example_group, '3.0.0.beta2'
Expand Down
1 change: 1 addition & 0 deletions spec/transpec/config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module Transpec
[:boolean_matcher_type, :conditional],
[:form_of_be_falsey, 'be_falsey'],
[:add_receiver_arg_to_any_instance_implementation_block?, true],
[:add_explicit_type_metadata_to_example_group?, true],
[:parenthesize_matcher_arg?, true]
].each do |attribute, value|
describe "##{attribute}" do
Expand Down
35 changes: 35 additions & 0 deletions spec/transpec/converter_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,41 @@ def some_method
end
end
end

context 'when RSpecVersion#implicit_spec_type_disablement_available? returns true' do
before { rspec_version.stub(:implicit_spec_type_disablement_available?).and_return(true) }

context 'and Config#add_explicit_type_metadata_to_example_group? is true' do
before { config.add_explicit_type_metadata_to_example_group = true }

it 'invokes ExampleGroup#add_explicit_type_metadata!' do
example_group.should_receive(:add_explicit_type_metadata!)
converter.process_example_group(example_group)
end
end

context 'and Config#add_explicit_type_metadata_to_example_group? is false' do
before { config.add_explicit_type_metadata_to_example_group = false }

it 'does nothing' do
example_group.should_not_receive(:add_explicit_type_metadata!)
converter.process_example_group(example_group)
end
end
end

context 'when RSpecVersion#implicit_spec_type_disablement_available? returns false' do
before { rspec_version.stub(:implicit_spec_type_disablement_available?).and_return(false) }

context 'and Config#add_explicit_type_metadata_to_example_group? is true' do
before { config.add_explicit_type_metadata_to_example_group = true }

it 'does nothing' do
example_group.should_not_receive(:add_explicit_type_metadata!)
converter.process_example_group(example_group)
end
end
end
end

describe '#process_rspec_configure' do
Expand Down
9 changes: 9 additions & 0 deletions spec/transpec/option_parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,15 @@ module Transpec
end
end

describe '-t/--no-explicit-spec-type option' do
let(:args) { ['--no-explicit-spec-type'] }

it 'sets Config#add_explicit_type_metadata_to_example_group? false' do
parser.parse(args)
config.add_explicit_type_metadata_to_example_group?.should be_false
end
end

describe '-t/--convert-stub-with-hash option' do
let(:args) { ['--convert-stub-with-hash'] }

Expand Down
16 changes: 16 additions & 0 deletions spec/transpec/rspec_version_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,22 @@ module Transpec
]
end

[
:implicit_spec_type_disablement_available?
].each do |method|
include_examples 'version comparisons', method, [
['2.14.0', false],
['2.99.0.beta1', false],
['2.99.0.beta2', false],
['2.99.0.rc1', true],
['2.99.0', true],
['3.0.0.beta1', false],
['3.0.0.beta2', false],
['3.0.0.rc1', true],
['3.0.0', true]
]
end

[
:receive_messages_available?
].each do |method|
Expand Down
5 changes: 3 additions & 2 deletions tasks/readme.rake
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,10 @@ class READMEContext
converted_source = nil

in_isolated_env do
FileHelper.create_file('spec/example_spec.rb', source)
path = options[:path] || 'spec/example_spec.rb'
FileHelper.create_file(path, source)
cli.run(cli_args)
converted_source = File.read('spec/example_spec.rb')
converted_source = File.read(path)
end

converted_source = unwrap_source(converted_source, options[:wrap_with])
Expand Down

0 comments on commit bc6847c

Please sign in to comment.