aasm 5.0.8

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.
Files changed (262) hide show
  1. checksums.yaml +7 -0
  2. data/.document +6 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +27 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. data/.gitignore +20 -0
  6. data/.travis.yml +100 -0
  7. data/API +34 -0
  8. data/Appraisals +71 -0
  9. data/CHANGELOG.md +431 -0
  10. data/CODE_OF_CONDUCT.md +13 -0
  11. data/CONTRIBUTING.md +24 -0
  12. data/Dockerfile +44 -0
  13. data/Gemfile +6 -0
  14. data/Gemfile.lock_old +151 -0
  15. data/HOWTO +12 -0
  16. data/LICENSE +20 -0
  17. data/PLANNED_CHANGES.md +11 -0
  18. data/README.md +1439 -0
  19. data/README_FROM_VERSION_3_TO_4.md +240 -0
  20. data/Rakefile +31 -0
  21. data/TESTING.md +25 -0
  22. data/aasm.gemspec +37 -0
  23. data/callbacks.txt +51 -0
  24. data/docker-compose.yml +40 -0
  25. data/gemfiles/norails.gemfile +10 -0
  26. data/gemfiles/rails_3.2.gemfile +14 -0
  27. data/gemfiles/rails_4.2.gemfile +16 -0
  28. data/gemfiles/rails_4.2_mongoid_5.gemfile +11 -0
  29. data/gemfiles/rails_4.2_nobrainer.gemfile +9 -0
  30. data/gemfiles/rails_5.0.gemfile +13 -0
  31. data/gemfiles/rails_5.0_nobrainer.gemfile +9 -0
  32. data/gemfiles/rails_5.1.gemfile +13 -0
  33. data/gemfiles/rails_5.2.gemfile +13 -0
  34. data/lib/aasm.rb +23 -0
  35. data/lib/aasm/aasm.rb +208 -0
  36. data/lib/aasm/base.rb +271 -0
  37. data/lib/aasm/configuration.rb +45 -0
  38. data/lib/aasm/core/event.rb +172 -0
  39. data/lib/aasm/core/invoker.rb +129 -0
  40. data/lib/aasm/core/invokers/base_invoker.rb +75 -0
  41. data/lib/aasm/core/invokers/class_invoker.rb +52 -0
  42. data/lib/aasm/core/invokers/literal_invoker.rb +47 -0
  43. data/lib/aasm/core/invokers/proc_invoker.rb +59 -0
  44. data/lib/aasm/core/state.rb +90 -0
  45. data/lib/aasm/core/transition.rb +83 -0
  46. data/lib/aasm/dsl_helper.rb +30 -0
  47. data/lib/aasm/errors.rb +21 -0
  48. data/lib/aasm/instance_base.rb +133 -0
  49. data/lib/aasm/localizer.rb +54 -0
  50. data/lib/aasm/minitest.rb +5 -0
  51. data/lib/aasm/minitest/allow_event.rb +13 -0
  52. data/lib/aasm/minitest/allow_transition_to.rb +13 -0
  53. data/lib/aasm/minitest/have_state.rb +13 -0
  54. data/lib/aasm/minitest/transition_from.rb +21 -0
  55. data/lib/aasm/minitest_spec.rb +15 -0
  56. data/lib/aasm/persistence.rb +54 -0
  57. data/lib/aasm/persistence/active_record_persistence.rb +165 -0
  58. data/lib/aasm/persistence/base.rb +78 -0
  59. data/lib/aasm/persistence/core_data_query_persistence.rb +94 -0
  60. data/lib/aasm/persistence/dynamoid_persistence.rb +92 -0
  61. data/lib/aasm/persistence/mongoid_persistence.rb +126 -0
  62. data/lib/aasm/persistence/no_brainer_persistence.rb +105 -0
  63. data/lib/aasm/persistence/orm.rb +150 -0
  64. data/lib/aasm/persistence/plain_persistence.rb +26 -0
  65. data/lib/aasm/persistence/redis_persistence.rb +112 -0
  66. data/lib/aasm/persistence/sequel_persistence.rb +83 -0
  67. data/lib/aasm/rspec.rb +5 -0
  68. data/lib/aasm/rspec/allow_event.rb +26 -0
  69. data/lib/aasm/rspec/allow_transition_to.rb +26 -0
  70. data/lib/aasm/rspec/have_state.rb +22 -0
  71. data/lib/aasm/rspec/transition_from.rb +36 -0
  72. data/lib/aasm/state_machine.rb +53 -0
  73. data/lib/aasm/state_machine_store.rb +76 -0
  74. data/lib/aasm/version.rb +3 -0
  75. data/lib/generators/aasm/aasm_generator.rb +16 -0
  76. data/lib/generators/aasm/orm_helpers.rb +41 -0
  77. data/lib/generators/active_record/aasm_generator.rb +40 -0
  78. data/lib/generators/active_record/templates/migration.rb +8 -0
  79. data/lib/generators/active_record/templates/migration_existing.rb +5 -0
  80. data/lib/generators/mongoid/aasm_generator.rb +28 -0
  81. data/lib/generators/nobrainer/aasm_generator.rb +28 -0
  82. data/lib/motion-aasm.rb +37 -0
  83. data/spec/database.rb +59 -0
  84. data/spec/database.yml +3 -0
  85. data/spec/en.yml +12 -0
  86. data/spec/en_deprecated_style.yml +10 -0
  87. data/spec/generators/active_record_generator_spec.rb +53 -0
  88. data/spec/generators/mongoid_generator_spec.rb +31 -0
  89. data/spec/generators/no_brainer_generator_spec.rb +29 -0
  90. data/spec/models/active_record/basic_active_record_two_state_machines_example.rb +25 -0
  91. data/spec/models/active_record/complex_active_record_example.rb +37 -0
  92. data/spec/models/active_record/derivate_new_dsl.rb +7 -0
  93. data/spec/models/active_record/false_state.rb +35 -0
  94. data/spec/models/active_record/gate.rb +39 -0
  95. data/spec/models/active_record/instance_level_skip_validation_example.rb +19 -0
  96. data/spec/models/active_record/invalid_persistor.rb +29 -0
  97. data/spec/models/active_record/localizer_test_model.rb +34 -0
  98. data/spec/models/active_record/no_direct_assignment.rb +21 -0
  99. data/spec/models/active_record/no_scope.rb +21 -0
  100. data/spec/models/active_record/persisted_state.rb +12 -0
  101. data/spec/models/active_record/person.rb +23 -0
  102. data/spec/models/active_record/provided_and_persisted_state.rb +24 -0
  103. data/spec/models/active_record/reader.rb +7 -0
  104. data/spec/models/active_record/readme_job.rb +21 -0
  105. data/spec/models/active_record/silent_persistor.rb +29 -0
  106. data/spec/models/active_record/simple_new_dsl.rb +32 -0
  107. data/spec/models/active_record/thief.rb +29 -0
  108. data/spec/models/active_record/transactor.rb +124 -0
  109. data/spec/models/active_record/transient.rb +6 -0
  110. data/spec/models/active_record/validator.rb +118 -0
  111. data/spec/models/active_record/with_enum.rb +39 -0
  112. data/spec/models/active_record/with_enum_without_column.rb +38 -0
  113. data/spec/models/active_record/with_false_enum.rb +31 -0
  114. data/spec/models/active_record/with_true_enum.rb +39 -0
  115. data/spec/models/active_record/work.rb +3 -0
  116. data/spec/models/active_record/worker.rb +2 -0
  117. data/spec/models/active_record/writer.rb +6 -0
  118. data/spec/models/basic_two_state_machines_example.rb +25 -0
  119. data/spec/models/callbacks/basic.rb +98 -0
  120. data/spec/models/callbacks/basic_multiple.rb +75 -0
  121. data/spec/models/callbacks/guard_within_block.rb +67 -0
  122. data/spec/models/callbacks/guard_within_block_multiple.rb +66 -0
  123. data/spec/models/callbacks/multiple_transitions_transition_guard.rb +66 -0
  124. data/spec/models/callbacks/multiple_transitions_transition_guard_multiple.rb +65 -0
  125. data/spec/models/callbacks/private_method.rb +44 -0
  126. data/spec/models/callbacks/private_method_multiple.rb +44 -0
  127. data/spec/models/callbacks/with_args.rb +62 -0
  128. data/spec/models/callbacks/with_args_multiple.rb +61 -0
  129. data/spec/models/callbacks/with_state_arg.rb +34 -0
  130. data/spec/models/callbacks/with_state_arg_multiple.rb +29 -0
  131. data/spec/models/complex_example.rb +222 -0
  132. data/spec/models/conversation.rb +93 -0
  133. data/spec/models/default_state.rb +12 -0
  134. data/spec/models/double_definer.rb +21 -0
  135. data/spec/models/dynamoid/complex_dynamoid_example.rb +37 -0
  136. data/spec/models/dynamoid/dynamoid_multiple.rb +18 -0
  137. data/spec/models/dynamoid/dynamoid_simple.rb +18 -0
  138. data/spec/models/foo.rb +106 -0
  139. data/spec/models/foo_callback_multiple.rb +45 -0
  140. data/spec/models/guard_arguments_check.rb +17 -0
  141. data/spec/models/guard_with_params.rb +24 -0
  142. data/spec/models/guard_with_params_multiple.rb +18 -0
  143. data/spec/models/guardian.rb +58 -0
  144. data/spec/models/guardian_multiple.rb +48 -0
  145. data/spec/models/guardian_without_from_specified.rb +18 -0
  146. data/spec/models/initial_state_proc.rb +31 -0
  147. data/spec/models/mongoid/complex_mongoid_example.rb +37 -0
  148. data/spec/models/mongoid/invalid_persistor_mongoid.rb +39 -0
  149. data/spec/models/mongoid/mongoid_relationships.rb +26 -0
  150. data/spec/models/mongoid/no_scope_mongoid.rb +21 -0
  151. data/spec/models/mongoid/silent_persistor_mongoid.rb +39 -0
  152. data/spec/models/mongoid/simple_mongoid.rb +23 -0
  153. data/spec/models/mongoid/simple_new_dsl_mongoid.rb +25 -0
  154. data/spec/models/mongoid/validator_mongoid.rb +100 -0
  155. data/spec/models/multi_transitioner.rb +34 -0
  156. data/spec/models/multiple_transitions_that_differ_only_by_guard.rb +31 -0
  157. data/spec/models/namespaced_multiple_example.rb +42 -0
  158. data/spec/models/no_initial_state.rb +25 -0
  159. data/spec/models/nobrainer/complex_no_brainer_example.rb +36 -0
  160. data/spec/models/nobrainer/invalid_persistor_no_brainer.rb +39 -0
  161. data/spec/models/nobrainer/no_scope_no_brainer.rb +21 -0
  162. data/spec/models/nobrainer/nobrainer_relationships.rb +25 -0
  163. data/spec/models/nobrainer/silent_persistor_no_brainer.rb +39 -0
  164. data/spec/models/nobrainer/simple_new_dsl_nobrainer.rb +25 -0
  165. data/spec/models/nobrainer/simple_no_brainer.rb +23 -0
  166. data/spec/models/nobrainer/validator_no_brainer.rb +98 -0
  167. data/spec/models/not_auto_loaded/process.rb +21 -0
  168. data/spec/models/parametrised_event.rb +42 -0
  169. data/spec/models/parametrised_event_multiple.rb +29 -0
  170. data/spec/models/process_with_new_dsl.rb +31 -0
  171. data/spec/models/provided_state.rb +24 -0
  172. data/spec/models/redis/complex_redis_example.rb +40 -0
  173. data/spec/models/redis/redis_multiple.rb +20 -0
  174. data/spec/models/redis/redis_simple.rb +20 -0
  175. data/spec/models/sequel/complex_sequel_example.rb +46 -0
  176. data/spec/models/sequel/invalid_persistor.rb +52 -0
  177. data/spec/models/sequel/sequel_multiple.rb +25 -0
  178. data/spec/models/sequel/sequel_simple.rb +26 -0
  179. data/spec/models/sequel/silent_persistor.rb +50 -0
  180. data/spec/models/sequel/transactor.rb +112 -0
  181. data/spec/models/sequel/validator.rb +93 -0
  182. data/spec/models/sequel/worker.rb +12 -0
  183. data/spec/models/silencer.rb +27 -0
  184. data/spec/models/simple_custom_example.rb +53 -0
  185. data/spec/models/simple_example.rb +23 -0
  186. data/spec/models/simple_example_with_guard_args.rb +17 -0
  187. data/spec/models/simple_multiple_example.rb +42 -0
  188. data/spec/models/state_machine_with_failed_event.rb +20 -0
  189. data/spec/models/states_on_one_line_example.rb +8 -0
  190. data/spec/models/sub_class.rb +41 -0
  191. data/spec/models/sub_class_with_more_states.rb +18 -0
  192. data/spec/models/sub_classing.rb +3 -0
  193. data/spec/models/super_class.rb +46 -0
  194. data/spec/models/this_name_better_not_be_in_use.rb +11 -0
  195. data/spec/models/valid_state_name.rb +23 -0
  196. data/spec/spec_helper.rb +36 -0
  197. data/spec/spec_helpers/active_record.rb +8 -0
  198. data/spec/spec_helpers/dynamoid.rb +35 -0
  199. data/spec/spec_helpers/mongoid.rb +26 -0
  200. data/spec/spec_helpers/nobrainer.rb +15 -0
  201. data/spec/spec_helpers/redis.rb +18 -0
  202. data/spec/spec_helpers/remove_warnings.rb +1 -0
  203. data/spec/spec_helpers/sequel.rb +7 -0
  204. data/spec/unit/abstract_class_spec.rb +27 -0
  205. data/spec/unit/api_spec.rb +100 -0
  206. data/spec/unit/basic_two_state_machines_example_spec.rb +10 -0
  207. data/spec/unit/callback_multiple_spec.rb +304 -0
  208. data/spec/unit/callbacks_spec.rb +521 -0
  209. data/spec/unit/complex_example_spec.rb +93 -0
  210. data/spec/unit/complex_multiple_example_spec.rb +115 -0
  211. data/spec/unit/edge_cases_spec.rb +16 -0
  212. data/spec/unit/event_multiple_spec.rb +73 -0
  213. data/spec/unit/event_naming_spec.rb +16 -0
  214. data/spec/unit/event_spec.rb +394 -0
  215. data/spec/unit/exception_spec.rb +11 -0
  216. data/spec/unit/guard_arguments_check_spec.rb +9 -0
  217. data/spec/unit/guard_multiple_spec.rb +60 -0
  218. data/spec/unit/guard_spec.rb +89 -0
  219. data/spec/unit/guard_with_params_multiple_spec.rb +10 -0
  220. data/spec/unit/guard_with_params_spec.rb +14 -0
  221. data/spec/unit/guard_without_from_specified_spec.rb +10 -0
  222. data/spec/unit/initial_state_multiple_spec.rb +15 -0
  223. data/spec/unit/initial_state_spec.rb +12 -0
  224. data/spec/unit/inspection_multiple_spec.rb +201 -0
  225. data/spec/unit/inspection_spec.rb +149 -0
  226. data/spec/unit/invoker_spec.rb +189 -0
  227. data/spec/unit/invokers/base_invoker_spec.rb +72 -0
  228. data/spec/unit/invokers/class_invoker_spec.rb +95 -0
  229. data/spec/unit/invokers/literal_invoker_spec.rb +86 -0
  230. data/spec/unit/invokers/proc_invoker_spec.rb +86 -0
  231. data/spec/unit/localizer_spec.rb +78 -0
  232. data/spec/unit/memory_leak_spec.rb +38 -0
  233. data/spec/unit/multiple_transitions_that_differ_only_by_guard_spec.rb +14 -0
  234. data/spec/unit/namespaced_multiple_example_spec.rb +75 -0
  235. data/spec/unit/new_dsl_spec.rb +12 -0
  236. data/spec/unit/override_warning_spec.rb +94 -0
  237. data/spec/unit/persistence/active_record_persistence_multiple_spec.rb +618 -0
  238. data/spec/unit/persistence/active_record_persistence_spec.rb +773 -0
  239. data/spec/unit/persistence/dynamoid_persistence_multiple_spec.rb +135 -0
  240. data/spec/unit/persistence/dynamoid_persistence_spec.rb +84 -0
  241. data/spec/unit/persistence/mongoid_persistence_multiple_spec.rb +200 -0
  242. data/spec/unit/persistence/mongoid_persistence_spec.rb +165 -0
  243. data/spec/unit/persistence/no_brainer_persistence_multiple_spec.rb +198 -0
  244. data/spec/unit/persistence/no_brainer_persistence_spec.rb +158 -0
  245. data/spec/unit/persistence/redis_persistence_multiple_spec.rb +88 -0
  246. data/spec/unit/persistence/redis_persistence_spec.rb +53 -0
  247. data/spec/unit/persistence/sequel_persistence_multiple_spec.rb +148 -0
  248. data/spec/unit/persistence/sequel_persistence_spec.rb +368 -0
  249. data/spec/unit/readme_spec.rb +41 -0
  250. data/spec/unit/reloading_spec.rb +15 -0
  251. data/spec/unit/rspec_matcher_spec.rb +88 -0
  252. data/spec/unit/simple_custom_example_spec.rb +39 -0
  253. data/spec/unit/simple_example_spec.rb +57 -0
  254. data/spec/unit/simple_multiple_example_spec.rb +91 -0
  255. data/spec/unit/state_spec.rb +89 -0
  256. data/spec/unit/states_on_one_line_example_spec.rb +16 -0
  257. data/spec/unit/subclassing_multiple_spec.rb +74 -0
  258. data/spec/unit/subclassing_spec.rb +46 -0
  259. data/spec/unit/transition_spec.rb +436 -0
  260. data/test/minitest_helper.rb +57 -0
  261. data/test/unit/minitest_matcher_test.rb +80 -0
  262. metadata +609 -0
