state_machine 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (240) hide show
  1. data/.gitignore +7 -11
  2. data/.travis.yml +49 -7
  3. data/Appraisals +255 -87
  4. data/CHANGELOG.md +30 -0
  5. data/README.md +142 -21
  6. data/Rakefile +1 -11
  7. data/examples/Gemfile +5 -0
  8. data/examples/Gemfile.lock +14 -0
  9. data/examples/auto_shop.rb +2 -0
  10. data/examples/car.rb +2 -0
  11. data/examples/doc/AutoShop.html +2856 -0
  12. data/examples/doc/AutoShop_state.png +0 -0
  13. data/examples/doc/Car.html +919 -0
  14. data/examples/doc/Car_state.png +0 -0
  15. data/examples/doc/TrafficLight.html +2230 -0
  16. data/examples/doc/TrafficLight_state.png +0 -0
  17. data/examples/doc/Vehicle.html +7921 -0
  18. data/examples/doc/Vehicle_state.png +0 -0
  19. data/examples/doc/_index.html +136 -0
  20. data/examples/doc/class_list.html +47 -0
  21. data/examples/doc/css/common.css +1 -0
  22. data/examples/doc/css/full_list.css +55 -0
  23. data/examples/doc/css/style.css +322 -0
  24. data/examples/doc/file_list.html +46 -0
  25. data/examples/doc/frames.html +13 -0
  26. data/examples/doc/index.html +136 -0
  27. data/examples/doc/js/app.js +205 -0
  28. data/examples/doc/js/full_list.js +173 -0
  29. data/examples/doc/js/jquery.js +16 -0
  30. data/examples/doc/method_list.html +734 -0
  31. data/examples/doc/top-level-namespace.html +105 -0
  32. data/examples/rails-rest/migration.rb +1 -5
  33. data/examples/rails-rest/view__form.html.erb +34 -0
  34. data/examples/rails-rest/view_edit.html.erb +2 -21
  35. data/examples/rails-rest/view_index.html.erb +6 -4
  36. data/examples/rails-rest/view_new.html.erb +2 -11
  37. data/examples/rails-rest/view_show.html.erb +5 -3
  38. data/examples/traffic_light.rb +2 -0
  39. data/examples/vehicle.rb +2 -0
  40. data/gemfiles/active_model-3.0.0.gemfile.lock +9 -6
  41. data/gemfiles/active_model-3.0.5.gemfile.lock +10 -7
  42. data/gemfiles/active_model-3.1.1.gemfile.lock +12 -10
  43. data/gemfiles/{active_model-3.2.0.gemfile → active_model-3.2.1.gemfile} +1 -1
  44. data/gemfiles/{graphviz-0.9.0.gemfile → active_model-3.2.12.gemfile} +1 -1
  45. data/gemfiles/active_model-3.2.12.gemfile.lock +36 -0
  46. data/gemfiles/{active_record-3.2.0.gemfile → active_model-3.2.13.rc1.gemfile} +1 -2
  47. data/gemfiles/active_model-3.2.13.rc1.gemfile.lock +36 -0
  48. data/gemfiles/active_model-4.0.0.gemfile +9 -0
  49. data/gemfiles/active_model-4.0.0.gemfile.lock +78 -0
  50. data/gemfiles/active_record-2.0.0.gemfile +2 -1
  51. data/gemfiles/active_record-2.0.0.gemfile.lock +15 -6
  52. data/gemfiles/active_record-2.0.5.gemfile +2 -1
  53. data/gemfiles/active_record-2.0.5.gemfile.lock +15 -6
  54. data/gemfiles/active_record-2.1.0.gemfile +2 -1
  55. data/gemfiles/active_record-2.1.0.gemfile.lock +15 -6
  56. data/gemfiles/active_record-2.1.2.gemfile +2 -1
  57. data/gemfiles/active_record-2.1.2.gemfile.lock +15 -6
  58. data/gemfiles/active_record-2.2.3.gemfile +2 -1
  59. data/gemfiles/active_record-2.2.3.gemfile.lock +15 -6
  60. data/gemfiles/active_record-2.3.12.gemfile +2 -1
  61. data/gemfiles/active_record-2.3.12.gemfile.lock +15 -6
  62. data/gemfiles/active_record-2.3.5.gemfile +9 -0
  63. data/gemfiles/active_record-2.3.5.gemfile.lock +39 -0
  64. data/gemfiles/active_record-3.0.0.gemfile +2 -1
  65. data/gemfiles/active_record-3.0.0.gemfile.lock +18 -11
  66. data/gemfiles/active_record-3.0.5.gemfile +2 -1
  67. data/gemfiles/active_record-3.0.5.gemfile.lock +19 -12
  68. data/gemfiles/active_record-3.1.1.gemfile +2 -1
  69. data/gemfiles/active_record-3.1.1.gemfile.lock +22 -16
  70. data/gemfiles/active_record-3.2.12.gemfile +9 -0
  71. data/gemfiles/active_record-3.2.12.gemfile.lock +51 -0
  72. data/gemfiles/active_record-3.2.13.rc1.gemfile +9 -0
  73. data/gemfiles/active_record-3.2.13.rc1.gemfile.lock +51 -0
  74. data/gemfiles/active_record-4.0.0.gemfile +11 -0
  75. data/gemfiles/active_record-4.0.0.gemfile.lock +83 -0
  76. data/gemfiles/data_mapper-0.10.2.gemfile +1 -0
  77. data/gemfiles/data_mapper-0.10.2.gemfile.lock +13 -9
  78. data/gemfiles/data_mapper-0.9.11.gemfile +1 -0
  79. data/gemfiles/data_mapper-0.9.11.gemfile.lock +31 -7
  80. data/gemfiles/data_mapper-0.9.4.gemfile.lock +25 -14
  81. data/gemfiles/data_mapper-0.9.7.gemfile +1 -0
  82. data/gemfiles/data_mapper-0.9.7.gemfile.lock +27 -15
  83. data/gemfiles/data_mapper-1.0.0.gemfile.lock +20 -17
  84. data/gemfiles/data_mapper-1.0.1.gemfile.lock +20 -17
  85. data/gemfiles/data_mapper-1.0.2.gemfile.lock +20 -17
  86. data/gemfiles/data_mapper-1.1.0.gemfile.lock +19 -16
  87. data/gemfiles/data_mapper-1.2.0.gemfile.lock +19 -16
  88. data/gemfiles/default.gemfile.lock +8 -5
  89. data/gemfiles/graphviz-0.9.17.gemfile +7 -0
  90. data/gemfiles/graphviz-0.9.17.gemfile.lock +29 -0
  91. data/gemfiles/graphviz-0.9.21.gemfile.lock +7 -4
  92. data/gemfiles/graphviz-1.0.0.gemfile.lock +7 -4
  93. data/gemfiles/graphviz-1.0.3.gemfile +7 -0
  94. data/gemfiles/graphviz-1.0.3.gemfile.lock +29 -0
  95. data/gemfiles/graphviz-1.0.8.gemfile +7 -0
  96. data/gemfiles/graphviz-1.0.8.gemfile.lock +29 -0
  97. data/gemfiles/mongo_mapper-0.10.0.gemfile +1 -0
  98. data/gemfiles/mongo_mapper-0.10.0.gemfile.lock +14 -11
  99. data/gemfiles/mongo_mapper-0.11.1.gemfile +7 -0
  100. data/gemfiles/mongo_mapper-0.11.1.gemfile.lock +44 -0
  101. data/gemfiles/mongo_mapper-0.11.2.gemfile +9 -0
  102. data/gemfiles/mongo_mapper-0.11.2.gemfile.lock +48 -0
  103. data/gemfiles/mongo_mapper-0.12.0.gemfile +9 -0
  104. data/gemfiles/mongo_mapper-0.12.0.gemfile.lock +48 -0
  105. data/gemfiles/mongo_mapper-0.5.5.gemfile.lock +7 -4
  106. data/gemfiles/mongo_mapper-0.5.8.gemfile.lock +7 -4
  107. data/gemfiles/mongo_mapper-0.6.0.gemfile.lock +7 -4
  108. data/gemfiles/mongo_mapper-0.6.10.gemfile.lock +7 -4
  109. data/gemfiles/mongo_mapper-0.7.0.gemfile.lock +7 -4
  110. data/gemfiles/mongo_mapper-0.7.5.gemfile.lock +7 -4
  111. data/gemfiles/mongo_mapper-0.8.0.gemfile.lock +7 -4
  112. data/gemfiles/mongo_mapper-0.8.3.gemfile.lock +7 -4
  113. data/gemfiles/mongo_mapper-0.8.4.gemfile.lock +7 -4
  114. data/gemfiles/mongo_mapper-0.8.6.gemfile.lock +7 -4
  115. data/gemfiles/mongo_mapper-0.9.0.gemfile.lock +7 -4
  116. data/gemfiles/mongoid-2.0.0.gemfile +2 -0
  117. data/gemfiles/mongoid-2.0.0.gemfile.lock +22 -18
  118. data/gemfiles/mongoid-2.1.4.gemfile +2 -0
  119. data/gemfiles/mongoid-2.1.4.gemfile.lock +21 -17
  120. data/gemfiles/mongoid-2.2.4.gemfile +2 -0
  121. data/gemfiles/mongoid-2.2.4.gemfile.lock +21 -17
  122. data/gemfiles/mongoid-2.3.3.gemfile +2 -0
  123. data/gemfiles/mongoid-2.3.3.gemfile.lock +21 -17
  124. data/gemfiles/mongoid-2.4.0.gemfile +9 -0
  125. data/gemfiles/mongoid-2.4.0.gemfile.lock +47 -0
  126. data/gemfiles/mongoid-2.4.10.gemfile +9 -0
  127. data/gemfiles/mongoid-2.4.10.gemfile.lock +47 -0
  128. data/gemfiles/mongoid-2.5.2.gemfile +9 -0
  129. data/gemfiles/mongoid-2.5.2.gemfile.lock +47 -0
  130. data/gemfiles/mongoid-2.6.0.gemfile +9 -0
  131. data/gemfiles/mongoid-2.6.0.gemfile.lock +47 -0
  132. data/gemfiles/mongoid-3.0.0.gemfile +8 -0
  133. data/gemfiles/mongoid-3.0.0.gemfile.lock +45 -0
  134. data/gemfiles/mongoid-3.0.22.gemfile +8 -0
  135. data/gemfiles/mongoid-3.0.22.gemfile.lock +45 -0
  136. data/gemfiles/mongoid-3.1.0.gemfile +8 -0
  137. data/gemfiles/mongoid-3.1.0.gemfile.lock +45 -0
  138. data/gemfiles/sequel-2.11.0.gemfile +2 -1
  139. data/gemfiles/sequel-2.11.0.gemfile.lock +11 -6
  140. data/gemfiles/sequel-2.12.0.gemfile +2 -1
  141. data/gemfiles/sequel-2.12.0.gemfile.lock +11 -6
  142. data/gemfiles/sequel-2.8.0.gemfile +2 -1
  143. data/gemfiles/sequel-2.8.0.gemfile.lock +11 -6
  144. data/gemfiles/sequel-3.0.0.gemfile +2 -1
  145. data/gemfiles/sequel-3.0.0.gemfile.lock +11 -6
  146. data/gemfiles/sequel-3.10.0.gemfile +9 -0
  147. data/gemfiles/sequel-3.10.0.gemfile.lock +33 -0
  148. data/gemfiles/sequel-3.13.0.gemfile +2 -1
  149. data/gemfiles/sequel-3.13.0.gemfile.lock +11 -6
  150. data/gemfiles/sequel-3.14.0.gemfile +2 -1
  151. data/gemfiles/sequel-3.14.0.gemfile.lock +11 -6
  152. data/gemfiles/sequel-3.23.0.gemfile +2 -1
  153. data/gemfiles/sequel-3.23.0.gemfile.lock +11 -6
  154. data/gemfiles/sequel-3.24.0.gemfile +2 -1
  155. data/gemfiles/sequel-3.24.0.gemfile.lock +11 -6
  156. data/gemfiles/sequel-3.29.0.gemfile +2 -1
  157. data/gemfiles/sequel-3.29.0.gemfile.lock +11 -6
  158. data/gemfiles/sequel-3.34.0.gemfile +9 -0
  159. data/gemfiles/sequel-3.34.0.gemfile.lock +33 -0
  160. data/gemfiles/sequel-3.35.0.gemfile +9 -0
  161. data/gemfiles/sequel-3.35.0.gemfile.lock +33 -0
  162. data/gemfiles/sequel-3.4.0.gemfile +9 -0
  163. data/gemfiles/sequel-3.4.0.gemfile.lock +33 -0
  164. data/gemfiles/sequel-3.44.0.gemfile +9 -0
  165. data/gemfiles/sequel-3.44.0.gemfile.lock +33 -0
  166. data/lib/state_machine.rb +6 -0
  167. data/lib/state_machine/branch.rb +9 -8
  168. data/lib/state_machine/callback.rb +2 -2
  169. data/lib/state_machine/core.rb +10 -0
  170. data/lib/state_machine/core_ext.rb +1 -0
  171. data/lib/state_machine/eval_helpers.rb +5 -3
  172. data/lib/state_machine/event.rb +17 -6
  173. data/lib/state_machine/graph.rb +92 -0
  174. data/lib/state_machine/integrations.rb +13 -1
  175. data/lib/state_machine/integrations/active_model.rb +14 -20
  176. data/lib/state_machine/integrations/active_model/observer.rb +3 -3
  177. data/lib/state_machine/integrations/active_model/observer_update.rb +42 -0
  178. data/lib/state_machine/integrations/active_record.rb +52 -25
  179. data/lib/state_machine/integrations/active_record/locale.rb +1 -1
  180. data/lib/state_machine/integrations/active_record/versions.rb +1 -17
  181. data/lib/state_machine/integrations/base.rb +15 -6
  182. data/lib/state_machine/integrations/data_mapper.rb +98 -35
  183. data/lib/state_machine/integrations/data_mapper/versions.rb +46 -8
  184. data/lib/state_machine/integrations/mongo_mapper.rb +39 -12
  185. data/lib/state_machine/integrations/mongo_mapper/locale.rb +1 -1
  186. data/lib/state_machine/integrations/mongo_mapper/versions.rb +3 -20
  187. data/lib/state_machine/integrations/mongoid.rb +52 -14
  188. data/lib/state_machine/integrations/mongoid/locale.rb +1 -1
  189. data/lib/state_machine/integrations/mongoid/versions.rb +52 -26
  190. data/lib/state_machine/integrations/sequel.rb +82 -33
  191. data/lib/state_machine/integrations/sequel/versions.rb +19 -44
  192. data/lib/state_machine/machine.rb +99 -59
  193. data/lib/state_machine/machine_collection.rb +1 -2
  194. data/lib/state_machine/macro_methods.rb +29 -0
  195. data/lib/state_machine/node_collection.rb +1 -1
  196. data/lib/state_machine/state.rb +18 -10
  197. data/lib/state_machine/state_context.rb +2 -2
  198. data/lib/state_machine/transition.rb +8 -1
  199. data/lib/state_machine/transition_collection.rb +2 -1
  200. data/lib/state_machine/version.rb +1 -1
  201. data/lib/state_machine/yard.rb +8 -0
  202. data/lib/state_machine/yard/handlers.rb +12 -0
  203. data/lib/state_machine/yard/handlers/base.rb +32 -0
  204. data/lib/state_machine/yard/handlers/event.rb +25 -0
  205. data/lib/state_machine/yard/handlers/machine.rb +344 -0
  206. data/lib/state_machine/yard/handlers/state.rb +25 -0
  207. data/lib/state_machine/yard/handlers/transition.rb +47 -0
  208. data/lib/state_machine/yard/templates.rb +3 -0
  209. data/lib/state_machine/yard/templates/default/class/html/setup.rb +30 -0
  210. data/lib/state_machine/yard/templates/default/class/html/state_machines.erb +12 -0
  211. data/lib/tasks/state_machine.rb +2 -1
  212. data/lib/yard-state_machine.rb +2 -0
  213. data/state_machine.gemspec +4 -3
  214. data/test/files/switch.rb +4 -0
  215. data/test/test_helper.rb +5 -0
  216. data/test/unit/branch_test.rb +117 -36
  217. data/test/unit/callback_test.rb +5 -2
  218. data/test/unit/eval_helpers_test.rb +49 -1
  219. data/test/unit/event_collection_test.rb +3 -1
  220. data/test/unit/event_test.rb +182 -12
  221. data/test/unit/graph_test.rb +98 -0
  222. data/test/unit/integrations/active_model_test.rb +82 -12
  223. data/test/unit/integrations/active_record_test.rb +393 -37
  224. data/test/unit/integrations/base_test.rb +7 -2
  225. data/test/unit/integrations/data_mapper_test.rb +326 -72
  226. data/test/unit/integrations/mongo_mapper_test.rb +338 -44
  227. data/test/unit/integrations/mongoid_test.rb +606 -98
  228. data/test/unit/integrations/sequel_test.rb +429 -102
  229. data/test/unit/integrations_test.rb +28 -6
  230. data/test/unit/machine_collection_test.rb +6 -2
  231. data/test/unit/machine_test.rb +134 -82
  232. data/test/unit/node_collection_test.rb +2 -2
  233. data/test/unit/path_test.rb +1 -1
  234. data/test/unit/state_test.rb +65 -21
  235. data/test/unit/transition_collection_test.rb +43 -23
  236. data/test/unit/transition_test.rb +8 -2
  237. metadata +303 -221
  238. data/gemfiles/active_model-3.2.0.gemfile.lock +0 -32
  239. data/gemfiles/active_record-3.2.0.gemfile.lock +0 -43
  240. data/gemfiles/graphviz-0.9.0.gemfile.lock +0 -26
