aye_commander 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.adoc +720 -0
- data/lib/aye_commander.rb +19 -0
- data/lib/aye_commander/abortable.rb +25 -0
- data/lib/aye_commander/callable.rb +41 -0
- data/lib/aye_commander/command.rb +30 -0
- data/lib/aye_commander/commander.rb +120 -0
- data/lib/aye_commander/errors.rb +24 -0
- data/lib/aye_commander/hookable.rb +82 -0
- data/lib/aye_commander/initializable.rb +18 -0
- data/lib/aye_commander/inspectable.rb +36 -0
- data/lib/aye_commander/ivar.rb +94 -0
- data/lib/aye_commander/limitable.rb +83 -0
- data/lib/aye_commander/resultable.rb +58 -0
- data/lib/aye_commander/shareable.rb +32 -0
- data/lib/aye_commander/status.rb +48 -0
- data/lib/aye_commander/version.rb +3 -0
- data/spec/aye_commander/abortable_spec.rb +24 -0
- data/spec/aye_commander/callable_spec.rb +47 -0
- data/spec/aye_commander/command_spec.rb +27 -0
- data/spec/aye_commander/commander_spec.rb +168 -0
- data/spec/aye_commander/errors_spec.rb +25 -0
- data/spec/aye_commander/hookable_spec.rb +105 -0
- data/spec/aye_commander/initializable_spec.rb +33 -0
- data/spec/aye_commander/inspectable_spec.rb +45 -0
- data/spec/aye_commander/ivar_spec.rb +130 -0
- data/spec/aye_commander/limitable_spec.rb +131 -0
- data/spec/aye_commander/resultable_spec.rb +64 -0
- data/spec/aye_commander/shareable_spec.rb +38 -0
- data/spec/aye_commander/status_spec.rb +97 -0
- data/spec/aye_commander_spec.rb +5 -0
- data/spec/spec_helper.rb +49 -0
- metadata +90 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
describe AyeCommander::MissingRequiredArgumentError do
|
2
|
+
let(:error) { AyeCommander::MissingRequiredArgumentError }
|
3
|
+
|
4
|
+
it 'is an AyeCommander::Error child' do
|
5
|
+
expect(error.superclass).to be AyeCommander::Error
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'should have a descriptive message of the error' do
|
9
|
+
errori = error.new [:taco]
|
10
|
+
expect(errori.message).to eq 'Missing required arguments: [:taco]'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe AyeCommander::UnexpectedReceivedArgumentError do
|
15
|
+
let(:error) { AyeCommander::UnexpectedReceivedArgumentError }
|
16
|
+
|
17
|
+
it 'is an AyeCommander::Error child' do
|
18
|
+
expect(error.superclass).to be AyeCommander::Error
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should have a descriptive message of the error' do
|
22
|
+
errori = error.new [:taco]
|
23
|
+
expect(errori.message).to eq 'Received unexpected arguments: [:taco]'
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
describe AyeCommander::Hookable::ClassMethods do
|
2
|
+
include_context :command
|
3
|
+
|
4
|
+
%i(before around after aborted).each do |kind|
|
5
|
+
context ".#{kind}" do
|
6
|
+
it "adds the args to the #{kind} hooks array" do
|
7
|
+
command.send kind, :some, :method
|
8
|
+
expect(command.send("#{kind}_hooks")).to eq [:some, :method]
|
9
|
+
expect(command.instance_variable_get(:@hooks)).to_not be_empty
|
10
|
+
expect(command.instance_variable_get(:@hooks).default).to be_empty
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'adds the received block as a block, after the args' do
|
14
|
+
command.send(kind, :some) { :hello }
|
15
|
+
expect(command.send("#{kind}_hooks").count).to eq 2
|
16
|
+
expect(command.send("#{kind}_hooks").last).to be_instance_of Proc
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'adds the args at the end of the array' do
|
20
|
+
command.send kind, :first
|
21
|
+
command.send kind, :second, :third
|
22
|
+
expect(command.send("#{kind}_hooks")).to eq [:first, :second, :third]
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'adds the args at the beginning of the array with the prepend option' do
|
26
|
+
command.send kind, :first
|
27
|
+
command.send kind, :second, :third, prepend: true
|
28
|
+
expect(command.send("#{kind}_hooks")).to eq [:second, :third, :first]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context ".#{kind}_hooks" do
|
33
|
+
it 'returns empty array with nothing set' do
|
34
|
+
expect(command.send("#{kind}_hooks")).to eq []
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns the array of hooks' do
|
38
|
+
command.instance_variable_set :@hooks, kind => [:hello]
|
39
|
+
expect(command.send("#{kind}_hooks")).to eq [:hello]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
%i(before after aborted).each do |kind|
|
45
|
+
context ".call_#{kind}_hooks" do
|
46
|
+
before :each do
|
47
|
+
body = -> { success? }
|
48
|
+
command.send :define_method, :by_symbol, &body
|
49
|
+
command.send :define_method, :by_method, &body
|
50
|
+
command.send kind, :by_symbol, instance.method(:by_method), body, &body
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'makes all supported hooks callable' do
|
54
|
+
expect(command.send("call_#{kind}_hooks", instance)).to all(respond_to :call)
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'calls all the prepared hooks' do
|
58
|
+
hooks = command.send "call_#{kind}_hooks", instance
|
59
|
+
allow(command).to receive(:prepare_hooks).and_return(hooks)
|
60
|
+
expect(hooks).to all(receive(:call))
|
61
|
+
command.send "call_#{kind}_hooks", instance
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'runs all the prepared hooks in the instance context' do
|
65
|
+
expect(instance).to receive(:success?).exactly(4).times
|
66
|
+
command.send "call_#{kind}_hooks", instance
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context '.call_around_hooks' do
|
72
|
+
before :each do
|
73
|
+
body = lambda do |step|
|
74
|
+
@order ||= []
|
75
|
+
number = order.count + 1
|
76
|
+
@order << number
|
77
|
+
|
78
|
+
success?
|
79
|
+
step.call
|
80
|
+
failure?
|
81
|
+
|
82
|
+
@order << number
|
83
|
+
end
|
84
|
+
|
85
|
+
command.send :define_method, :by_symbol, &body
|
86
|
+
command.send :define_method, :by_method, &body
|
87
|
+
command.around :by_symbol, instance.method(:by_method), body, &body
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'compacts everything into one proc' do
|
91
|
+
expect(command.call_around_hooks(instance).count).to eq 1
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'calls everything' do
|
95
|
+
expect(instance).to receive(:success?).exactly(4).times
|
96
|
+
expect(instance).to receive(:failure?).exactly(4).times
|
97
|
+
command.call_around_hooks(instance)
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should call the hooks in the correct order' do
|
101
|
+
command.call_around_hooks(instance)
|
102
|
+
expect(instance.order).to eq [1, 2, 3, 4, 4, 3, 2, 1]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
describe AyeCommander::Initializable do
|
2
|
+
include_context :command
|
3
|
+
|
4
|
+
context '#initialize' do
|
5
|
+
it 'sets the instance variables with the received arguments' do
|
6
|
+
i = command.new(taco: :burrito, dogo: :hungry)
|
7
|
+
expect(i.taco).to eq :burrito
|
8
|
+
expect(i.dogo).to eq :hungry
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'is able to handle the case when the variable start with @' do
|
12
|
+
i = command.new(:@taco => :burrito, :@dogo => :hungry)
|
13
|
+
expect(i.taco).to eq :burrito
|
14
|
+
expect(i.dogo).to eq :hungry
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'is able to handle the case when no args are received' do
|
18
|
+
expect { command.new }.to_not raise_error
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when a command' do
|
22
|
+
it 'sets the status to :success if no other succeed has been set' do
|
23
|
+
command.succeeds_with :potato
|
24
|
+
expect(instance.status).to eq :success
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'sets the status to the first suceed if success has been excluded' do
|
28
|
+
command.succeeds_with :potato, exclude_success: true
|
29
|
+
expect(instance.status).to eq :potato
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
describe AyeCommander::Inspectable do
|
2
|
+
include_context :command
|
3
|
+
|
4
|
+
before :each do
|
5
|
+
instance.instance_variable_set :@variable, :something
|
6
|
+
instance.instance_variable_set :@other, :potato
|
7
|
+
end
|
8
|
+
|
9
|
+
context '#inspect' do
|
10
|
+
it 'gives a string representation of the innards of the class' do
|
11
|
+
expect(instance.inspect).to match(/#<#<Class:\dx\w+> @status: success, @variable: something, @other: potato>/)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context '#to_hash' do
|
16
|
+
it 'gives a hash representation of the innards of the class' do
|
17
|
+
result = { :@status => :success, :@variable => :something, :@other => :potato }
|
18
|
+
expect(instance.to_hash).to eq result
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'gives a hash representation of the innards of the class with the requested values' do
|
22
|
+
result = { :@variable => :something, :@other => :potato }
|
23
|
+
expect(instance.to_hash([:@variable, :other])).to eq result
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context '#to_result_hash' do
|
28
|
+
it 'gives a hash of all values for the result if no return was specified' do
|
29
|
+
result = { :@status => :success, :@variable => :something, :@other => :potato }
|
30
|
+
expect(instance.to_result_hash).to eq result
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'gives the necessary values for the result when a return was specified' do
|
34
|
+
command.returns :other
|
35
|
+
result = { :@status => :success, :@other => :potato }
|
36
|
+
expect(instance.to_result_hash).to eq result
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'assigns nil to the values that were not created when a result was specified' do
|
40
|
+
command.returns :badger
|
41
|
+
result = { :@status => :success, :@badger => nil }
|
42
|
+
expect(instance.to_result_hash).to eq result
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
describe AyeCommander::Ivar::ClassMethods do
|
2
|
+
include_context :command
|
3
|
+
|
4
|
+
context '.define_missing_reader' do
|
5
|
+
it 'calls uses if its a command' do
|
6
|
+
expect(command).to receive(:uses).with(:taco)
|
7
|
+
command.define_missing_reader(:taco)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'defines the attr_reader if its a result' do
|
11
|
+
command.result_class.define_missing_reader(:taco)
|
12
|
+
expect(result).to respond_to :taco
|
13
|
+
expect(result).to_not respond_to :taco=
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context '.to_ivar' do
|
18
|
+
it 'returns itself when the name is already in ivar form' do
|
19
|
+
expect(command.to_ivar(:@var)).to eq :@var
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns the ivar form when name is not in ivar form' do
|
23
|
+
expect(command.to_ivar(:var)).to eq :@var
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'is able to handle strings' do
|
27
|
+
expect(command.to_ivar('@var')).to eq :@var
|
28
|
+
expect(command.to_ivar('var')).to eq :@var
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context '.to_nvar' do
|
33
|
+
it 'returns itself when name is already in nvar form' do
|
34
|
+
expect(command.to_nvar(:var)).to eq :var
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns the nvar form when name is not in nvar form' do
|
38
|
+
expect(command.to_nvar(:@var)).to eq :var
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'is able to handle strings' do
|
42
|
+
expect(command.to_nvar('@var')).to eq :var
|
43
|
+
expect(command.to_nvar('var')).to eq :var
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe AyeCommander::Ivar::Readable do
|
49
|
+
include_context :command
|
50
|
+
|
51
|
+
context '#method_missing' do
|
52
|
+
it 'raises if asked a method without an instance variable defined' do
|
53
|
+
expect { instance.taco }.to raise_error NoMethodError
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'responds if asked the name of an instance variable' do
|
57
|
+
instance.instance_variable_set :@taco, :badger
|
58
|
+
expect(instance.taco).to eq :badger
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'calls .define_missing_reader' do
|
62
|
+
expect(command).to receive(:define_missing_reader).with(:taco)
|
63
|
+
instance.instance_variable_set :@taco, :badger
|
64
|
+
instance.taco
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context '#remove!' do
|
69
|
+
it 'removes an instance variable' do
|
70
|
+
instance.remove!(:status)
|
71
|
+
expect(instance.instance_variables).to be_empty
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context '#to_ivar' do
|
76
|
+
it 'calls the .to_ivar' do
|
77
|
+
instance
|
78
|
+
expect(command).to receive(:to_ivar).with(:var)
|
79
|
+
instance.to_ivar(:var)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context '#to_nvar' do
|
84
|
+
it 'calls the .to_nvar' do
|
85
|
+
expect(command).to receive(:to_nvar).with(:var)
|
86
|
+
instance.to_nvar(:var)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'p#respond_to_missing?' do
|
91
|
+
it 'returns true if the variable name is defined' do
|
92
|
+
instance.instance_variable_set :@taco, :badger
|
93
|
+
expect(instance.send(:respond_to_missing?, :taco, [false])).to be true
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'uses super if the variable name is not defined' do
|
97
|
+
expect(instance.send(:respond_to_missing?, :taco, [false])).to be false
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'uses super if the variable name is not valid' do
|
101
|
+
expect(instance.send(:respond_to_missing?, :taco!, [false])).to be false
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe AyeCommander::Ivar::Writeable do
|
107
|
+
include_context :command
|
108
|
+
|
109
|
+
context '#method_missing' do
|
110
|
+
it 'responds to equality assignments' do
|
111
|
+
expect { instance.taco = 1 }.to_not raise_error
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'defines the method so next time it doesnt go through method_missing' do
|
115
|
+
instance.taco = 1
|
116
|
+
expect(instance).to respond_to :taco
|
117
|
+
expect(instance).to respond_to :taco=
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'p#respond_to_missing?' do
|
122
|
+
it 'returns true if variable name ends with =' do
|
123
|
+
expect(instance.send(:respond_to_missing?, :taco=, [false])).to be true
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'uses super otherwise' do
|
127
|
+
expect(instance.send(:respond_to_missing?, :taco, [false])).to be false
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
describe AyeCommander::Limitable::ClassMethods do
|
2
|
+
include_context :command
|
3
|
+
let(:args) { %i(arg1 arg2) }
|
4
|
+
|
5
|
+
context '.uses' do
|
6
|
+
it 'should call save_variable' do
|
7
|
+
command.uses(*args)
|
8
|
+
expect(command.uses).to eq args
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should create accessors for the received values' do
|
12
|
+
command.uses(*args)
|
13
|
+
args.each do |arg|
|
14
|
+
expect(instance).to respond_to arg
|
15
|
+
expect(instance).to respond_to "#{arg}="
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
%i(receives requires returns).each do |limiter|
|
21
|
+
context ".#{limiter}" do
|
22
|
+
before :each do
|
23
|
+
command.public_send limiter, *args
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should call .uses' do
|
27
|
+
expect(command).to receive(:uses).with(*args).and_return(true)
|
28
|
+
command.public_send limiter, *args
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should save the values to a class instance variable' do
|
32
|
+
expect(command.limiters[limiter]).to eq args
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should add consecutive values without any problem' do
|
36
|
+
command.public_send limiter, :arg3
|
37
|
+
expect(command.limiters[limiter]).to eq %i(arg1 arg2 arg3)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should not add repeated args' do
|
41
|
+
command.public_send limiter, :arg1, :arg4
|
42
|
+
expect(command.limiters[limiter]).to eq %i(arg1 arg2 arg4)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context '.validate_arguments' do
|
48
|
+
let(:args) { { hello: :world, how: :are, you: :! } }
|
49
|
+
|
50
|
+
it 'calls .validate_required_arguments if it has requires' do
|
51
|
+
expect(command).to receive(:validate_required_arguments).and_return(true)
|
52
|
+
command.requires :something
|
53
|
+
command.validate_arguments args
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'does not call .validate_required_arguments if theres no requires' do
|
57
|
+
expect(command).to_not receive(:validate_required_arguments)
|
58
|
+
command.validate_arguments args
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'does not call .validate_required_arguments with skip_validations: :requires option' do
|
62
|
+
command.requires :something
|
63
|
+
expect(command).to_not receive(:validate_required_arguments)
|
64
|
+
command.validate_arguments args, skip_validations: :requires
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'calls .validate_received_arguments if it has receives' do
|
68
|
+
expect(command).to receive(:validate_received_arguments).and_return(true)
|
69
|
+
command.receives :something
|
70
|
+
command.validate_arguments args
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'does not call .validate_received_argumnts if theres no receives' do
|
74
|
+
expect(command).to_not receive(:validate_received_arguments)
|
75
|
+
command.validate_arguments args
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'does not call .validate_receiveed_arguments with skip_validations: :receives option' do
|
79
|
+
command.receives :something
|
80
|
+
expect(command).to_not receive(:validate_received_arguments)
|
81
|
+
command.validate_arguments args, skip_validations: :receives
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'does not call either with skip_validations: true option' do
|
85
|
+
command.requires :something
|
86
|
+
command.receives :something_else
|
87
|
+
expect(command).to_not receive(:validate_received_arguments)
|
88
|
+
expect(command).to_not receive(:validate_required_arguments)
|
89
|
+
|
90
|
+
command.validate_arguments args, skip_validations: true
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context '.validate_required_arguments' do
|
95
|
+
let(:args) { { hello: :world, how: :are, you: :! } }
|
96
|
+
|
97
|
+
it 'does nothing if the required arguments are contained in the received ones' do
|
98
|
+
command.requires :hello, :you
|
99
|
+
expect { command.validate_required_arguments args }.to_not raise_error
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'does nothing if it receives extra arguments' do
|
103
|
+
command.requires :hello, :you
|
104
|
+
expect { command.validate_required_arguments(**args, extra: :arg) }.to_not raise_error
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'raises an error when the required arguments are not fully contained in the received ones' do
|
108
|
+
command.requires :hello, :you, :doc
|
109
|
+
expect { command.validate_required_arguments args }.to raise_error AyeCommander::MissingRequiredArgumentError
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context '.validate_received_arguments' do
|
114
|
+
let(:args) { { hello: :world, how: :are, you: :! } }
|
115
|
+
|
116
|
+
it 'does nothing if receives contains all the received arguments' do
|
117
|
+
command.receives :hello, :how, :you
|
118
|
+
expect { command.validate_received_arguments args }.to_not raise_error
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'does nothing if some of the arguments are missing' do
|
122
|
+
command.receives :hello, :how, :you, :potato
|
123
|
+
expect { command.validate_received_arguments args }.to_not raise_error
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'raises an error when it receives arguments not contained in the receives array' do
|
127
|
+
command.receives :hello, :how, :potato
|
128
|
+
expect { command.validate_received_arguments args }.to raise_error AyeCommander::UnexpectedReceivedArgumentError
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|