Class: Statecraft::RSpec::Transition

Inherits:
Object
  • Object
show all
Defined in:
lib/statecraft/rspec/transition.rb

Overview

expect { order.fire!(:pay) }.to transition(order) .from(:pending).to(:paid).via_event(:pay).with_metadata("k" => "v")

The transition through the eyes of a test: the state column moved to the target AND exactly one log row was appended with the matching from/to/event/metadata — and under versioning: the version column incremented together with the state. A non-bang call that returned false leaves both untouched — the matcher fails and explains why, from the same introspection the pipeline consulted. Exceptions of the bang forms fly through, like with the change matcher: refusals are asserted with refuse_event or raise_error, not here.

Instance Method Summary collapse

Constructor Details

#initialize(record) ⇒ Transition

Returns a new instance of Transition.



17
18
19
20
# File 'lib/statecraft/rspec/transition.rb', line 17

def initialize(record)
  @record = record
  @failures = []
end

Instance Method Details

#descriptionObject



75
76
77
# File 'lib/statecraft/rspec/transition.rb', line 75

def description
  "transition #{@record.class.name} to #{@to_state.inspect}"
end

#failure_messageObject



61
62
63
64
65
66
# File 'lib/statecraft/rspec/transition.rb', line 61

def failure_message
  expected_event = " via event #{@event_name.inspect}" if @event_name
  header = "expected the block to transition #{@record.class.name} " \
           "#{@before_state.inspect} -> #{@to_state.inspect}#{expected_event}"
  ([header] + @failures).join("\n  ")
end

#failure_message_when_negatedObject



68
69
70
71
72
73
# File 'lib/statecraft/rspec/transition.rb', line 68

def failure_message_when_negated
  row = @appended.last
  written_by = " by event #{row.event.inspect}" if row.event
  "expected the block not to transition #{@record.class.name} to #{@to_state.inspect}, " \
    "but it did: #{row.from_state.inspect} -> #{row.to_state.inspect}#{written_by}"
end

#from(state_name) ⇒ Object



22
23
24
25
# File 'lib/statecraft/rspec/transition.rb', line 22

def from(state_name)
  @from_state = state_name.to_sym
  self
end

#matches?(block) ⇒ Boolean

Returns:

  • (Boolean)

Raises:

  • (ArgumentError)


46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/statecraft/rspec/transition.rb', line 46

def matches?(block)
  raise ArgumentError, "transition(record).to(:state) — the .to target is required" unless @to_state

  @version_column = @record.class.statecraft_mounting.version_column
  @before_state = StateReport.current_state(@record)
  @before_version = @record[@version_column] if @version_column
  appended_before = @record.history.count
  block.call
  @after_state = StateReport.current_state(@record)
  @after_version = @record[@version_column] if @version_column
  @appended = @record.history.offset(appended_before).to_a
  collect_failures
  @failures.empty?
end

#supports_block_expectations?Boolean

Returns:

  • (Boolean)


42
43
44
# File 'lib/statecraft/rspec/transition.rb', line 42

def supports_block_expectations?
  true
end

#to(state_name) ⇒ Object



27
28
29
30
# File 'lib/statecraft/rspec/transition.rb', line 27

def to(state_name)
  @to_state = state_name.to_sym
  self
end

#via_event(event_name) ⇒ Object



32
33
34
35
# File 'lib/statecraft/rspec/transition.rb', line 32

def via_event(event_name)
  @event_name = event_name.to_sym
  self
end

#with_metadata(metadata) ⇒ Object



37
38
39
40
# File 'lib/statecraft/rspec/transition.rb', line 37

def ()
  @metadata = 
  self
end