@@ -0,0 +1,3 @@
1
+ require 'yard'
2
+
3
+ YARD::Templates::Engine.register_template_path File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
@@ -0,0 +1,30 @@
1
+ require 'tempfile'
2
+
3
+ # Define where state machine descriptions will be rendered
4
+ def init
5
+ super
6
+ sections.place(:state_machine_details).before(:children)
7
+ end
8
+
9
+ # Renders state machine details in the main content of the class's documentation
10
+ def state_machine_details
11
+ erb(:state_machines) if state_machines
12
+ end
13
+
14
+ # Gets a list of state machines prased for this class
15
+ def state_machines
16
+ @state_machines ||= begin
17
+ if state_machines = object['state_machines']
18
+ state_machines.each do |name, machine|
19
+ serializer.serialize(state_machine_image_path(machine), machine[:image]) if machine[:image]
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ # Generates the image path for the given machine's visualization
26
+ def state_machine_image_path(machine)
27
+ base_path = File.dirname(serializer.serialized_path(object))
28
+ image_name = "#{object.name}_#{machine[:name]}"
29
+ "#{File.join(base_path, image_name)}.png"
30
+ end
@@ -0,0 +1,12 @@
1
+ <h2>State Machines</h2>
2
+
3
+ This class contains <%= state_machines.count %> state machine(s).
4
+
5
+ <% state_machines.each do |name, machine| %>
6
+ <h3><%= h(machine[:name]) %></h3>
7
+ <p><%= h(machine[:description]) %></p>
8
+
9
+ <% if machine[:image] %>
10
+ <img alt="State machine diagram for <%= h(machine[:name]) %>" src="<%= url_for(state_machine_image_path(machine)) %>" />
11
+ <% end %>
12
+ <% end %>
@@ -1,5 +1,5 @@
1
1
  namespace :state_machine do
