thor 0.12.2 → 0.13.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/lib/thor/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class Thor
2
- VERSION = "0.12.2".freeze
2
+ VERSION = "0.13.0".freeze
3
3
  end
data/lib/thor.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'thor/base'
2
- require 'thor/group'
3
- require 'thor/actions'
4
2
 
3
+ # TODO: Update thor to allow for git-style CLI (git bisect run)
5
4
  class Thor
6
5
  class << self
7
6
  # Sets the default task when thor is executed without an explicit task to be called.
@@ -139,51 +138,47 @@ class Thor
139
138
  end
140
139
  end
141
140
 
142
- # Prints help information. If a task name is given, it shows information
143
- # only about the specific task.
141
+ # Prints help information for the given task.
144
142
  #
145
143
  # ==== Parameters
146
- # meth<String>:: An optional task name to print usage information about.
147
- #
148
- # ==== Options
149
- # namespace:: When true, shows the namespace in the output before the usage.
150
- # skip_inherited:: When true, does not show tasks from superclass.
151
- #
152
- def help(shell, options={})
153
- if options[:task]
154
- task = all_tasks[options[:task]]
155
- raise UndefinedTaskError, "task '#{options[:task]}' could not be found in namespace '#{self.namespace}'" unless task
156
-
157
- shell.say "Usage:"
158
- shell.say " #{banner(task)}"
159
- shell.say
160
- class_options_help(shell, nil => task.options.map { |_, o| o })
161
- shell.say task.description
162
- else
163
- list = printable_tasks(!options[:short])
164
-
165
- Thor::Util.thor_classes_in(self).each do |klass|
166
- list += klass.printable_tasks(false)
167
- end
168
-
169
- list.sort!{ |a,b| a[0] <=> b[0] }
144
+ # shell<Thor::Shell>
145
+ # task_name<String>
146
+ #
147
+ def task_help(shell, task_name)
148
+ task = all_tasks[task_name]
149
+ raise UndefinedTaskError, "task '#{task_name}' could not be found in namespace '#{self.namespace}'" unless task
150
+
151
+ shell.say "Usage:"
152
+ shell.say " #{banner(task)}"
153
+ shell.say
154
+ class_options_help(shell, nil => task.options.map { |_, o| o })
155
+ shell.say task.description
156
+ end
170
157
 
171
- if options[:short]
172
- shell.print_table(list, :truncate => true)
173
- else
174
- shell.say "Tasks:"
175
- shell.print_table(list, :ident => 2, :truncate => true)
176
- shell.say
177
- class_options_help(shell)
178
- end
158
+ # Prints help information for this class.
159
+ #
160
+ # ==== Parameters
161
+ # shell<Thor::Shell>
162
+ #
163
+ def help(shell)
164
+ list = printable_tasks
165
+ Thor::Util.thor_classes_in(self).each do |klass|
166
+ list += klass.printable_tasks(false)
179
167
  end
168
+ list.sort!{ |a,b| a[0] <=> b[0] }
169
+
170
+ shell.say "Tasks:"
171
+ shell.print_table(list, :ident => 2, :truncate => true)
172
+ shell.say
173
+ class_options_help(shell)
180
174
  end
181
175
 
176
+ # Returns tasks ready to be printed.
182
177
  def printable_tasks(all=true)
183
178
  (all ? all_tasks : tasks).map do |_, task|
184
179
  item = []
185
180
  item << banner(task)
186
- item << "# #{task.description}" if task.description
181
+ item << (task.description ? "# #{task.description.gsub(/\s+/m,' ')}" : "")
187
182
  item
188
183
  end
189
184
  end
@@ -196,7 +191,8 @@ class Thor
196
191
  # the namespace should be displayed as arguments.
197
192
  #
198
193
  def banner(task)
199
- "thor " + task.formatted_usage(self)
194
+ base = $thor_runner ? "thor" : File.basename($0.split(" ").first)
195
+ "#{base} #{task.formatted_usage(self, base == "thor")}"
200
196
  end
201
197
 
202
198
  def baseclass #:nodoc:
@@ -239,6 +235,6 @@ class Thor
239
235
 
240
236
  desc "help [TASK]", "Describe available tasks or one specific task"
241
237
  def help(task=nil)
242
- self.class.help(shell, :task => task)
238
+ task ? self.class.task_help(shell, task) : self.class.help(shell)
243
239
  end
