rubocop-rspec 1.7.0 → 3.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +955 -79
  3. data/CODE_OF_CONDUCT.md +17 -0
  4. data/MIT-LICENSE.md +1 -2
  5. data/README.md +35 -35
  6. data/config/default.yml +940 -52
  7. data/config/obsoletion.yml +30 -0
  8. data/lib/rubocop/cop/rspec/align_left_let_brace.rb +49 -0
  9. data/lib/rubocop/cop/rspec/align_right_let_brace.rb +49 -0
  10. data/lib/rubocop/cop/rspec/any_instance.rb +10 -13
  11. data/lib/rubocop/cop/rspec/around_block.rb +97 -0
  12. data/lib/rubocop/cop/rspec/base.rb +26 -0
  13. data/lib/rubocop/cop/rspec/be.rb +39 -0
  14. data/lib/rubocop/cop/rspec/be_empty.rb +45 -0
  15. data/lib/rubocop/cop/rspec/be_eq.rb +47 -0
  16. data/lib/rubocop/cop/rspec/be_eql.rb +18 -15
  17. data/lib/rubocop/cop/rspec/be_nil.rb +74 -0
  18. data/lib/rubocop/cop/rspec/before_after_all.rb +45 -0
  19. data/lib/rubocop/cop/rspec/change_by_zero.rb +184 -0
  20. data/lib/rubocop/cop/rspec/class_check.rb +101 -0
  21. data/lib/rubocop/cop/rspec/contain_exactly.rb +56 -0
  22. data/lib/rubocop/cop/rspec/context_method.rb +57 -0
  23. data/lib/rubocop/cop/rspec/context_wording.rb +117 -0
  24. data/lib/rubocop/cop/rspec/describe_class.rb +52 -21
  25. data/lib/rubocop/cop/rspec/describe_method.rb +26 -11
  26. data/lib/rubocop/cop/rspec/describe_symbol.rb +37 -0
  27. data/lib/rubocop/cop/rspec/described_class.rb +181 -34
  28. data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +38 -0
  29. data/lib/rubocop/cop/rspec/dialect.rb +84 -0
  30. data/lib/rubocop/cop/rspec/duplicated_metadata.rb +58 -0
  31. data/lib/rubocop/cop/rspec/empty_example_group.rb +134 -47
  32. data/lib/rubocop/cop/rspec/empty_hook.rb +49 -0
  33. data/lib/rubocop/cop/rspec/empty_line_after_example.rb +82 -0
  34. data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +42 -0
  35. data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +40 -0
  36. data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +82 -0
  37. data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +36 -0
  38. data/lib/rubocop/cop/rspec/empty_metadata.rb +46 -0
  39. data/lib/rubocop/cop/rspec/empty_output.rb +47 -0
  40. data/lib/rubocop/cop/rspec/eq.rb +47 -0
  41. data/lib/rubocop/cop/rspec/example_length.rb +38 -20
  42. data/lib/rubocop/cop/rspec/example_without_description.rb +98 -0
  43. data/lib/rubocop/cop/rspec/example_wording.rb +117 -27
  44. data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +110 -0
  45. data/lib/rubocop/cop/rspec/expect_actual.rb +46 -20
  46. data/lib/rubocop/cop/rspec/expect_change.rb +86 -0
  47. data/lib/rubocop/cop/rspec/expect_in_hook.rb +50 -0
  48. data/lib/rubocop/cop/rspec/expect_in_let.rb +42 -0
  49. data/lib/rubocop/cop/rspec/expect_output.rb +50 -0
  50. data/lib/rubocop/cop/rspec/focus.rb +79 -25
  51. data/lib/rubocop/cop/rspec/hook_argument.rb +48 -36
  52. data/lib/rubocop/cop/rspec/hooks_before_examples.rb +81 -0
  53. data/lib/rubocop/cop/rspec/identical_equality_assertion.rb +37 -0
  54. data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +68 -0
  55. data/lib/rubocop/cop/rspec/implicit_expect.rb +100 -0
  56. data/lib/rubocop/cop/rspec/implicit_subject.rb +167 -0
  57. data/lib/rubocop/cop/rspec/indexed_let.rb +112 -0
  58. data/lib/rubocop/cop/rspec/instance_spy.rb +74 -0
  59. data/lib/rubocop/cop/rspec/instance_variable.rb +28 -14
  60. data/lib/rubocop/cop/rspec/is_expected_specify.rb +45 -0
  61. data/lib/rubocop/cop/rspec/it_behaves_like.rb +49 -0
  62. data/lib/rubocop/cop/rspec/iterated_expectation.rb +74 -0
  63. data/lib/rubocop/cop/rspec/leading_subject.rb +57 -29
  64. data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +127 -0
  65. data/lib/rubocop/cop/rspec/let_before_examples.rb +101 -0
  66. data/lib/rubocop/cop/rspec/let_setup.rb +32 -16
  67. data/lib/rubocop/cop/rspec/match_array.rb +59 -0
  68. data/lib/rubocop/cop/rspec/message_chain.rb +10 -15
  69. data/lib/rubocop/cop/rspec/message_expectation.rb +12 -9
  70. data/lib/rubocop/cop/rspec/message_spies.rb +88 -0
  71. data/lib/rubocop/cop/rspec/metadata_style.rb +202 -0
  72. data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +35 -0
  73. data/lib/rubocop/cop/rspec/missing_expectation_target_method.rb +54 -0
  74. data/lib/rubocop/cop/rspec/mixin/comments_help.rb +38 -0
  75. data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +59 -0
  76. data/lib/rubocop/cop/rspec/mixin/file_help.rb +14 -0
  77. data/lib/rubocop/cop/rspec/mixin/final_end_location.rb +19 -0
  78. data/lib/rubocop/cop/rspec/mixin/inside_example_group.rb +29 -0
  79. data/lib/rubocop/cop/rspec/mixin/location_help.rb +37 -0
  80. data/lib/rubocop/cop/rspec/mixin/metadata.rb +63 -0
  81. data/lib/rubocop/cop/rspec/mixin/namespace.rb +23 -0
  82. data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +39 -0
  83. data/lib/rubocop/cop/rspec/mixin/top_level_group.rb +54 -0
  84. data/lib/rubocop/cop/rspec/mixin/variable.rb +21 -0
  85. data/lib/rubocop/cop/rspec/multiple_describes.rb +14 -12
  86. data/lib/rubocop/cop/rspec/multiple_expectations.rb +86 -26
  87. data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +146 -0
  88. data/lib/rubocop/cop/rspec/multiple_subjects.rb +97 -0
  89. data/lib/rubocop/cop/rspec/named_subject.rb +107 -27
  90. data/lib/rubocop/cop/rspec/nested_groups.rb +84 -47
  91. data/lib/rubocop/cop/rspec/no_expectation_example.rb +102 -0
  92. data/lib/rubocop/cop/rspec/not_to_not.rb +30 -27
  93. data/lib/rubocop/cop/rspec/overwriting_setup.rb +74 -0
  94. data/lib/rubocop/cop/rspec/pending.rb +80 -0
  95. data/lib/rubocop/cop/rspec/pending_without_reason.rb +159 -0
  96. data/lib/rubocop/cop/rspec/predicate_matcher.rb +341 -0
  97. data/lib/rubocop/cop/rspec/receive_counts.rb +89 -0
  98. data/lib/rubocop/cop/rspec/receive_messages.rb +161 -0
  99. data/lib/rubocop/cop/rspec/receive_never.rb +41 -0
  100. data/lib/rubocop/cop/rspec/redundant_around.rb +65 -0
  101. data/lib/rubocop/cop/rspec/redundant_predicate_matcher.rb +67 -0
  102. data/lib/rubocop/cop/rspec/remove_const.rb +39 -0
  103. data/lib/rubocop/cop/rspec/repeated_description.rb +98 -0
  104. data/lib/rubocop/cop/rspec/repeated_example.rb +53 -0
  105. data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +100 -0
  106. data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +96 -0
  107. data/lib/rubocop/cop/rspec/repeated_include_example.rb +105 -0
  108. data/lib/rubocop/cop/rspec/repeated_subject_call.rb +125 -0
  109. data/lib/rubocop/cop/rspec/return_from_stub.rb +169 -0
  110. data/lib/rubocop/cop/rspec/scattered_let.rb +59 -0
  111. data/lib/rubocop/cop/rspec/scattered_setup.rb +92 -0
  112. data/lib/rubocop/cop/rspec/shared_context.rb +107 -0
  113. data/lib/rubocop/cop/rspec/shared_examples.rb +125 -0
  114. data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +93 -0
  115. data/lib/rubocop/cop/rspec/skip_block_inside_example.rb +46 -0
  116. data/lib/rubocop/cop/rspec/sort_metadata.rb +71 -0
  117. data/lib/rubocop/cop/rspec/spec_file_path_format.rb +133 -0
  118. data/lib/rubocop/cop/rspec/spec_file_path_suffix.rb +40 -0
  119. data/lib/rubocop/cop/rspec/stubbed_mock.rb +176 -0
  120. data/lib/rubocop/cop/rspec/subject_declaration.rb +46 -0
  121. data/lib/rubocop/cop/rspec/subject_stub.rb +93 -74
  122. data/lib/rubocop/cop/rspec/undescriptive_literals_description.rb +69 -0
  123. data/lib/rubocop/cop/rspec/unspecified_exception.rb +67 -0
  124. data/lib/rubocop/cop/rspec/variable_definition.rb +77 -0
  125. data/lib/rubocop/cop/rspec/variable_name.rb +68 -0
  126. data/lib/rubocop/cop/rspec/verified_double_reference.rb +111 -0
  127. data/lib/rubocop/cop/rspec/verified_doubles.rb +28 -14
  128. data/lib/rubocop/cop/rspec/void_expect.rb +60 -0
  129. data/lib/rubocop/cop/rspec/yield.rb +82 -0
  130. data/lib/rubocop/cop/rspec_cops.rb +112 -0
  131. data/lib/rubocop/rspec/align_let_brace.rb +63 -0
  132. data/lib/rubocop/rspec/concept.rb +33 -0
  133. data/lib/rubocop/rspec/config_formatter.rb +27 -4
  134. data/lib/rubocop/rspec/cop/generator.rb +25 -0
  135. data/lib/rubocop/rspec/corrector/move_node.rb +51 -0
  136. data/lib/rubocop/rspec/description_extractor.rb +60 -18
  137. data/lib/rubocop/rspec/example.rb +37 -0
  138. data/lib/rubocop/rspec/example_group.rb +67 -0
  139. data/lib/rubocop/rspec/hook.rb +79 -0
  140. data/lib/rubocop/rspec/inject.rb +3 -1
  141. data/lib/rubocop/rspec/language.rb +184 -41
  142. data/lib/rubocop/rspec/node.rb +19 -0
  143. data/lib/rubocop/rspec/shared_contexts/default_rspec_language_config_context.rb +29 -0
  144. data/lib/rubocop/rspec/version.rb +1 -1
  145. data/lib/rubocop/rspec/wording.rb +61 -19
  146. data/lib/rubocop/rspec.rb +6 -2
  147. data/lib/rubocop-rspec.rb +45 -34
  148. metadata +130 -195
  149. data/Gemfile +0 -13
  150. data/Rakefile +0 -48
  151. data/lib/rubocop/cop/rspec/file_path.rb +0 -83
  152. data/lib/rubocop/rspec/language/node_pattern.rb +0 -16
  153. data/lib/rubocop/rspec/spec_only.rb +0 -61
  154. data/lib/rubocop/rspec/top_level_describe.rb +0 -61
  155. data/lib/rubocop/rspec/util.rb +0 -19
  156. data/rubocop-rspec.gemspec +0 -42
  157. data/spec/expect_violation/expectation_spec.rb +0 -85
  158. data/spec/project/changelog_spec.rb +0 -81
  159. data/spec/project/default_config_spec.rb +0 -52
  160. data/spec/project/project_requires_spec.rb +0 -8
  161. data/spec/rubocop/cop/rspec/any_instance_spec.rb +0 -30
  162. data/spec/rubocop/cop/rspec/be_eql_spec.rb +0 -59
  163. data/spec/rubocop/cop/rspec/describe_class_spec.rb +0 -113
  164. data/spec/rubocop/cop/rspec/describe_method_spec.rb +0 -32
  165. data/spec/rubocop/cop/rspec/described_class_spec.rb +0 -219
  166. data/spec/rubocop/cop/rspec/empty_example_group_spec.rb +0 -79
  167. data/spec/rubocop/cop/rspec/example_length_spec.rb +0 -117
  168. data/spec/rubocop/cop/rspec/example_wording_spec.rb +0 -82
  169. data/spec/rubocop/cop/rspec/expect_actual_spec.rb +0 -136
  170. data/spec/rubocop/cop/rspec/file_path_spec.rb +0 -236
  171. data/spec/rubocop/cop/rspec/focus_spec.rb +0 -130
  172. data/spec/rubocop/cop/rspec/hook_argument_spec.rb +0 -189
  173. data/spec/rubocop/cop/rspec/instance_variable_spec.rb +0 -75
  174. data/spec/rubocop/cop/rspec/leading_subject_spec.rb +0 -54
  175. data/spec/rubocop/cop/rspec/let_setup_spec.rb +0 -66
  176. data/spec/rubocop/cop/rspec/message_chain_spec.rb +0 -21
  177. data/spec/rubocop/cop/rspec/message_expectation_spec.rb +0 -63
  178. data/spec/rubocop/cop/rspec/multiple_describes_spec.rb +0 -28
  179. data/spec/rubocop/cop/rspec/multiple_expectations_spec.rb +0 -84
  180. data/spec/rubocop/cop/rspec/named_subject_spec.rb +0 -62
  181. data/spec/rubocop/cop/rspec/nested_groups_spec.rb +0 -55
  182. data/spec/rubocop/cop/rspec/not_to_not_spec.rb +0 -57
  183. data/spec/rubocop/cop/rspec/subject_stub_spec.rb +0 -183
  184. data/spec/rubocop/cop/rspec/verified_doubles_spec.rb +0 -71
  185. data/spec/rubocop/rspec/config_formatter_spec.rb +0 -48
  186. data/spec/rubocop/rspec/description_extractor_spec.rb +0 -35
  187. data/spec/rubocop/rspec/language/selector_set_spec.rb +0 -29
  188. data/spec/rubocop/rspec/spec_only_spec.rb +0 -97
  189. data/spec/rubocop/rspec/util/one_spec.rb +0 -21
  190. data/spec/rubocop/rspec/wording_spec.rb +0 -44
  191. data/spec/shared/rspec_only_cop_behavior.rb +0 -68
  192. data/spec/spec_helper.rb +0 -41
  193. data/spec/support/expect_violation.rb +0 -166
