mirror of
https://github.com/aasm/aasm
synced 2023-03-27 23:22:41 -04:00
Support Minitest spec expectations (#387)
* must_allow_event * must_allow_transition_to * must_have_state * must_transition_to * minitest assertions
This commit is contained in:
parent
405fd7b922
commit
b9c9a4e738
11 changed files with 310 additions and 1 deletions
|
@ -26,6 +26,10 @@ before_script:
|
|||
- java -Djava.library.path=/tmp/dynamodb/DynamoDBLocal_lib -jar /tmp/dynamodb/DynamoDBLocal.jar -inMemory -delayTransientStatuses -port 30180 &
|
||||
- mongod --version
|
||||
|
||||
script:
|
||||
- bundle exec rspec spec
|
||||
- bundle exec rake test
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- rvm: 1.9.3
|
||||
|
|
88
README.md
88
README.md
|
@ -1020,7 +1020,9 @@ the 'instance method symbol / string' way whenever possible when defining guardi
|
|||
|
||||
### Testing
|
||||
|
||||
AASM provides some matchers for [RSpec](http://rspec.info): `transition_from`, `have_state`, `allow_event` and `allow_transition_to`. Add `require 'aasm/rspec'` to your `spec_helper.rb` file and use them like this
|
||||
#### RSpec
|
||||
|
||||
AASM provides some matchers for [RSpec](http://rspec.info): `transition_from`, `have_state`, `allow_event` and `allow_transition_to`. Add `require 'aasm/rspec'` to your `spec_helper.rb` file and use them like this:
|
||||
|
||||
```ruby
|
||||
# classes with only the default state machine
|
||||
|
@ -1056,6 +1058,90 @@ expect(multiple).to allow_transition_to(:processing).on(:move)
|
|||
expect(multiple).to_not allow_transition_to(:sleeping).on(:move)
|
||||
```
|
||||
|
||||
#### Minitest
|
||||
|
||||
AASM provides assertions and rspec-like expectations for [Minitest](https://github.com/seattlerb/minitest).
|
||||
|
||||
##### Assertions
|
||||
|
||||
List of supported assertions: `assert_have_state`, `refute_have_state`, `assert_transitions_from`, `refute_transitions_from`, `assert_event_allowed`, `refute_event_allowed`, `assert_transition_to_allowed`, `refute_transition_to_allowed`.
|
||||
|
||||
Add `require 'aasm/minitest' to your `test_helper.rb` file and use them like this:
|
||||
|
||||
```ruby
|
||||
# classes with only the default state machine
|
||||
job = Job.new
|
||||
assert_transitions_from job, :sleeping, to: :running, on_event: :run
|
||||
refute_transitions_from job, :sleeping, to: :cleaning, on_event: :run
|
||||
assert_have_state job, :sleeping
|
||||
refute_have_state job, :running
|
||||
assert_event_allowed job, :run
|
||||
refute_event_allowed job, :clean
|
||||
assert_transition_to_allowed job, :running
|
||||
refute_transition_to_allowed job, :cleaning
|
||||
# on_event also accept arguments
|
||||
assert_transitions_from job, :sleeping, :defragmentation, to: :running, on_event: :run
|
||||
|
||||
# classes with multiple state machine
|
||||
multiple = SimpleMultipleExample.new
|
||||
assert_transitions_from multiple, :standing, to: :walking, on_event: :walk, on: :move
|
||||
refute_transitions_from multiple, :standing, to: :running, on_event: :walk, on: :move
|
||||
assert_have_state multiple, :standing, on: :move
|
||||
refute_have_state multiple, :walking, on: :move
|
||||
assert_event_allowed multiple, :walk, on: :move
|
||||
refute_event_allowed multiple, :hold, on: :move
|
||||
assert_transition_to_allowed multiple, :walking, on: :move
|
||||
refute_transition_to_allowed multiple, :running, on: :move
|
||||
assert_transitions_from multiple, :sleeping, to: :processing, on_event: :start, on: :work
|
||||
refute_transitions_from multiple, :sleeping, to: :sleeping, on_event: :start, on: :work
|
||||
assert_have_state multiple, :sleeping, on: :work
|
||||
refute_have_state multiple, :processing, on: :work
|
||||
assert_event_allowed multiple, :start, on: :move
|
||||
refute_event_allowed multiple, :stop, on: :move
|
||||
assert_transition_to_allowed multiple, :processing, on: :move
|
||||
refute_transition_to_allowed multiple, :sleeping, on: :move
|
||||
```
|
||||
|
||||
##### Expectations
|
||||
|
||||
List of supported expectations: `must_transition_from`, `wont_transition_from`, `must_have_state`, `wont_have_state`, `must_allow_event`, `wont_allow_event`, `must_allow_transition_to`, `wont_allow_transition_to`.
|
||||
|
||||
Add `require 'aasm/minitest_spec'` to your `test_helper.rb` file and use them like this:
|
||||
|
||||
```ruby
|
||||
# classes with only the default state machine
|
||||
job = Job.new
|
||||
job.must_transition_from :sleeping, to: :running, on_event: :run
|
||||
job.wont_transition_from :sleeping, to: :cleaning, on_event: :run
|
||||
job.must_have_state :sleeping
|
||||
job.wont_have_state :running
|
||||
job.must_allow_event :run
|
||||
job.wont_allow_event :clean
|
||||
job.must_allow_transition_to :running
|
||||
job.wont_allow_transition_to :cleaning
|
||||
# on_event also accept arguments
|
||||
job.must_transition_from :sleeping, :defragmentation, to: :running, on_event: :run
|
||||
|
||||
# classes with multiple state machine
|
||||
multiple = SimpleMultipleExample.new
|
||||
multiple.must_transition_from :standing, to: :walking, on_event: :walk, on: :move
|
||||
multiple.wont_transition_from :standing, to: :running, on_event: :walk, on: :move
|
||||
multiple.must_have_state :standing, on: :move
|
||||
multiple.wont_have_state :walking, on: :move
|
||||
multiple.must_allow_event :walk, on: :move
|
||||
multiple.wont_allow_event :hold, on: :move
|
||||
multiple.must_allow_transition_to :walking, on: :move
|
||||
multiple.wont_allow_transition_to :running, on: :move
|
||||
multiple.must_transition_from :sleeping, to: :processing, on_event: :start, on: :work
|
||||
multiple.wont_transition_from :sleeping, to: :sleeping, on_event: :start, on: :work
|
||||
multiple.must_have_state :sleeping, on: :work
|
||||
multiple.wont_have_state :processing, on: :work
|
||||
multiple.must_allow_event :start, on: :move
|
||||
multiple.wont_allow_event :stop, on: :move
|
||||
multiple.must_allow_transition_to :processing, on: :move
|
||||
multiple.wont_allow_transition_to :sleeping, on: :move
|
||||
```
|
||||
|
||||
## <a id="installation">Installation ##
|
||||
|
||||
### Manually from RubyGems.org ###
|
||||
|
|
5
lib/aasm/minitest.rb
Normal file
5
lib/aasm/minitest.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
Minitest = MiniTest unless defined? Minitest
|
||||
# relative-require all minitest_spec files
|
||||
Dir[File.dirname(__FILE__) + '/minitest/*.rb'].each do |file|
|
||||
require 'aasm/minitest/' + File.basename(file, File.extname(file))
|
||||
end
|
13
lib/aasm/minitest/allow_event.rb
Normal file
13
lib/aasm/minitest/allow_event.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
module Minitest::Assertions
|
||||
def assert_event_allowed(object, event, options = {})
|
||||
state_machine_name = options.fetch(:on, :default)
|
||||
assert object.aasm(state_machine_name).may_fire_event?(event),
|
||||
"Expected that the event :#{event} would be allowed (on :#{state_machine_name})"
|
||||
end
|
||||
|
||||
def refute_event_allowed(object, event, options = {})
|
||||
state_machine_name = options.fetch(:on, :default)
|
||||
refute object.aasm(state_machine_name).may_fire_event?(event),
|
||||
"Expected that the event :#{event} would not be allowed (on :#{state_machine_name})"
|
||||
end
|
||||
end
|
13
lib/aasm/minitest/allow_transition_to.rb
Normal file
13
lib/aasm/minitest/allow_transition_to.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
module Minitest::Assertions
|
||||
def assert_transition_to_allowed(object, to_state, options = {})
|
||||
state_machine_name = options.fetch(:on, :default)
|
||||
assert object.aasm(state_machine_name).states(permitted: true).include?(to_state),
|
||||
"Expected that the state :#{to_state} would be reachable (on :#{state_machine_name})"
|
||||
end
|
||||
|
||||
def refute_transition_to_allowed(object, to_state, options = {})
|
||||
state_machine_name = options.fetch(:on, :default)
|
||||
refute object.aasm(state_machine_name).states(permitted: true).include?(to_state),
|
||||
"Expected that the state :#{to_state} would be reachable (on :#{state_machine_name})"
|
||||
end
|
||||
end
|
13
lib/aasm/minitest/have_state.rb
Normal file
13
lib/aasm/minitest/have_state.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
module Minitest::Assertions
|
||||
def assert_have_state(object, state, options = {})
|
||||
state_machine_name = options.fetch(:on, :default)
|
||||
assert object.aasm(state_machine_name).current_state == state,
|
||||
"Expected that :#{object.aasm(state_machine_name).current_state} would be :#{state} (on :#{state_machine_name})"
|
||||
end
|
||||
|
||||
def refute_have_state(object, state, options = {})
|
||||
state_machine_name = options.fetch(:on, :default)
|
||||
refute object.aasm(state_machine_name).current_state == state,
|
||||
"Expected that :#{object.aasm(state_machine_name).current_state} would be :#{state} (on :#{state_machine_name})"
|
||||
end
|
||||
end
|
21
lib/aasm/minitest/transition_from.rb
Normal file
21
lib/aasm/minitest/transition_from.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
module Minitest::Assertions
|
||||
def assert_transitions_from(object, from_state, *args)
|
||||
options = args.extract_options!
|
||||
options[:on] ||= :default
|
||||
assert _transitions_from?(object, from_state, args, options),
|
||||
"Expected transition state to :#{options[:to]} from :#{from_state} on event :#{options[:on_event]}, (on :#{options[:on]})"
|
||||
end
|
||||
|
||||
def refute_transitions_from(object, from_state, *args)
|
||||
options = args.extract_options!
|
||||
options[:on] ||= :default
|
||||
refute _transitions_from?(object, from_state, args, options),
|
||||
"Expected transition state to :#{options[:to]} from :#{from_state} on event :#{options[:on_event]}, (on :#{options[:on]})"
|
||||
end
|
||||
|
||||
def _transitions_from?(object, from_state, args, options)
|
||||
state_machine_name = options[:on]
|
||||
object.aasm(state_machine_name).current_state = from_state.to_sym
|
||||
object.send(options[:on_event], *args) && options[:to].to_sym == object.aasm(state_machine_name).current_state
|
||||
end
|
||||
end
|
15
lib/aasm/minitest_spec.rb
Normal file
15
lib/aasm/minitest_spec.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
require 'aasm/minitest'
|
||||
|
||||
module Minitest::Expectations
|
||||
AASM.infect_an_assertion :assert_transitions_from, :must_transition_from, :do_not_flip
|
||||
AASM.infect_an_assertion :refute_transitions_from, :wont_transition_from, :do_not_flip
|
||||
|
||||
AASM.infect_an_assertion :assert_transition_to_allowed, :must_allow_transition_to, :do_not_flip
|
||||
AASM.infect_an_assertion :refute_transition_to_allowed, :wont_allow_transition_to, :do_not_flip
|
||||
|
||||
AASM.infect_an_assertion :assert_have_state, :must_have_state, :do_not_flip
|
||||
AASM.infect_an_assertion :refute_have_state, :wont_have_state, :do_not_flip
|
||||
|
||||
AASM.infect_an_assertion :assert_event_allowed, :must_allow_event, :do_not_flip
|
||||
AASM.infect_an_assertion :refute_event_allowed, :wont_allow_event, :do_not_flip
|
||||
end
|
|
@ -11,6 +11,8 @@ file_dependencies = {
|
|||
|
||||
exclude_files = [
|
||||
'aasm/rspec.*',
|
||||
'aasm/minitest.*',
|
||||
'aasm/minitest_spec.*',
|
||||
'aasm/persistence/active_record_persistence.rb',
|
||||
'aasm/persistence/dynamoid_persistence.rb',
|
||||
'aasm/persistence/mongoid_persistence.rb',
|
||||
|
|
57
test/minitest_helper.rb
Normal file
57
test/minitest_helper.rb
Normal file
|
@ -0,0 +1,57 @@
|
|||
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
|
||||
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec', 'models')))
|
||||
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
|
||||
require 'aasm'
|
||||
require 'minitest/autorun'
|
||||
require 'aasm/minitest_spec'
|
||||
require 'pry'
|
||||
|
||||
# require 'ruby-debug'; Debugger.settings[:autoeval] = true; debugger; rubys_debugger = 'annoying'
|
||||
# require 'ruby-debug/completion'
|
||||
# require 'pry'
|
||||
|
||||
SEQUEL_DB = defined?(JRUBY_VERSION) ? 'jdbc:sqlite::memory:' : 'sqlite:/'
|
||||
|
||||
def load_schema
|
||||
require 'logger'
|
||||
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
||||
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
|
||||
ActiveRecord::Base.establish_connection(config['sqlite3'])
|
||||
require File.dirname(__FILE__) + "/database.rb"
|
||||
end
|
||||
|
||||
# Dynamoid initialization
|
||||
begin
|
||||
require 'dynamoid'
|
||||
require 'aws-sdk-resources'
|
||||
|
||||
ENV['ACCESS_KEY'] ||= 'abcd'
|
||||
ENV['SECRET_KEY'] ||= '1234'
|
||||
|
||||
Aws.config.update({
|
||||
region: 'us-west-2',
|
||||
credentials: Aws::Credentials.new(ENV['ACCESS_KEY'], ENV['SECRET_KEY'])
|
||||
})
|
||||
|
||||
Dynamoid.configure do |config|
|
||||
config.namespace = "dynamoid_tests"
|
||||
config.endpoint = 'http://127.0.0.1:30180'
|
||||
config.warn_on_scan = false
|
||||
end
|
||||
|
||||
Dynamoid.logger.level = Logger::FATAL
|
||||
|
||||
class Minitest::Spec
|
||||
before do
|
||||
Dynamoid.adapter.list_tables.each do |table|
|
||||
Dynamoid.adapter.delete_table(table) if table =~ /^#{Dynamoid::Config.namespace}/
|
||||
end
|
||||
Dynamoid.adapter.tables.clear
|
||||
end
|
||||
end
|
||||
rescue LoadError
|
||||
# Without Dynamoid settings
|
||||
end
|
||||
|
||||
# example model classes
|
||||
Dir[File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec', 'models')) + '/*.rb'].sort.each { |f| require File.expand_path(f) }
|
80
test/unit/minitest_matcher_test.rb
Normal file
80
test/unit/minitest_matcher_test.rb
Normal file
|
@ -0,0 +1,80 @@
|
|||
require 'minitest_helper'
|
||||
|
||||
class StateMachineTest < Minitest::Spec
|
||||
|
||||
let(:simple) { SimpleExample.new }
|
||||
let(:multiple) { SimpleMultipleExample.new }
|
||||
|
||||
describe 'transition_from' do
|
||||
it "works for simple state machines" do
|
||||
simple.must_transition_from :initialised, to: :filled_out, on_event: :fill_out
|
||||
simple.wont_transition_from :initialised, to: :authorised, on_event: :fill_out
|
||||
end
|
||||
|
||||
it "works for multiple state machines" do
|
||||
multiple.must_transition_from :standing, to: :walking, on_event: :walk, on: :move
|
||||
multiple.wont_transition_from :standing, to: :running, on_event: :walk, on: :move
|
||||
|
||||
multiple.must_transition_from :sleeping, to: :processing, on_event: :start, on: :work
|
||||
multiple.wont_transition_from :sleeping, to: :sleeping, on_event: :start, on: :work
|
||||
end
|
||||
end
|
||||
|
||||
describe 'allow_transition_to' do
|
||||
it "works for simple state machines" do
|
||||
simple.must_allow_transition_to :filled_out
|
||||
simple.wont_allow_transition_to :authorised
|
||||
end
|
||||
|
||||
it "works for multiple state machines" do
|
||||
multiple.must_allow_transition_to :walking, on: :move
|
||||
multiple.wont_allow_transition_to :standing, on: :move
|
||||
|
||||
multiple.must_allow_transition_to :processing, on: :work
|
||||
multiple.wont_allow_transition_to :sleeping, on: :work
|
||||
end
|
||||
end
|
||||
|
||||
describe "have_state" do
|
||||
it "works for simple state machines" do
|
||||
simple.must_have_state :initialised
|
||||
simple.wont_have_state :filled_out
|
||||
simple.fill_out
|
||||
simple.must_have_state :filled_out
|
||||
end
|
||||
|
||||
it "works for multiple state machines" do
|
||||
multiple.must_have_state :standing, on: :move
|
||||
multiple.wont_have_state :walking, on: :move
|
||||
multiple.walk
|
||||
multiple.must_have_state :walking, on: :move
|
||||
|
||||
multiple.must_have_state :sleeping, on: :work
|
||||
multiple.wont_have_state :processing, on: :work
|
||||
multiple.start
|
||||
multiple.must_have_state :processing, on: :work
|
||||
end
|
||||
end
|
||||
|
||||
describe "allow_event" do
|
||||
it "works for simple state machines" do
|
||||
simple.must_allow_event :fill_out
|
||||
simple.wont_allow_event :authorise
|
||||
simple.fill_out
|
||||
simple.must_allow_event :authorise
|
||||
end
|
||||
|
||||
it "works for multiple state machines" do
|
||||
multiple.must_allow_event :walk, on: :move
|
||||
multiple.wont_allow_event :hold, on: :move
|
||||
multiple.walk
|
||||
multiple.must_allow_event :hold, on: :move
|
||||
|
||||
multiple.must_allow_event :start, on: :work
|
||||
multiple.wont_allow_event :stop, on: :work
|
||||
multiple.start
|
||||
multiple.must_allow_event :stop, on: :work
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
Reference in a new issue