Class: RailsSemanticLogging::RSpec::HaveLoggedMessageMatcher
- Inherits:
-
Object
- Object
- RailsSemanticLogging::RSpec::HaveLoggedMessageMatcher
- Defined in:
- lib/rails_semantic_logging/rspec/matchers.rb
Overview
Block matcher that finds a specific log event by message and exposes both the raw SemanticLogger::Log and an optionally formatted version to a user block, so the test can make arbitrary assertions on the event.
Complementary to log_semantic:
log_semanticis declarative ("was anything matching these criteria logged?") and returns a boolean.have_logged_messageis imperative — it finds the event, hands it over to the test, and lets the test assert whatever it needs.
Usage:
expect { logger.info("hello", key: "val") }.to ("hello")
expect { do_work }.to (/import/, :warn)
expect { service.call }
.to ("Completed").with_formatted_event { |event, formatted|
expect(event.payload).to include(order_id: order.id)
expect(formatted.dig("http", "status_code")).to eq(200)
}
The optional with_formatted_event block receives (event, formatted)
where formatted is the JSON output of the chosen formatter parsed back
with indifferent access. By default the gem's Datadog formatter is used;
pass any SemanticLogger::Formatters::Base subclass to override:
.with_formatted_event(SemanticLogger::Formatters::Json) { |event, formatted| ... }
Constant Summary collapse
- DEFAULT_FORMATTER =
::RailsSemanticLogging::Formatters::Datadog
Instance Attribute Summary collapse
-
#event_block ⇒ Object
readonly
Returns the value of attribute event_block.
Instance Method Summary collapse
- #failure_message ⇒ Object
- #failure_message_when_negated ⇒ Object
-
#initialize(expected, expected_level = nil) ⇒ HaveLoggedMessageMatcher
constructor
A new instance of HaveLoggedMessageMatcher.
- #matches?(block) ⇒ Boolean
- #supports_block_expectations? ⇒ Boolean
-
#with_formatted_event(formatter_class = nil, &block) ⇒ Object
Attach a block that receives the matched
(log_event, formatted)pair.
Constructor Details
#initialize(expected, expected_level = nil) ⇒ HaveLoggedMessageMatcher
Returns a new instance of HaveLoggedMessageMatcher.
181 182 183 184 185 |
# File 'lib/rails_semantic_logging/rspec/matchers.rb', line 181 def initialize(expected, expected_level = nil) @expected_message = expected @expected_level = expected_level @formatter_class = DEFAULT_FORMATTER end |
Instance Attribute Details
#event_block ⇒ Object (readonly)
Returns the value of attribute event_block.
177 178 179 |
# File 'lib/rails_semantic_logging/rspec/matchers.rb', line 177 def event_block @event_block end |
Instance Method Details
#failure_message ⇒ Object
223 224 225 226 227 228 229 230 |
# File 'lib/rails_semantic_logging/rspec/matchers.rb', line 223 def return @error. if @error if @log_event && @expected_level && @log_event.level != @expected_level return "expected log level #{@expected_level.inspect}, got #{@log_event.level.inspect}" end "expected block to log a message matching #{@expected_message.inspect}" end |
#failure_message_when_negated ⇒ Object
232 233 234 |
# File 'lib/rails_semantic_logging/rspec/matchers.rb', line 232 def "expected block NOT to log a message matching #{@expected_message.inspect}, but a matching event was emitted" end |
#matches?(block) ⇒ Boolean
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'lib/rails_semantic_logging/rspec/matchers.rb', line 187 def matches?(block) # Capture the live appender BEFORE we attach our test appender. The # Datadog formatter reads `logger.host` on the appender it receives, so # the formatter call later on needs a real one (any subscriber will do). @live_appender = ::SemanticLogger.appenders.first @log_event = capture_first_matching_event(block) return false unless @log_event return false if @expected_level && @log_event.level != @expected_level @event_block&.call(@log_event, formatted) true rescue ::RSpec::Expectations::ExpectationNotMetError => e @error = e false end |
#supports_block_expectations? ⇒ Boolean
203 204 205 |
# File 'lib/rails_semantic_logging/rspec/matchers.rb', line 203 def supports_block_expectations? true end |
#with_formatted_event(formatter_class = nil, &block) ⇒ Object
Attach a block that receives the matched (log_event, formatted) pair.
formatted is the JSON output of the configured formatter, parsed back
with HashWithIndifferentAccess so callers can navigate the structure
with either string or symbol keys.
211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/rails_semantic_logging/rspec/matchers.rb', line 211 def with_formatted_event(formatter_class = nil, &block) raise ArgumentError, 'block is required' unless block if formatter_class && !(formatter_class < ::SemanticLogger::Formatters::Base) raise ArgumentError, "formatter must inherit from SemanticLogger::Formatters::Base, got #{formatter_class.inspect}" end @formatter_class = formatter_class if formatter_class @event_block = block self end |