ego 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +20 -0
- data/.rubocop_todo.yml +36 -0
- data/Gemfile +2 -0
- data/Guardfile +9 -2
- data/Rakefile +5 -1
- data/bin/ego +2 -0
- data/ego.gemspec +22 -17
- data/lib/ego.rb +3 -1
- data/lib/ego/capability.rb +2 -0
- data/lib/ego/filesystem.rb +2 -0
- data/lib/ego/handler.rb +8 -2
- data/lib/ego/options.rb +13 -8
- data/lib/ego/plugin.rb +3 -1
- data/lib/ego/plugin_helper.rb +18 -16
- data/lib/ego/plugins/capabilities.rb +9 -3
- data/lib/ego/plugins/fallback.rb +9 -7
- data/lib/ego/plugins/robot_io.rb +2 -0
- data/lib/ego/plugins/social.rb +3 -1
- data/lib/ego/plugins/status.rb +2 -0
- data/lib/ego/plugins/system.rb +4 -2
- data/lib/ego/printer.rb +9 -5
- data/lib/ego/robot.rb +9 -6
- data/lib/ego/robot_error.rb +2 -0
- data/lib/ego/runner.rb +12 -7
- data/lib/ego/version.rb +3 -1
- data/spec/ego/acceptance/help_spec.rb +9 -0
- data/spec/ego/acceptance/no_args_spec.rb +9 -0
- data/spec/ego/acceptance/shell_spec.rb +11 -0
- data/spec/ego/acceptance/simple_query_spec.rb +9 -0
- data/spec/ego/acceptance/template_spec.rb +43 -0
- data/spec/ego/acceptance/usage_error_spec.rb +17 -0
- data/spec/ego/acceptance/version_spec.rb +9 -0
- data/spec/ego/capability_spec.rb +2 -0
- data/spec/ego/handler_spec.rb +18 -6
- data/spec/ego/options_spec.rb +8 -1
- data/spec/ego/plugin_helper_spec.rb +4 -2
- data/spec/ego/plugin_spec.rb +5 -4
- data/spec/ego/plugins/capabilities_spec.rb +4 -4
- data/spec/ego/plugins/fallback_spec.rb +16 -6
- data/spec/ego/plugins/robot_io_spec.rb +3 -3
- data/spec/ego/plugins/social_spec.rb +3 -3
- data/spec/ego/plugins/status_spec.rb +3 -3
- data/spec/ego/plugins/system_spec.rb +8 -8
- data/spec/ego/printer_spec.rb +86 -86
- data/spec/ego/robot_error_spec.rb +2 -0
- data/spec/ego/robot_spec.rb +24 -22
- data/spec/ego/runner_spec.rb +12 -0
- data/spec/spec_helper.rb +5 -48
- data/spec/support/aruba.rb +3 -0
- data/spec/support/plugin_helper.rb +64 -0
- metadata +71 -9
@@ -1,8 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
subject { robot_with_plugin('capabilities') }
|
3
|
+
require 'ego/robot'
|
5
4
|
|
5
|
+
RSpec.describe Ego::Robot, 'with capabilities plug-in', plugin: 'capabilities' do
|
6
6
|
describe '#understand?' do
|
7
7
|
it 'is defined on the robot instance' do
|
8
8
|
expect(subject.respond_to?(:understand?)).to be true
|
@@ -13,7 +13,7 @@ RSpec.describe Ego::Robot, 'with capabilities plug-in' do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'returns true for queries the robot can handle' do
|
16
|
-
subject.on(/^zzz$/) {
|
16
|
+
subject.on(/^zzz$/) {}
|
17
17
|
expect(subject.understand?('zzz')).to be true
|
18
18
|
end
|
19
19
|
end
|
@@ -1,22 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'ego/robot'
|
2
4
|
|
3
|
-
RSpec.describe Ego::Robot, 'with fallback plug-in' do
|
4
|
-
subject { robot_with_plugin('fallback') }
|
5
|
+
RSpec.describe Ego::Robot, 'with fallback plug-in', plugin: 'fallback' do
|
5
6
|
let(:unhandlable_query) { 'xxx' }
|
7
|
+
let(:empty_query) { '' }
|
6
8
|
|
7
9
|
it { should be_able_to 'help you write plug-ins' }
|
8
10
|
|
9
|
-
it { should_not handle_query
|
11
|
+
it { should_not handle_query unhandlable_query }
|
10
12
|
|
11
13
|
it 'prints a hint when a query is unhandled' do
|
12
|
-
expect { subject.handle(
|
14
|
+
expect { subject.handle(unhandlable_query) }.to output(
|
13
15
|
/^Ego\.plugin/
|
14
16
|
).to_stdout
|
15
17
|
end
|
16
18
|
|
17
19
|
it 'prints a hint containing the original query' do
|
18
|
-
expect { subject.handle(
|
19
|
-
|
20
|
+
expect { subject.handle(unhandlable_query) }.to output(
|
21
|
+
Regexp.new(unhandlable_query)
|
22
|
+
).to_stdout
|
23
|
+
end
|
24
|
+
|
25
|
+
it { should handle_query empty_query }
|
26
|
+
|
27
|
+
it 'prints a message when the query is empty' do
|
28
|
+
expect { subject.handle(empty_query) }.to output(
|
29
|
+
/^(Yes|Hello|\.\.\.)\?$/
|
20
30
|
).to_stdout
|
21
31
|
end
|
22
32
|
end
|
@@ -1,8 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
subject { robot_with_plugin('robot_io') }
|
3
|
+
require 'ego/robot'
|
5
4
|
|
5
|
+
RSpec.describe Ego::Robot, 'with robot_io plug-in', plugin: 'robot_io' do
|
6
6
|
it { should be_able_to 'output text to the terminal' }
|
7
7
|
|
8
8
|
describe '#verbose?' do
|
@@ -1,8 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
subject { robot_with_plugin('social') }
|
3
|
+
require 'ego/robot'
|
5
4
|
|
5
|
+
RSpec.describe Ego::Robot, 'with social plug-in', plugin: 'social' do
|
6
6
|
it { should be_able_to 'socialize' }
|
7
7
|
|
8
8
|
it { should handle_query 'who are you' }
|
@@ -1,8 +1,8 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
subject { robot_with_plugin('status') }
|
3
|
+
require 'ego/robot'
|
5
4
|
|
5
|
+
RSpec.describe Ego::Robot, 'with status plug-in', plugin: 'status' do
|
6
6
|
it { should be_able_to 'report robot status' }
|
7
7
|
|
8
8
|
it { should handle_query 'status' }
|
@@ -1,12 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
subject { robot_with_plugin('system') }
|
3
|
+
require 'ego/robot'
|
5
4
|
|
5
|
+
RSpec.describe Ego::Robot, 'with system plug-in', plugin: 'system' do
|
6
6
|
it { should be_able_to 'execute system commands' }
|
7
7
|
|
8
8
|
describe '#system' do
|
9
|
-
let(:args) { [
|
9
|
+
let(:args) { %w[foo bar] }
|
10
10
|
|
11
11
|
before do
|
12
12
|
allow(Kernel).to receive(:system).and_return(true)
|
@@ -20,7 +20,7 @@ RSpec.describe Ego::Robot, 'with system plug-in' do
|
|
20
20
|
|
21
21
|
it 'calls Kernel.system' do
|
22
22
|
expect(Kernel).to receive(:system).with(*args)
|
23
|
-
subject.system
|
23
|
+
subject.system(*args)
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'prints a debug message' do
|
@@ -28,12 +28,12 @@ RSpec.describe Ego::Robot, 'with system plug-in' do
|
|
28
28
|
'Running system with arguments %s.',
|
29
29
|
args
|
30
30
|
)
|
31
|
-
subject.system
|
31
|
+
subject.system(*args)
|
32
32
|
end
|
33
33
|
|
34
34
|
it 'prints nothing on success' do
|
35
35
|
expect(subject).not_to receive(:alert)
|
36
|
-
subject.system
|
36
|
+
subject.system(*args)
|
37
37
|
end
|
38
38
|
|
39
39
|
it 'prints an alert on error' do
|
@@ -42,7 +42,7 @@ RSpec.describe Ego::Robot, 'with system plug-in' do
|
|
42
42
|
'Sorry, there was a problem running %s.',
|
43
43
|
args.first
|
44
44
|
)
|
45
|
-
subject.system
|
45
|
+
subject.system(*args)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
data/spec/ego/printer_spec.rb
CHANGED
@@ -1,122 +1,122 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'ego/printer'
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
let(:printer) { (Class.new { include Printer }).new }
|
5
|
+
RSpec.describe Ego::Printer do
|
6
|
+
let(:verbose_printer) { (Class.new { include Ego::Printer; def verbose?; true; end }).new }
|
7
|
+
let(:printer) { (Class.new { include Ego::Printer }).new }
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
before(:all) { String.disable_colorization = false }
|
10
|
+
after(:all) { String.disable_colorization = true }
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
describe '#puts' do
|
13
|
+
it 'is callable on the module' do
|
14
|
+
expect(described_class.respond_to?(:puts)).to be true
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
it 'is private on the instance' do
|
18
|
+
expect(printer.respond_to?(:puts)).to be false
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
it 'prints to STDOUT' do
|
22
|
+
expect { described_class.puts 'bar' }.to output("bar\n").to_stdout
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
end
|
25
|
+
it 'concatenates multiple arguments' do
|
26
|
+
expect { described_class.puts 'bar', 'baz' }.to output("bar\nbaz\n").to_stdout
|
27
27
|
end
|
28
|
+
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
describe '#errs' do
|
31
|
+
it 'is callable on the module' do
|
32
|
+
expect(described_class.respond_to?(:errs)).to be true
|
33
|
+
end
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
it 'is private on the instance' do
|
36
|
+
expect(printer.respond_to?(:errs)).to be false
|
37
|
+
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
it 'prints to STDERR' do
|
40
|
+
expect { described_class.errs 'bar' }.to output("bar\n").to_stderr
|
41
|
+
end
|
41
42
|
|
42
|
-
|
43
|
-
|
44
|
-
end
|
43
|
+
it 'concatenates multiple arguments' do
|
44
|
+
expect { described_class.errs 'bar', 'baz' }.to output("bar\nbaz\n").to_stderr
|
45
45
|
end
|
46
|
+
end
|
46
47
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
48
|
+
describe '#say' do
|
49
|
+
it 'is not callable on the module' do
|
50
|
+
expect(described_class.respond_to?(:say)).to be false
|
51
|
+
end
|
51
52
|
|
52
|
-
|
53
|
-
|
54
|
-
|
53
|
+
it 'is callable on the instance' do
|
54
|
+
expect(printer.respond_to?(:say)).to be true
|
55
|
+
end
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
57
|
+
it 'prints the message to STDOUT bolded with newline' do
|
58
|
+
expect { printer.say('X') }.to output("\e[1;39;49mX\e[0m\n").to_stdout
|
59
|
+
end
|
59
60
|
|
60
|
-
|
61
|
-
|
62
|
-
end
|
61
|
+
it 'accepts placeholders and replacement strings' do
|
62
|
+
expect { printer.say('Hello, %s.', 'world') }.to output("\e[1;39;49mHello, world.\e[0m\n").to_stdout
|
63
63
|
end
|
64
|
+
end
|
64
65
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
66
|
+
describe '#emote' do
|
67
|
+
it 'is not callable on the module' do
|
68
|
+
expect(described_class.respond_to?(:emote)).to be false
|
69
|
+
end
|
69
70
|
|
70
|
-
|
71
|
-
|
72
|
-
|
71
|
+
it 'is callable on the instance' do
|
72
|
+
expect(printer.respond_to?(:emote)).to be true
|
73
|
+
end
|
73
74
|
|
74
|
-
|
75
|
-
|
76
|
-
end
|
75
|
+
it 'prints the message to STDOUT with color and asterisks' do
|
76
|
+
expect { printer.emote('FOO') }.to output("\e[0;35;49m*FOO*\e[0m\n").to_stdout
|
77
77
|
end
|
78
|
+
end
|
78
79
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
80
|
+
describe '#alert' do
|
81
|
+
it 'is not callable on the module' do
|
82
|
+
expect(described_class.respond_to?(:alert)).to be false
|
83
|
+
end
|
83
84
|
|
84
|
-
|
85
|
-
|
86
|
-
|
85
|
+
it 'is callable on the instance' do
|
86
|
+
expect(printer.respond_to?(:alert)).to be true
|
87
|
+
end
|
87
88
|
|
88
|
-
|
89
|
-
|
90
|
-
|
89
|
+
it 'prints the message to STDERR with color and newline' do
|
90
|
+
expect { printer.alert('FOO') }.to output("\e[0;91;49mFOO\e[0m\n").to_stderr
|
91
|
+
end
|
91
92
|
|
92
|
-
|
93
|
-
|
94
|
-
end
|
93
|
+
it 'accepts placeholders and replacement strings' do
|
94
|
+
expect { printer.alert('Error: %s.', 'foo') }.to output("\e[0;91;49mError: foo.\e[0m\n").to_stderr
|
95
95
|
end
|
96
|
+
end
|
96
97
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
98
|
+
describe '#debug' do
|
99
|
+
it 'is not callable on the module' do
|
100
|
+
expect(described_class.respond_to?(:debug)).to be false
|
101
|
+
end
|
101
102
|
|
102
|
-
|
103
|
-
|
104
|
-
|
103
|
+
it 'is callable on the instance' do
|
104
|
+
expect(printer.respond_to?(:debug)).to be true
|
105
|
+
end
|
105
106
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
107
|
+
context 'in verbose instance' do
|
108
|
+
it 'prints the message to STDERR with newline' do
|
109
|
+
expect { verbose_printer.debug('FOO') }.to output("FOO\n").to_stderr
|
110
|
+
end
|
110
111
|
|
111
|
-
|
112
|
-
|
113
|
-
end
|
112
|
+
it 'accepts placeholders and replacement strings' do
|
113
|
+
expect { verbose_printer.debug('Hello, %s.', 'world') }.to output("Hello, world.\n").to_stderr
|
114
114
|
end
|
115
|
+
end
|
115
116
|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
end
|
117
|
+
context 'in default instance' do
|
118
|
+
it 'does not print anything' do
|
119
|
+
expect { printer.debug('FOO') }.not_to output.to_stderr
|
120
120
|
end
|
121
121
|
end
|
122
122
|
end
|
data/spec/ego/robot_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'ego/robot'
|
2
4
|
|
3
5
|
RSpec.describe Ego::Robot do
|
@@ -5,10 +7,10 @@ RSpec.describe Ego::Robot do
|
|
5
7
|
let(:options) { double('Ego::Options') }
|
6
8
|
let(:plugin) { double('Ego::Plugin') }
|
7
9
|
subject do
|
8
|
-
allow(options).to receive_messages(
|
10
|
+
allow(options).to receive_messages(
|
9
11
|
robot_name: name,
|
10
|
-
verbose: false
|
11
|
-
|
12
|
+
verbose: false
|
13
|
+
)
|
12
14
|
|
13
15
|
described_class.new(options)
|
14
16
|
end
|
@@ -97,7 +99,7 @@ RSpec.describe Ego::Robot do
|
|
97
99
|
let(:priority) { 9 }
|
98
100
|
|
99
101
|
before do
|
100
|
-
subject.on(condition, priority) {
|
102
|
+
subject.on(condition, priority) {}
|
101
103
|
end
|
102
104
|
|
103
105
|
it 'passes the condition and action to a new handler' do
|
@@ -114,9 +116,9 @@ RSpec.describe Ego::Robot do
|
|
114
116
|
context 'given a hash' do
|
115
117
|
before do
|
116
118
|
subject.on(
|
117
|
-
->(
|
118
|
-
->(
|
119
|
-
) {
|
119
|
+
->(_q) { 'foo' } => 1,
|
120
|
+
->(_q) { 'bar' } => 2
|
121
|
+
) {}
|
120
122
|
end
|
121
123
|
|
122
124
|
it 'creates a new handler for each item' do
|
@@ -145,7 +147,7 @@ RSpec.describe Ego::Robot do
|
|
145
147
|
end
|
146
148
|
|
147
149
|
it 'executes the action in the context of the robot instance' do
|
148
|
-
expect(subject.run_action(->
|
150
|
+
expect(subject.run_action(-> { name }, [])).to eq(subject.name)
|
149
151
|
end
|
150
152
|
end
|
151
153
|
|
@@ -161,12 +163,12 @@ RSpec.describe Ego::Robot do
|
|
161
163
|
|
162
164
|
it 'is run by #run_action' do
|
163
165
|
subject.before_action { print 'Before!' }
|
164
|
-
expect { subject.run_action(->(
|
166
|
+
expect { subject.run_action(->(_p) { true }, 'p') }.to output('Before!').to_stdout
|
165
167
|
end
|
166
168
|
|
167
169
|
it 'receives the action and action parameters' do
|
168
|
-
subject.before_action { |
|
169
|
-
expect { subject.run_action(->(
|
170
|
+
subject.before_action { |_action, params| print params }
|
171
|
+
expect { subject.run_action(->(_p) { true }, 'p') }.to output('p').to_stdout
|
170
172
|
end
|
171
173
|
end
|
172
174
|
|
@@ -182,22 +184,22 @@ RSpec.describe Ego::Robot do
|
|
182
184
|
|
183
185
|
it 'is run by #run_action' do
|
184
186
|
subject.after_action { print 'After!' }
|
185
|
-
expect { subject.run_action(->(
|
187
|
+
expect { subject.run_action(->(_p) { 'out' }, 'p') }.to output('After!').to_stdout
|
186
188
|
end
|
187
189
|
|
188
190
|
it 'receives the action, parameters, and return value' do
|
189
|
-
subject.after_action { |
|
190
|
-
expect { subject.run_action(->(
|
191
|
+
subject.after_action { |_action, params, result| print result + params }
|
192
|
+
expect { subject.run_action(->(_p) { 'out' }, 'p') }.to output('outp').to_stdout
|
191
193
|
end
|
192
194
|
end
|
193
195
|
|
194
196
|
describe '#first_handler_for' do
|
195
197
|
before do
|
196
198
|
subject.on(
|
197
|
-
->(q) { {} if
|
198
|
-
->(q) { {} if
|
199
|
-
->(q) { {} if
|
200
|
-
) {
|
199
|
+
->(q) { {} if /bar/ =~ q } => 3,
|
200
|
+
->(q) { {} if /foo/ =~ q } => 2,
|
201
|
+
->(q) { {} if /foo/ =~ q } => 1
|
202
|
+
) {}
|
201
203
|
end
|
202
204
|
|
203
205
|
it 'chooses the highest-priority handler that matches the query' do
|
@@ -212,9 +214,9 @@ RSpec.describe Ego::Robot do
|
|
212
214
|
describe '#handle' do
|
213
215
|
before do
|
214
216
|
subject.on(
|
215
|
-
->(q) { {param: :three} if
|
216
|
-
->(q) { {param: :two} if
|
217
|
-
->(q) { {param: :one} if
|
217
|
+
->(q) { { param: :three } if /bar/ =~ q } => 3,
|
218
|
+
->(q) { { param: :two } if /foo/ =~ q } => 2,
|
219
|
+
->(q) { { param: :one } if /foo/ =~ q } => 1
|
218
220
|
) { |param| param }
|
219
221
|
end
|
220
222
|
|
@@ -289,7 +291,7 @@ RSpec.describe Ego::Robot do
|
|
289
291
|
end
|
290
292
|
|
291
293
|
it 'is not run by #handle when the query is handled' do
|
292
|
-
subject.on('xxx') {
|
294
|
+
subject.on('xxx') {}
|
293
295
|
expect { subject.handle('xxx') }.not_to output('Oops!').to_stdout
|
294
296
|
end
|
295
297
|
|