@@ -0,0 +1,93 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'on initialization' do
4
+ let(:auth) {ComplexExample.new}
5
+
6
+ it 'should be in the pending state' do
7
+ expect(auth.aasm.current_state).to eq(:pending)
8
+ end
9
+
10
+ it 'should have an activation code' do
11
+ expect(auth.has_activation_code?).to be_truthy
12
+ expect(auth.activation_code).not_to be_nil
13
+ end
14
+ end
15
+
16
+ describe 'when being unsuspended' do
17
+ let(:auth) {ComplexExample.new}
18
+
19
+ it 'should be able to be unsuspended' do
20
+ auth.activate!
21
+ auth.suspend!
22
+ expect(auth.may_unsuspend?).to be true
23
+ end
24
+
25
+ it 'should not be able to be unsuspended into active' do
26
+ auth.suspend!
27
+ expect(auth.may_unsuspend?(:active)).not_to be true
28
+ end
29
+
30
+ it 'should be able to be unsuspended into active if polite' do
31
+ auth.suspend!
32
+ expect(auth.may_wait?(:waiting, :please)).to be true
33
+ auth.wait!(:please)
34
+ end
35
+
36
+ it 'should not be able to be unsuspended into active if not polite' do
37
+ auth.suspend!
38
+ expect(auth.may_wait?(:waiting)).not_to be true
39
+ expect(auth.may_wait?(:waiting, :rude)).not_to be true
40
+ expect {auth.wait!(:rude)}.to raise_error(AASM::InvalidTransition)
41
+ expect {auth.wait!}.to raise_error(AASM::InvalidTransition)
42
+ end
43
+
44
+ it 'should not be able to be unpassified' do
45
+ auth.activate!
46
+ auth.suspend!
47
+ auth.unsuspend!
48
+
49
+ expect(auth.may_unpassify?).not_to be true
50
+ expect {auth.unpassify!}.to raise_error(AASM::InvalidTransition)
51
+ end
52
+
53
+ it 'should be active if previously activated' do
54
+ auth.activate!
55
+ auth.suspend!
56
+ auth.unsuspend!
57
+
58
+ expect(auth.aasm.current_state).to eq(:active)
59
+ end
60
+
61
+ it 'should be pending if not previously activated, but an activation code is present' do
62
+ auth.suspend!
63
+ auth.unsuspend!
64
+
65
+ expect(auth.aasm.current_state).to eq(:pending)
66
+ end
67
+
68
+ it 'should be passive if not previously activated and there is no activation code' do
69
+ auth.activation_code = nil
70
+ auth.suspend!
71
+ auth.unsuspend!
72
+
73
+ expect(auth.aasm.current_state).to eq(:passive)
74
+ end
75
+
76
+ it "should be able to fire known events" do
77
+ expect(auth.aasm.may_fire_event?(:activate)).to be true
78
+ end
79
+
80
+ it "should be able to fire event by name" do
81
+ expect(auth.aasm.fire(:activate)).to be true
82
+ expect(auth.aasm.current_state).to eq(:active)
83
+ end
84
+
85
+ it "should be able to fire! event by name" do
86
+ expect(auth.aasm.fire!(:activate)).to be true
87
+ expect(auth.aasm.current_state).to eq(:active)
88
+ end
89
+
90
+ it "should not be able to fire unknown events" do
91
+ expect(auth.aasm.may_fire_event?(:unknown)).to be false
92
+ end
93
+ end
@@ -0,0 +1,115 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'on initialization' do
4
+ let(:auth) {ComplexExampleMultiple.new}
5
+
6
+ it 'should be in the initial state' do
7
+ expect(auth.aasm(:left).current_state).to eq(:pending)
8
+ expect(auth.aasm(:right).current_state).to eq(:pending)
9
+ end
10
+
11
+ it 'should have an activation code' do
12
+ expect(auth.has_activation_code?).to be_truthy
13
+ expect(auth.activation_code).to eq '12'
14
+ end
15
+ end
16
+
17
+ describe 'when being unsuspended' do
18
+ let(:auth) {ComplexExampleMultiple.new}
19
+
20
+ it 'should be able to unsuspend' do
21
+ auth.left_activate!
22
+ auth.left_suspend!
23
+ expect(auth.may_left_unsuspend?).to be true
24
+
25
+ auth.right_activate!
26
+ auth.right_suspend!
27
+ expect(auth.may_right_unsuspend?).to be true
28
+ end
29
+
30
+ it 'should not be able to unsuspend into active' do
31
+ auth.left_suspend!
32
+ expect(auth.may_left_unsuspend?(:active)).not_to be true
33
+
34
+ auth.right_activate!
35
+ auth.right_suspend!
36
+ expect(auth.may_right_unsuspend?(:active)).to be true
37
+ end
38
+
39
+ it 'should be able to wait into waiting if polite' do
40
+ auth.left_suspend!
41
+ expect(auth.may_left_wait?(:waiting, :please)).to be true
42
+ auth.left_wait!(:please)
43
+
44
+ auth.right_suspend!
45
+ expect(auth.may_right_wait?(:waiting)).to be false
46
+ auth.right_wait!(:please)
47
+ end
48
+
49
+ it 'should not be able to be unsuspended into active if not polite' do
50
+ auth.left_suspend!
51
+ expect(auth.may_left_wait?(:waiting)).not_to be true
52
+ expect(auth.may_left_wait?(:waiting, :rude)).not_to be true
53
+ expect {auth.left_wait!(:rude)}.to raise_error(AASM::InvalidTransition)
54
+ expect {auth.left_wait!}.to raise_error(AASM::InvalidTransition)
55
+ end
56
+
57
+ it 'should not be able to be unpassified' do
58
+ auth.left_activate!
59
+ auth.left_suspend!
60
+ auth.left_unsuspend!
61
+
62
+ expect(auth.may_left_unpassify?).not_to be true
63
+ expect {auth.left_unpassify!}.to raise_error(AASM::InvalidTransition)
64
+ end
65
+
66
+ it 'should be active if previously activated' do
67
+ auth.left_activate!
68
+ auth.left_suspend!
69
+ auth.left_unsuspend!
70
+
71
+ expect(auth.aasm(:left).current_state).to eq(:active)
72
+ end
73
+
74
+ it 'should be pending if not previously activated, but an activation code is present' do
75
+ auth.left_suspend!
76
+ auth.left_unsuspend!
77
+
78
+ expect(auth.aasm(:left).current_state).to eq(:pending)
79
+ end
80
+
81
+ it 'should be passive if not previously activated and there is no activation code' do
82
+ auth.activation_code = nil
83
+ auth.left_suspend!
84
+ auth.left_unsuspend!
85
+
86
+ expect(auth.aasm(:left).current_state).to eq(:passive)
87
+ end
88
+
89
+ it "should be able to fire known events" do
90
+ expect(auth.aasm(:left).may_fire_event?(:left_activate)).to be true
91
+ expect(auth.aasm(:right).may_fire_event?(:right_activate)).to be true
92
+ end
93
+
94
+ it 'should not be able to fire unknown events' do
95
+ expect(auth.aasm(:left).may_fire_event?(:unknown)).to be false
96
+ expect(auth.aasm(:right).may_fire_event?(:unknown)).to be false
97
+ end
98
+
99
+ it 'should be able to fire event by name' do
100
+ expect(auth.aasm(:left).fire(:left_activate)).to be true
101
+ expect(auth.aasm(:left).current_state).to eq(:active)
102
+
103
+ expect(auth.aasm(:right).fire(:right_activate)).to be true
104
+ expect(auth.aasm(:right).current_state).to eq(:active)
105
+ end
106
+
107
+ it 'should be able to fire! event by name' do
108
+ expect(auth.aasm(:left).fire!(:left_activate)).to be true
109
+ expect(auth.aasm(:left).current_state).to eq(:active)
110
+
111
+ expect(auth.aasm(:right).fire!(:right_activate)).to be true
112
+ expect(auth.aasm(:right).current_state).to eq(:active)
113
+ end
114
+
115
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe "edge cases" do
4
+ describe "for classes with multiple state machines" do
5
+ it "allows accessing a multiple state machine class without state machine name" do
6
+ # it's like starting to define a new state machine within the
7
+ # requested class
8
+ expect(SimpleMultipleExample.aasm.states.map(&:name)).to be_empty
9
+ end
10
+
11
+ it "do not know yet" do
12
+ example = ComplexExampleMultiple.new
13
+ expect { example.aasm.states.inspect }.to raise_error(AASM::UnknownStateMachineError)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'current event' do
4
+ let(:pe) {ParametrisedEventMultiple.new}
5
+
6
+ it 'if no event has been triggered' do
7
+ expect(pe.aasm(:left).current_event).to be_nil
8
+ end
9
+
10
+ it 'if a event has been triggered' do
11
+ pe.wakeup
12
+ expect(pe.aasm(:left).current_event).to eql :wakeup
13
+ end
14
+
15
+ it 'if no event has been triggered' do
16
+ pe.wakeup!
17
+ expect(pe.aasm(:left).current_event).to eql :wakeup!
18
+ end
19
+ end
20
+
21
+ describe 'parametrised events' do
22
+ let(:pe) {ParametrisedEventMultiple.new}
23
+
24
+ it 'should transition to specified next state (sleeping to showering)' do
25
+ pe.wakeup!(:showering)
26
+ expect(pe.aasm(:left).current_state).to eq(:showering)
27
+ end
28
+
29
+ it 'should transition to specified next state (sleeping to working)' do
30
+ pe.wakeup!(:working)
31
+ expect(pe.aasm(:left).current_state).to eq(:working)
32
+ end
33
+
34
+ it 'should transition to default (first or showering) state' do
35
+ pe.wakeup!
36
+ expect(pe.aasm(:left).current_state).to eq(:showering)
37
+ end
38
+
39
+ it 'should transition to default state when :after transition invoked' do
40
+ pe.dress!('purple', 'dressy')
41
+ expect(pe.aasm(:left).current_state).to eq(:working)
42
+ end
43
+
44
+ it 'should call :after transition method with args' do
45
+ pe.wakeup!(:showering)
46
+ expect(pe).to receive(:wear_clothes).with('blue', 'jeans')
47
+ pe.dress!(:working, 'blue', 'jeans')
48
+ end
49
+
50
+ it 'should call :after transition proc' do
51
+ pe.wakeup!(:showering)
52
+ expect(pe).to receive(:wear_clothes).with('purple', 'slacks')
53
+ pe.dress!(:dating, 'purple', 'slacks')
54
+ end
55
+
56
+ it 'should call :after transition with an array of methods' do
57
+ pe.wakeup!(:showering)
58
+ expect(pe).to receive(:condition_hair)
59
+ expect(pe).to receive(:fix_hair)
60
+ pe.dress!(:prettying_up)
61
+ end
62
+ end
63
+
64
+ describe 'event firing without persistence' do
65
+ it 'should attempt to persist if aasm_write_state is defined' do
66
+ foo = Foo.new
67
+ def foo.aasm_write_state; end
68
+ expect(foo).to be_open
69
+
70
+ expect(foo).to receive(:aasm_write_state_without_persistence)
71
+ foo.close
72
+ end
73
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+
3
+ describe "event naming" do
4
+ let(:state_machine) { StateMachineWithFailedEvent.new }
5
+
6
+ it "allows an event of failed without blowing the stack aka stack level too deep" do
7
+ state_machine.failed
8
+ expect { state_machine.failed }.to raise_error(AASM::InvalidTransition)
9
+ end
10
+
11
+ it "allows send as event name" do
12
+ expect(state_machine.aasm.current_state).to eq :init
13
+ state_machine.send
14
+ expect(state_machine.aasm.current_state).to eq :sent
15
+ end
16
+ end
@@ -0,0 +1,394 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'adding an event' do
4
+ let(:state_machine) { AASM::StateMachine.new(:name) }
5
+ let(:event) do
6
+ AASM::Core::Event.new(:close_order, state_machine, {:success => :success_callback}) do
7
+ before :before_callback
8
+ after :after_callback
9
+ transitions :to => :closed, :from => [:open, :received], success: [:transition_success_callback]
10
+ end
11
+ end
12
+
13
+ it 'should set the name' do
14
+ expect(event.name).to eq(:close_order)
15
+ end
16
+
17
+ it 'should set the success callback' do
18
+ expect(event.options[:success]).to eq(:success_callback)
19
+ end
20
+
21
+ it 'should set the after callback' do
22
+ expect(event.options[:after]).to eq([:after_callback])
23
+ end
24
+
25
+ it 'should set the before callback' do
26
+ expect(event.options[:before]).to eq([:before_callback])
27
+ end
28
+
29
+ it 'should create transitions' do
30
+ transitions = event.transitions
31
+ expect(transitions[0].from).to eq(:open)
32
+ expect(transitions[0].to).to eq(:closed)
33
+ expect(transitions[1].from).to eq(:received)
34
+ expect(transitions[1].to).to eq(:closed)
35
+ end
36
+ end
37
+
38
+ describe 'transition inspection' do
39
+ let(:state_machine) { AASM::StateMachine.new(:name) }
40
+ let(:event) do
41
+ AASM::Core::Event.new(:run, state_machine) do
42
+ transitions :to => :running, :from => :sleeping
43
+ end
44
+ end
45
+
46
+ it 'should support inspecting transitions from other states' do
47
+ expect(event.transitions_from_state(:sleeping).map(&:to)).to eq([:running])
48
+ expect(event.transitions_from_state?(:sleeping)).to be_truthy
49
+
50
+ expect(event.transitions_from_state(:cleaning).map(&:to)).to eq([])
51
+ expect(event.transitions_from_state?(:cleaning)).to be_falsey
52
+ end
53
+
54
+ it 'should support inspecting transitions to other states' do
55
+ expect(event.transitions_to_state(:running).map(&:from)).to eq([:sleeping])
56
+ expect(event.transitions_to_state?(:running)).to be_truthy
57
+
58
+ expect(event.transitions_to_state(:cleaning).map(&:to)).to eq([])
59
+ expect(event.transitions_to_state?(:cleaning)).to be_falsey
60
+ end
61
+ end
62
+
63
+ describe 'transition inspection without from' do
64
+ let(:state_machine) { AASM::StateMachine.new(:name) }
65
+ let(:event) do
66
+ AASM::Core::Event.new(:run, state_machine) do
67
+ transitions :to => :running
68
+ end
69
+ end
70
+
71
+ it 'should support inspecting transitions from other states' do
72
+ expect(event.transitions_from_state(:sleeping).map(&:to)).to eq([:running])
73
+ expect(event.transitions_from_state?(:sleeping)).to be_truthy
74
+
75
+ expect(event.transitions_from_state(:cleaning).map(&:to)).to eq([:running])
76
+ expect(event.transitions_from_state?(:cleaning)).to be_truthy
77
+ end
78
+
79
+ end
80
+
81
+ describe 'firing an event' do
82
+ let(:state_machine) { AASM::StateMachine.new(:name) }
83
+
84
+ it 'should return nil if the transitions are empty' do
85
+ obj = double('object', :aasm => double('aasm', :current_state => 'open'))
86
+
87
+ event = AASM::Core::Event.new(:event, state_machine)
88
+ expect(event.fire(obj)).to be_nil
89
+ end
90
+
91
+ it 'should return the state of the first matching transition it finds' do
92
+ event = AASM::Core::Event.new(:event, state_machine) do
93
+ transitions :to => :closed, :from => [:open, :received]
94
+ end
95
+
96
+ obj = double('object', :aasm => double('aasm', :current_state => :open))
97
+
98
+ expect(event.fire(obj)).to eq(:closed)
99
+ end
100
+
101
+ it 'should call the guard with the params passed in' do
102
+ event = AASM::Core::Event.new(:event, state_machine) do
103
+ transitions :to => :closed, :from => [:open, :received], :guard => :guard_fn
104
+ end
105
+
106
+ obj = double('object', :aasm => double('aasm', :current_state => :open))
107
+ expect(obj).to receive(:guard_fn).with('arg1', 'arg2').and_return(true)
108
+
109
+ expect(event.fire(obj, {}, 'arg1', 'arg2')).to eq(:closed)
110
+ end
111
+
112
+ context 'when given a gaurd proc' do
113
+ it 'should have access to callback failures in the transitions' do
114
+ event = AASM::Core::Event.new(:graduate, state_machine) do
115
+ transitions :to => :alumni, :from => [:student, :applicant],
116
+ :guard => Proc.new { 1 + 1 == 3 }
117
+ end
118
+ line_number = __LINE__ - 2
119
+ obj = double('object', :aasm => double('aasm', :current_state => :student))
120
+
121
+ event.fire(obj, {})
122
+ expect(event.failed_callbacks).to eq ["#{__FILE__}##{line_number}"]
123
+ end
124
+ end
125
+
126
+ context 'when given a guard symbol' do
127
+ it 'should have access to callback failures in the transitions' do
128
+ event = AASM::Core::Event.new(:graduate, state_machine) do
129
+ transitions :to => :alumni, :from => [:student, :applicant],
130
+ guard: :paid_tuition?
131
+ end
132
+
133
+ obj = double('object', :aasm => double('aasm', :current_state => :student))
134
+ allow(obj).to receive(:paid_tuition?).and_return(false)
135
+
136
+ event.fire(obj, {})
137
+ expect(event.failed_callbacks).to eq [:paid_tuition?]
138
+ end
139
+ end
140
+
141
+ end
142
+
143
+ describe 'should fire callbacks' do
144
+ describe 'success' do
145
+ it "if it's a symbol" do
146
+ ThisNameBetterNotBeInUse.instance_eval {
147
+ aasm do
148
+ event :with_symbol, :success => :symbol_success_callback do
149
+ transitions :to => :symbol, :from => [:initial]
150
+ end
151
+ end
152
+ }
153
+
154
+ model = ThisNameBetterNotBeInUse.new
155
+ expect(model).to receive(:symbol_success_callback)
156
+ model.with_symbol!
157
+ end
158
+
159
+ it "if it's a string" do
160
+ ThisNameBetterNotBeInUse.instance_eval {
161
+ aasm do
162
+ event :with_string, :success => 'string_success_callback' do
163
+ transitions :to => :string, :from => [:initial]
164
+ end
165
+ end
166
+ }
167
+
168
+ model = ThisNameBetterNotBeInUse.new
169
+ expect(model).to receive(:string_success_callback)
170
+ model.with_string!
171
+ end
172
+
173
+ it "if passed an array of strings and/or symbols" do
174
+ ThisNameBetterNotBeInUse.instance_eval {
175
+ aasm do
176
+ event :with_array, :success => [:success_callback1, 'success_callback2'] do
177
+ transitions :to => :array, :from => [:initial]
178
+ end
179
+ end
180
+ }
181
+
182
+ model = ThisNameBetterNotBeInUse.new
183
+ expect(model).to receive(:success_callback1)
184
+ expect(model).to receive(:success_callback2)
185
+ model.with_array!
186
+ end
187
+
188
+ it "if passed an array of strings and/or symbols and/or procs" do
189
+ ThisNameBetterNotBeInUse.instance_eval {
190
+ aasm do
191
+ event :with_array_including_procs, :success => [:success_callback1, 'success_callback2', lambda { proc_success_callback }] do
192
+ transitions :to => :array, :from => [:initial]
193
+ end
194
+ end
195
+ }
196
+
197
+ model = ThisNameBetterNotBeInUse.new
198
+ expect(model).to receive(:success_callback1)
199
+ expect(model).to receive(:success_callback2)
200
+ expect(model).to receive(:proc_success_callback)
201
+ model.with_array_including_procs!
202
+ end
203
+
204
+ it "if it's a proc" do
205
+ ThisNameBetterNotBeInUse.instance_eval {
206
+ aasm do
207
+ event :with_proc, :success => lambda { proc_success_callback } do
208
+ transitions :to => :proc, :from => [:initial]
209
+ end
210
+ end
211
+ }
212
+
213
+ model = ThisNameBetterNotBeInUse.new
214
+ expect(model).to receive(:proc_success_callback)
215
+ model.with_proc!
216
+ end
217
+ end
218
+
219
+ describe 'after' do
220
+ it "if they set different ways" do
221
+ ThisNameBetterNotBeInUse.instance_eval do
222
+ aasm do
223
+ event :with_afters, :after => :do_one_thing_after do
224
+ after do
225
+ do_another_thing_after_too
226
+ end
227
+ after do
228
+ do_third_thing_at_last
229
+ end
230
+ transitions :to => :proc, :from => [:initial]
231
+ end
232
+ end
233
+ end
234
+
235
+ model = ThisNameBetterNotBeInUse.new
236
+ expect(model).to receive(:do_one_thing_after).once.ordered
237
+ expect(model).to receive(:do_another_thing_after_too).once.ordered
238
+ expect(model).to receive(:do_third_thing_at_last).once.ordered
239
+ model.with_afters!
240
+ end
241
+ end
242
+
243
+ describe 'before' do
244
+ it "if it's a proc" do
245
+ ThisNameBetterNotBeInUse.instance_eval do
246
+ aasm do
247
+ event :before_as_proc do
248
+ before do
249
+ do_something_before
250
+ end
251
+ transitions :to => :proc, :from => [:initial]
252
+ end
253
+ end
254
+ end
255
+
256
+ model = ThisNameBetterNotBeInUse.new
257
+ expect(model).to receive(:do_something_before).once
258
+ model.before_as_proc!
259
+ end
260
+ end
261
+
262
+ it 'in right order' do
263
+ ThisNameBetterNotBeInUse.instance_eval do
264
+ aasm do
265
+ event :in_right_order, :after => :do_something_after do
266
+ before do
267
+ do_something_before
268
+ end
269
+ transitions :to => :proc, :from => [:initial]
270
+ end
271
+ end
272
+ end
273
+
274
+ model = ThisNameBetterNotBeInUse.new
275
+ expect(model).to receive(:do_something_before).once.ordered
276
+ expect(model).to receive(:do_something_after).once.ordered
277
+ model.in_right_order!
278
+ end
279
+ end
280
+
281
+ describe 'current event' do
282
+ let(:pe) {ParametrisedEvent.new}
283
+
284
+ it 'if no event has been triggered' do
285
+ expect(pe.aasm.current_event).to be_nil
286
+ end
287
+
288
+ it 'if a event has been triggered' do
289
+ pe.wakeup
290
+ expect(pe.aasm.current_event).to eql :wakeup
291
+ end
292
+
293
+ it 'if no event has been triggered' do
294
+ pe.wakeup!
295
+ expect(pe.aasm.current_event).to eql :wakeup!
296
+ end
297
+
298
+ describe "when calling events with fire/fire!" do
299
+ it "fire should populate aasm.current_event and transition (sleeping to showering)" do
300
+ pe.aasm.fire(:wakeup)
301
+ expect(pe.aasm.current_event).to eq :wakeup
302
+ expect(pe.aasm.current_state).to eq :showering
303
+ end
304
+ it "fire! should populate aasm.current_event and transition (sleeping to showering)" do
305
+ pe.aasm.fire!(:wakeup)
306
+ expect(pe.aasm.current_event).to eq :wakeup!
307
+ expect(pe.aasm.current_state).to eq :showering
308
+ end
309
+ end
310
+ end
311
+
312
+ describe 'parametrised events' do
313
+ let(:pe) {ParametrisedEvent.new}
314
+
315
+ it 'should transition to specified next state (sleeping to showering)' do
316
+ pe.wakeup!(:showering)
317
+ expect(pe.aasm.current_state).to eq(:showering)
318
+ end
319
+
320
+ it 'should transition to specified next state (sleeping to working)' do
321
+ pe.wakeup!(:working)
322
+ expect(pe.aasm.current_state).to eq(:working)
323
+ end
324
+
325
+ it 'should transition to default (first or showering) state' do
326
+ pe.wakeup!
327
+ expect(pe.aasm.current_state).to eq(:showering)
328
+ end
329
+
330
+ it 'should transition to default state when :after transition invoked' do
331
+ pe.dress!('purple', 'dressy')
332
+ expect(pe.aasm.current_state).to eq(:working)
333
+ end
334
+
335
+ it 'should call :after transition method with args' do
336
+ pe.wakeup!(:showering)
337
+ expect(pe).to receive(:wear_clothes).with('blue', 'jeans')
338
+ pe.dress!(:working, 'blue', 'jeans')
339
+ end
340
+
341
+ it 'should call :after transition method if arg is nil' do
342
+ dryer = nil
343
+ expect(pe).to receive(:wet_hair).with(dryer)
344
+ pe.shower!(dryer)
345
+ end
346
+
347
+ it 'should call :after transition proc' do
348
+ pe.wakeup!(:showering)
349
+ expect(pe).to receive(:wear_clothes).with('purple', 'slacks')
350
+ pe.dress!(:dating, 'purple', 'slacks')
351
+ end
352
+
353
+ it 'should call :after transition with an array of methods' do
354
+ pe.wakeup!(:showering)
355
+ expect(pe).to receive(:condition_hair)
356
+ expect(pe).to receive(:fix_hair)
357
+ pe.dress!(:prettying_up)
358
+ end
359
+
360
+ it 'should call :success transition method with args' do
361
+ pe.wakeup!(:showering)
362
+ expect(pe).to receive(:wear_makeup).with('foundation', 'SPF')
363
+ pe.dress!(:working, 'foundation', 'SPF')
364
+ end
365
+
366
+ it 'should call :success transition method if arg is nil' do
367
+ shirt_color = nil
368
+ expect(pe).to receive(:wear_clothes).with(shirt_color)
369
+ pe.shower!(shirt_color)
370
+ end
371
+
372
+ it 'should call :success transition proc' do
373
+ pe.wakeup!(:showering)
374
+ expect(pe).to receive(:wear_makeup).with('purple', 'slacks')
375
+ pe.dress!(:dating, 'purple', 'slacks')
376
+ end
377
+
378
+ it 'should call :success transition with an array of methods' do
379
+ pe.wakeup!(:showering)
380
+ expect(pe).to receive(:touch_up_hair)
381
+ pe.dress!(:prettying_up)
382
+ end
383
+ end
384
+
385
+ describe 'event firing without persistence' do
386
+ it 'should attempt to persist if aasm_write_state is defined' do
387
+ foo = Foo.new
388
+ def foo.aasm_write_state; end
389
+ expect(foo).to be_open
390
+
391
+ expect(foo).to receive(:aasm_write_state_without_persistence)
392
+ foo.close
393
+ end
394
+ end