Class: RuboCop::Cop::RSpecGuide::HappyPathFirst
- Inherits:
-
RuboCop::Cop::RSpec::Base
- Object
- RuboCop::Cop::RSpec::Base
- RuboCop::Cop::RSpecGuide::HappyPathFirst
- Defined in:
- lib/rubocop/cop/rspec_guide/happy_path_first.rb
Overview
Checks that corner cases are not the first context in a describe block.
Placing happy path scenarios first improves test readability by establishing the expected behavior before diving into edge cases. This makes it easier for readers to understand the primary purpose of the code being tested.
The cop allows corner case contexts to appear first if there are example blocks (it/specify) before the first context, as those examples represent the happy path.
Constant Summary collapse
- MSG =
"Place happy path contexts before corner cases. " \ "First context appears to be a corner case: %<description>s"
- CORNER_CASE_WORDS =
Words indicating corner cases
%w[ error failure invalid suspended blocked denied fails missing absent unavailable ].freeze
Instance Method Summary collapse
Instance Method Details
#context_with_description?(node) ⇒ Object
102 103 104 105 106 |
# File 'lib/rubocop/cop/rspec_guide/happy_path_first.rb', line 102 def_node_matcher :context_with_description?, "(block\n (send nil? :context (str $_description) ...)\n ...)\n" |
#on_block(node) ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
# File 'lib/rubocop/cop/rspec_guide/happy_path_first.rb', line 108 def on_block(node) # Fast pre-check: only process describe/context blocks return unless node.method?(:describe) || node.method?(:context) return unless example_group?(node) contexts = collect_direct_child_contexts(node) return if contexts.size < 2 # If there are any examples (it/specify) before the first context, # this is a happy path, so no offense return if has_examples_before_first_context?(node, contexts.first) # Check first context context_with_description?(contexts.first) do |description| if corner_case_context?(description) add_offense( contexts.first, message: format(MSG, description: description) ) end end end |