1
0
Fork 0
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:
Farrukh 2017-04-03 02:55:59 -04:00 committed by Anil Kumar Maurya
parent 405fd7b922
commit b9c9a4e738
11 changed files with 310 additions and 1 deletions

View file

@ -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

View file

@ -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
View 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

View 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

View 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

View 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

View 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
View 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

View file

@ -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
View 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) }

View 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