aye_commander 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|