244
240
  end
@@ -8,7 +8,7 @@ describe Thor::Actions::CreateFile do
8
8
 
9
9
  def create_file(destination=nil, config={}, options={})
10
10
  @base = MyCounter.new([1,2], options, { :destination_root => destination_root })
11
- stub(@base).file_name { 'rdoc' }
11
+ @base.stub!(:file_name).and_return('rdoc')
12
12
 
13
13
  @action = Thor::Actions::CreateFile.new(@base, destination, "CONFIGURATION",
14
14
  { :verbose => !@silence }.merge(config))
@@ -103,7 +103,7 @@ describe Thor::Actions::CreateFile do
103
103
 
104
104
  it "shows conflict status to ther user" do
105
105
  create_file("doc/config.rb").must_not be_identical
106
- mock($stdin).gets{ 's' }
106
+ $stdin.should_receive(:gets).and_return('s')
107
107
  file = File.join(destination_root, 'doc/config.rb')
108
108
 
109
109
  content = invoke!
@@ -114,21 +114,21 @@ describe Thor::Actions::CreateFile do
114
114
 
115
115
  it "creates the file if the file collision menu returns true" do
116
116
  create_file("doc/config.rb")
117
- mock($stdin).gets{ 'y' }
117
+ $stdin.should_receive(:gets).and_return('y')
118
118
  invoke!.must =~ /force doc\/config\.rb/
119
119
  end
120
120
 
121
121
  it "skips the file if the file collision menu returns false" do
122
122
  create_file("doc/config.rb")
123
- mock($stdin).gets{ 'n' }
123
+ $stdin.should_receive(:gets).and_return('n')
124
124
  invoke!.must =~ /skip doc\/config\.rb/
125
125
  end
126
126
 
127
127
  it "executes the block given to show file content" do
128
128
  create_file("doc/config.rb")
129
- mock($stdin).gets{ 'd' }
130
- mock($stdin).gets{ 'n' }
131
- mock(@base.shell).system(/diff -u/)
129
+ $stdin.should_receive(:gets).and_return('d')
130
+ $stdin.should_receive(:gets).and_return('n')
131
+ @base.shell.should_receive(:system).with(/diff -u/)
132
132
  invoke!
133
133
  end
134
134
  end
@@ -4,7 +4,7 @@ require 'thor/actions'
4
4
  describe Thor::Actions::Directory do
5
5
  before(:each) do
6
6
  ::FileUtils.rm_rf(destination_root)
7
- stub(invoker).file_name{ "rdoc" }
7
+ invoker.stub!(:file_name).and_return("rdoc")
8
8
  end
9
9
 
10
10
  def invoker
@@ -29,23 +29,23 @@ describe Thor::Actions do
29
29
 
30
30
  describe "#chmod" do
31
31
  it "executes the command given" do
32
- mock(FileUtils).chmod_R(0755, file)
32
+ FileUtils.should_receive(:chmod_R).with(0755, file)
33
33
  action :chmod, "foo", 0755
34
34
  end
35
35
 
36
36
  it "does not execute the command if pretending given" do
37
- dont_allow(FileUtils).chmod_R(0755, file)
37
+ FileUtils.should_not_receive(:chmod_R)
38
38
  runner(:pretend => true)
39
39
  action :chmod, "foo", 0755
40
40
  end
41
41
 
42
42
  it "logs status" do
43
- mock(FileUtils).chmod_R(0755, file)
43
+ FileUtils.should_receive(:chmod_R).with(0755, file)
44
44
  action(:chmod, "foo", 0755).must == " chmod foo\n"
45
45
  end
46
46
 
47
47
  it "does not log status if required" do
48
- mock(FileUtils).chmod_R(0755, file)
48
+ FileUtils.should_receive(:chmod_R).with(0755, file)
49
49
  action(:chmod, "foo", 0755, :verbose => false).must be_empty
50
50
  end
51
51
  end
@@ -123,7 +123,7 @@ describe Thor::Actions do
123
123
  end
124
124
 
125
125
  it "converts enconded instructions" do
126
- mock(runner).file_name{ "rdoc" }
126
+ runner.should_receive(:file_name).and_return("rdoc")
127
127
  action :template, "doc/%file_name%.rb.tt"
128
128
  file = File.join(destination_root, "doc/rdoc.rb.tt")