@@ -1,48 +0,0 @@
1
- require 'rubocop/rspec/config_formatter'
2
-
3
- RSpec.describe RuboCop::RSpec::ConfigFormatter do
4
- let(:config) do
5
- {
6
- 'AllCops' => {
7
- 'Setting' => 'fourty two'
8
- },
9
- 'RSpec/Foo' => {
10
- 'Config' => 2,
11
- 'Enabled' => true
12
- },
13
- 'RSpec/Bar' => {
14
- 'Enabled' => true
15
- }
16
- }
17
- end
18
-
19
- let(:descriptions) do
20
- {
21
- 'RSpec/Foo' => {
22
- 'Description' => 'Blah'
23
- },
24
- 'RSpec/Bar' => {
25
- 'Description' => 'Wow'
26
- }
27
- }
28
- end
29
-
30
- it 'builds a YAML dump with spacing between cops' do
31
- formatter = described_class.new(config, descriptions)
32
-
33
- expect(formatter.dump).to eql(<<-YAML.gsub(/^\s+\|/, ''))
34
- |---
35
- |AllCops:
36
- | Setting: fourty two
37
- |
38
- |RSpec/Foo:
39
- | Config: 2
40
- | Enabled: true
41
- | Description: Blah
42
- |
43
- |RSpec/Bar:
44
- | Enabled: true
45
- | Description: Wow
46
- YAML
47
- end
48
- end
@@ -1,35 +0,0 @@
1
- require 'yard'
2
-
3
- require 'rubocop/rspec/description_extractor'
4
-
5
- RSpec.describe RuboCop::RSpec::DescriptionExtractor do
6
- let(:yardocs) do
7
- [
8
- instance_double(
9
- YARD::CodeObjects::MethodObject,
10
- docstring: "Checks foo\n\nLong description",
11
- to_s: 'RuboCop::Cop::RSpec::Foo',
12
- type: :class,
13
- name: 'Foo'
14
- ),
15
- instance_double(
16
- YARD::CodeObjects::MethodObject,
17
- docstring: 'Hi',
18
- to_s: 'RuboCop::Cop::RSpec::Foo#bar',
19
- type: :method,
20
- name: 'Foo#bar'
21
- ),
22
- instance_double(
23
- YARD::CodeObjects::MethodObject,
24
- docstring: 'This is not a cop',
25
- to_s: 'RuboCop::Cop::Mixin::Sneaky',
26
- type: :class
27
- )
28
- ]
29
- end
30
-
31
- it 'builds a hash of descriptions' do
32
- expect(described_class.new(yardocs).to_h)
33
- .to eql('RSpec/Foo' => { 'Description' => 'Checks foo' })
34
- end
35
- end
@@ -1,29 +0,0 @@
1
- describe RuboCop::RSpec::Language::SelectorSet do
2
- subject(:selector_set) { described_class.new(%i(foo bar)) }
3
-
4
- it 'composes sets' do
5
- combined = selector_set + described_class.new(%i(baz))
6
-
7
- expect(combined).to eq(described_class.new(%i(foo bar baz)))
8
- end
9
-
10
- it 'compares by value' do
11
- expect(selector_set).not_to eq(described_class.new(%i(foo bar baz)))
12
- end
13
-
14
- context '#include?' do
15
- it 'returns false for selectors not in the set' do
16
- expect(selector_set.include?(:baz)).to be(false)
17
- end
18
-
19
- it 'returns true for selectors in the set' do
20
- expect(selector_set.include?(:foo)).to be(true)
21
- end
22
- end
23
-
24
- context '#to_node_pattern' do
25
- it 'builds a node pattern' do
26
- expect(selector_set.to_node_pattern).to eql(':foo :bar')
27
- end
28
- end
29
- end
@@ -1,97 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe RuboCop::RSpec::SpecOnly do
4
- subject(:cop) { fake_cop.new(config) }
5
-
6
- let(:config) do
7
- rubocop_config =
8
- {
9
- 'AllCops' => {
10
- 'RSpec' => {
11
- 'Patterns' => rspec_patterns
12
- }
13
- },
14
- 'RSpec/FakeCop' => {
15
- 'Exclude' => %w(bar_spec.rb)
16
- }
17
- }
18
-
19
- RuboCop::Config.new(rubocop_config, 'fake_cop_config.yml')
20
- end
21
-
22
- let(:fake_cop) do
23
- Class.new(RuboCop::Cop::Cop) do
24
- include RuboCop::RSpec::SpecOnly
25
-
26
- def self.name
27
- 'RuboCop::RSpec::FakeCop'
28
- end
29
-
30
- def on_send(node)
31
- add_offense(node, :expression, 'I flag everything')
32
- end
33
- end
34
- end
35
-
36
- let(:rspec_patterns) { ['_spec.rb$', '(?:^|/)spec/'] }
37
-
38
- context 'when the source path ends with `_spec.rb`' do
39
- it 'registers an offense' do
40
- expect_violation(<<-RUBY, filename: 'foo_spec.rb')
41
- foo(1)
42
- ^^^^^^ I flag everything
43
- RUBY
44
- end
45
-
46
- it 'ignores the file if it is ignored' do
47
- expect_no_violations(<<-RUBY, filename: 'bar_spec.rb')
48
- foo(1)
49
- RUBY
50
- end
51
- end
52
-
53
- context 'when the source path contains `/spec/`' do
54
- it 'registers an offense' do
55
- expect_violation(<<-RUBY, filename: '/spec/support/thing.rb')
56
- foo(1)
57
- ^^^^^^ I flag everything
58
- RUBY
59
- end
60
- end
61
-
62
- context 'when the source path starts with `spec/`' do
63
- it 'registers an offense' do
64
- expect_violation(<<-RUBY, filename: 'spec/support/thing.rb')
65
- foo(1)
66
- ^^^^^^ I flag everything
67
- RUBY
68
- end
69
- end
70
-
71
- context 'when the file is a source file without "spec" in the name' do
72
- it 'ignores the source when the path is not a spec file' do
73
- expect_no_violations(<<-RUBY, filename: 'foo.rb')
74
- foo(1)
75
- RUBY
76
- end
77
-
78
- it 'ignores the source when the path is not a specified pattern' do
79
- expect_no_violations(<<-RUBY, filename: 'foo_test.rb')
80
- foo(1)
81
- RUBY
82
- end
83
- end
84
-
85
- context 'when custom patterns are specified' do
86
- let(:rspec_patterns) do
87
- ['_test\.rb$']
88
- end
89
-
90
- it 'registers offenses when the path matches a custom specified pattern' do
91
- expect_violation(<<-RUBY, filename: 'foo_test.rb')
92
- foo(1)
93
- ^^^^^^ I flag everything
94
- RUBY
95
- end
96
- end
97
- end
@@ -1,21 +0,0 @@
1
- describe RuboCop::RSpec::Util, '.one' do
2
- let(:first) { instance_double(Object) }
3
- let(:array) { instance_double(Array, one?: true, first: first) }
4
- let(:client) { Class.new.extend(described_class) }
5
-
6
- it 'returns first element' do
7
- expect(client.one(array)).to be(first)
8
- end
9
-
10
- it 'fails if the list is empty' do
11
- expect { client.one([]) }
12
- .to raise_error(described_class::SizeError)
13
- .with_message('expected size to be exactly 1 but size was 0')
14
- end
15
-
16
- it 'fails if the list has more than one element' do
17
- expect { client.one([1, 2]) }
18
- .to raise_error(described_class::SizeError)
19
- .with_message('expected size to be exactly 1 but size was 2')
20
- end
21
- end
@@ -1,44 +0,0 @@
1
- describe RuboCop::RSpec::Wording do
2
- let(:replacements) do
3
- { 'have' => 'has', 'not' => 'does not' }
4
- end
5
-
6
- let(:ignores) do
7
- %w(only really)
8
- end
9
-
10
- expected_rewrites =
11
- {
12
- 'should return something' => 'returns something',
13
- 'should not return something' => 'does not return something',
14
- 'should do nothing' => 'does nothing',
15
- 'should have sweets' => 'has sweets',
16
- 'should worry about the future' => 'worries about the future',
17
- 'should pay for pizza' => 'pays for pizza',
18
- 'should obey my orders' => 'obeys my orders',
19
- 'should deploy the app' => 'deploys the app',
20
- 'should buy the product' => 'buys the product',
21
- 'should miss me' => 'misses me',
22
- 'should fax the document' => 'faxes the document',
23
- 'should amass debt' => 'amasses debt',
24
- 'should echo the input' => 'echoes the input',
25
- 'should alias the method' => 'aliases the method',
26
- 'should search the internet' => 'searches the internet',
27
- 'should wish me luck' => 'wishes me luck',
28
- 'should really only return one item' => 'really only returns one item',
29
- "shouldn't return something" => 'does not return something'
30
- }
31
-
32
- expected_rewrites.each do |old, new|
33
- it %(rewrites "#{old}" as "#{new}") do
34
- rewrite =
35
- described_class.new(
36
- old,
37
- replace: replacements,
38
- ignore: ignores
39
- ).rewrite
40
-
41
- expect(rewrite).to eql(new)
42
- end
43
- end
44
- end
@@ -1,68 +0,0 @@
1
- module SpecHelper
2
- # Provides a helper method for checking that `cop` works
3
- #
4
- # @note this is defined in a module so that the failure message can be
5
- # a constant without creating a bunch of warnings when the shared
6
- # context is included
7
- #
8
- module CheckCop
9
- CURRENT_FILE = Pathname.new(__FILE__).relative_path_from(ROOT).freeze
10
-
11
- FAILURE = <<-MSG.freeze
12
- Attempting to access `cop` produced the following error:
13
-
14
- %<exception>s
15
-
16
- The shared context under #{CURRENT_FILE} is included for all RSpec
17
- cops. This context expects you to define a subject named `cop` like so:
18
-
19
- describe RuboCop::Cop::RSpec::SomeCheck do
20
- subject(:cop) { described_class.new }
21
-
22
- ...
23
- end
24
-
25
- or if your cop is configurable you should have something like:
26
-
27
- describe RuboCop::Cop::RSpec::SomeConfigurableCheck, :config do
28
- subject(:cop) { described_class.new(config) }
29
-
30
- let(:cop_config) do
31
- { 'EnforcedStyle' => 'fancy', 'WhateverElse' => 'YouNeed' }
32
- end
33
-
34
- ...
35
- end
36
-
37
- This error likely means that you either don't define `cop` at the top
38
- level or you have dependent definitions (like `cop_config`) that are not
39
- defined at the top level.
40
- MSG
41
-
42
- # This method exists to reduce confusion for contributors. It is important
43
- # that these shared examples are automatically included for all cops but
44
- # it is easy for these to fail if you don't realize that your top level
45
- # describe needs to define a useable `cop` subject.
46
- def check_cop_definition
47
- cop
48
- rescue => exception
49
- raise format(FAILURE, exception: exception)
50
- end
51
- end
52
- end
53
-
54
- RSpec.shared_examples 'an rspec only cop', rspec_cop: true do
55
- include SpecHelper::CheckCop
56
-
57
- before do
58
- check_cop_definition
59
- end
60
-
61
- it 'does not deem lib/feature/thing.rb to be a relevant file' do
62
- expect(cop.relevant_file?('lib/feature/thing.rb')).to be_falsey
63
- end
64
-
65
- it 'deems spec/feature/thing_spec.rb to be a relevant file' do
66
- expect(cop.relevant_file?('spec/feature/thing_spec.rb')).to be(true)
67
- end
68
- end
data/spec/spec_helper.rb DELETED
@@ -1,41 +0,0 @@
1
- require 'rubocop'
2
-
3
- require 'rubocop/rspec/support'
4
-
5
- if ENV['CI']
6
- require 'codeclimate-test-reporter'
7
- CodeClimate::TestReporter.start
8
- end
9
-
10
- module SpecHelper
11
- ROOT = Pathname.new(__dir__).parent.freeze
12
- end
13
-
14
- spec_helper_glob = File.expand_path('{support,shared}/*.rb', __dir__)
15
- Dir.glob(spec_helper_glob).map(&method(:require))
16
-
17
- RSpec.configure do |config|
18
- config.order = :random
19
-
20
- # Define spec metadata for all rspec cop spec files
21
- cop_specs = 'spec/rubocop/cop/rspec/'
22
- config.define_derived_metadata(file_path: /\b#{cop_specs}/) do |metadata|
23
- # Attach metadata that signals the specified code is for an RSpec only cop
24
- metadata[:rspec_cop] = true
25
- end
26
-
27
- config.expect_with :rspec do |expectations|
28
- expectations.syntax = :expect # Disable `should`
29
- end
30
-
31
- config.mock_with :rspec do |mocks|
32
- mocks.syntax = :expect # Disable `should_receive` and `stub`
33
- end
34
-
35
- config.include(ExpectViolation)
36
- end
37
-
38
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
39
- $LOAD_PATH.unshift(File.dirname(__FILE__))
40
-
41
- require 'rubocop-rspec'
@@ -1,166 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'adamantium'
4
- require 'concord'
5
- require 'anima'
6
-
7
- module ExpectViolation
8
- DEFAULT_FILENAME = 'example_spec.rb'.freeze
9
-
10
- # rubocop:disable Metrics/AbcSize
11
- def expect_violation(source, filename: DEFAULT_FILENAME)
12
- expectation = Expectation.new(source)
13
- inspect_source(cop, expectation.source, filename)
14
- offenses = cop.offenses.map(&method(:to_assertion)).sort
15
-
16
- if expectation.assertions.empty?
17
- raise 'Use expect_no_violations to assert no violations'
18
- end
19
-
20
- expect(offenses).to eq(expectation.assertions.sort)
21
- end
22
-
23
- def expect_no_violations(source, filename: DEFAULT_FILENAME)
24
- inspect_source(cop, source, filename)
25
-
26
- expect(cop.offenses.empty?).to be(true)
27
- end
28
-
29
- private
30
-
31
- def to_assertion(offense)
32
- Expectation::Assertion.new(
33
- message: offense.message,
34
- line_number: offense.location.line,
35
- column_range: offense.location.column_range
36
- )
37
- end
38
-
39
- class Expectation
40
- VIOLATION_LINE_PATTERN = /\A *\^/
41
-
42
- VIOLATION = :violation
43
- SOURCE = :line
44
-
45
- include Adamantium, Concord.new(:string)
46
-
47
- def source
48
- source_map.to_s
49
- end
50
-
51
- def assertions
52
- source_map.assertions
53
- end
54
-
55
- private
56
-
57
- def source_map
58
- tokens.reduce(Source::BLANK) do |source, (type, tokens)|
59
- tokens.reduce(source, :"add_#{type}")
60
- end
61
- end
62
- memoize :source_map
63
-
64
- def tokens
65
- string.each_line.chunk do |line|
66
- next SOURCE unless line =~ VIOLATION_LINE_PATTERN
67
-
68
- VIOLATION
69
- end
70
- end
71
-
72
- class Source
73
- include Concord.new(:lines)
74
-
75
- BLANK = new([].freeze)
76
-
77
- def add_line(line)
78
- self.class.new(lines + [Line.new(text: line, number: lines.size + 1)])
79
- end
80
-
81
- def add_violation(violation)
82
- self.class.new([*lines[0...-1], lines.last.add_violation(violation)])
83
- end
84
-
85
- def to_s
86
- lines.map(&:text).join
87
- end
88
-
89
- def assertions
90
- lines.flat_map(&:assertions)
91
- end
92
-
93
- class Line
94
- DEFAULTS = { violations: [] }.freeze
95
-
96
- include Anima.new(:text, :number, :violations)
97
-
98
- def initialize(options)
99
- super(DEFAULTS.merge(options))
100
- end
101
-
102
- def add_violation(violation)
103
- with(violations: violations + [violation])
104
- end
105
-
106
- def assertions
107
- violations.map do |violation|
108
- Assertion.parse(
109
- text: violation,
110
- line_number: number
111
- )
112
- end
113
- end
114
- end
115
- end
116
-
117
- class Assertion
118
- def self.parse(text:, line_number:)
119
- parser = Parser.new(text)
120
-
121
- new(
122
- message: parser.message,
123
- column_range: parser.column_range,
124
- line_number: line_number
125
- )
126
- end
127
-
128
- include Anima.new(:message, :column_range, :line_number),
129
- Adamantium,
130
- Comparable
131
-
132
- def <=>(other)
133
- to_a <=> other.to_a
134
- end
135
-
136
- protected
137
-
138
- def to_a
139
- [line_number, column_range.first, column_range.last, message]
140
- end
141
-
142
- class Parser
143
- COLUMN_PATTERN = /^ *(?<carets>\^\^*) (?<message>.+)$/
144
-
145
- include Concord.new(:text), Adamantium
146
-
147
- def column_range
148
- Range.new(*match.offset(:carets), true)
149
- end
150
-
151
- def message
152
- match[:message]
153
- end
154
-
155
- private
156
-
157
- def match
158
- text.match(COLUMN_PATTERN)
159
- end
160
- memoize :match
161
- end
162
-
163
- private_constant(*constants(false))
164
- end
165
- end
166
- end