state_machines-yard 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,84 @@
1
+ require 'test_helper'
2
+
3
+ class EventHandlerTest < Minitest::Test
4
+ include TestHelpers
5
+
6
+ def setup
7
+ setup_yard
8
+ end
9
+
10
+ def teardown
11
+ cleanup_yard
12
+ end
13
+
14
+ def test_event_handler_registers_events
15
+ code = <<-RUBY
16
+ class Vehicle
17
+ state_machine :status, initial: :parked do
18
+ # Ignition event
19
+ event :ignite do
20
+ transition parked: :idling
21
+ end
22
+
23
+ # Drive event
24
+ event :drive do
25
+ transition idling: :moving
26
+ end
27
+ end
28
+ end
29
+ RUBY
30
+
31
+ parse_code(code)
32
+
33
+ vehicle_class = YARD::Registry.at('Vehicle')
34
+ refute_nil vehicle_class, "Vehicle class should be registered"
35
+
36
+ # Check for methods that should be generated for events
37
+ can_ignite_method = YARD::Registry.at('Vehicle#can_ignite?')
38
+ refute_nil can_ignite_method, "can_ignite? method should be registered"
39
+ assert_match(/Checks whether :ignite can be fired/, can_ignite_method.docstring.to_s)
40
+
41
+ ignite_method = YARD::Registry.at('Vehicle#ignite')
42
+ refute_nil ignite_method, "ignite method should be registered"
43
+ assert_match(/Fires the :ignite event/, ignite_method.docstring.to_s)
44
+
45
+ ignite_bang_method = YARD::Registry.at('Vehicle#ignite!')
46
+ refute_nil ignite_bang_method, "ignite! method should be registered"
47
+ assert_match(/Fires the :ignite event, raising an exception if it fails/, ignite_bang_method.docstring.to_s)
48
+
49
+ ignite_transition_method = YARD::Registry.at('Vehicle#ignite_transition')
50
+ refute_nil ignite_transition_method, "ignite_transition method should be registered"
51
+ assert_match(/Gets the next transition that would be performed if :ignite were to be fired/, ignite_transition_method.docstring.to_s)
52
+ end
53
+
54
+ def test_event_handler_with_multiple_events
55
+ code = <<-RUBY
56
+ class Vehicle
57
+ state_machine :status do
58
+ # These are the possible events
59
+ event :ignite, :drive, :park
60
+ end
61
+ end
62
+ RUBY
63
+
64
+ parse_code(code)
65
+
66
+ vehicle_class = YARD::Registry.at('Vehicle')
67
+ refute_nil vehicle_class, "Vehicle class should be registered"
68
+
69
+ # Check for methods that should be generated for each event
70
+ %w(ignite drive park).each do |event|
71
+ can_method = YARD::Registry.at("Vehicle#can_#{event}?")
72
+ refute_nil can_method, "can_#{event}? method should be registered"
73
+
74
+ event_method = YARD::Registry.at("Vehicle##{event}")
75
+ refute_nil event_method, "#{event} method should be registered"
76
+
77
+ bang_method = YARD::Registry.at("Vehicle##{event}!")
78
+ refute_nil bang_method, "#{event}! method should be registered"
79
+
80
+ transition_method = YARD::Registry.at("Vehicle##{event}_transition")
81
+ refute_nil transition_method, "#{event}_transition method should be registered"
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,72 @@
1
+ require 'test_helper'
2
+
3
+ class MachineHandlerTest < Minitest::Test
4
+ include TestHelpers
5
+
6
+ def setup
7
+ setup_yard
8
+ end
9
+
10
+ def teardown
11
+ cleanup_yard
12
+ end
13
+
14
+ def test_machine_handler_registers_state_machine
15
+ code = <<-RUBY
16
+ class Vehicle
17
+ # This is a state machine for vehicle status
18
+ state_machine :status, initial: :parked do
19
+ # States and events
20
+ end
21
+ end
22
+ RUBY
23
+
24
+ parse_code(code)
25
+
26
+ vehicle_class = YARD::Registry.at('Vehicle')
27
+ refute_nil vehicle_class, "Vehicle class should be registered"
28
+ assert has_attribute?(vehicle_class, 'state_machines'), "Vehicle class should have state_machines attribute"
29
+ assert_equal 1, vehicle_class['state_machines'].size, "Vehicle should have one state machine"
30
+ assert vehicle_class['state_machines'].key?(:status), "Vehicle should have a status state machine"
31
+
32
+ machine = vehicle_class['state_machines'][:status]
33
+ assert_equal :status, machine[:name], "Machine name should be :status"
34
+ assert_equal "This is a state machine for vehicle status", machine[:description], "Machine description should match"
35
+ end
36
+
37
+ def test_machine_handler_with_default_name
38
+ code = <<-RUBY
39
+ class Vehicle
40
+ # Default state machine
41
+ state_machine do
42
+ # States and events
43
+ end
44
+ end
45
+ RUBY
46
+
47
+ parse_code(code)
48
+
49
+ vehicle_class = YARD::Registry.at('Vehicle')
50
+ refute_nil vehicle_class, "Vehicle class should be registered"
51
+ assert vehicle_class['state_machines'].key?(:state), "Vehicle should have a default state machine"
52
+ end
53
+
54
+ def test_machine_handler_with_options
55
+ code = <<-RUBY
56
+ class Vehicle
57
+ # State machine with options
58
+ state_machine :status, initial: :parked, namespace: 'vehicle', attribute: :vehicle_status do
59
+ # States and events
60
+ end
61
+ end
62
+ RUBY
63
+
64
+ parse_code(code)
65
+
66
+ vehicle_class = YARD::Registry.at('Vehicle')
67
+ refute_nil vehicle_class, "Vehicle class should be registered"
68
+
69
+ machine = vehicle_class['state_machines'][:status]
70
+ refute_nil machine, "Status state machine should be registered"
71
+ end
72
+ end
@@ -0,0 +1,66 @@
1
+ require 'test_helper'
2
+
3
+ class StateHandlerTest < Minitest::Test
4
+ include TestHelpers
5
+
6
+ def setup
7
+ setup_yard
8
+ end
9
+
10
+ def teardown
11
+ cleanup_yard
12
+ end
13
+
14
+ def test_state_handler_registers_states
15
+ code = <<-RUBY
16
+ class Vehicle
17
+ state_machine :status, initial: :parked do
18
+ # Parked state
19
+ state :parked do
20
+ # State behavior
21
+ end
22
+
23
+ # Moving state
24
+ state :moving
25
+ end
26
+ end
27
+ RUBY
28
+
29
+ parse_code(code)
30
+
31
+ vehicle_class = YARD::Registry.at('Vehicle')
32
+ refute_nil vehicle_class, "Vehicle class should be registered"
33
+
34
+ # Check for methods that should be generated for states
35
+ parked_method = YARD::Registry.at('Vehicle#parked?')
36
+ refute_nil parked_method, "parked? method should be registered"
37
+ assert_equal "Checks whether :parked is the current state.", parked_method.docstring.to_s
38
+
39
+ moving_method = YARD::Registry.at('Vehicle#moving?')
40
+ refute_nil moving_method, "moving? method should be registered"
41
+ assert_equal "Checks whether :moving is the current state.", moving_method.docstring.to_s
42
+ end
43
+
44
+ def test_state_handler_with_multiple_states
45
+ code = <<-RUBY
46
+ class Vehicle
47
+ state_machine :status do
48
+ # These are the possible states
49
+ state :parked, :idling, :moving
50
+ end
51
+ end
52
+ RUBY
53
+
54
+ parse_code(code)
55
+
56
+ vehicle_class = YARD::Registry.at('Vehicle')
57
+ refute_nil vehicle_class, "Vehicle class should be registered"
58
+
59
+ # Check for methods that should be generated for each state
60
+ %w(parked idling moving).each do |state|
61
+ method = YARD::Registry.at("Vehicle##{state}?")
62
+ refute_nil method, "#{state}? method should be registered"
63
+ assert_equal "Checks whether :#{state} is the current state.", method.docstring.to_s
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,108 @@
1
+ require 'test_helper'
2
+
3
+ class TransitionHandlerTest < Minitest::Test
4
+ include TestHelpers
5
+
6
+ def setup
7
+ setup_yard
8
+ end
9
+
10
+ def teardown
11
+ cleanup_yard
12
+ end
13
+
14
+ def test_transition_handler_in_event_context
15
+ code = <<-RUBY
16
+ class Vehicle
17
+ state_machine :status, initial: :parked do
18
+ event :ignite do
19
+ # Transition from parked to idling
20
+ transition parked: :idling
21
+ end
22
+ end
23
+ end
24
+ RUBY
25
+
26
+ parse_code(code)
27
+ vehicle_class = YARD::Registry.at('Vehicle')
28
+ refute_nil vehicle_class, "Vehicle class should be registered"
29
+
30
+ # Check for transitions documentation through the event methods
31
+ ignite_method = YARD::Registry.at('Vehicle#ignite')
32
+ refute_nil ignite_method, "ignite method should be registered"
33
+ end
34
+
35
+ def test_transition_handler_with_multiple_states
36
+ code = <<-RUBY
37
+ class Vehicle
38
+ state_machine :status, initial: :parked do
39
+ event :drive do
40
+ # Transition from multiple states
41
+ transition [:idling, :parked] => :moving
42
+ end
43
+ end
44
+ end
45
+ RUBY
46
+
47
+ parse_code(code)
48
+
49
+ vehicle_class = YARD::Registry.at('Vehicle')
50
+ refute_nil vehicle_class, "Vehicle class should be registered"
51
+
52
+ # The drive method should be registered
53
+ drive_method = YARD::Registry.at('Vehicle#drive')
54
+ refute_nil drive_method, "drive method should be registered"
55
+ end
56
+
57
+ def test_transition_handler_with_conditional
58
+ code = <<-RUBY
59
+ class Vehicle
60
+ state_machine :status, initial: :parked do
61
+ event :drive do
62
+ # Transition with a conditional
63
+ transition parked: :moving, if: :engine_started?
64
+ end
65
+ end
66
+ end
67
+ RUBY
68
+
69
+ parse_code(code)
70
+
71
+ vehicle_class = YARD::Registry.at('Vehicle')
72
+ refute_nil vehicle_class, "Vehicle class should be registered"
73
+
74
+ # The drive method should be registered despite the conditional
75
+ drive_method = YARD::Registry.at('Vehicle#drive')
76
+ refute_nil drive_method, "drive method should be registered"
77
+ end
78
+
79
+ def test_transition_handler_with_special_matchers
80
+ code = <<-RUBY
81
+ class Vehicle
82
+ state_machine :status, initial: :parked do
83
+ event :repair do
84
+ # Use 'all' matcher
85
+ transition any => :parked
86
+ end
87
+
88
+ event :maintain do
89
+ # Use 'same' matcher
90
+ transition all => same
91
+ end
92
+ end
93
+ end
94
+ RUBY
95
+
96
+ parse_code(code)
97
+
98
+ vehicle_class = YARD::Registry.at('Vehicle')
99
+ refute_nil vehicle_class, "Vehicle class should be registered"
100
+
101
+ # Both methods should be registered
102
+ repair_method = YARD::Registry.at('Vehicle#repair')
103
+ refute_nil repair_method, "repair method should be registered"
104
+
105
+ maintain_method = YARD::Registry.at('Vehicle#maintain')
106
+ refute_nil maintain_method, "maintain method should be registered"
107
+ end
108
+ end
@@ -0,0 +1,152 @@
1
+ require 'test_helper'
2
+
3
+ class IntegrationTest < Minitest::Test
4
+ include TestHelpers
5
+
6
+ def setup
7
+ setup_yard
8
+ end
9
+
10
+ def teardown
11
+ cleanup_yard
12
+ end
13
+
14
+ def test_full_documentation_integration
15
+ # Create a more complex class with state machine
16
+ code = <<-RUBY
17
+ # A vehicle class representing automobiles
18
+ # @author Test Author
19
+ class Vehicle
20
+ # The vehicle's engine state
21
+ # @return [Boolean] true if the engine is on, false otherwise
22
+ attr_accessor :engine_on
23
+ # Status state machine tracks the operational status of the vehicle
24
+ state_machine :status, initial: :parked do
25
+ description "Controls the vehicle's operational status"
26
+
27
+ # Parked state - vehicle is not moving and can be started
28
+ state :parked do
29
+ description "Vehicle is stopped and secured"
30
+ end
31
+
32
+ # Idling state - engine is running but vehicle is not moving
33
+ state :idling do
34
+ description "Engine is running but vehicle is stationary"
35
+ end
36
+
37
+ # Moving state - vehicle is in motion
38
+ state :moving do
39
+ description "Vehicle is in motion"
40
+ end
41
+
42
+ # Stalled state - vehicle has encountered a problem
43
+ state :stalled do
44
+ description "Vehicle has encountered a problem"
45
+ end
46
+
47
+ # Ignition event - turns on the engine
48
+ event :ignite do
49
+ description "Starts the vehicle's engine"
50
+ transition parked: :idling
51
+ end
52
+
53
+ # Drive event - puts vehicle in motion
54
+ event :drive do
55
+ description "Puts the vehicle in motion"
56
+ transition idling: :moving
57
+ end
58
+
59
+ # Stop event - brings vehicle to a stop
60
+ event :stop do
61
+ description "Stops the vehicle"
62
+ transition moving: :idling
63
+ end
64
+
65
+ # Park event - secure the vehicle
66
+ event :park do
67
+ description "Secures the vehicle"
68
+ transition idling: :parked
69
+ end
70
+
71
+ # Stall event - unexpected problem
72
+ event :stall do
73
+ description "Vehicle encountered a problem"
74
+ transition [:idling, :moving] => :stalled
75
+ end
76
+
77
+ # Repair event - fix the stalled vehicle
78
+ event :repair do
79
+ description "Fix vehicle issues"
80
+ transition stalled: :parked
81
+ end
82
+ end
83
+
84
+ # Second state machine for the gear position
85
+ state_machine :gear, initial: :neutral do
86
+ state :neutral
87
+ state :first
88
+ state :second
89
+ state :third
90
+
91
+ event :shift_up do
92
+ transition neutral: :first, first: :second, second: :third
93
+ end
94
+
95
+ event :shift_down do
96
+ transition third: :second, second: :first, first: :neutral
97
+ end
98
+ end
99
+ end
100
+ RUBY
101
+
102
+ parse_code(code)
103
+
104
+ # Verify YARD Registry
105
+ vehicle_class = YARD::Registry.at('Vehicle')
106
+ refute_nil vehicle_class, "Vehicle class should be registered"
107
+
108
+ # Check state machines attribute exists
109
+ assert has_attribute?(vehicle_class, 'state_machines'), "Vehicle class should have state_machines attribute"
110
+ assert_equal 2, vehicle_class['state_machines'].size, "Vehicle should have two state machines"
111
+
112
+ # Check both state machines exist
113
+ assert vehicle_class['state_machines'].key?(:status), "Vehicle should have a status state machine"
114
+ assert vehicle_class['state_machines'].key?(:gear), "Vehicle should have a gear state machine"
115
+
116
+ # Check state methods
117
+ %w(parked? idling? moving? stalled? neutral? first? second? third?).each do |method_name|
118
+ method = YARD::Registry.at("Vehicle##{method_name}")
119
+ refute_nil method, "#{method_name} method should be registered"
120
+ end
121
+
122
+ # Check event methods for status machine
123
+ %w(ignite drive stop park stall repair).each do |event|
124
+ method = YARD::Registry.at("Vehicle##{event}")
125
+ refute_nil method, "#{event} method should be registered"
126
+ bang_method = YARD::Registry.at("Vehicle##{event}!")
127
+ refute_nil bang_method, "#{event}! method should be registered"
128
+ end
129
+
130
+ # Check event methods for gear machine
131
+ %w(shift_up shift_down).each do |event|
132
+ method = YARD::Registry.at("Vehicle##{event}")
133
+ refute_nil method, "#{event} method should be registered"
134
+ bang_method = YARD::Registry.at("Vehicle##{event}!")
135
+ refute_nil bang_method, "#{event}! method should be registered"
136
+ end
137
+
138
+ # Check attribute-related methods
139
+ status_method = YARD::Registry.at("Vehicle#status")
140
+ refute_nil status_method, "status method should be registered"
141
+
142
+ status_events_method = YARD::Registry.at("Vehicle#status_events")
143
+ refute_nil status_events_method, "status_events method should be registered"
144
+
145
+ # Generate documentation
146
+ YARD::CLI::Yardoc.run('--no-save', '--no-progress', '--quiet', '-o', @yard_dir)
147
+
148
+ # Check if the HTML file was generated
149
+ html_file = File.join(@yard_dir, 'Vehicle.html')
150
+ assert File.exist?(html_file), "HTML file for Vehicle should exist"
151
+ end
152
+ end
@@ -0,0 +1,72 @@
1
+ require 'test_helper'
2
+ require 'nokogiri'
3
+
4
+ class TemplatesTest < Minitest::Test
5
+ include TestHelpers
6
+
7
+ def setup
8
+ setup_yard
9
+ end
10
+
11
+ def teardown
12
+ cleanup_yard
13
+ end
14
+
15
+ def test_html_template_rendering
16
+ # Create a sample class with a state machine
17
+ code = <<-RUBY
18
+ # A vehicle class
19
+ # @author Test Author
20
+ class Vehicle
21
+ # This is a state machine for vehicle status
22
+ state_machine :status, initial: :parked do
23
+ state :parked
24
+ state :idling
25
+ state :moving
26
+
27
+ event :ignite do
28
+ transition parked: :idling
29
+ end
30
+
31
+ event :drive do
32
+ transition idling: :moving
33
+ end
34
+
35
+ event :park do
36
+ transition moving: :parked
37
+ end
38
+ end
39
+ end
40
+ RUBY
41
+
42
+ parse_code(code)
43
+
44
+ # Generate documentation
45
+ options = YARD::CLI::YardocOptions.new
46
+ options.files = []
47
+ options.output = @yard_dir
48
+
49
+ YARD::CLI::Yardoc.run('--no-save', '--no-progress', '--quiet', '-o', @yard_dir)
50
+
51
+ # Check if the HTML file was generated
52
+ html_file = File.join(@yard_dir, 'Vehicle.html')
53
+ assert File.exist?(html_file), "HTML file for Vehicle should exist"
54
+
55
+ # Parse the HTML and check for state machine content
56
+ html = File.read(html_file)
57
+ doc = Nokogiri::HTML(html)
58
+
59
+ # Check for state machine section
60
+ state_machines_section = doc.at_css('h2:contains("State Machines")')
61
+ refute_nil state_machines_section, "State Machines section should exist in the HTML"
62
+
63
+ # Check for status machine
64
+ status_machine = doc.at_css('h3:contains("status")')
65
+ refute_nil status_machine, "Status machine heading should exist in the HTML"
66
+
67
+ # Check for description
68
+ description = status_machine.next_element
69
+ refute_nil description, "Machine description should exist"
70
+ assert_equal "This is a state machine for vehicle status", description.text.strip
71
+ end
72
+ end
@@ -0,0 +1,37 @@
1
+ require 'minitest/autorun'
2
+ require 'yard'
3
+ require 'state_machines'
4
+ require 'state_machines/yard'
5
+ require 'state_machines/graphviz'
6
+ require 'nokogiri'
7
+ require 'fileutils'
8
+
9
+ # Helper module for tests
10
+ module TestHelpers
11
+ # Create a temporary directory for YARD outputs
12
+ def setup_yard
13
+ @yard_dir = File.expand_path('../tmp/yard', __dir__)
14
+ FileUtils.rm_rf(@yard_dir) if Dir.exist?(@yard_dir)
15
+ FileUtils.mkdir_p(@yard_dir)
16
+ YARD::Registry.clear
17
+ # Register our handlers
18
+ YARD::Tags::Library.define_tag("State Machines", :state_machines)
19
+ end
20
+
21
+ # Parse the given code with YARD
22
+ def parse_code(code)
23
+ YARD.parse_string(code)
24
+ YARD::Registry.load
25
+ end
26
+
27
+ # Clean up after test
28
+ def cleanup_yard
29
+ FileUtils.rm_rf(@yard_dir) if Dir.exist?(@yard_dir)
30
+ YARD::Registry.clear
31
+ end
32
+
33
+ # Helper method to check if registry object has attribute
34
+ def has_attribute?(obj, name)
35
+ obj.respond_to?(:[]) && obj[name] != nil
36
+ end
37
+ end