Last active
March 10, 2017 05:04
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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