File: machine_with_enum_integration_test.rb

package info (click to toggle)
ruby-state-machines-activerecord 0.103.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 432 kB
  • sloc: ruby: 2,527; makefile: 6
file content (196 lines) | stat: -rw-r--r-- 7,031 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# frozen_string_literal: true

require_relative 'test_helper'

class MachineWithEnumIntegrationTest < BaseTestCase
  def setup
    @original_stderr = $stderr
    $stderr = StringIO.new

    @model = new_model do
      connection.add_column table_name, :status, :integer, default: 0
      enum :status, { pending: 0, processing: 1, completed: 2, failed: 3 }
    end
  end

  def teardown
    $stderr = @original_stderr
  end

  test 'should auto detect enum integration' do
    @machine = StateMachines::Machine.new(@model, :status)
    @machine.state :pending, :processing, :completed, :failed

    # Test enum integration detection
    assert @machine.respond_to?(:enum_integrated?), 'Machine should respond to enum_integrated?'
    assert @machine.enum_integrated?
    assert_equal({ 'pending' => 0, 'processing' => 1, 'completed' => 2, 'failed' => 3 }, @machine.enum_mapping)

    # Test that states are properly defined using shared assertions
    assert_sm_states_list(@machine, %i[pending processing completed failed])
  end

  test 'should not auto detect when no enum exists' do
    @model_without_enum = new_model
    machine = @model_without_enum.state_machine(:status) do
      state :pending, :processing, :completed, :failed
    end

    assert_not machine.enum_integrated?
    # Test that states are still properly defined even without enum integration
    assert_sm_states_list(machine, %i[pending processing completed failed])
  end

  test 'should detect existing enum methods' do
    machine = @model.state_machine(:status) do
      state :pending, :processing, :completed, :failed
    end

    original_methods = machine.original_enum_methods
    assert_includes original_methods, 'pending?'
    assert_includes original_methods, 'processing?'
    assert_includes original_methods, 'completed?'
    assert_includes original_methods, 'failed?'
  end

  test 'should generate prefixed method names for enum integration' do
    machine = @model.state_machine(:status) do
      state :pending, :processing, :completed, :failed
    end

    assert_equal 'status_pending?', machine.send(:generate_state_method_name, 'pending', :predicate)
    assert_equal 'status_processing!', machine.send(:generate_state_method_name, 'processing', :bang)
    assert_equal 'status_completed', machine.send(:generate_state_method_name, 'completed', :scope)
  end

  test 'should store default enum integration metadata' do
    machine = @model.state_machine(:status) do
      state :pending, :processing, :completed, :failed
    end

    config = machine.enum_integration
    assert_equal true, config[:prefix]
    assert_equal false, config[:suffix]
    assert_equal true, config[:scopes]
  end

  test 'should generate prefixed predicate methods' do
    @model.state_machine(:status) do
      state :pending, :processing, :completed, :failed
    end

    record = @model.create(status: :pending)

    # Test using shared state machine assertions
    assert_sm_state(record, :pending, machine_name: :status)

    # Original enum methods should still work
    assert record.pending?
    assert_not record.processing?

    # Prefixed state machine methods should be generated
    assert record.respond_to?(:status_pending?)
    assert record.respond_to?(:status_processing?)
    assert record.respond_to?(:status_completed?)
    assert record.respond_to?(:status_failed?)

    # Prefixed methods should work correctly
    assert record.status_pending?
    assert_not record.status_processing?
    assert_not record.status_completed?
    assert_not record.status_failed?
  end

  test 'should generate prefixed bang methods' do
    @model.state_machine(:status) do
      state :pending, :processing, :completed, :failed

      event :process do
        transition pending: :processing
      end

      event :complete do
        transition processing: :completed
      end

      event :fail do
        transition %i[pending processing] => :failed
      end
    end

    record = @model.create(status: :pending)

    # Prefixed bang methods should be available
    assert record.respond_to?(:status_processing!)
    assert record.respond_to?(:status_completed!)
    assert record.respond_to?(:status_failed!)

    # Bang methods should exist but raise an exception (conflict resolution, not full functionality)
    assert_raises(RuntimeError) do
      record.status_failed!
    end
  end

  test 'should generate prefixed scope methods' do
    @model.state_machine(:status) do
      state :pending, :processing, :completed, :failed
    end

    pending_record = @model.create(status: :pending)
    processing_record = @model.create(status: :processing)
    completed_record = @model.create(status: :completed)

    # Test record states using shared assertions
    assert_sm_state(pending_record, :pending, machine_name: :status)
    assert_sm_state(processing_record, :processing, machine_name: :status)
    assert_sm_state(completed_record, :completed, machine_name: :status)

    # Test state persistence using shared assertions
    assert_sm_state_persisted(pending_record, 'pending', :status)
    assert_sm_state_persisted(processing_record, 'processing', :status)
    assert_sm_state_persisted(completed_record, 'completed', :status)

    # Prefixed scope methods should be available
    assert @model.respond_to?(:status_pending)
    assert @model.respond_to?(:status_processing)
    assert @model.respond_to?(:status_completed)
    assert @model.respond_to?(:status_failed)

    # Negative scope methods should be available
    assert @model.respond_to?(:not_status_pending)
    assert @model.respond_to?(:not_status_processing)

    # Scopes should work correctly
    assert_equal [pending_record], @model.status_pending.to_a
    assert_equal [processing_record], @model.status_processing.to_a
    assert_equal [completed_record], @model.status_completed.to_a
    assert_equal [], @model.status_failed.to_a

    # Negative scopes should work
    assert_equal [processing_record, completed_record], @model.not_status_pending.order(:id).to_a
  end

  test 'should track generated methods for introspection' do
    machine = @model.state_machine(:status) do
      state :pending, :processing, :completed, :failed
    end

    generated_methods = machine.state_machine_methods

    # Should track all generated prefixed methods
    assert_includes generated_methods, 'status_pending?'
    assert_includes generated_methods, 'status_processing?'
    assert_includes generated_methods, 'status_completed?'
    assert_includes generated_methods, 'status_failed?'

    assert_includes generated_methods, 'status_pending!'
    assert_includes generated_methods, 'status_processing!'
    assert_includes generated_methods, 'status_completed!'
    assert_includes generated_methods, 'status_failed!'

    assert_includes generated_methods, 'status_pending'
    assert_includes generated_methods, 'status_processing'
    assert_includes generated_methods, 'status_completed'
    assert_includes generated_methods, 'status_failed'
  end
end