129
129
  File.exists?(file).must be_true
@@ -179,18 +179,18 @@ describe Thor::Actions do
179
179
  describe "#gsub_file" do
180
180
  it "replaces the content in the file" do
181
181
  action :gsub_file, "doc/README", "__start__", "START"
182
- File.open(file).read.must == "START\nREADME\n__end__\n"
182
+ File.binread(file).must == "START\nREADME\n__end__\n"
183
183
  end
184
184
 
185
185
  it "does not replace if pretending" do
186
186
  runner(:pretend => true)
187
187
  action :gsub_file, "doc/README", "__start__", "START"
188
- File.open(file).read.must == "__start__\nREADME\n__end__\n"
188
+ File.binread(file).must == "__start__\nREADME\n__end__\n"
189
189
  end
190
190
 
191
191
  it "accepts a block" do
192
192
  action(:gsub_file, "doc/README", "__start__"){ |match| match.gsub('__', '').upcase }
193
- File.open(file).read.must == "START\nREADME\n__end__\n"
193
+ File.binread(file).must == "START\nREADME\n__end__\n"
194
194
  end
195
195
 
196
196
  it "logs status" do
@@ -205,12 +205,12 @@ describe Thor::Actions do
205
205
  describe "#append_file" do
206
206
  it "appends content to the file" do
207
207
  action :append_file, "doc/README", "END\n"
208
- File.open(file).read.must == "__start__\nREADME\n__end__\nEND\n"
208
+ File.binread(file).must == "__start__\nREADME\n__end__\nEND\n"
209
209
  end
210
210
 
211
211
  it "accepts a block" do
212
212
  action(:append_file, "doc/README"){ "END\n" }
213
- File.open(file).read.must == "__start__\nREADME\n__end__\nEND\n"
213
+ File.binread(file).must == "__start__\nREADME\n__end__\nEND\n"
214
214
  end
215
215
 
216
216
  it "logs status" do
@@ -221,12 +221,12 @@ describe Thor::Actions do
221
221
  describe "#prepend_file" do
222
222
  it "prepends content to the file" do
223
223
  action :prepend_file, "doc/README", "START\n"
224
- File.open(file).read.must == "START\n__start__\nREADME\n__end__\n"
224
+ File.binread(file).must == "START\n__start__\nREADME\n__end__\n"
225
225
  end
226
226
 
227
227
  it "accepts a block" do
228
228
  action(:prepend_file, "doc/README"){ "START\n" }
229
- File.open(file).read.must == "START\n__start__\nREADME\n__end__\n"
229
+ File.binread(file).must == "START\n__start__\nREADME\n__end__\n"
230
230
  end
231
231
 
232
232
  it "logs status" do
@@ -241,12 +241,12 @@ describe Thor::Actions do
241
241
 
242
242
  it "appends content to a class" do
243
243
  action :inject_into_class, "application.rb", Application, " filter_parameters :password\n"
244
- File.open(file).read.must == "class Application < Base\n filter_parameters :password\nend\n"
244
+ File.binread(file).must == "class Application < Base\n filter_parameters :password\nend\n"
245
245
  end
246
246
 
247
247
  it "accepts a block" do
248
248
  action(:inject_into_class, "application.rb", Application){ " filter_parameters :password\n" }
249
- File.open(file).read.must == "class Application < Base\n filter_parameters :password\nend\n"
249
+ File.binread(file).must == "class Application < Base\n filter_parameters :password\nend\n"
250
250
  end
251
251
 
252
252
  it "logs status" do
@@ -255,7 +255,7 @@ describe Thor::Actions do
255
255
 
256
256
  it "does not append if class name does not match" do
257
257
  action :inject_into_class, "application.rb", "App", " filter_parameters :password\n"
258
- File.open(file).read.must == "class Application < Base\nend\n"
258
+ File.binread(file).must == "class Application < Base\nend\n"
259
259
  end
260
260
  end
261
261
  end
@@ -55,6 +55,35 @@ describe Thor::Actions::InjectIntoFile do
55
55
  invoke! "doc/README", "\nmore content", :after => "__start__"
56
56
  File.read(file).must == "__start__\nREADME\n__end__\n"
57
57
  end
