millisami-thor 0.14.6

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.
Files changed (82) hide show
  1. data/.autotest +8 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +1 -0
  5. data/CHANGELOG.rdoc +103 -0
  6. data/Gemfile +11 -0
  7. data/LICENSE.md +20 -0
  8. data/README.md +26 -0
  9. data/Thorfile +13 -0
  10. data/bin/rake2thor +86 -0
  11. data/bin/thor +6 -0
  12. data/lib/thor/actions/create_file.rb +105 -0
  13. data/lib/thor/actions/create_link.rb +57 -0
  14. data/lib/thor/actions/directory.rb +93 -0
  15. data/lib/thor/actions/empty_directory.rb +134 -0
  16. data/lib/thor/actions/file_manipulation.rb +270 -0
  17. data/lib/thor/actions/inject_into_file.rb +109 -0
  18. data/lib/thor/actions.rb +314 -0
  19. data/lib/thor/base.rb +598 -0
  20. data/lib/thor/core_ext/file_binary_read.rb +9 -0
  21. data/lib/thor/core_ext/hash_with_indifferent_access.rb +75 -0
  22. data/lib/thor/core_ext/ordered_hash.rb +100 -0
  23. data/lib/thor/error.rb +30 -0
  24. data/lib/thor/group.rb +276 -0
  25. data/lib/thor/invocation.rb +168 -0
  26. data/lib/thor/parser/argument.rb +67 -0
  27. data/lib/thor/parser/arguments.rb +165 -0
  28. data/lib/thor/parser/option.rb +120 -0
  29. data/lib/thor/parser/options.rb +181 -0
  30. data/lib/thor/parser.rb +4 -0
  31. data/lib/thor/rake_compat.rb +70 -0
  32. data/lib/thor/runner.rb +309 -0
  33. data/lib/thor/shell/basic.rb +302 -0
  34. data/lib/thor/shell/color.rb +108 -0
  35. data/lib/thor/shell/html.rb +121 -0
  36. data/lib/thor/shell.rb +88 -0
  37. data/lib/thor/task.rb +129 -0
  38. data/lib/thor/util.rb +229 -0
  39. data/lib/thor/version.rb +3 -0
  40. data/lib/thor.rb +336 -0
  41. data/spec/actions/create_file_spec.rb +170 -0
  42. data/spec/actions/directory_spec.rb +136 -0
  43. data/spec/actions/empty_directory_spec.rb +98 -0
  44. data/spec/actions/file_manipulation_spec.rb +317 -0
  45. data/spec/actions/inject_into_file_spec.rb +135 -0
  46. data/spec/actions_spec.rb +322 -0
  47. data/spec/base_spec.rb +274 -0
  48. data/spec/core_ext/hash_with_indifferent_access_spec.rb +43 -0
  49. data/spec/core_ext/ordered_hash_spec.rb +115 -0
  50. data/spec/fixtures/application.rb +2 -0
  51. data/spec/fixtures/bundle/execute.rb +6 -0
  52. data/spec/fixtures/bundle/main.thor +1 -0
  53. data/spec/fixtures/doc/%file_name%.rb.tt +1 -0
  54. data/spec/fixtures/doc/README +3 -0
  55. data/spec/fixtures/doc/block_helper.rb +3 -0
  56. data/spec/fixtures/doc/components/.empty_directory +0 -0
  57. data/spec/fixtures/doc/config.rb +1 -0
  58. data/spec/fixtures/doc/config.yaml.tt +1 -0
  59. data/spec/fixtures/group.thor +114 -0
  60. data/spec/fixtures/invoke.thor +112 -0
  61. data/spec/fixtures/path with spaces +0 -0
  62. data/spec/fixtures/script.thor +184 -0
  63. data/spec/fixtures/task.thor +10 -0
  64. data/spec/group_spec.rb +216 -0
  65. data/spec/invocation_spec.rb +100 -0
  66. data/spec/parser/argument_spec.rb +47 -0
  67. data/spec/parser/arguments_spec.rb +65 -0
  68. data/spec/parser/option_spec.rb +202 -0
  69. data/spec/parser/options_spec.rb +329 -0
  70. data/spec/rake_compat_spec.rb +72 -0
  71. data/spec/register_spec.rb +92 -0
  72. data/spec/runner_spec.rb +210 -0
  73. data/spec/shell/basic_spec.rb +223 -0
  74. data/spec/shell/color_spec.rb +41 -0
  75. data/spec/shell/html_spec.rb +27 -0
  76. data/spec/shell_spec.rb +47 -0
  77. data/spec/spec_helper.rb +54 -0
  78. data/spec/task_spec.rb +74 -0
  79. data/spec/thor_spec.rb +362 -0
  80. data/spec/util_spec.rb +163 -0
  81. data/thor.gemspec +25 -0
  82. metadata +241 -0
