Skip to content

Instantly share code, notes, and snippets.

@guizmaii
Last active March 10, 2017 05:04
Show Gist options
  • Save guizmaii/d8571351557ac1e94561 to your computer and use it in GitHub Desktop.
Save guizmaii/d8571351557ac1e94561 to your computer and use it in GitHub Desktop.
state_machine callbacks mock helper. More infos : http://stackoverflow.com/a/29774904/2431728
class StateMachineHelper
module MOCK_METHOD
ALLOW = :allow
EXPECT = :expect
end
module CALLBACK_TYPE
BEFORE = :before
AFTER = :after
AROUND = :around
FAILURE = :failure
end
# TODO : You need to change the default value of "state_machine_class" parameter if you want one
# or just delete the default value if you don't want one
#
# Usage : In your Rspec spec, for example :
#
# * StateMachineHelper.new(self).mock_all_callbacks(:toto)
#
# where ":toto" is the name of your state machine
#
def initialize(rspec_context, state_machine_class = MyClassThatContainsTheStateMachine)
@rspec_context = rspec_context
@state_machine_class = state_machine_class
end
def allow_all_callbacks(state_machine_name)
mock_callbacks(state_machine_name, MOCK_METHOD::ALLOW)
end
def allow_before_callbacks(state_machine_name)
mock_before_callbacks(state_machine_name, MOCK_METHOD::ALLOW)
end
def allow_after_callbacks(state_machine_name)
mock_after_callbacks(state_machine_name, MOCK_METHOD::ALLOW)
end
def allow_around_callbacks(state_machine_name)
mock_around_callbacks(state_machine_name, MOCK_METHOD::ALLOW)
end
def allow_failure_callbacks(state_machine_name)
mock_failure_callbacks(state_machine_name, MOCK_METHOD::ALLOW)
end
def expect_all_callbacks(state_machine_name)
mock_callbacks(state_machine_name, MOCK_METHOD::EXPECT)
end
def expect_before_callbacks(state_machine_name)
mock_before_callbacks(state_machine_name, MOCK_METHOD::EXPECT)
end
def expect_after_callbacks(state_machine_name)
mock_after_callbacks(state_machine_name, MOCK_METHOD::EXPECT)
end
def expect_around_callbacks(state_machine_name)
mock_around_callbacks(state_machine_name, MOCK_METHOD::EXPECT)
end
def expect_failure_callbacks(state_machine_name)
mock_failure_callbacks(state_machine_name, MOCK_METHOD::EXPECT)
end
private
# An explanation on how it works : http://stackoverflow.com/a/29774904/2431728
def mock_callbacks(
state_machine_name,
method,
callback_types = [CALLBACK_TYPE::BEFORE, CALLBACK_TYPE::AFTER, CALLBACK_TYPE::AROUND, CALLBACK_TYPE::FAILURE]
)
@state_machine_class
.state_machines[state_machine_name]
.callbacks
.flat_map{ |k, callbackArray| callbackArray if callback_types.include?(k) }
.compact
.find_all{ |callback|
callback.instance_variable_get('@methods').any? { |callback_method_proc|
/#{state_machine_class_file_name}/.match callback_method_proc.to_s
}
}.map{ |our_callback|
@rspec_context.send(method, our_callback.branch).to @rspec_context.receive(:if_condition).and_return(lambda {false})
}
end
def mock_all_callbacks(state_machine_name, method)
mock_callbacks(state_machine_name, method)
end
def mock_before_callbacks(state_machine_name, method)
mock_callbacks(state_machine_name, method, [CALLBACK_TYPE::BEFORE])
end
def mock_after_callbacks(state_machine_name, method)
mock_callbacks(state_machine_name, method, [CALLBACK_TYPE::AFTER])
end
def mock_around_callbacks(state_machine_name, method)
mock_callbacks(state_machine_name, method, [CALLBACK_TYPE::AROUND])
end
def mock_failure_callbacks(state_machine_name, method)
mock_callbacks(state_machine_name, method, [CALLBACK_TYPE::FAILURE])
end
def state_machine_class_file_name
@state_machine_class.name.underscore
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment