Module: ModelTimeline::RSpec::Matchers

Defined in:
lib/model_timeline/rspec/matchers.rb

Overview

Custom RSpec matchers for testing model timeline entries

These matchers help you test the timeline entries created by the ModelTimeline gem. Use them in your specs to verify that your models are correctly recording timeline events.

Examples:

Basic usage with different matchers

# Check for any timeline entries
expect(user).to have_timeline_entries

# Check for specific number of entries
expect(user).to have_timeline_entries(3)

# Check for specific action
expect(user).to have_timeline_entry_action(:update)

# Check for changes to a specific attribute
expect(user).to have_timeline_entry_change(:email)

# Check for specific value change
expect(user).to have_timeline_entry(:status, "active")

Defined Under Namespace

Classes: HaveTimelineAction, HaveTimelineChange, HaveTimelineEntriesMatcher, HaveTimelineEntry, HaveTimelineEntryMetadata

Class Method Summary collapse

Class Method Details

.define_timeline_matchers_for(association_name) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/model_timeline/rspec/matchers.rb', line 30

def self.define_timeline_matchers_for(association_name)
  association_name_singularized = association_name.to_s.singularize

  Module.new do
    # Check if a model has timeline entries
    #
    # @param count [Integer, nil] The expected number of timeline entries (optional)
    # @return [HaveTimelineEntriesMatcher] A matcher that checks for timeline entries
    # @example Without count parameter
    #   expect(user).to have_timeline_entries
    # @example With count parameter
    #   expect(user).to have_timeline_entries(3)
    define_method(:"have_#{association_name}") do |count = nil|
      HaveTimelineEntriesMatcher.new(count, association_name)
    end

    # Check if a specific action was recorded in the timeline
    #
    # @param action [String, Symbol] The action name to look for
    # @return [HaveTimelineAction] A matcher that checks for a specific action
    # @example
    #   expect(user).to have_timeline_entry_action(:create)
    #   expect(user).to have_timeline_entry_action("update")
    define_method(:"have_#{association_name_singularized}_action") do |action|
      HaveTimelineAction.new(action, association_name)
    end

    # Check if a specific attribute change was recorded in the timeline
    #
    # @param attribute [String, Symbol] The attribute name to check for changes
    # @return [HaveTimelineChange] A matcher that checks if an attribute was changed
    # @example
    #   expect(user).to have_timeline_entry_change(:email)
    #   expect(user).to have_timeline_entry_change("status")
    define_method(:"have_#{association_name_singularized}_change") do |attribute|
      HaveTimelineChange.new(attribute, association_name)
    end

    # Check if an attribute was changed to a specific value in the timeline
    #
    # @param attribute [String, Symbol] The attribute name to check
    # @param value [Object] The value to check for
    # @return [HaveTimelineEntry] A matcher that checks for specific attribute values
    # @example
    #   expect(user).to have_timeline_entry(:status, "active")
    #   expect(user).to have_timeline_entry(:role, :admin)
    define_method(:"have_#{association_name_singularized}") do |attribute, value|
      HaveTimelineEntry.new(attribute, value, association_name)
    end

    # Check if a model has timeline entries with specific metadata
    #
    # @param expected_metadata [Hash] The metadata key-value pairs to check for
    # @return [HaveTimelineEntryMetadata] A matcher that checks for specific metadata
    # @example
    #   expect(user).to have_timeline_entry_metadata(foo: 'bar', baz: 'biz')
    define_method(:"have_#{association_name_singularized}_metadata") do ||
      .new(, association_name)
    end
  end
end

.included(base) ⇒ Object



26
27
28
# File 'lib/model_timeline/rspec/matchers.rb', line 26

def self.included(base)
  base.include define_timeline_matchers_for(:timeline_entries)
end