yuyi 0.0.3

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.
@@ -0,0 +1,291 @@
1
+ require 'spec_helper'
2
+
3
+ options = Yuyi::Cli::CLI_OPTIONS.keys
4
+
5
+ describe Yuyi::Cli do
6
+ before do
7
+ class CliTest; extend Yuyi::Cli; end
8
+ allow(CliTest).to receive(:say)
9
+ end
10
+
11
+ describe 'CLI_OPTIONS' do
12
+ it 'should have options with a unique first character' do
13
+ flags = options.map{ |option| option.to_s.chars.first }
14
+
15
+ expect(flags.uniq.length).to eq options.length
16
+ end
17
+ end
18
+
19
+ describe '#init' do
20
+ context 'without arguments' do
21
+ before do
22
+ allow(CliTest).to receive :start
23
+ CliTest.init []
24
+ end
25
+
26
+ it 'should call start' do
27
+ expect(CliTest).to have_received(:start)
28
+ end
29
+ end
30
+
31
+ context 'with an invalid argument' do
32
+ before do
33
+ allow(CliTest).to receive :help
34
+ CliTest.init 'foo'
35
+ end
36
+
37
+ it 'should call the help method' do
38
+ expect(CliTest).to have_received(:help)
39
+ end
40
+ end
41
+
42
+ context 'with the respective argument' do
43
+ options.each do |option|
44
+ before do
45
+ allow(CliTest).to receive option.to_s.downcase.to_sym
46
+
47
+ # Test both option forms
48
+ CliTest.init "-#{option.to_s.chars.first}"
49
+ CliTest.init "--#{option}"
50
+ end
51
+
52
+ the "#{option} option is valid" do
53
+ expect(CliTest).to have_received(option.to_s.downcase.to_sym).twice
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ describe '#say' do
60
+ before do
61
+ allow(CliTest).to receive(:say).and_call_original
62
+ allow(STDOUT).to receive(:puts)
63
+ end
64
+
65
+ after do
66
+ allow(STDOUT).to receive(:puts).and_call_original
67
+ end
68
+
69
+ it 'should output the correct type' do
70
+ expect(STDOUT).to receive(:puts).with("\e[31mfoo type\e[0m")
71
+ CliTest.say 'foo type', :type => :fail
72
+ end
73
+
74
+ it 'should output the correct color' do
75
+ expect(STDOUT).to receive(:puts).with("\e[123mfoo color\e[0m")
76
+ CliTest.say 'foo color', :color => 123
77
+ end
78
+
79
+ it 'should output the correct justification & padding' do
80
+ expect(STDOUT).to receive(:puts).with(' foo justify padding ')
81
+ CliTest.say 'foo justify padding', :justify => :center, :padding => 22
82
+ end
83
+
84
+ it 'should output the correct indentation' do
85
+ expect(STDOUT).to receive(:puts).with(' foo indent')
86
+ CliTest.say 'foo indent', :indent => 2
87
+ end
88
+ end
89
+
90
+ describe '#ask' do
91
+ before do
92
+ allow(CliTest).to receive(:say)
93
+ allow(STDIN).to receive(:gets).and_return 'foo'
94
+ end
95
+
96
+ after do
97
+ allow(STDIN).to receive(:gets).and_call_original
98
+ end
99
+
100
+ it 'should pass the user input to the block' do
101
+ CliTest.ask 'why?' do |response|
102
+ expect(response).to eq 'foo'
103
+ end
104
+ end
105
+ end
106
+
107
+ describe '#command?' do
108
+ it 'should return true if command exists' do
109
+ expect(CliTest.command?('ruby -v')).to eq true
110
+ end
111
+
112
+ it 'should return false if command does not exist' do
113
+ expect(CliTest.command?('rubyfoo')).to eq false
114
+ end
115
+ end
116
+
117
+ describe '#write_to_file' do
118
+ before do
119
+ CliTest.write_to_file 'test', 'foo'
120
+ end
121
+
122
+ after do
123
+ FileUtils.rm 'test'
124
+ end
125
+
126
+ it 'should create a file if it doesnt exist' do
127
+ expect(File.exists?('test')).to be true
128
+ end
129
+
130
+ it 'should append to the file' do
131
+ CliTest.write_to_file 'test', 'bar'
132
+ expect(File.open('test').read).to eq "foo\nbar\n"
133
+ end
134
+
135
+ it 'should accept multiple text arguments' do
136
+ CliTest.write_to_file 'test', 'arg1', 'arg2'
137
+ expect(File.open('test').read).to eq "foo\narg1\narg2\n"
138
+ end
139
+ end
140
+
141
+ describe '#delete_from_file' do
142
+ before do
143
+ CliTest.write_to_file 'test', 'foo', 'remove1', 'remove2', 'bar'
144
+ end
145
+
146
+ after do
147
+ FileUtils.rm 'test'
148
+ end
149
+
150
+ it 'should remove a line from the file' do
151
+ CliTest.delete_from_file 'test', 'remove1'
152
+ expect(File.open('test').read).to eq "foo\nremove2\nbar\n"
153
+ end
154
+
155
+ it 'should accept multiple text arguments' do
156
+ CliTest.delete_from_file 'test', 'remove1', 'remove2'
157
+ expect(File.open('test').read).to eq "foo\nbar\n"
158
+ end
159
+ end
160
+
161
+ describe '#get_menu' do
162
+ before do
163
+ stub_const 'Yuyi::DEFAULT_MENU', 'spec/fixtures/menu.yaml'
164
+ allow(Yuyi::Menu).to receive(:load_from_file).and_return true
165
+ end
166
+
167
+ after do
168
+ CliTest.send :get_menu
169
+ allow(Readline).to receive(:readline).and_call_original
170
+ allow(Yuyi::Menu).to receive(:new).and_call_original
171
+ allow(Yuyi::Menu).to receive(:load_from_file).and_call_original
172
+ end
173
+
174
+ context 'when no input is given' do
175
+ before do
176
+ allow(Readline).to receive(:readline).and_return('')
177
+ allow(Yuyi::Menu).to receive(:new).and_return(true)
178
+ end
179
+
180
+ it 'should load the default menu' do
181
+ expect(Yuyi::Menu).to receive(:new).with('spec/fixtures/menu.yaml')
182
+ end
183
+ end
184
+
185
+ context 'when an invalid path is given' do
186
+ before do
187
+ allow(Readline).to receive(:readline).and_return('foo', 'bar', '')
188
+ allow(Yuyi::Menu).to receive(:new).and_return(false, false, true)
189
+ end
190
+
191
+ it 'should request input again' do
192
+ expect(Yuyi::Menu).to receive(:new).exactly(3).times
193
+ end
194
+ end
195
+
196
+ context 'when a custom path is given' do
197
+ before do
198
+ allow(Readline).to receive(:readline).and_return('spec/fixtures/menu.yaml')
199
+ allow(Yuyi::Menu).to receive(:new).and_return(true)
200
+ end
201
+
202
+ it 'should load the menu' do
203
+ expect(Yuyi::Menu).to receive(:new).with('spec/fixtures/menu.yaml')
204
+ end
205
+ end
206
+ end
207
+
208
+ describe '#present_options' do
209
+ before do
210
+ @output = ''
211
+ allow(CliTest).to receive :say do |o, p|
212
+ @output << (o || '')
213
+ end
214
+
215
+ class PresentOptionsRoll; end
216
+ allow(PresentOptionsRoll).to receive(:title).and_return 'Present Options Roll'
217
+ allow(PresentOptionsRoll).to receive(:file_name).and_return :present_options_roll
218
+ allow(PresentOptionsRoll).to receive(:options).and_return({ :option_foo => '3.0' })
219
+ allow(PresentOptionsRoll).to receive(:option_defs).and_return({
220
+ :option_foo => {
221
+ :description => 'foo description',
222
+ :example => '1.0',
223
+ :default => '2.0'
224
+ }
225
+ })
226
+
227
+ CliTest.send :present_options, PresentOptionsRoll
228
+ end
229
+
230
+ it 'should output the neccessary information' do
231
+ expect(@output).to include 'Present Options Roll'
232
+ expect(@output).to include 'present_options_roll'
233
+ expect(@output).to include 'foo description'
234
+ expect(@output).to include '1.0'
235
+ expect(@output).to include '2.0'
236
+ end
237
+ end
238
+
239
+ # Argument Methods
240
+ #
241
+ describe '#help' do
242
+ before do
243
+ stub_const 'Yuyi::Cli::CLI_OPTIONS', {
244
+ :FOO => 'doo',
245
+ :bar => 'boo'
246
+ }
247
+
248
+ @output = ''
249
+ allow(CliTest).to receive :say do |o, p|
250
+ @output << (o || '')
251
+ end
252
+
253
+ CliTest.send :help
254
+ end
255
+
256
+ it 'should return options' do
257
+ expect(@output).to include '-F'
258
+ expect(@output).to include '--FOO'
259
+ expect(@output).to include 'doo'
260
+ expect(@output).to include '-b'
261
+ expect(@output).to include '--bar'
262
+ expect(@output).to include 'boo'
263
+ end
264
+ end
265
+
266
+ describe '#list' do
267
+ before do
268
+ class ListRollSource; end
269
+ allow(ListRollSource).to receive(:available_rolls).and_return({ :list_roll => nil })
270
+
271
+ allow(CliTest).to receive :get_menu
272
+ allow(Yuyi::Menu).to receive :set_sources
273
+ allow(Yuyi::Menu).to receive(:sources).and_return([ ListRollSource ])
274
+
275
+ @output = ''
276
+ allow(CliTest).to receive :say do |o, p|
277
+ @output << (o || '')
278
+ end
279
+
280
+ CliTest.send :list
281
+ end
282
+
283
+ after do
284
+ allow(Yuyi::Menu).to receive(:set_sources).and_call_original
285
+ end
286
+
287
+ it 'should return all rolls' do
288
+ expect(@output).to include 'list_roll'
289
+ end
290
+ end
291
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hash do
4
+ describe '.deep_symbolize_keys!' do
5
+ before do
6
+ @hash = {
7
+ 'foo' => 'bar',
8
+ 'nested_hash' => { 'nested_key' => 'nested_value'},
9
+ 'nested_array' => ['array_element']
10
+ }
11
+
12
+ @hash.deep_symbolize_keys!
13
+ end
14
+
15
+ it 'should recursively symbolize keys' do
16
+ expect(@hash).to eq({
17
+ :foo => 'bar',
18
+ :nested_hash => { :nested_key => 'nested_value' },
19
+ :nested_array => ['array_element']
20
+ })
21
+ end
22
+ end
23
+
24
+ describe '.deep_stringify_keys!' do
25
+ before do
26
+ @hash = {
27
+ :foo => 'bar',
28
+ :nested_hash => { :nested_key => 'nested_value' },
29
+ :nested_array => ['array_element']
30
+ }
31
+
32
+ @hash.deep_stringify_keys!
33
+ end
34
+
35
+ it 'should recursively symbolize keys' do
36
+ expect(@hash).to eq({
37
+ 'foo' => 'bar',
38
+ 'nested_hash' => { 'nested_key' => 'nested_value'},
39
+ 'nested_array' => ['array_element']
40
+ })
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,207 @@
1
+ require 'spec_helper'
2
+
3
+ describe Yuyi::Menu do
4
+ before do
5
+ @menu = Yuyi::Menu.new 'spec/fixtures/menu.yaml'
6
+ end
7
+
8
+ describe '.load_from_file' do
9
+ before do
10
+ Yuyi::Menu.load_from_file 'spec/fixtures/menu2.yaml'
11
+ end
12
+
13
+ it 'should update the menu object' do
14
+ expect(@menu.object[:rolls][:foo_roll]).to eq({ :bar => 'foo' })
15
+ end
16
+ end
17
+
18
+ describe '.add_roll' do
19
+ before do
20
+ class MenuAddRollRoll; end
21
+ Yuyi::Menu.add_roll :menu_add_roll_roll, MenuAddRollRoll
22
+ end
23
+
24
+ it 'should add a roll instance' do
25
+ expect(Yuyi::Menu.instance_var(:rolls)[:menu_add_roll_roll]).to be_a MenuAddRollRoll
26
+ end
27
+ end
28
+
29
+ describe '.pre_install' do
30
+ before do
31
+ @pre_install = lambda {}
32
+ Yuyi::Menu.instance_var :pre_installs, [@pre_install,]
33
+ allow(@pre_install).to receive(:call)
34
+ Yuyi::Menu.pre_install
35
+ end
36
+
37
+ after do
38
+ allow(@pre_install).to receive(:call).and_call_original
39
+ end
40
+
41
+ it 'should run pre_installs' do
42
+ expect(@pre_install).to have_received(:call)
43
+ end
44
+ end
45
+
46
+ describe '.post_install' do
47
+ before do
48
+ @post_install = lambda {}
49
+ Yuyi::Menu.instance_var :post_installs, [@post_install,]
50
+ allow(@post_install).to receive(:call)
51
+ Yuyi::Menu.post_install
52
+ end
53
+
54
+ after do
55
+ allow(@post_install).to receive(:call).and_call_original
56
+ end
57
+
58
+ it 'should run post_installs' do
59
+ expect(@post_install).to have_received(:call)
60
+ end
61
+ end
62
+
63
+ describe '#initialize' do
64
+ it 'should set the path var' do
65
+ expect(@menu.var(:path)).to eq 'spec/fixtures/menu.yaml'
66
+ end
67
+
68
+ it 'should set the instance on the menu class' do
69
+ expect(Yuyi::Menu.instance).to eq @menu
70
+ end
71
+
72
+ it 'should set the object var' do
73
+ expect(Yuyi::Menu.instance_var(:object)[:sources][0]).to eq({ :local => 'spec/fixtures/roll_dir' })
74
+ expect(Yuyi::Menu.instance_var(:object)[:sources][1]).to eq({ :yuyi => 'spec/fixtures/roll_zip.zip' })
75
+ expect(Yuyi::Menu.instance_var(:object)[:rolls][:foo_roll]).to eq({ :foo => 'bar' })
76
+ end
77
+
78
+ context 'with an invalid path' do
79
+ before do
80
+ @menu = Yuyi::Menu.new 'foo'
81
+ end
82
+
83
+ it 'should not update menu state' do
84
+ expect(Yuyi::Menu).to_not eq @menu
85
+ end
86
+
87
+ it 'should have a nil object' do
88
+ expect(Yuyi::Menu.instance_var(:object)).to be_nil
89
+ end
90
+ end
91
+ end
92
+
93
+ describe '#set_sources' do
94
+ before do
95
+ Yuyi::Menu.instance_var :object, { :sources => [{ :foo_source => 'foo/path' }]}
96
+
97
+ class FooSource; end
98
+ allow(Yuyi::Source).to receive(:new).and_return FooSource
99
+
100
+ @menu.send :set_sources
101
+ end
102
+
103
+ it 'should set the sources var' do
104
+ expect(@menu.var(:sources).size).to eq(1)
105
+ expect(@menu.var(:sources)[0]).to eq FooSource
106
+ end
107
+ end
108
+
109
+ describe '#find_roll' do
110
+ before do
111
+ allow(@menu).to receive :require_roll
112
+ end
113
+
114
+ context 'when a source is specified' do
115
+ before do
116
+ @menu.send :find_roll, :foo_roll, { :source => 'foo_source' }
117
+ end
118
+
119
+ it 'should require the specific roll' do
120
+ expect(@menu).to have_received(:require_roll).once.with(:foo_roll, 'foo_source/foo_roll')
121
+ end
122
+ end
123
+
124
+ context 'when no source is specified' do
125
+ before do
126
+ class TestSourceA; end
127
+ class TestSourceB; end
128
+ allow(TestSourceA).to receive(:available_rolls).and_return({ :foo_roll => 'foo_roll' })
129
+ allow(TestSourceB).to receive(:available_rolls).and_return({ :bar_roll => 'bar_roll' })
130
+
131
+ @menu.var :sources, [TestSourceA, TestSourceB]
132
+ end
133
+
134
+ it 'should require the first roll found' do
135
+ expect(@menu).to receive(:require_roll).once.with(:bar_roll, 'bar_roll')
136
+ @menu.send :find_roll, :bar_roll
137
+ end
138
+ end
139
+
140
+ context 'when no roll is found' do
141
+ before do
142
+ class TestSource; end
143
+ allow(TestSource).to receive(:available_rolls).and_return({})
144
+
145
+ @menu.var :sources, [TestSource]
146
+ end
147
+
148
+ it 'should not attempt to require a roll' do
149
+ expect(@menu).to_not receive(:require_roll)
150
+ @menu.send :find_roll, :no_roll
151
+ end
152
+ end
153
+ end
154
+
155
+ describe '#on_the_menu?' do
156
+ before do
157
+ allow(@menu).to receive(:object).and_return({ :rolls => { :foo => nil }})
158
+ end
159
+
160
+ it 'should return true if on the menu' do
161
+ expect(@menu.on_the_menu?(:foo)).to be true
162
+ end
163
+ end
164
+
165
+ describe '#sorted_rolls' do
166
+ before do
167
+ class DependencyRoll
168
+ def dependencies; ['foo', 'bar']; end
169
+ end
170
+ class EmptyDependencyRoll
171
+ def dependencies; []; end
172
+ end
173
+ allow(@menu).to receive(:rolls).and_return({ :dependency_roll => DependencyRoll.new, :foo => EmptyDependencyRoll.new, :bar => EmptyDependencyRoll.new })
174
+ end
175
+
176
+ it 'should add the roll to the class var' do
177
+ expect(@menu.send(:sorted_rolls).sort_by { |sym| sym.to_s }).to eq([:bar, :dependency_roll, :foo])
178
+ end
179
+ end
180
+
181
+ describe '#order_rolls' do
182
+ before do
183
+ class MenuOrderRollsRoll; end
184
+ allow(MenuOrderRollsRoll).to receive :order
185
+
186
+ allow(Yuyi::Menu).to receive(:pre_install)
187
+ allow(Yuyi::Menu).to receive(:post_install)
188
+ allow(@menu).to receive(:sorted_rolls).and_return([:order_rolls_roll])
189
+ allow(@menu).to receive(:rolls).and_return({ :order_rolls_roll => MenuOrderRollsRoll })
190
+
191
+ @menu.send :order_rolls
192
+ end
193
+
194
+ after do
195
+ allow(Yuyi::Menu).to receive(:pre_install).and_call_original
196
+ allow(Yuyi::Menu).to receive(:post_install).and_call_original
197
+ allow(@menu).to receive(:sorted_rolls).and_call_original
198
+ allow(@menu).to receive(:rolls).and_call_original
199
+ end
200
+
201
+ it 'should initialize a roll with the roll options' do
202
+ expect(Yuyi::Menu).to have_received(:pre_install).ordered
203
+ expect(MenuOrderRollsRoll).to have_received(:order).ordered
204
+ expect(Yuyi::Menu).to have_received(:post_install).ordered
205
+ end
206
+ end
207
+ end