58
+
59
+ it "does not change the file if already include content" do
60
+ invoke! "doc/README", :before => "__end__" do
61
+ "more content\n"
62
+ end
63
+
64
+ File.read(file).must == "__start__\nREADME\nmore content\n__end__\n"
65
+
66
+ invoke! "doc/README", :before => "__end__" do
67
+ "more content\n"
68
+ end
69
+
70
+ File.read(file).must == "__start__\nREADME\nmore content\n__end__\n"
71
+ end
72
+
73
+ it "does change the file if already include content and :force == true" do
74
+ invoke! "doc/README", :before => "__end__" do
75
+ "more content\n"
76
+ end
77
+
78
+ File.read(file).must == "__start__\nREADME\nmore content\n__end__\n"
79
+
80
+ invoke! "doc/README", :before => "__end__", :force => true do
81
+ "more content\n"
82
+ end
83
+
84
+ File.read(file).must == "__start__\nREADME\nmore content\nmore content\n__end__\n"
85
+ end
86
+
58
87
  end
59
88
 
60
89
  describe "#revoke!" do
data/spec/actions_spec.rb CHANGED
@@ -55,9 +55,10 @@ describe Thor::Actions do
55
55
  end
56
56
 
57
57
  it "does not use the current directory if one is given" do
58
+ root = File.expand_path("/")
58
59
  base = MyCounter.new([1])
59
- base.destination_root = "/"
60
- base.destination_root.must == "/"
60
+ base.destination_root = root
61
+ base.destination_root.must == root
61
62
  end
62
63
 
63
64
  it "uses the current directory if none is given" do
@@ -194,7 +195,7 @@ describe Thor::Actions do
194
195
  @template.instance_eval "def read; self; end" # Make the string respond to read
195
196
 
196
197
  @file = "http://gist.github.com/103208.txt"
197
- mock(runner).open(@file){ @template }
198
+ runner.should_receive(:open).and_return(@template)
198
199
  end
199
200
 
200
201
  it "opens a file and executes its content in the instance binding" do
@@ -219,7 +220,7 @@ describe Thor::Actions do
219
220
 
220
221
  describe "#run" do
221
222
  before(:each) do
222
- mock(runner).system("ls")
223
+ runner.should_receive(:system).with("ls")
223
224
  end
224
225
 
225
226
  it "executes the command given" do
@@ -235,15 +236,15 @@ describe Thor::Actions do
235
236
  end
236
237
 
237
238
  it "accepts a color as status" do
238
- mock(runner.shell).say_status(:run, 'ls from "."', :yellow)
239
+ runner.shell.should_receive(:say_status).with(:run, 'ls from "."', :yellow)
239
240
  action :run, "ls", :verbose => :yellow
240
241
  end
241
242
  end
242
243
 
243
244
  describe "#run_ruby_script" do
244
245
  before(:each) do
245
- stub(Thor::Util).ruby_command{ "/opt/jruby" }
246
- mock(runner).system("/opt/jruby script.rb")
246
+ Thor::Util.stub!(:ruby_command).and_return("/opt/jruby")
247
+ runner.should_receive(:system).with("/opt/jruby script.rb")
247
248
  end
248
249
 
249
250
  it "executes the ruby script" do
@@ -261,30 +262,30 @@ describe Thor::Actions do
261
262
 
262
263
  describe "#thor" do
263
264
  it "executes the thor command" do
264
- mock(runner).system("thor list")
265
+ runner.should_receive(:system).with("thor list")
265
266
  action :thor, :list, :verbose => true
266
267
  end
267
268
 
268
269
  it "converts extra arguments to command arguments" do
269
- mock(runner).system("thor list foo bar")
270
+ runner.should_receive(:system).with("thor list foo bar")
270
271
  action :thor, :list, "foo", "bar"
271
272
  end
272
273
 
273
274
  it "converts options hash to switches" do
274
- mock(runner).system("thor list foo bar --foo")
275
+ runner.should_receive(:system).with("thor list foo bar --foo")
275
276
  action :thor, :list, "foo", "bar", :foo => true
276
277
 
277
- mock(runner).system("thor list --foo 1 2 3")
278
+ runner.should_receive(:system).with("thor list --foo 1 2 3")
278
279
  action :thor, :list, :foo => [1,2,3]
279
280
  end
280
281
 
281
282
  it "logs status" do
