thor 0.14.6 → 0.15.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.
- data/.autotest +8 -0
- data/.document +5 -0
- data/.gemtest +0 -0
- data/.gitignore +44 -0
- data/.rspec +2 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.rdoc +4 -4
- data/Gemfile +19 -0
- data/{LICENSE → LICENSE.md} +2 -2
- data/README.md +21 -300
- data/Thorfile +21 -15
- data/lib/thor.rb +56 -11
- data/lib/thor/actions.rb +7 -3
- data/lib/thor/actions/create_link.rb +1 -1
- data/lib/thor/actions/directory.rb +7 -3
- data/lib/thor/actions/empty_directory.rb +24 -5
- data/lib/thor/actions/file_manipulation.rb +40 -2
- data/lib/thor/base.rb +66 -28
- data/lib/thor/error.rb +6 -1
- data/lib/thor/group.rb +20 -8
- data/lib/thor/invocation.rb +4 -2
- data/lib/thor/parser/arguments.rb +6 -2
- data/lib/thor/parser/option.rb +3 -2
- data/lib/thor/parser/options.rb +13 -8
- data/lib/thor/rake_compat.rb +13 -8
- data/lib/thor/runner.rb +16 -4
- data/lib/thor/shell.rb +2 -2
- data/lib/thor/shell/basic.rb +86 -29
- data/lib/thor/shell/color.rb +40 -4
- data/lib/thor/shell/html.rb +28 -26
- data/lib/thor/task.rb +26 -8
- data/lib/thor/util.rb +26 -7
- data/lib/thor/version.rb +1 -1
- data/spec/actions/create_link_spec.rb +81 -0
- data/spec/actions/empty_directory_spec.rb +32 -0
- data/spec/actions/file_manipulation_spec.rb +61 -1
- data/spec/actions_spec.rb +4 -0
- data/spec/base_spec.rb +10 -5
- data/spec/exit_condition_spec.rb +19 -0
- data/spec/fixtures/script.thor +8 -2
- data/spec/group_spec.rb +39 -1
- data/spec/parser/arguments_spec.rb +1 -0
- data/spec/parser/options_spec.rb +12 -2
- data/spec/rake_compat_spec.rb +11 -7
- data/spec/register_spec.rb +43 -0
- data/spec/runner_spec.rb +34 -3
- data/spec/shell/basic_spec.rb +50 -3
- data/spec/shell/color_spec.rb +46 -6
- data/spec/shell/html_spec.rb +10 -5
- data/spec/spec_helper.rb +4 -0
- data/spec/task_spec.rb +26 -16
- data/spec/thor_spec.rb +56 -3
- data/thor.gemspec +26 -0
- metadata +174 -117
data/spec/actions_spec.rb
CHANGED
@@ -82,6 +82,10 @@ describe Thor::Actions do
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
|
+
it "creates proper relative paths for absolute file location" do
|
86
|
+
runner.relative_to_original_destination_root('/test/file').should == "/test/file"
|
87
|
+
end
|
88
|
+
|
85
89
|
describe "#source_paths_for_search" do
|
86
90
|
it "add source_root to source_paths_for_search" do
|
87
91
|
MyCounter.source_paths_for_search.should include(File.expand_path("fixtures", File.dirname(__FILE__)))
|
data/spec/base_spec.rb
CHANGED
@@ -227,10 +227,15 @@ describe Thor::Base do
|
|
227
227
|
end
|
228
228
|
|
229
229
|
describe "#start" do
|
230
|
-
it "raises an error instead of rescueing if
|
231
|
-
|
232
|
-
|
233
|
-
|
230
|
+
it "raises an error instead of rescueing if THOR_DEBUG=1 is given" do
|
231
|
+
begin
|
232
|
+
ENV["THOR_DEBUG"] = 1
|
233
|
+
lambda {
|
234
|
+
MyScript.start ["what", "--debug"]
|
235
|
+
}.should raise_error(Thor::UndefinedTaskError, 'Could not find task "what" in "my_script" namespace.')
|
236
|
+
rescue
|
237
|
+
ENV["THOR_DEBUG"] = nil
|
238
|
+
end
|
234
239
|
end
|
235
240
|
|
236
241
|
it "does not steal args" do
|
@@ -247,7 +252,7 @@ describe Thor::Base do
|
|
247
252
|
|
248
253
|
it "checks unknown options except specified" do
|
249
254
|
capture(:stderr) {
|
250
|
-
MyScript.start(["with_optional", "NAME", "--omg", "--invalid"]).should == ["NAME", {}]
|
255
|
+
MyScript.start(["with_optional", "NAME", "--omg", "--invalid"]).should == ["NAME", {}, ["--omg", "--invalid"]]
|
251
256
|
}.strip.should be_empty
|
252
257
|
end
|
253
258
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require 'thor/base'
|
3
|
+
|
4
|
+
describe "Exit conditions" do
|
5
|
+
it "should exit 0, not bubble up EPIPE, if EPIPE is raised" do
|
6
|
+
epiped = false
|
7
|
+
|
8
|
+
task = Class.new(Thor) do
|
9
|
+
desc "my_action", "testing EPIPE"
|
10
|
+
define_method :my_action do
|
11
|
+
epiped = true
|
12
|
+
raise Errno::EPIPE
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
lambda { task.start(["my_action"]) }.should raise_error(SystemExit)
|
17
|
+
epiped.should == true
|
18
|
+
end
|
19
|
+
end
|
data/spec/fixtures/script.thor
CHANGED
@@ -10,6 +10,8 @@ class MyScript < Thor
|
|
10
10
|
|
11
11
|
map "-T" => :animal, ["-f", "--foo"] => :foo
|
12
12
|
|
13
|
+
map "animal_prison" => "zoo"
|
14
|
+
|
13
15
|
desc "zoo", "zoo around"
|
14
16
|
def zoo
|
15
17
|
true
|
@@ -26,11 +28,15 @@ class MyScript < Thor
|
|
26
28
|
[type]
|
27
29
|
end
|
28
30
|
|
31
|
+
map "hid" => "hidden"
|
32
|
+
|
29
33
|
desc "hidden TYPE", "this is hidden", :hide => true
|
30
34
|
def hidden(type)
|
31
35
|
[type]
|
32
36
|
end
|
33
37
|
|
38
|
+
map "fu" => "zoo"
|
39
|
+
|
34
40
|
desc "foo BAR", <<END
|
35
41
|
do some fooing
|
36
42
|
This is more info!
|
@@ -77,8 +83,8 @@ END
|
|
77
83
|
method_option :lazy_array, :type => :array, :lazy_default => %w[eat at joes]
|
78
84
|
method_option :lazy_hash, :type => :hash, :lazy_default => {'swedish' => 'meatballs'}
|
79
85
|
desc "with_optional NAME", "invoke with optional name"
|
80
|
-
def with_optional(name=nil)
|
81
|
-
[ name, options ]
|
86
|
+
def with_optional(name=nil, *args)
|
87
|
+
[ name, options, args ]
|
82
88
|
end
|
83
89
|
|
84
90
|
class AnotherScript < Thor
|
data/spec/group_spec.rb
CHANGED
@@ -32,7 +32,7 @@ describe Thor::Group do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
it "raises an error when a Thor group task expects arguments" do
|
35
|
-
lambda { WhinyGenerator.start }.should raise_error(ArgumentError, /
|
35
|
+
lambda { WhinyGenerator.start }.should raise_error(ArgumentError, /thor wrong_arity takes 1 argument, but it should not/)
|
36
36
|
end
|
37
37
|
|
38
38
|
it "invokes help message if any of the shortcuts is given" do
|
@@ -175,4 +175,42 @@ describe Thor::Group do
|
|
175
175
|
end
|
176
176
|
end
|
177
177
|
end
|
178
|
+
|
179
|
+
describe "edge-cases" do
|
180
|
+
it "can handle boolean options followed by arguments" do
|
181
|
+
klass = Class.new(Thor::Group) do
|
182
|
+
desc "say hi to name"
|
183
|
+
argument :name, :type => :string
|
184
|
+
class_option :loud, :type => :boolean
|
185
|
+
|
186
|
+
def hi
|
187
|
+
name.upcase! if options[:loud]
|
188
|
+
"Hi #{name}"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
klass.start(["jose"]).should == ["Hi jose"]
|
193
|
+
klass.start(["jose", "--loud"]).should == ["Hi JOSE"]
|
194
|
+
klass.start(["--loud", "jose"]).should == ["Hi JOSE"]
|
195
|
+
end
|
196
|
+
|
197
|
+
it "provides extra args as `args`" do
|
198
|
+
klass = Class.new(Thor::Group) do
|
199
|
+
desc "say hi to name"
|
200
|
+
argument :name, :type => :string
|
201
|
+
class_option :loud, :type => :boolean
|
202
|
+
|
203
|
+
def hi
|
204
|
+
name.upcase! if options[:loud]
|
205
|
+
out = "Hi #{name}"
|
206
|
+
out << ": " << args.join(", ") unless args.empty?
|
207
|
+
out
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
klass.start(["jose"]).should == ["Hi jose"]
|
212
|
+
klass.start(["jose", "--loud"]).should == ["Hi JOSE"]
|
213
|
+
klass.start(["--loud", "jose"]).should == ["Hi JOSE"]
|
214
|
+
end
|
215
|
+
end
|
178
216
|
end
|
@@ -26,6 +26,7 @@ describe Thor::Arguments do
|
|
26
26
|
create :string => nil, :hash => nil
|
27
27
|
parse("product", "title:string", "age:integer")["string"].should == "product"
|
28
28
|
parse("product", "title:string", "age:integer")["hash"].should == { "title" => "string", "age" => "integer"}
|
29
|
+
parse("product", "url:http://www.amazon.com/gp/product/123")["hash"].should == { "url" => "http://www.amazon.com/gp/product/123" }
|
29
30
|
end
|
30
31
|
|
31
32
|
it "accepts arrays" do
|
data/spec/parser/options_spec.rb
CHANGED
@@ -121,13 +121,13 @@ describe Thor::Options do
|
|
121
121
|
check_unknown!
|
122
122
|
end
|
123
123
|
|
124
|
-
it "
|
124
|
+
it "accepts underscores in commandline args hash for boolean" do
|
125
125
|
create :foo_bar => :boolean
|
126
126
|
parse("--foo_bar")["foo_bar"].should == true
|
127
127
|
parse("--no_foo_bar")["foo_bar"].should == false
|
128
128
|
end
|
129
129
|
|
130
|
-
it "
|
130
|
+
it "accepts underscores in commandline args hash for strings" do
|
131
131
|
create :foo_bar => :string, :baz_foo => :string
|
132
132
|
parse("--foo_bar", "baz")["foo_bar"].should == "baz"
|
133
133
|
parse("--baz_foo", "foo bar")["baz_foo"].should == "foo bar"
|
@@ -229,6 +229,10 @@ describe Thor::Options do
|
|
229
229
|
parse("--foo", "--bar")["foo"].should == true
|
230
230
|
end
|
231
231
|
|
232
|
+
it "uses the default value if no switch is given" do
|
233
|
+
parse("")["foo"].should == false
|
234
|
+
end
|
235
|
+
|
232
236
|
it "accepts --opt=value assignment" do
|
233
237
|
parse("--foo=true")["foo"].should == true
|
234
238
|
parse("--foo=false")["foo"].should == false
|
@@ -258,6 +262,12 @@ describe Thor::Options do
|
|
258
262
|
parse("--no-foo-bar")["foo_bar"].should == false
|
259
263
|
parse("--skip-foo-bar")["foo_bar"].should == false
|
260
264
|
end
|
265
|
+
|
266
|
+
it "doesn't eat the next part of the param" do
|
267
|
+
create :foo => :boolean
|
268
|
+
parse("--foo", "bar").should == {"foo" => true}
|
269
|
+
@opt.remaining.should == ["bar"]
|
270
|
+
end
|
261
271
|
end
|
262
272
|
|
263
273
|
describe "with :hash type" do
|
data/spec/rake_compat_spec.rb
CHANGED
@@ -2,20 +2,24 @@ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
2
|
require 'thor/rake_compat'
|
3
3
|
require 'rake/tasklib'
|
4
4
|
|
5
|
+
$main = self
|
6
|
+
|
5
7
|
class RakeTask < Rake::TaskLib
|
6
8
|
def initialize
|
7
9
|
define
|
8
10
|
end
|
9
11
|
|
10
12
|
def define
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
$main.instance_eval do
|
14
|
+
desc "Say it's cool"
|
15
|
+
task :cool do
|
16
|
+
puts "COOL"
|
17
|
+
end
|
15
18
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
+
namespace :hiper_mega do
|
20
|
+
task :super do
|
21
|
+
puts "HIPER MEGA SUPER"
|
22
|
+
end
|
19
23
|
end
|
20
24
|
end
|
21
25
|
end
|
data/spec/register_spec.rb
CHANGED
@@ -40,6 +40,19 @@ class GroupPlugin < Thor::Group
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
class ClassOptionGroupPlugin < Thor::Group
|
44
|
+
class_option :who,
|
45
|
+
:type => :string,
|
46
|
+
:aliases => "-w",
|
47
|
+
:default => "zebra"
|
48
|
+
end
|
49
|
+
|
50
|
+
class CompatibleWith19Plugin < ClassOptionGroupPlugin
|
51
|
+
desc "animal"
|
52
|
+
def animal
|
53
|
+
p options[:who]
|
54
|
+
end
|
55
|
+
end
|
43
56
|
|
44
57
|
BoringVendorProvidedCLI.register(
|
45
58
|
ExcitingPluginCLI,
|
@@ -60,6 +73,12 @@ BoringVendorProvidedCLI.register(
|
|
60
73
|
"Do a bunch of things in a row",
|
61
74
|
"purple monkey dishwasher")
|
62
75
|
|
76
|
+
BoringVendorProvidedCLI.register(
|
77
|
+
CompatibleWith19Plugin,
|
78
|
+
'zoo',
|
79
|
+
"zoo [-w animal]",
|
80
|
+
"Shows a provided animal or just zebra")
|
81
|
+
|
63
82
|
describe ".register-ing a Thor subclass" do
|
64
83
|
it "registers the plugin as a subcommand" do
|
65
84
|
fireworks_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[exciting fireworks]) }
|
@@ -71,6 +90,18 @@ describe ".register-ing a Thor subclass" do
|
|
71
90
|
help_output.should include('do exciting things')
|
72
91
|
end
|
73
92
|
|
93
|
+
context "when $thor_runner is false" do
|
94
|
+
it "includes the plugin's subcommand name in subcommand's help" do
|
95
|
+
begin
|
96
|
+
$thor_runner = false
|
97
|
+
help_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[exciting]) }
|
98
|
+
help_output.should include('thor exciting_plugin_c_l_i fireworks')
|
99
|
+
ensure
|
100
|
+
$thor_runner = true
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
74
105
|
context "when hidden" do
|
75
106
|
it "omits the hidden plugin's usage from the help" do
|
76
107
|
help_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[help]) }
|
@@ -90,3 +121,15 @@ describe ".register-ing a Thor::Group subclass" do
|
|
90
121
|
group_output.should == "part one\npart two\n"
|
91
122
|
end
|
92
123
|
end
|
124
|
+
|
125
|
+
describe "1.8 and 1.9 syntax compatibility" do
|
126
|
+
it "is compatible with both 1.8 and 1.9 syntax w/o task options" do
|
127
|
+
group_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[zoo]) }
|
128
|
+
group_output.should match /zebra/
|
129
|
+
end
|
130
|
+
|
131
|
+
it "is compatible with both 1.8 and 1.9 syntax w/task options" do
|
132
|
+
group_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[zoo -w lion]) }
|
133
|
+
group_output.should match /lion/
|
134
|
+
end
|
135
|
+
end
|
data/spec/runner_spec.rb
CHANGED
@@ -2,6 +2,16 @@ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
|
|
2
2
|
require 'thor/runner'
|
3
3
|
|
4
4
|
describe Thor::Runner do
|
5
|
+
def when_no_thorfiles_exist
|
6
|
+
old_dir = Dir.pwd
|
7
|
+
Dir.chdir '..'
|
8
|
+
delete = Thor::Base.subclasses.select {|e| e.namespace == 'default' }
|
9
|
+
delete.each {|e| Thor::Base.subclasses.delete e }
|
10
|
+
yield
|
11
|
+
Thor::Base.subclasses.concat delete
|
12
|
+
Dir.chdir old_dir
|
13
|
+
end
|
14
|
+
|
5
15
|
describe "#help" do
|
6
16
|
it "shows information about Thor::Runner itself" do
|
7
17
|
capture(:stdout){ Thor::Runner.start(["help"]) }.should =~ /List the available thor tasks/
|
@@ -33,6 +43,14 @@ describe Thor::Runner do
|
|
33
43
|
content = capture(:stderr){ Thor::Runner.start(["help", "unknown"]) }
|
34
44
|
content.strip.should == 'Could not find task "unknown" in "default" namespace.'
|
35
45
|
end
|
46
|
+
|
47
|
+
it "raises error if a class/task cannot be found for a setup without thorfiles" do
|
48
|
+
when_no_thorfiles_exist do
|
49
|
+
Thor::Runner.should_receive :exit
|
50
|
+
content = capture(:stderr){ Thor::Runner.start(["help", "unknown"]) }
|
51
|
+
content.strip.should == 'Could not find task "unknown".'
|
52
|
+
end
|
53
|
+
end
|
36
54
|
end
|
37
55
|
|
38
56
|
describe "#start" do
|
@@ -72,6 +90,15 @@ describe Thor::Runner do
|
|
72
90
|
content.strip.should == 'Could not find task "unknown" in "default" namespace.'
|
73
91
|
end
|
74
92
|
|
93
|
+
it "raises an error if class/task can't be found in a setup without thorfiles" do
|
94
|
+
when_no_thorfiles_exist do
|
95
|
+
ARGV.replace ["unknown"]
|
96
|
+
Thor::Runner.should_receive :exit
|
97
|
+
content = capture(:stderr){ Thor::Runner.start }
|
98
|
+
content.strip.should == 'Could not find task "unknown".'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
75
102
|
it "does not swallow NoMethodErrors that occur inside the called method" do
|
76
103
|
ARGV.replace ["my_script:call_unexistent_method"]
|
77
104
|
lambda { Thor::Runner.start }.should raise_error(NoMethodError)
|
@@ -79,13 +106,13 @@ describe Thor::Runner do
|
|
79
106
|
|
80
107
|
it "does not swallow Thor::Group InvocationError" do
|
81
108
|
ARGV.replace ["whiny_generator"]
|
82
|
-
lambda { Thor::Runner.start }.should raise_error(ArgumentError, /
|
109
|
+
lambda { Thor::Runner.start }.should raise_error(ArgumentError, /thor wrong_arity takes 1 argument, but it should not/)
|
83
110
|
end
|
84
111
|
|
85
112
|
it "does not swallow Thor InvocationError" do
|
86
113
|
ARGV.replace ["my_script:animal"]
|
87
114
|
content = capture(:stderr) { Thor::Runner.start }
|
88
|
-
content.strip.should == '
|
115
|
+
content.strip.should == 'thor animal requires at least 1 argument: "thor my_script:animal TYPE".'
|
89
116
|
end
|
90
117
|
end
|
91
118
|
|
@@ -197,7 +224,11 @@ describe Thor::Runner do
|
|
197
224
|
|
198
225
|
it "updates existing thor files" do
|
199
226
|
path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
|
200
|
-
File.
|
227
|
+
if File.directory? path
|
228
|
+
FileUtils.should_receive(:rm_rf).with(path)
|
229
|
+
else
|
230
|
+
File.should_receive(:delete).with(path)
|
231
|
+
end
|
201
232
|
silence(:stdout) { Thor::Runner.start(["update", "random"]) }
|
202
233
|
end
|
203
234
|
|
data/spec/shell/basic_spec.rb
CHANGED
@@ -21,6 +21,19 @@ describe Thor::Shell::Basic do
|
|
21
21
|
$stdin.should_receive(:gets).and_return('Sure')
|
22
22
|
shell.ask("Should I overwrite it?").should == "Sure"
|
23
23
|
end
|
24
|
+
|
25
|
+
it "prints a message to the user with the available options and determines the correctness of the answer" do
|
26
|
+
$stdout.should_receive(:print).with('What\'s your favorite Neopolitan flavor? ["strawberry", "chocolate", "vanilla"] ')
|
27
|
+
$stdin.should_receive(:gets).and_return('chocolate')
|
28
|
+
shell.ask("What's your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"]).should == "chocolate"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "prints a message to the user with the available options and reasks the question after an incorrect repsonse" do
|
32
|
+
$stdout.should_receive(:print).with('What\'s your favorite Neopolitan flavor? ["strawberry", "chocolate", "vanilla"] ').twice
|
33
|
+
$stdout.should_receive(:puts).with('Your response must be one of: ["strawberry", "chocolate", "vanilla"]. Please try again.')
|
34
|
+
$stdin.should_receive(:gets).and_return('moose tracks', 'chocolate')
|
35
|
+
shell.ask("What's your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"]).should == "chocolate"
|
36
|
+
end
|
24
37
|
end
|
25
38
|
|
26
39
|
describe "#yes?" do
|
@@ -122,8 +135,8 @@ xyz #786 last three
|
|
122
135
|
TABLE
|
123
136
|
end
|
124
137
|
|
125
|
-
it "prints a table with
|
126
|
-
content = capture(:stdout){ shell.print_table(@table, :
|
138
|
+
it "prints a table with indentation" do
|
139
|
+
content = capture(:stdout){ shell.print_table(@table, :indent => 2) }
|
127
140
|
content.should == <<-TABLE
|
128
141
|
abc #123 first three
|
129
142
|
#0 empty
|
@@ -133,7 +146,7 @@ TABLE
|
|
133
146
|
|
134
147
|
it "uses maximum terminal width" do
|
135
148
|
shell.should_receive(:terminal_width).and_return(20)
|
136
|
-
content = capture(:stdout){ shell.print_table(@table, :
|
149
|
+
content = capture(:stdout){ shell.print_table(@table, :indent => 2, :truncate => true) }
|
137
150
|
content.should == <<-TABLE
|
138
151
|
abc #123 firs...
|
139
152
|
#0 empty
|
@@ -147,6 +160,40 @@ TABLE
|
|
147
160
|
abc #123 first three
|
148
161
|
#0 empty
|
149
162
|
xyz #786 last three
|
163
|
+
TABLE
|
164
|
+
end
|
165
|
+
|
166
|
+
it "prints tables with implicit columns" do
|
167
|
+
2.times { @table.first.pop }
|
168
|
+
content = capture(:stdout){ shell.print_table(@table) }
|
169
|
+
content.should == <<-TABLE
|
170
|
+
abc
|
171
|
+
#0 empty
|
172
|
+
xyz #786 last three
|
173
|
+
TABLE
|
174
|
+
end
|
175
|
+
|
176
|
+
it "prints a table with small numbers, and right-aligns them" do
|
177
|
+
table = [
|
178
|
+
["Name", "Number", "Color"],
|
179
|
+
["Erik", 1, "green"]
|
180
|
+
]
|
181
|
+
content = capture(:stdout){ shell.print_table(table) }
|
182
|
+
content.should == <<-TABLE
|
183
|
+
Name Number Color
|
184
|
+
Erik 1 green
|
185
|
+
TABLE
|
186
|
+
end
|
187
|
+
|
188
|
+
it "prints a table with big numbers" do
|
189
|
+
table = [
|
190
|
+
["Name", "Number", "Color"],
|
191
|
+
["Erik", 1234567890123, "green"]
|
192
|
+
]
|
193
|
+
content = capture(:stdout){ shell.print_table(table) }
|
194
|
+
content.should == <<-TABLE
|
195
|
+
Name Number Color
|
196
|
+
Erik 1234567890123 green
|
150
197
|
TABLE
|
151
198
|
end
|
152
199
|
end
|