2
- desc 'Draws state machines using GraphViz (options: CLASS=User,Vehicle; FILE=user.rb,vehicle.rb [not required in Rails / Merb]; FONT=Arial; FORMAT=png; ORIENTATION=portrait'
2
+ desc 'Draws state machines using GraphViz (options: CLASS=User,Vehicle; FILE=user.rb,vehicle.rb [not required in Rails / Merb]; FONT=Arial; FORMAT=png; ORIENTATION=portrait; HUMAN_NAMES=true'
3
3
  task :draw do
4
4
  # Build drawing options
5
5
  options = {}
@@ -8,6 +8,7 @@ namespace :state_machine do
8
8
  options[:format] = ENV['FORMAT'] if ENV['FORMAT']
9
9
  options[:font] = ENV['FONT'] if ENV['FONT']
10
10
  options[:orientation] = ENV['ORIENTATION'] if ENV['ORIENTATION']
11
+ options[:human_names] = ENV['HUMAN_NAMES'] == 'true' if ENV['HUMAN_NAMES']
11
12
 
12
13
  if defined?(Rails)
13
14
  puts "Files are automatically loaded in Rails; ignoring FILE option" if options.delete(:file)
@@ -0,0 +1,2 @@
1
+ require 'state_machine/core'
2
+ require 'state_machine/yard'
@@ -10,12 +10,13 @@ Gem::Specification.new do |s|
10
10
  s.description = "Adds support for creating state machines for attributes on any Ruby class"