282
- mock(runner).system("thor list")
283
+ runner.should_receive(:system).with("thor list")
283
284
  action(:thor, :list).must == " run thor list from \".\"\n"
284
285
  end
285
286
 
286
287
  it "does not log status if required" do
287
- mock(runner).system("thor list --foo 1 2 3")
288
+ runner.should_receive(:system).with("thor list --foo 1 2 3")
288
289
  action(:thor, :list, :foo => [1,2,3], :verbose => false).must be_empty
289
290
  end
290
291
  end
data/spec/base_spec.rb CHANGED
@@ -233,4 +233,19 @@ describe Thor::Base do
233
233
  }.must raise_error(Thor::UndefinedTaskError, /the 'what' task of MyScript is private/)
234
234
  end
235
235
  end
236
+
237
+ describe "attr_*" do
238
+ it "should not add attr_reader as a task" do
239
+ capture(:stderr){ MyScript.start(["another_attribute"]) }.must =~ /could not find/
240
+ end
241
+
242
+ it "should not add attr_writer as a task" do
243
+ capture(:stderr){ MyScript.start(["another_attribute=", "foo"]) }.must =~ /could not find/
244
+ end
245
+
246
+ it "should not add attr_accessor as a task" do
247
+ capture(:stderr){ MyScript.start(["some_attribute"]) }.must =~ /could not find/
248
+ capture(:stderr){ MyScript.start(["some_attribute=", "foo"]) }.must =~ /could not find/
249
+ end
250
+ end
236
251
  end
@@ -1,4 +1,8 @@
1
1
  class MyScript < Thor
2
+ attr_accessor :some_attribute
3
+ attr_writer :another_attribute
4
+ attr_reader :another_attribute
5
+
2
6
  group :script
3
7
  default_task :example_default_task
4
8
 
data/spec/group_spec.rb CHANGED
@@ -29,7 +29,7 @@ describe Thor::Group do
29
29
  end
30
30
 
31
31
  it "invokes help message if any of the shortcuts is given" do
32
- stub(MyCounter).help
32
+ MyCounter.should_receive(:help)
33
33
  MyCounter.start(["-h"])
34
34
  end
35
35
  end
@@ -66,12 +66,6 @@ describe Thor::Group do
66
66
  @content.must =~ /Options/
67
67
  @content.must =~ /\[\-\-third=THREE\]/
68
68
  end
69
-
70
- it "shows only usage if a short help is required" do
71
- content = capture(:stdout){ MyCounter.help(Thor::Base.shell.new, :short => true) }
72
- content.must =~ /my_counter N \[N\]/
73
- content.must_not =~ /Options/
74
- end
75
69
  end
76
70
 
77
71
  describe "#invoke" do
data/spec/runner_spec.rb CHANGED
@@ -26,11 +26,11 @@ describe Thor::Runner do
26
26
 
27
27
  it "shows information about a specific Thor group class" do
28
28
  content = capture(:stdout){ Thor::Runner.start(["help", "my_counter"]) }
29
- content.must =~ /my_counter N \[N\]/
29
+ content.must =~ /my_counter N/
30
30
  end
31
31
 
32
32
  it "raises error if a class/task cannot be found" do
33
- mock(Thor::Runner).exit(1)
33
+ Thor::Runner.should_receive(:exit).with(1)
34
34
  content = capture(:stderr){ Thor::Runner.start(["help", "unknown"]) }
35
35
  content.must =~ /could not find Thor class or task 'unknown'/
36
36
  end
@@ -39,7 +39,7 @@ describe Thor::Runner do
39
39
  describe "#start" do
40
40
  it "invokes a task from Thor::Runner" do
41
41
  ARGV.replace ["list"]
42
- capture(:stdout){ Thor::Runner.start }.must =~ /my_counter N \[N\]/
42
+ capture(:stdout){ Thor::Runner.start }.must =~ /my_counter N/
43
43
  end
44
44
 
45
45
  it "invokes a task from a specific Thor class" do
@@ -68,7 +68,7 @@ describe Thor::Runner do
68
68
  end
69
69
 
70
70
  it "raises an error if class/task can't be found" do
71
- mock(Thor::Runner).exit(1)
71
+ Thor::Runner.should_receive(:exit).with(1)
72
72
  ARGV.replace ["unknown"]
73
73
  capture(:stderr){ Thor::Runner.start }.must =~ /could not find Thor class or task 'unknown'/