@@ -0,0 +1,210 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
+ require 'thor/runner'
3
+
4
+ describe Thor::Runner do
5
+ describe "#help" do
6
+ it "shows information about Thor::Runner itself" do
7
+ capture(:stdout){ Thor::Runner.start(["help"]) }.should =~ /List the available thor tasks/
8
+ end
9
+
10
+ it "shows information about an specific Thor::Runner task" do
11
+ content = capture(:stdout){ Thor::Runner.start(["help", "list"]) }
12
+ content.should =~ /List the available thor tasks/
13
+ content.should_not =~ /help \[TASK\]/
14
+ end
15
+
16
+ it "shows information about a specific Thor class" do
17
+ content = capture(:stdout){ Thor::Runner.start(["help", "my_script"]) }
18
+ content.should =~ /zoo\s+# zoo around/m
19
+ end
20
+
21
+ it "shows information about an specific task from an specific Thor class" do
22
+ content = capture(:stdout){ Thor::Runner.start(["help", "my_script:zoo"]) }
23
+ content.should =~ /zoo around/
24
+ content.should_not =~ /help \[TASK\]/
25
+ end
26
+
27
+ it "shows information about a specific Thor group class" do
28
+ content = capture(:stdout){ Thor::Runner.start(["help", "my_counter"]) }
29
+ content.should =~ /my_counter N/
30
+ end
31
+
32
+ it "raises error if a class/task cannot be found" do
33
+ content = capture(:stderr){ Thor::Runner.start(["help", "unknown"]) }
34
+ content.strip.should == 'Could not find task "unknown" in "default" namespace.'
35
+ end
36
+ end
37
+
38
+ describe "#start" do
39
+ it "invokes a task from Thor::Runner" do
40
+ ARGV.replace ["list"]
41
+ capture(:stdout){ Thor::Runner.start }.should =~ /my_counter N/
42
+ end
43
+
44
+ it "invokes a task from a specific Thor class" do
45
+ ARGV.replace ["my_script:zoo"]
46
+ Thor::Runner.start.should be_true
47
+ end
48
+
49
+ it "invokes the default task from a specific Thor class if none is specified" do
50
+ ARGV.replace ["my_script"]
51
+ Thor::Runner.start.should == "default task"
52
+ end
53
+
54
+ it "forwads arguments to the invoked task" do
55
+ ARGV.replace ["my_script:animal", "horse"]
56
+ Thor::Runner.start.should == ["horse"]
57
+ end
58
+
59
+ it "invokes tasks through shortcuts" do
60
+ ARGV.replace ["my_script", "-T", "horse"]
61
+ Thor::Runner.start.should == ["horse"]
62
+ end
63
+
64
+ it "invokes a Thor::Group" do
65
+ ARGV.replace ["my_counter", "1", "2", "--third", "3"]
66
+ Thor::Runner.start.should == [1, 2, 3]
67
+ end
68
+
69
+ it "raises an error if class/task can't be found" do
70
+ ARGV.replace ["unknown"]
71
+ content = capture(:stderr){ Thor::Runner.start }
72
+ content.strip.should == 'Could not find task "unknown" in "default" namespace.'
73
+ end
74
+
75
+ it "does not swallow NoMethodErrors that occur inside the called method" do
76
+ ARGV.replace ["my_script:call_unexistent_method"]
77
+ lambda { Thor::Runner.start }.should raise_error(NoMethodError)
78
+ end
79
+
80
+ it "does not swallow Thor::Group InvocationError" do
81
+ ARGV.replace ["whiny_generator"]
82
+ lambda { Thor::Runner.start }.should raise_error(ArgumentError, /Are you sure it has arity equals to 0\?/)
83
+ end
84
+
85
+ it "does not swallow Thor InvocationError" do
86
+ ARGV.replace ["my_script:animal"]
87
+ content = capture(:stderr) { Thor::Runner.start }
88
+ content.strip.should == '"animal" was called incorrectly. Call as "thor my_script:animal TYPE".'
89
+ end
90
+ end
91
+
92
+ describe "tasks" do
93
+ before(:each) do
94
+ @location = "#{File.dirname(__FILE__)}/fixtures/task.thor"
95
+ @original_yaml = {
96
+ "random" => {
97
+ :location => @location,
98
+ :filename => "4a33b894ffce85d7b412fc1b36f88fe0",
99
+ :namespaces => ["amazing"]
100
+ }
101
+ }
102
+
103
+ root_file = File.join(Thor::Util.thor_root, "thor.yml")
104
+
105
+ # Stub load and save to avoid thor.yaml from being overwritten
106
+ YAML.stub!(:load_file).and_return(@original_yaml)
107
+ File.stub!(:exists?).with(root_file).and_return(true)
108
+ File.stub!(:open).with(root_file, "w")
109
+ end
110
+
111
+ describe "list" do
112
+ it "gives a list of the available tasks" do
113
+ ARGV.replace ["list"]
114
+ content = capture(:stdout) { Thor::Runner.start }
115
+ content.should =~ /amazing:describe NAME\s+# say that someone is amazing/m
116
+ end
117
+
118
+ it "gives a list of the available Thor::Group classes" do
119
+ ARGV.replace ["list"]
120
+ capture(:stdout) { Thor::Runner.start }.should =~ /my_counter N/
121
+ end
122
+
123
+ it "can filter a list of the available tasks by --group" do
124
+ ARGV.replace ["list", "--group", "standard"]
125
+ capture(:stdout) { Thor::Runner.start }.should =~ /amazing:describe NAME/
126
+ ARGV.replace []
127
+ capture(:stdout) { Thor::Runner.start }.should_not =~ /my_script:animal TYPE/
128
+ ARGV.replace ["list", "--group", "script"]
129
+ capture(:stdout) { Thor::Runner.start }.should =~ /my_script:animal TYPE/
130
+ end
131
+
132
+ it "can skip all filters to show all tasks using --all" do
133
+ ARGV.replace ["list", "--all"]
134
+ content = capture(:stdout) { Thor::Runner.start }
135
+ content.should =~ /amazing:describe NAME/
136
+ content.should =~ /my_script:animal TYPE/
137
+ end
138
+
139
+ it "doesn't list superclass tasks in the subclass" do
140
+ ARGV.replace ["list"]
141
+ capture(:stdout) { Thor::Runner.start }.should_not =~ /amazing:help/
142
+ end
143
+
144
+ it "presents tasks in the default namespace with an empty namespace" do
145
+ ARGV.replace ["list"]
146
+ capture(:stdout) { Thor::Runner.start }.should =~ /^thor :cow\s+# prints 'moo'/m
147
+ end
148
+
149
+ it "runs tasks with an empty namespace from the default namespace" do
150
+ ARGV.replace [":task_conflict"]
151
+ capture(:stdout) { Thor::Runner.start }.should == "task\n"
152
+ end
153
+
154
+ it "runs groups even when there is a task with the same name" do
155
+ ARGV.replace ["task_conflict"]
156
+ capture(:stdout) { Thor::Runner.start }.should == "group\n"
157
+ end
158
+
159
+ it "runs tasks with no colon in the default namespace" do
160
+ ARGV.replace ["cow"]
161
+ capture(:stdout) { Thor::Runner.start }.should == "moo\n"
162
+ end
163
+ end
164
+
165
+ describe "uninstall" do
166
+ before(:each) do
167
+ path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
168
+ FileUtils.should_receive(:rm_rf).with(path)
169
+ end
170
+
171
+ it "uninstalls existing thor modules" do
172
+ silence(:stdout) { Thor::Runner.start(["uninstall", "random"]) }
173
+ end
174
+ end
175
+
176
+ describe "installed" do
177
+ before(:each) do
178
+ Dir.should_receive(:[]).and_return([])
179
+ end
180
+
181
+ it "displays the modules installed in a pretty way" do
182
+ stdout = capture(:stdout) { Thor::Runner.start(["installed"]) }
183
+ stdout.should =~ /random\s*amazing/
184
+ stdout.should =~ /amazing:describe NAME\s+# say that someone is amazing/m
185
+ end
186
+ end
187
+
188
+ describe "install/update" do
189
+ before(:each) do
190
+ FileUtils.stub!(:mkdir_p)
191
+ FileUtils.stub!(:touch)
192
+ $stdin.stub!(:gets).and_return("Y")
193
+
194
+ path = File.join(Thor::Util.thor_root, Digest::MD5.hexdigest(@location + "random"))
195
+ File.should_receive(:open).with(path, "w")
196
+ end
197
+
198
+ it "updates existing thor files" do
199
+ path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
200
+ File.should_receive(:delete).with(path)
201
+ silence(:stdout) { Thor::Runner.start(["update", "random"]) }
202
+ end
203
+
204
+ it "installs thor files" do
205
+ ARGV.replace ["install", @location]
206
+ silence(:stdout) { Thor::Runner.start }
207
+ end
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,223 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Thor::Shell::Basic do
4
+ def shell
5
+ @shell ||= Thor::Shell::Basic.new
6
+ end
7
+
8
+ describe "#padding" do
9
+ it "cannot be set to below zero" do
10
+ shell.padding = 10
11
+ shell.padding.should == 10
12
+
13
+ shell.padding = -1
14
+ shell.padding.should == 0
15
+ end
16
+ end
17
+
18
+ describe "#ask" do
19
+ it "prints a message to the user and gets the response" do
20
+ $stdout.should_receive(:print).with("Should I overwrite it? ")
21
+ $stdin.should_receive(:gets).and_return('Sure')
22
+ shell.ask("Should I overwrite it?").should == "Sure"
23
+ end
24
+ end
25
+
26
+ describe "#yes?" do
27
+ it "asks the user and returns true if the user replies yes" do
28
+ $stdout.should_receive(:print).with("Should I overwrite it? ")
29
+ $stdin.should_receive(:gets).and_return('y')
30
+ shell.yes?("Should I overwrite it?").should === true
31
+
32
+ $stdout.should_receive(:print).with("Should I overwrite it? ")
33
+ $stdin.should_receive(:gets).and_return('n')
34
+ shell.yes?("Should I overwrite it?").should_not === true
35
+ end
36
+ end
37
+
38
+ describe "#no?" do
39
+ it "asks the user and returns true if the user replies no" do
40
+ $stdout.should_receive(:print).with("Should I overwrite it? ")
41
+ $stdin.should_receive(:gets).and_return('n')
42
+ shell.no?("Should I overwrite it?").should === true
43
+
44
+ $stdout.should_receive(:print).with("Should I overwrite it? ")
45
+ $stdin.should_receive(:gets).and_return('Yes')
46
+ shell.no?("Should I overwrite it?").should === false
47
+ end
48
+ end
49
+
50
+ describe "#say" do
51
+ it "prints a message to the user" do
52
+ $stdout.should_receive(:puts).with("Running...")
53
+ shell.say("Running...")
54
+ end
55
+
56
+ it "prints a message to the user without new line if it ends with a whitespace" do
57
+ $stdout.should_receive(:print).with("Running... ")
58
+ shell.say("Running... ")
59
+ end
60
+
61
+ it "prints a message to the user without new line" do
62
+ $stdout.should_receive(:print).with("Running...")
63
+ shell.say("Running...", nil, false)
64
+ end
65
+ end
66
+
67
+ describe "#say_status" do
68
+ it "prints a message to the user with status" do
69
+ $stdout.should_receive(:puts).with(" create ~/.thor/task.thor")
70
+ shell.say_status(:create, "~/.thor/task.thor")
71
+ end
72
+
73
+ it "always use new line" do
74
+ $stdout.should_receive(:puts).with(" create ")
75
+ shell.say_status(:create, "")
76
+ end
77
+
78
+ it "does not print a message if base is muted" do
79
+ shell.should_receive(:mute?).and_return(true)
80
+ $stdout.should_not_receive(:puts)
81
+
82
+ shell.mute do
83
+ shell.say_status(:created, "~/.thor/task.thor")
84
+ end
85
+ end
86
+
87
+ it "does not print a message if base is set to quiet" do
88
+ base = MyCounter.new [1,2]
89
+ base.should_receive(:options).and_return(:quiet => true)
90
+
91
+ $stdout.should_not_receive(:puts)
92
+ shell.base = base
93
+ shell.say_status(:created, "~/.thor/task.thor")
94
+ end
95
+
96
+ it "does not print a message if log status is set to false" do
97
+ $stdout.should_not_receive(:puts)
98
+ shell.say_status(:created, "~/.thor/task.thor", false)
99
+ end
100
+
101
+ it "uses padding to set messages left margin" do
102
+ shell.padding = 2
103
+ $stdout.should_receive(:puts).with(" create ~/.thor/task.thor")
104
+ shell.say_status(:create, "~/.thor/task.thor")
105
+ end
106
+ end
107
+
108
+ describe "#print_table" do
109
+ before(:each) do
110
+ @table = []
111
+ @table << ["abc", "#123", "first three"]
112
+ @table << ["", "#0", "empty"]
113
+ @table << ["xyz", "#786", "last three"]
114
+ end
115
+
116
+ it "prints a table" do
117
+ content = capture(:stdout){ shell.print_table(@table) }
118
+ content.should == <<-TABLE
119
+ abc #123 first three
120
+ #0 empty
121
+ xyz #786 last three
122
+ TABLE
123
+ end
124
+
125
+ it "prints a table with identation" do
126
+ content = capture(:stdout){ shell.print_table(@table, :ident => 2) }
127
+ content.should == <<-TABLE
128
+ abc #123 first three
129
+ #0 empty
130
+ xyz #786 last three
131
+ TABLE
132
+ end
133
+
134
+ it "uses maximum terminal width" do
135
+ shell.should_receive(:terminal_width).and_return(20)
136
+ content = capture(:stdout){ shell.print_table(@table, :ident => 2, :truncate => true) }
137
+ content.should == <<-TABLE
138
+ abc #123 firs...
139
+ #0 empty
140
+ xyz #786 last...
141
+ TABLE
142
+ end
143
+
144
+ it "honors the colwidth option" do
145
+ content = capture(:stdout){ shell.print_table(@table, :colwidth => 10)}
146
+ content.should == <<-TABLE
147
+ abc #123 first three
148
+ #0 empty
149
+ xyz #786 last three
150
+ TABLE
151
+ end
152
+ end
153
+
154
+ describe "#file_collision" do
155
+ it "shows a menu with options" do
156
+ $stdout.should_receive(:print).with('Overwrite foo? (enter "h" for help) [Ynaqh] ')
157
+ $stdin.should_receive(:gets).and_return('n')
158
+ shell.file_collision('foo')
159
+ end
160
+
161
+ it "returns true if the user choose default option" do
162
+ $stdout.stub!(:print)
163
+ $stdin.should_receive(:gets).and_return('')
164
+ shell.file_collision('foo').should be_true
165
+ end
166
+
167
+ it "returns false if the user choose no" do
168
+ $stdout.stub!(:print)
169
+ $stdin.should_receive(:gets).and_return('n')
170
+ shell.file_collision('foo').should be_false
171
+ end
172
+
173
+ it "returns true if the user choose yes" do
174
+ $stdout.stub!(:print)
175
+ $stdin.should_receive(:gets).and_return('y')
176
+ shell.file_collision('foo').should be_true
177
+ end
178
+
179
+ it "shows help usage if the user choose help" do
180
+ $stdout.stub!(:print)
181
+ $stdin.should_receive(:gets).and_return('h')
182
+ $stdin.should_receive(:gets).and_return('n')
183
+ help = capture(:stdout){ shell.file_collision('foo') }
184
+ help.should =~ /h \- help, show this help/
185
+ end
186
+
187
+ it "quits if the user choose quit" do
188
+ $stdout.stub!(:print)
189
+ $stdout.should_receive(:puts).with('Aborting...')
190
+ $stdin.should_receive(:gets).and_return('q')
191
+
192
+ lambda {
193
+ shell.file_collision('foo')
194
+ }.should raise_error(SystemExit)
195
+ end
196
+
197
+ it "always returns true if the user choose always" do
198
+ $stdout.should_receive(:print).with('Overwrite foo? (enter "h" for help) [Ynaqh] ')
199
+ $stdin.should_receive(:gets).and_return('a')
200
+
201
+ shell.file_collision('foo').should be_true
202
+
203
+ $stdout.should_not_receive(:print)
204
+ shell.file_collision('foo').should be_true
205
+ end
206
+
207
+ describe "when a block is given" do
208
+ it "displays diff options to the user" do
209
+ $stdout.should_receive(:print).with('Overwrite foo? (enter "h" for help) [Ynaqdh] ')
210
+ $stdin.should_receive(:gets).and_return('s')
211
+ shell.file_collision('foo'){ }
212
+ end
213
+
214
+ it "invokes the diff command" do
215
+ $stdout.stub!(:print)
216
+ $stdin.should_receive(:gets).and_return('d')
217
+ $stdin.should_receive(:gets).and_return('n')
218
+ shell.should_receive(:system).with(/diff -u/)
219
+ capture(:stdout){ shell.file_collision('foo'){ } }
220
+ end
221
+ end
222
+ end
223
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Thor::Shell::Color do
4
+ def shell
5
+ @shell ||= Thor::Shell::Color.new
6
+ end
7
+
8
+ describe "#say" do
9
+ it "set the color if specified" do
10
+ $stdout.should_receive(:puts).with("\e[32mWow! Now we have colors!\e[0m")
11
+ shell.say "Wow! Now we have colors!", :green
12
+ end
13
+
14
+ it "does not use a new line even with colors" do
15
+ $stdout.should_receive(:print).with("\e[32mWow! Now we have colors! \e[0m")
16
+ shell.say "Wow! Now we have colors! ", :green
17
+ end
18
+ end
19
+
20
+ describe "#say_status" do
21
+ it "uses color to say status" do
22
+ $stdout.should_receive(:puts).with("\e[1m\e[31m conflict\e[0m README")
23
+ shell.say_status :conflict, "README", :red
24
+ end
25
+ end
26
+
27
+ describe "#file_collision" do
28
+ describe "when a block is given" do
29
+ it "invokes the diff command" do
30
+ $stdout.stub!(:print)
31
+ $stdin.should_receive(:gets).and_return('d')
32
+ $stdin.should_receive(:gets).and_return('n')
33
+
34
+ output = capture(:stdout){ shell.file_collision('spec/fixtures/doc/README'){ "README\nEND\n" } }
35
+ output.should =~ /\e\[31m\- __start__\e\[0m/
36
+ output.should =~ /^ README/
37
+ output.should =~ /\e\[32m\+ END\e\[0m/
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Thor::Shell::HTML do
4
+ def shell
5
+ @shell ||= Thor::Shell::HTML.new
6
+ end
7
+
8
+ describe "#say" do
9
+ it "set the color if specified" do
10
+ $stdout.should_receive(:puts).with('<span style="color: green;">Wow! Now we have colors!</span>')
11
+ shell.say "Wow! Now we have colors!", :green
12
+ end
13
+
14
+ it "does not use a new line even with colors" do
15
+ $stdout.should_receive(:print).with('<span style="color: green;">Wow! Now we have colors! </span>')
16
+ shell.say "Wow! Now we have colors! ", :green
17
+ end
18
+ end
19
+
20
+ describe "#say_status" do
21
+ it "uses color to say status" do
22
+ $stdout.should_receive(:puts).with('<strong><span style="color: red;"> conflict</span></strong> README')
23
+ shell.say_status :conflict, "README", :red
24
+ end
25
+ end
26
+
27
+ end
@@ -0,0 +1,47 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Thor::Shell do
4
+ def shell
5
+ @shell ||= Thor::Base.shell.new
6
+ end
7
+
8
+ describe "#initialize" do
9
+ it "sets shell value" do
10
+ base = MyCounter.new [1, 2], { }, :shell => shell
11
+ base.shell.should == shell
12
+ end
13
+
14
+ it "sets the base value on the shell if an accessor is available" do
15
+ base = MyCounter.new [1, 2], { }, :shell => shell
16
+ shell.base.should == base
17
+ end
18
+ end
19
+
20
+ describe "#shell" do
21
+ it "returns the shell in use" do
22
+ MyCounter.new([1,2]).shell.should be_kind_of(Thor::Base.shell)
23
+ end
24
+
25
+ it "uses $THOR_SHELL" do
26
+ class Thor::Shell::TestShell < Thor::Shell::Basic; end
27
+
28
+ Thor::Base.shell.should == shell.class
29
+ ENV['THOR_SHELL'] = 'TestShell'
30
+ Thor::Base.shell = nil
31
+ Thor::Base.shell.should == Thor::Shell::TestShell
32
+ ENV['THOR_SHELL'] = ''
33
+ Thor::Base.shell = shell.class
34
+ Thor::Base.shell.should == shell.class
35
+ end
36
+ end
37
+
38
+ describe "with_padding" do
39
+ it "uses padding for inside block outputs" do
40
+ base = MyCounter.new([1,2])
41
+ base.with_padding do
42
+ capture(:stdout){ base.say_status :padding, "cool" }.strip.should == "padding cool"
43
+ end
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,54 @@
1
+ $TESTING=true
2
+
3
+ require 'simplecov'
4
+ SimpleCov.start do
5
+ add_group 'Libraries', 'lib'
6
+ add_group 'Specs', 'spec'
7
+ end
8
+
9
+ $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
10
+ require 'thor'
11
+ require 'thor/group'
12
+ require 'stringio'
13
+
14
+ require 'rdoc'
15
+ require 'rspec'
16
+ require 'diff/lcs' # You need diff/lcs installed to run specs (but not to run Thor).
17
+ require 'fakeweb' # You need fakeweb installed to run specs (but not to run Thor).
18
+
19
+ # Set shell to basic
20
+ $0 = "thor"
21
+ $thor_runner = true
22
+ ARGV.clear
23
+ Thor::Base.shell = Thor::Shell::Basic
24
+
25
+ # Load fixtures
26
+ load File.join(File.dirname(__FILE__), "fixtures", "task.thor")
27
+ load File.join(File.dirname(__FILE__), "fixtures", "group.thor")
28
+ load File.join(File.dirname(__FILE__), "fixtures", "script.thor")
29
+ load File.join(File.dirname(__FILE__), "fixtures", "invoke.thor")
30
+
31
+ RSpec.configure do |config|
32
+ def capture(stream)
33
+ begin
34
+ stream = stream.to_s
35
+ eval "$#{stream} = StringIO.new"
36
+ yield
37
+ result = eval("$#{stream}").string
38
+ ensure
39
+ eval("$#{stream} = #{stream.upcase}")
40
+ end
41
+
42
+ result
43
+ end
44
+
45
+ def source_root
46
+ File.join(File.dirname(__FILE__), 'fixtures')
47
+ end
48
+
49
+ def destination_root
50
+ File.join(File.dirname(__FILE__), 'sandbox')
51
+ end
52
+
53
+ alias :silence :capture
54
+ end
data/spec/task_spec.rb ADDED
@@ -0,0 +1,74 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe Thor::Task do
4
+ def task(options={})
5
+ options.each do |key, value|
6
+ options[key] = Thor::Option.parse(key, value)
7
+ end
8
+
9
+ @task ||= Thor::Task.new(:can_has, "I can has cheezburger", "I can has cheezburger\nLots and lots of it", "can_has", options)
10
+ end
11
+
12
+ describe "#formatted_usage" do
13
+ it "includes namespace within usage" do
14
+ object = Struct.new(:namespace, :arguments).new("foo", [])
15
+ task(:bar => :required).formatted_usage(object).should == "foo:can_has --bar=BAR"
16
+ end
17
+
18
+ it "removes default from namespace" do
19
+ object = Struct.new(:namespace, :arguments).new("default:foo", [])
20
+ task(:bar => :required).formatted_usage(object).should == ":foo:can_has --bar=BAR"
21
+ end
22
+
23
+ it "injects arguments into usage" do
24
+ object = Struct.new(:namespace, :arguments).new("foo", [Thor::Argument.new(:bar, nil, true, :string)])
25
+ task(:foo => :required).formatted_usage(object).should == "foo:can_has BAR --foo=FOO"
26
+ end
27
+ end
28
+
29
+ describe "#dynamic" do
30
+ it "creates a dynamic task with the given name" do
31
+ Thor::DynamicTask.new('task').name.should == 'task'
32
+ Thor::DynamicTask.new('task').description.should == 'A dynamically-generated task'
33
+ Thor::DynamicTask.new('task').usage.should == 'task'
34
+ Thor::DynamicTask.new('task').options.should == {}
35
+ end
36
+
37
+ it "does not invoke an existing method" do
38
+ mock = mock()
39
+ mock.class.should_receive(:handle_no_task_error).with("to_s")
40
+ Thor::DynamicTask.new('to_s').run_cmd(mock)
41
+ end
42
+ end
43
+
44
+ describe "#dup" do
45
+ it "dup options hash" do
46
+ task = Thor::Task.new("can_has", nil, nil, nil, :foo => true, :bar => :required)
47
+ task.dup.options.delete(:foo)
48
+ task.options[:foo].should be
49
+ end
50
+ end
51
+
52
+ describe "#run_cmd" do
53
+ it "runs a task by calling a method in the given instance" do
54
+ mock = mock()
55
+ mock.should_receive(:can_has).and_return {|*args| args }
56
+ task.run_cmd(mock, [1, 2, 3]).should == [1, 2, 3]
57
+ end
58
+
59
+ it "raises an error if the method to be invoked is private" do
60
+ klass = Class.new do
61
+ def self.handle_no_task_error(name)
62
+ name
63
+ end
64
+
65
+ private
66
+ def can_has
67
+ "fail"
68
+ end
69
+ end
70
+
71
+ task.run_cmd(klass.new).should == "can_has"
72
+ end
73
+ end
74
+ end