11
11
  s.summary = "State machines for attributes"
12
12
  s.require_paths = ["lib"]
13
- s.files = `git ls-files`.split("\n")
14
- s.test_files = `git ls-files -- test/*`.split("\n")
13
+ ignores = File.read(".gitignore").split.map {|i| i.sub(/\/$/, "/*").sub(/^[^\/]/, "**/\\0")}
14
+ s.files = (Dir[".*"] + Dir["**/*"]).select {|f| File.file?(f) && !ignores.any? {|i| File.fnmatch(i, "/#{f}")}}
15
+ s.test_files = s.files.grep(/^test\//)
15
16
  s.rdoc_options = %w(--line-numbers --inline-source --title state_machine --main README.md)
16
17
  s.extra_rdoc_files = %w(README.md CHANGELOG.md LICENSE)
17
18
 
18
19
  s.add_development_dependency("rake")
19
- s.add_development_dependency("rcov")
20
+ s.add_development_dependency("simplecov")
20
21
  s.add_development_dependency("appraisal", "~> 0.4.0")
21
22
  end
@@ -1,4 +1,8 @@
1
1
  class Switch
2
+ def self.name
3
+ @name ||= "Switch_#{rand(1000000)}"
4
+ end
5
+
2
6
  state_machine do
3
7
  event :turn_on do
4
8
  transition all => :on
@@ -1,2 +1,7 @@
1
+ if ENV['COVERAGE']
2
+ require 'simplecov'
3
+ SimpleCov.start { add_filter '/test/' }
4
+ end
5
+
1
6
  require 'test/unit'
2
7
  require 'state_machine'
@@ -125,6 +125,25 @@ class BranchWithMultipleFromRequirementsTest < Test::Unit::TestCase
125
125
  end
126
126
  end
127
127
 
128
+ class BranchWithFromMatcherRequirementTest < Test::Unit::TestCase
129
+ def setup
130
+ @object = Object.new
131
+ @branch = StateMachine::Branch.new(:from => StateMachine::BlacklistMatcher.new([:idling, :parked]))
132
+ end
133
+
134
+ def test_should_match_if_included
135
+ assert @branch.matches?(@object, :from => :first_gear)
136
+ end
137
+
138
+ def test_should_not_match_if_not_included
139
+ assert !@branch.matches?(@object, :from => :idling)
140
+ end
141
+
142
+ def test_include_values_in_known_states
143
+ assert_equal [:idling, :parked], @branch.known_states
144
+ end
145
+ end
146
+
128
147
  class BranchWithToRequirementTest < Test::Unit::TestCase
129
148
  def setup
130
149
  @object = Object.new
@@ -188,6 +207,25 @@ class BranchWithMultipleToRequirementsTest < Test::Unit::TestCase
188
207
  end
189
208
  end
190
209
 
210
+ class BranchWithToMatcherRequirementTest < Test::Unit::TestCase
211
+ def setup
212
+ @object = Object.new
213
+ @branch = StateMachine::Branch.new(:to => StateMachine::BlacklistMatcher.new([:idling, :parked]))
214
+ end
215
+
216
+ def test_should_match_if_included
217
+ assert @branch.matches?(@object, :to => :first_gear)
218
+ end
219
+
220
+ def test_should_not_match_if_not_included
221
+ assert !@branch.matches?(@object, :to => :idling)
222
+ end
223
+
224
+ def test_include_values_in_known_states
225
+ assert_equal [:idling, :parked], @branch.known_states
226
+ end
227
+ end
228
+
191
229
  class BranchWithOnRequirementTest < Test::Unit::TestCase
192
230
  def setup
193
231
  @object = Object.new
@@ -247,6 +285,21 @@ class BranchWithMultipleOnRequirementsTest < Test::Unit::TestCase
247
285
  end
248
286
  end
249
287
 
288
+ class BranchWithOnMatcherRequirementTest < Test::Unit::TestCase
289
+ def setup
290
+ @object = Object.new
291
+ @branch = StateMachine::Branch.new(:on => StateMachine::BlacklistMatcher.new([:ignite, :park]))
292
+ end
293
+
294
+ def test_should_match_if_included
295
+ assert @branch.matches?(@object, :on => :shift_up)
296
+ end
297
+
298
+ def test_should_not_match_if_not_included
299
+ assert !@branch.matches?(@object, :on => :ignite)
300
+ end
301
+ end
302
+
250
303
  class BranchWithExceptFromRequirementTest < Test::Unit::TestCase
251
304
  def setup
252
305
  @object = Object.new
@@ -301,6 +354,13 @@ class BranchWithMultipleExceptFromRequirementsTest < Test::Unit::TestCase
301
354
  end
302
355
  end
303
356
 
357
+ class BranchWithExceptFromMatcherRequirementTest < Test::Unit::TestCase
358
+ def test_should_raise_an_exception
359
+ exception = assert_raise(ArgumentError) { StateMachine::Branch.new(:except_from => StateMachine::AllMatcher.instance) }
360
+ assert_equal ':except_from option cannot use matchers; use :from instead', exception.message
361
+ end
362
+ end
363
+
304
364
  class BranchWithExceptToRequirementTest < Test::Unit::TestCase
305
365
  def setup
306
366
  @object = Object.new
@@ -355,6 +415,13 @@ class BranchWithMultipleExceptToRequirementsTest < Test::Unit::TestCase
355
415
  end
356
416
  end
357
417
 
418
+ class BranchWithExceptToMatcherRequirementTest < Test::Unit::TestCase
419
+ def test_should_raise_an_exception
420
+ exception = assert_raise(ArgumentError) { StateMachine::Branch.new(:except_to => StateMachine::AllMatcher.instance) }
421
+ assert_equal ':except_to option cannot use matchers; use :to instead', exception.message
422
+ end
423
+ end
424
+
358
425
  class BranchWithExceptOnRequirementTest < Test::Unit::TestCase
359
426
  def setup
360
427
  @object = Object.new
@@ -390,6 +457,13 @@ class BranchWithExceptOnRequirementTest < Test::Unit::TestCase
390
457
  end
391
458
  end
392
459
 
460
+ class BranchWithExceptOnMatcherRequirementTest < Test::Unit::TestCase
461
+ def test_should_raise_an_exception
462
+ exception = assert_raise(ArgumentError) { StateMachine::Branch.new(:except_on => StateMachine::AllMatcher.instance) }
463
+ assert_equal ':except_on option cannot use matchers; use :on instead', exception.message
464
+ end
465
+ end
466
+
393
467
  class BranchWithMultipleExceptOnRequirementsTest < Test::Unit::TestCase
394
468
  def setup
395
469
  @object = Object.new
@@ -707,6 +781,10 @@ class BranchWithMultipleUnlessConditionalsTest < Test::Unit::TestCase
707
781
  end
708
782
 
709
783
  class BranchWithConflictingConditionalsTest < Test::Unit::TestCase
784
+ def setup
785
+ @object = Object.new
786
+ end
787
+
710
788
  def test_should_match_if_if_is_true_and_unless_is_false
711
789
  branch = StateMachine::Branch.new(:if => lambda {true}, :unless => lambda {false})
712
790
  assert branch.match(@object)
@@ -763,27 +841,28 @@ begin
763
841
  @machine = StateMachine::Machine.new(Class.new)
764
842
  states = [:parked, :idling]
765
843
 
766
- graph = GraphViz.new('G')
767
- states.each {|state| graph.add_node(state.to_s)}
844
+ @graph = StateMachine::Graph.new('test')
845
+ states.each {|state| @graph.add_nodes(state.to_s)}
768
846
 
769
847
  @branch = StateMachine::Branch.new(:from => :idling, :to => :parked)
770
- @edges = @branch.draw(graph, :park, states)
848
+ @branch.draw(@graph, :park, states)
849
+ @edge = @graph.get_edge_at_index(0)
771
850
  end
772
851
 
773
852
  def test_should_create_edges
774
- assert_equal 1, @edges.size
853
+ assert_equal 1, @graph.edge_count
775
854
  end
776
855
 
777
856
  def test_should_use_from_state_from_start_node
778
- assert_equal 'idling', @edges.first.instance_variable_get('@xNodeOne')
857
+ assert_equal 'idling', @edge.node_one(false)
779
858
  end
780
859
 
781
860
  def test_should_use_to_state_for_end_node
782
- assert_equal 'parked', @edges.first.instance_variable_get('@xNodeTwo')
861
+ assert_equal 'parked', @edge.node_two(false)
783
862
  end
784
863
 
785
864
  def test_should_use_event_name_as_label
786
- assert_equal 'park', @edges.first['label'].to_s.gsub('"', '')
865
+ assert_equal 'park', @edge['label'].to_s.gsub('"', '')
787
866
  end
788
867
  end
789
868
 
@@ -792,18 +871,18 @@ begin
792
871
  @machine = StateMachine::Machine.new(Class.new)
793
872
  states = [:parked, :idling, :first_gear]
794
873
 
795
- graph = GraphViz.new('G')
796
- states.each {|state| graph.add_node(state.to_s)}
874
+ @graph = StateMachine::Graph.new('test')
875
+ states.each {|state| @graph.add_nodes(state.to_s)}
797
876
 
798
877
  @branch = StateMachine::Branch.new(:from => [:idling, :first_gear], :to => :parked)
799
- @edges = @branch.draw(graph, :park, states)
878
+ @branch.draw(@graph, :park, states)
800
879
  end
801
880
 
802
881
  def test_should_generate_edges_for_each_valid_from_state
803
882
  [:idling, :first_gear].each_with_index do |from_state, index|
804
- edge = @edges[index]
805
- assert_equal from_state.to_s, edge.instance_variable_get('@xNodeOne')
806
- assert_equal 'parked', edge.instance_variable_get('@xNodeTwo')
883
+ edge = @graph.get_edge_at_index(index)
884
+ assert_equal from_state.to_s, edge.node_one(false)
885
+ assert_equal 'parked', edge.node_two(false)
807
886
  end
808
887
  end
809
888
  end
@@ -813,18 +892,18 @@ begin
813
892
  @machine = StateMachine::Machine.new(Class.new)
814
893
  states = [:parked, :idling, :first_gear]
815
894
 
816
- graph = GraphViz.new('G')
817
- states.each {|state| graph.add_node(state.to_s)}
895
+ @graph = StateMachine::Graph.new('test')
896
+ states.each {|state| @graph.add_nodes(state.to_s)}
818
897
 
819
898
  @branch = StateMachine::Branch.new(:except_from => :parked, :to => :parked)
820
- @edges = @branch.draw(graph, :park, states)
899
+ @branch.draw(@graph, :park, states)
821
900
  end
822
901
 
823
902
  def test_should_generate_edges_for_each_valid_from_state
824
903
  %w(idling first_gear).each_with_index do |from_state, index|
825
- edge = @edges[index]
826
- assert_equal from_state, edge.instance_variable_get('@xNodeOne')
827
- assert_equal 'parked', edge.instance_variable_get('@xNodeTwo')
904
+ edge = @graph.get_edge_at_index(index)
905
+ assert_equal from_state, edge.node_one(false)
906
+ assert_equal 'parked', edge.node_two(false)
828
907
  end
829
908
  end
830
909
  end
@@ -834,18 +913,18 @@ begin
834
913
  @machine = StateMachine::Machine.new(Class.new)
835
914
  states = [:parked, :idling, :first_gear]
836
915
 
837
- graph = GraphViz.new('G')
838
- states.each {|state| graph.add_node(state.to_s)}
916
+ @graph = StateMachine::Graph.new('test')
917
+ states.each {|state| @graph.add_nodes(state.to_s)}
839
918
 
840
919
  @branch = StateMachine::Branch.new(:to => :parked)
841
- @edges = @branch.draw(graph, :park, states)
920
+ @branch.draw(@graph, :park, states)
842
921
  end
843
922
 
844
923
  def test_should_generate_edges_for_each_valid_from_state
845
924
  %w(parked idling first_gear).each_with_index do |from_state, index|
846
- edge = @edges[index]
847
- assert_equal from_state, edge.instance_variable_get('@xNodeOne')
848
- assert_equal 'parked', edge.instance_variable_get('@xNodeTwo')
925
+ edge = @graph.get_edge_at_index(index)
926
+ assert_equal from_state, edge.node_one(false)
927
+ assert_equal 'parked', edge.node_two(false)
849
928
  end
850
929
  end
851
930
  end
@@ -854,16 +933,17 @@ begin
854
933
  def setup
855
934
  @machine = StateMachine::Machine.new(Class.new)
856
935
 
857
- graph = GraphViz.new('G')
858
- graph.add_node('parked')
936
+ graph = StateMachine::Graph.new('test')
937
+ graph.add_nodes('parked')
859
938
 
860
939
  @branch = StateMachine::Branch.new(:from => :parked)
861
- @edges = @branch.draw(graph, :park, [:parked])
940
+ @branch.draw(graph, :park, [:parked])
941
+ @edge = graph.get_edge_at_index(0)
862
942
  end
863
943
 
864
944
  def test_should_create_loopback_edge
865
- assert_equal 'parked', @edges.first.instance_variable_get('@xNodeOne')
866
- assert_equal 'parked', @edges.first.instance_variable_get('@xNodeTwo')
945
+ assert_equal 'parked', @edge.node_one(false)
946
+ assert_equal 'parked', @edge.node_two(false)
867
947
  end
868
948
  end
869
949
 
@@ -871,18 +951,19 @@ begin
871
951
  def setup
872
952
  @machine = StateMachine::Machine.new(Class.new)
873
953
 
874
- graph = GraphViz.new('G')
875
- graph.add_node('parked')
954
+ graph = StateMachine::Graph.new('test')
955
+ graph.add_nodes('parked')
876
956
 
877
957
  @branch = StateMachine::Branch.new(:from => :idling, :to => nil)
878
- @edges = @branch.draw(graph, :park, [nil, :idling])
958
+ @branch.draw(graph, :park, [nil, :idling])
959
+ @edge = graph.get_edge_at_index(0)
879
960
  end
880
961
 
881
962
  def test_should_generate_edges_for_each_valid_from_state
882
- assert_equal 'idling', @edges.first.instance_variable_get('@xNodeOne')
883
- assert_equal 'nil', @edges.first.instance_variable_get('@xNodeTwo')
963
+ assert_equal 'idling', @edge.node_one(false)
964
+ assert_equal 'nil', @edge.node_two(false)
884
965
  end
885
966
  end
886
967
  rescue LoadError
887
- $stderr.puts 'Skipping GraphViz StateMachine::Branch tests. `gem install ruby-graphviz` >= v0.9.0 and try again.'
968
+ $stderr.puts 'Skipping GraphViz StateMachine::Branch tests. `gem install ruby-graphviz` >= v0.9.17 and try again.'
888
969
  end unless ENV['TRAVIS']
@@ -485,7 +485,7 @@ end
485
485
 
486
486
  class CallbackWithApplicationTerminatorTest < Test::Unit::TestCase
487
487
  def setup
488
- @original_terminator = StateMachine::Callback.bind_to_object
488
+ @original_terminator = StateMachine::Callback.terminator
489
489
  StateMachine::Callback.terminator = lambda {|result| result == false}
490
490
 
491
491
  @object = Object.new
@@ -502,7 +502,7 @@ class CallbackWithApplicationTerminatorTest < Test::Unit::TestCase
502
502
  end
503
503
 
504
504
  def teardown
505
- StateMachine::Callback.bind_to_object = @original_bind_to_object
505
+ StateMachine::Callback.terminator = @original_terminator
506
506
  end
507
507
  end
508
508
 
@@ -597,6 +597,7 @@ class CallbackWithAroundTypeAndMultipleMethodsTest < Test::Unit::TestCase
597
597
 
598
598
  def test_should_halt_if_first_doesnt_yield
599
599
  class << @object
600
+ remove_method :run_1
600
601
  def run_1
601
602
  (@before_callbacks ||= []) << :run_1
602
603
  end
@@ -612,6 +613,7 @@ class CallbackWithAroundTypeAndMultipleMethodsTest < Test::Unit::TestCase
612
613
 
613
614
  def test_should_halt_if_last_doesnt_yield
614
615
  class << @object
616
+ remove_method :run_2
615
617
  def run_2
616
618
  (@before_callbacks ||= []) << :run_2
617
619
  end
@@ -624,6 +626,7 @@ class CallbackWithAroundTypeAndMultipleMethodsTest < Test::Unit::TestCase
624
626
 
625
627
  def test_should_not_evaluate_further_methods_if_after_halts
626
628
  class << @object
629
+ remove_method :run_2
627
630
  def run_2
628
631
  (@before_callbacks ||= []) << :run_2
629
632
  yield
@@ -14,7 +14,7 @@ class EvalHelpersTest < EvalHelpersBaseTest
14
14
 
15
15
  def test_should_raise_exception_if_method_is_not_symbol_string_or_proc
16
16
  exception = assert_raise(ArgumentError) { evaluate_method(@object, 1) }
17
- assert_match /Methods must/, exception.message
17
+ assert_match(/Methods must/, exception.message)
18
18
  end
19
19
  end
20
20
 
@@ -32,6 +32,36 @@ class EvalHelpersSymbolTest < EvalHelpersBaseTest
32
32
  end
33
33
  end
34
34
 
35
+ class EvalHelpersSymbolProtectedTest < EvalHelpersBaseTest
36
+ def setup
37
+ class << (@object = Object.new)
38
+ protected
39
+ def callback
40
+ true
41
+ end
42
+ end
43
+ end
44
+
45
+ def test_should_call_method_on_object_with_no_arguments
46
+ assert_equal true, evaluate_method(@object, :callback, 1, 2, 3)
47
+ end
48
+ end
49
+
50
+ class EvalHelpersSymbolPrivateTest < EvalHelpersBaseTest
51
+ def setup
52
+ class << (@object = Object.new)
53
+ private
54
+ def callback
55
+ true
56
+ end
57
+ end
58
+ end
59
+
60
+ def test_should_call_method_on_object_with_no_arguments
61
+ assert_equal true, evaluate_method(@object, :callback, 1, 2, 3)
62
+ end
63
+ end
64
+
35
65
  class EvalHelpersSymbolWithArgumentsTest < EvalHelpersBaseTest
36
66
  def setup
37
67
  class << (@object = Object.new)
@@ -90,6 +120,24 @@ class EvalHelpersSymbolTaintedMethodTest < EvalHelpersBaseTest
90
120
  end
91
121
  end
92
122
 
123
+ class EvalHelpersSymbolMethodMissingTest < EvalHelpersBaseTest
124
+ def setup
125
+ class << (@object = Object.new)
126
+ def method_missing(symbol, *args)
127
+ send("method_missing_#{symbol}", *args)
128
+ end
129
+
130
+ def method_missing_callback(*args)
131
+ args
132
+ end
133
+ end
134
+ end
135
+
136
+ def test_should_call_dynamic_method_with_all_arguments
137
+ assert_equal [1, 2, 3], evaluate_method(@object, :callback, 1, 2, 3)
138
+ end
139
+ end
140
+
93
141
  class EvalHelpersStringTest < EvalHelpersBaseTest
94
142
  def setup
95
143
  @object = Object.new