74
74
  end
@@ -96,14 +96,16 @@ describe Thor::Runner do
96
96
  "random" => {
97
97
  :location => @location,
98
98
  :filename => "4a33b894ffce85d7b412fc1b36f88fe0",
99
- :constants => ["Amazing"]
99
+ :namespaces => ["amazing"]
100
100
  }
101
101
  }
102
102
 
103
+ root_file = File.join(Thor::Util.thor_root, "thor.yml")
104
+
103
105
  # Stub load and save to avoid thor.yaml from being overwritten
104
- stub(YAML).load_file { @original_yaml }
105
- stub(File).exists?(File.join(Thor::Util.thor_root, "thor.yml")){ true }
106
- stub(File).open(File.join(Thor::Util.thor_root, "thor.yml"), "w")
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")
107
109
  end
108
110
 
109
111
  describe "list" do
@@ -115,7 +117,7 @@ describe Thor::Runner do
115
117
 
116
118
  it "gives a list of the available Thor::Group classes" do
117
119
  ARGV.replace ["list"]
118
- capture(:stdout) { Thor::Runner.start }.must =~ /my_counter N \[N\]/
120
+ capture(:stdout) { Thor::Runner.start }.must =~ /my_counter N/
119
121
  end
120
122
 
121
123
  it "can filter a list of the available tasks by --group" do
@@ -148,26 +150,12 @@ describe Thor::Runner do
148
150
  ARGV.replace [":test"]
149
151
  capture(:stdout) { Thor::Runner.start }.must == "test\n"
150
152
  end
151
-
152
- it "updates the yaml file when invoked" do
153
- capture(:stdout) { Thor::Runner.start(["list"]) }
154
- @original_yaml["random"][:namespaces].must == ["amazing"]
155
- end
156
- end
157
-
158
- describe "update" do
159
- it "updates existing thor files" do
160
- mock.instance_of(Thor::Runner).install(@original_yaml["random"][:location]) { true }
161
- stub(File).delete(File.join(Thor::Util.thor_root, @original_yaml["random"][:filename]))
162
- silence(:stdout) { Thor::Runner.start(["update", "random"]) }
163
- end
164
153
  end
165
154
 
166
155
  describe "uninstall" do
167
156
  before(:each) do
168
- stub.instance_of(Thor::Runner).save_yaml(anything)
169
- stub(File).delete(anything)
170
- stub(@original_yaml).delete(anything)
157
+ path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
158
+ FileUtils.should_receive(:rm_rf).with(path)
171
159
  end
172
160
 
173
161
  it "uninstalls existing thor modules" do
@@ -177,7 +165,7 @@ describe Thor::Runner do
177
165
 
178
166
  describe "installed" do
179
167
  before(:each) do
180
- stub(Dir).[](anything) { [] }
168
+ Dir.should_receive(:[]).and_return([])
181
169
  end
182
170
 
183
171
  it "displays the modules installed in a pretty way" do
@@ -187,16 +175,24 @@ describe Thor::Runner do
187
175
  end
188
176
  end
189
177
 
190
- describe "install" do
191
- it "installs thor files" do
192
- ARGV.replace ["install", @location]
178
+ describe "install/update" do
179
+ before(:each) do
180
+ FileUtils.stub!(:mkdir_p)
181
+ FileUtils.stub!(:touch)
182
+ $stdin.stub!(:gets).and_return("Y")
193
183
 
194
- # Stubs for the file system interactions
195
- stub.instance_of(Thor::Base.shell).no? { false }
196
- stub(FileUtils).mkdir_p
197
- stub(FileUtils).touch
184
+ path = File.join(Thor::Util.thor_root, Digest::MD5.hexdigest(@location + "random"))
185
+ File.should_receive(:open).with(path, "w")
186
+ end
198
187
 
199
- mock(File).open(File.join(Thor::Util.thor_root, Digest::MD5.hexdigest(@location + "random")), "w")
188
+ it "updates existing thor files" do
189
+ path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
190
+ File.should_receive(:delete).with(path)
191
+ silence(:stdout) { Thor::Runner.start(["update", "random"]) }
192
+ end
193
+
194
+ it "installs thor files" do
195
+ ARGV.replace ["install", @location]
200
196
  silence(:stdout) { Thor::Runner.start }
201
197
  end
202
198
  end