Class: Reek::Spec::ShouldReekOf

Inherits:
Object
  • Object
show all
Includes:
RSpec::Matchers::Composable
Defined in:
lib/reek/spec/should_reek_of.rb

Overview

An rspec matcher that matches when the actual has the specified code smell.

Direct Known Subclasses

ShouldReekOnlyOf

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(smell_type, smell_details = {}, configuration = Configuration::AppConfiguration.default) ⇒ ShouldReekOf

Returns a new instance of ShouldReekOf.



18
19
20
21
22
23
24
25
26
# File 'lib/reek/spec/should_reek_of.rb', line 18

def initialize(smell_type,
               smell_details = {},
               configuration = Configuration::AppConfiguration.default)
  @smell_type = smell_type.to_s
  @smell_details = smell_details
  configuration.load_values(DETECTORS_KEY =>
                              { smell_type => { SmellConfiguration::ENABLED_KEY => true } })
  @configuration = configuration
end

Instance Attribute Details

#configurationObject (readonly, private)

Returns the value of attribute configuration.



46
47
48
# File 'lib/reek/spec/should_reek_of.rb', line 46

def configuration
  @configuration
end

#examinerObject (private)

Returns the value of attribute examiner.



48
49
50
# File 'lib/reek/spec/should_reek_of.rb', line 48

def examiner
  @examiner
end

#failure_messageObject

Returns the value of attribute failure_message.



16
17
18
# File 'lib/reek/spec/should_reek_of.rb', line 16

def failure_message
  @failure_message
end

#failure_message_when_negatedObject

Returns the value of attribute failure_message_when_negated.



16
17
18
# File 'lib/reek/spec/should_reek_of.rb', line 16

def failure_message_when_negated
  @failure_message_when_negated
end

#smell_detailsObject (readonly, private)

Returns the value of attribute smell_details.



46
47
48
# File 'lib/reek/spec/should_reek_of.rb', line 46

def smell_details
  @smell_details
end

#smell_typeObject (readonly, private)

Returns the value of attribute smell_type.



46
47
48
# File 'lib/reek/spec/should_reek_of.rb', line 46

def smell_type
  @smell_type
end

Instance Method Details

#all_relevant_smell_details_formattedObject (private)



91
92
93
94
95
96
97
98
# File 'lib/reek/spec/should_reek_of.rb', line 91

def all_relevant_smell_details_formatted
  matching_smell_types.each_with_object([]).with_index do |(smell, accumulator), index|
    accumulator << "#{index + 1}.)\n"
    warning_as_hash = smell.smell_warning.to_hash
    warning_as_hash.delete('smell_type')
    accumulator << "#{warning_as_hash}\n"
  end.join
end

#matches?(source) ⇒ Boolean

Returns:

  • (Boolean)


28
29
30
31
32
33
34
35
# File 'lib/reek/spec/should_reek_of.rb', line 28

def matches?(source)
  @matching_smell_types = nil
  self.examiner = Examiner.new(source,
                               filter_by_smells: [smell_type],
                               configuration: configuration)
  set_failure_messages
  matching_smell_details?
end

#matching_smell_details?Boolean (private)

Returns:

  • (Boolean)


67
68
69
# File 'lib/reek/spec/should_reek_of.rb', line 67

def matching_smell_details?
  matching_smell_types.any? { |warning| warning.matches_attributes?(smell_details) }
end

#matching_smell_typesObject (private)



59
60
61
# File 'lib/reek/spec/should_reek_of.rb', line 59

def matching_smell_types
  @matching_smell_types ||= examiner.smells.map { |it| SmellMatcher.new(it) }
end

#matching_smell_types?Boolean (private)

Returns:

  • (Boolean)


63
64
65
# File 'lib/reek/spec/should_reek_of.rb', line 63

def matching_smell_types?
  matching_smell_types.any?
end

#originObject (private)



100
101
102
# File 'lib/reek/spec/should_reek_of.rb', line 100

def origin
  examiner.origin
end

#set_failure_messagesObject (private)



50
51
52
53
54
55
56
57
# File 'lib/reek/spec/should_reek_of.rb', line 50

def set_failure_messages
  # We set the failure messages for non-matching smell type unconditionally since we
  # need that in any case for "failure_message_when_negated" below.
  # Depending on the existence of matching smell type we check for matching
  # smell details and then overwrite our failure messages conditionally.
  set_failure_messages_for_smell_type
  set_failure_messages_for_smell_details if matching_smell_types? && !matching_smell_details?
end

#set_failure_messages_for_smell_detailsObject (private)



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/reek/spec/should_reek_of.rb', line 78

def set_failure_messages_for_smell_details
  self.failure_message =
    "Expected #{origin} to reek of #{smell_type} " \
    "(which it did) with smell details #{smell_details}, which it didn't.\n" \
    "The number of smell details I had to compare with the given one was #{matching_smell_types.count} " \
    "and here they are:\n" \
    "#{all_relevant_smell_details_formatted}"
  self.failure_message_when_negated =
    "Expected #{origin} not to reek of " \
    "#{smell_type} with smell details #{smell_details}, but it did"
end

#set_failure_messages_for_smell_typeObject (private)



71
72
73
74
75
76
# File 'lib/reek/spec/should_reek_of.rb', line 71

def set_failure_messages_for_smell_type
  self.failure_message = "Expected #{origin} to reek of #{smell_type}, " \
                         'but it didn\'t'
  self.failure_message_when_negated = "Expected #{origin} not to reek " \
                                      "of #{smell_type}, but it did"
end

#with_config(config_hash) ⇒ Object



37
38
39
40
41
42
# File 'lib/reek/spec/should_reek_of.rb', line 37

def with_config(config_hash)
  new_configuration = Configuration::AppConfiguration.default
  new_configuration.load_values(DETECTORS_KEY =>
                                  { smell_type => config_hash })
  self.class.new(smell_type, smell_details, new_configuration)
end