thor 0.18.1 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +13 -7
  3. data/Thorfile +4 -5
  4. data/bin/thor +1 -1
  5. data/lib/thor.rb +78 -67
  6. data/lib/thor/actions.rb +57 -56
  7. data/lib/thor/actions/create_file.rb +33 -35
  8. data/lib/thor/actions/create_link.rb +2 -3
  9. data/lib/thor/actions/directory.rb +37 -38
  10. data/lib/thor/actions/empty_directory.rb +67 -69
  11. data/lib/thor/actions/file_manipulation.rb +17 -15
  12. data/lib/thor/actions/inject_into_file.rb +27 -29
  13. data/lib/thor/base.rb +193 -189
  14. data/lib/thor/command.rb +20 -23
  15. data/lib/thor/core_ext/hash_with_indifferent_access.rb +21 -24
  16. data/lib/thor/core_ext/io_binary_read.rb +2 -4
  17. data/lib/thor/core_ext/ordered_hash.rb +9 -11
  18. data/lib/thor/error.rb +5 -1
  19. data/lib/thor/group.rb +53 -54
  20. data/lib/thor/invocation.rb +44 -38
  21. data/lib/thor/line_editor.rb +17 -0
  22. data/lib/thor/line_editor/basic.rb +35 -0
  23. data/lib/thor/line_editor/readline.rb +88 -0
  24. data/lib/thor/parser.rb +4 -4
  25. data/lib/thor/parser/argument.rb +28 -29
  26. data/lib/thor/parser/arguments.rb +102 -98
  27. data/lib/thor/parser/option.rb +26 -22
  28. data/lib/thor/parser/options.rb +86 -86
  29. data/lib/thor/rake_compat.rb +9 -10
  30. data/lib/thor/runner.rb +141 -141
  31. data/lib/thor/shell.rb +27 -34
  32. data/lib/thor/shell/basic.rb +91 -63
  33. data/lib/thor/shell/color.rb +44 -43
  34. data/lib/thor/shell/html.rb +59 -60
  35. data/lib/thor/util.rb +24 -27
  36. data/lib/thor/version.rb +1 -1
  37. data/spec/actions/create_file_spec.rb +25 -27
  38. data/spec/actions/create_link_spec.rb +19 -18
  39. data/spec/actions/directory_spec.rb +31 -31
  40. data/spec/actions/empty_directory_spec.rb +18 -18
  41. data/spec/actions/file_manipulation_spec.rb +38 -28
  42. data/spec/actions/inject_into_file_spec.rb +13 -13
  43. data/spec/actions_spec.rb +43 -43
  44. data/spec/base_spec.rb +45 -38
  45. data/spec/command_spec.rb +13 -14
  46. data/spec/core_ext/hash_with_indifferent_access_spec.rb +19 -19
  47. data/spec/core_ext/ordered_hash_spec.rb +6 -6
  48. data/spec/exit_condition_spec.rb +4 -4
  49. data/spec/fixtures/invoke.thor +19 -0
  50. data/spec/fixtures/script.thor +1 -1
  51. data/spec/group_spec.rb +30 -24
  52. data/spec/helper.rb +28 -15
  53. data/spec/invocation_spec.rb +39 -19
  54. data/spec/line_editor/basic_spec.rb +28 -0
  55. data/spec/line_editor/readline_spec.rb +69 -0
  56. data/spec/line_editor_spec.rb +43 -0
  57. data/spec/parser/argument_spec.rb +12 -12
  58. data/spec/parser/arguments_spec.rb +11 -11
  59. data/spec/parser/option_spec.rb +33 -25
  60. data/spec/parser/options_spec.rb +66 -52
  61. data/spec/quality_spec.rb +75 -0
  62. data/spec/rake_compat_spec.rb +10 -10
  63. data/spec/register_spec.rb +60 -30
  64. data/spec/runner_spec.rb +67 -62
  65. data/spec/sandbox/application.rb +2 -0
  66. data/spec/sandbox/app{1}/README +3 -0
  67. data/spec/sandbox/bundle/execute.rb +6 -0
  68. data/spec/sandbox/bundle/main.thor +1 -0
  69. data/spec/sandbox/command.thor +10 -0
  70. data/spec/sandbox/doc/%file_name%.rb.tt +1 -0
  71. data/spec/sandbox/doc/COMMENTER +11 -0
  72. data/spec/sandbox/doc/README +3 -0
  73. data/spec/sandbox/doc/block_helper.rb +3 -0
  74. data/spec/sandbox/doc/config.rb +1 -0
  75. data/spec/sandbox/doc/config.yaml.tt +1 -0
  76. data/spec/sandbox/doc/excluding/%file_name%.rb.tt +1 -0
  77. data/spec/sandbox/enum.thor +10 -0
  78. data/spec/sandbox/group.thor +128 -0
  79. data/spec/sandbox/invoke.thor +131 -0
  80. data/spec/sandbox/path with spaces b/data/spec/sandbox/path with → spaces +0 -0
  81. data/spec/sandbox/preserve/script.sh +3 -0
  82. data/spec/sandbox/script.thor +220 -0
  83. data/spec/sandbox/subcommand.thor +17 -0
  84. data/spec/shell/basic_spec.rb +107 -86
  85. data/spec/shell/color_spec.rb +32 -8
  86. data/spec/shell/html_spec.rb +3 -4
  87. data/spec/shell_spec.rb +7 -7
  88. data/spec/subcommand_spec.rb +20 -2
  89. data/spec/thor_spec.rb +111 -97
  90. data/spec/util_spec.rb +30 -30
  91. data/thor.gemspec +14 -14
  92. metadata +69 -25
@@ -0,0 +1,75 @@
1
+ if defined?(Encoding) && Encoding.default_external != "UTF-8"
2
+ Encoding.default_external = "UTF-8"
3
+ end
4
+
5
+ describe "The library itself" do
6
+ def check_for_spec_defs_with_single_quotes(filename)
7
+ failing_lines = []
8
+
9
+ File.readlines(filename).each_with_index do |line,number|
10
+ failing_lines << number + 1 if line =~ /^ *(describe|it|context) {1}'{1}/
11
+ end
12
+
13
+ unless failing_lines.empty?
14
+ "#{filename} uses inconsistent single quotes on lines #{failing_lines.join(', ')}"
15
+ end
16
+ end
17
+
18
+ def check_for_tab_characters(filename)
19
+ failing_lines = []
20
+ File.readlines(filename).each_with_index do |line,number|
21
+ failing_lines << number + 1 if line =~ /\t/
22
+ end
23
+
24
+ unless failing_lines.empty?
25
+ "#{filename} has tab characters on lines #{failing_lines.join(', ')}"
26
+ end
27
+ end
28
+
29
+ def check_for_extra_spaces(filename)
30
+ failing_lines = []
31
+ File.readlines(filename).each_with_index do |line,number|
32
+ next if line =~ /^\s+#.*\s+\n$/
33
+ failing_lines << number + 1 if line =~ /\s+\n$/
34
+ end
35
+
36
+ unless failing_lines.empty?
37
+ "#{filename} has spaces on the EOL on lines #{failing_lines.join(', ')}"
38
+ end
39
+ end
40
+
41
+ RSpec::Matchers.define :be_well_formed do
42
+ failure_message_for_should do |actual|
43
+ actual.join("\n")
44
+ end
45
+
46
+ match do |actual|
47
+ actual.empty?
48
+ end
49
+ end
50
+
51
+ it "has no malformed whitespace" do
52
+ exempt = /\.gitmodules|\.marshal|fixtures|vendor|spec|ssl_certs|LICENSE/
53
+ error_messages = []
54
+ Dir.chdir(File.expand_path("../..", __FILE__)) do
55
+ `git ls-files`.split("\n").each do |filename|
56
+ next if filename =~ exempt
57
+ error_messages << check_for_tab_characters(filename)
58
+ error_messages << check_for_extra_spaces(filename)
59
+ end
60
+ end
61
+ expect(error_messages.compact).to be_well_formed
62
+ end
63
+
64
+ it "uses double-quotes consistently in specs" do
65
+ included = /spec/
66
+ error_messages = []
67
+ Dir.chdir(File.expand_path("../", __FILE__)) do
68
+ `git ls-files`.split("\n").each do |filename|
69
+ next unless filename =~ included
70
+ error_messages << check_for_spec_defs_with_single_quotes(filename)
71
+ end
72
+ end
73
+ expect(error_messages.compact).to be_well_formed
74
+ end
75
+ end
@@ -1,6 +1,6 @@
1
- require 'helper'
2
- require 'thor/rake_compat'
3
- require 'rake/tasklib'
1
+ require "helper"
2
+ require "thor/rake_compat"
3
+ require "rake/tasklib"
4
4
 
5
5
  $main = self
6
6
 
@@ -32,7 +32,7 @@ end
32
32
 
33
33
  describe Thor::RakeCompat do
34
34
  it "sets the rakefile application" do
35
- expect(["rake_compat_spec.rb", "Thorfile"]).to include(Rake.application.rakefile)
35
+ expect(%w[rake_compat_spec.rb Thorfile]).to include(Rake.application.rakefile)
36
36
  end
37
37
 
38
38
  it "adds rake tasks to thor classes too" do
@@ -61,12 +61,12 @@ describe Thor::RakeCompat do
61
61
  end
62
62
 
63
63
  it "invoking the thor task invokes the rake task" do
64
- expect(capture(:stdout) {
65
- ThorTask.start ["cool"]
66
- }).to eq("COOL\n")
64
+ expect(capture(:stdout) do
65
+ ThorTask.start %w[cool]
66
+ end).to eq("COOL\n")
67
67
 
68
- expect(capture(:stdout) {
69
- ThorTask::HiperMega.start ["super"]
70
- }).to eq("HIPER MEGA SUPER\n")
68
+ expect(capture(:stdout) do
69
+ ThorTask::HiperMega.start %w[super]
70
+ end).to eq("HIPER MEGA SUPER\n")
71
71
  end
72
72
  end
@@ -1,4 +1,4 @@
1
- require 'helper'
1
+ require "helper"
2
2
 
3
3
  class BoringVendorProvidedCLI < Thor
4
4
  desc "boring", "do boring stuff"
@@ -42,9 +42,9 @@ end
42
42
 
43
43
  class ClassOptionGroupPlugin < Thor::Group
44
44
  class_option :who,
45
- :type => :string,
46
- :aliases => "-w",
47
- :default => "zebra"
45
+ :type => :string,
46
+ :aliases => "-w",
47
+ :default => "zebra"
48
48
  end
49
49
 
50
50
  class CompatibleWith19Plugin < ClassOptionGroupPlugin
@@ -82,6 +82,20 @@ class PluginWithDefaultcommandAndDeclaredArgument < Thor
82
82
  default_command :say
83
83
  end
84
84
 
85
+ class SubcommandWithDefault < Thor
86
+ default_command :default
87
+
88
+ desc "default", "default subcommand"
89
+ def default
90
+ puts "default"
91
+ end
92
+
93
+ desc "with_args", "subcommand with arguments"
94
+ def with_args(*args)
95
+ puts "received arguments: " + args.join(",")
96
+ end
97
+ end
98
+
85
99
  BoringVendorProvidedCLI.register(
86
100
  ExcitingPluginCLI,
87
101
  "exciting",
@@ -97,33 +111,36 @@ BoringVendorProvidedCLI.register(
97
111
 
98
112
  BoringVendorProvidedCLI.register(
99
113
  GroupPlugin,
100
- 'groupwork',
114
+ "groupwork",
101
115
  "Do a bunch of things in a row",
102
116
  "purple monkey dishwasher")
103
117
 
104
118
  BoringVendorProvidedCLI.register(
105
119
  CompatibleWith19Plugin,
106
- 'zoo',
120
+ "zoo",
107
121
  "zoo [-w animal]",
108
122
  "Shows a provided animal or just zebra")
109
123
 
110
124
  BoringVendorProvidedCLI.register(
111
125
  PluginWithDefault,
112
- 'say',
113
- 'say message',
114
- 'subcommands ftw')
126
+ "say",
127
+ "say message",
128
+ "subcommands ftw")
115
129
 
116
130
  BoringVendorProvidedCLI.register(
117
131
  PluginWithDefaultMultipleArguments,
118
- 'say_multiple',
119
- 'say message',
120
- 'subcommands ftw')
132
+ "say_multiple",
133
+ "say message",
134
+ "subcommands ftw")
121
135
 
122
136
  BoringVendorProvidedCLI.register(
123
137
  PluginWithDefaultcommandAndDeclaredArgument,
124
- 'say_argument',
125
- 'say message',
126
- 'subcommands ftw')
138
+ "say_argument",
139
+ "say message",
140
+ "subcommands ftw")
141
+
142
+ BoringVendorProvidedCLI.register(SubcommandWithDefault,
143
+ "subcommand", "subcommand", "Run subcommands")
127
144
 
128
145
  describe ".register-ing a Thor subclass" do
129
146
  it "registers the plugin as a subcommand" do
@@ -133,23 +150,36 @@ describe ".register-ing a Thor subclass" do
133
150
 
134
151
  it "includes the plugin's usage in the help" do
135
152
  help_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[help]) }
136
- expect(help_output).to include('do exciting things')
153
+ expect(help_output).to include("do exciting things")
137
154
  end
138
155
 
139
- it "invokes the default command correctly" do
140
- output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say hello]) }
141
- expect(output).to include("hello")
142
- end
156
+ context "with a default command," do
157
+ it "invokes the default command correctly" do
158
+ output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say hello]) }
159
+ expect(output).to include("hello")
160
+ end
143
161
 
144
- it "invokes the default command correctly with multiple args" do
145
- output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say_multiple hello adam]) }
146
- expect(output).to include("hello")
147
- expect(output).to include("adam")
148
- end
162
+ it "invokes the default command correctly with multiple args" do
163
+ output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say_multiple hello adam]) }
164
+ expect(output).to include("hello")
165
+ expect(output).to include("adam")
166
+ end
167
+
168
+ it "invokes the default command correctly with a declared argument" do
169
+ output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say_argument hello]) }
170
+ expect(output).to include("hello")
171
+ end
172
+
173
+ it "displays the subcommand's help message" do
174
+ output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[subcommand help]) }
175
+ expect(output).to include("default subcommand")
176
+ expect(output).to include("subcommand with argument")
177
+ end
149
178
 
150
- it "invokes the default command correctly with a declared argument" do
151
- output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[say_argument hello]) }
152
- expect(output).to include("hello")
179
+ it "invokes commands with their actual args" do
180
+ output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[subcommand with_args actual_argument]) }
181
+ expect(output.strip).to eql("received arguments: actual_argument")
182
+ end
153
183
  end
154
184
 
155
185
  context "when $thor_runner is false" do
@@ -157,7 +187,7 @@ describe ".register-ing a Thor subclass" do
157
187
  begin
158
188
  $thor_runner = false
159
189
  help_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[exciting]) }
160
- expect(help_output).to include('thor exciting_plugin_c_l_i fireworks')
190
+ expect(help_output).to include("thor exciting_plugin_c_l_i fireworks")
161
191
  ensure
162
192
  $thor_runner = true
163
193
  end
@@ -167,7 +197,7 @@ describe ".register-ing a Thor subclass" do
167
197
  context "when hidden" do
168
198
  it "omits the hidden plugin's usage from the help" do
169
199
  help_output = capture(:stdout) { BoringVendorProvidedCLI.start(%w[help]) }
170
- expect(help_output).not_to include('secret stuff')
200
+ expect(help_output).not_to include("secret stuff")
171
201
  end
172
202
 
173
203
  it "registers the plugin as a subcommand" do
@@ -1,12 +1,12 @@
1
- require 'helper'
2
- require 'thor/runner'
1
+ require "helper"
2
+ require "thor/runner"
3
3
 
4
4
  describe Thor::Runner do
5
5
  def when_no_thorfiles_exist
6
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 }
7
+ Dir.chdir ".."
8
+ delete = Thor::Base.subclasses.select { |e| e.namespace == "default" }
9
+ delete.each { |e| Thor::Base.subclasses.delete e }
10
10
  yield
11
11
  Thor::Base.subclasses.concat delete
12
12
  Dir.chdir old_dir
@@ -14,40 +14,40 @@ describe Thor::Runner do
14
14
 
15
15
  describe "#help" do
16
16
  it "shows information about Thor::Runner itself" do
17
- expect(capture(:stdout) { Thor::Runner.start(["help"]) }).to match(/List the available thor commands/)
17
+ expect(capture(:stdout) { Thor::Runner.start(%w[help]) }).to match(/List the available thor commands/)
18
18
  end
19
19
 
20
20
  it "shows information about a specific Thor::Runner command" do
21
- content = capture(:stdout) { Thor::Runner.start(["help", "list"]) }
21
+ content = capture(:stdout) { Thor::Runner.start(%w[help list]) }
22
22
  expect(content).to match(/List the available thor commands/)
23
23
  expect(content).not_to match(/help \[COMMAND\]/)
24
24
  end
25
25
 
26
26
  it "shows information about a specific Thor class" do
27
- content = capture(:stdout) { Thor::Runner.start(["help", "my_script"]) }
27
+ content = capture(:stdout) { Thor::Runner.start(%w[help my_script]) }
28
28
  expect(content).to match(/zoo\s+# zoo around/m)
29
29
  end
30
30
 
31
- it "shows information about an specific command from an specific Thor class" do
32
- content = capture(:stdout) { Thor::Runner.start(["help", "my_script:zoo"]) }
31
+ it "shows information about a specific command from a specific Thor class" do
32
+ content = capture(:stdout) { Thor::Runner.start(%w[help my_script:zoo]) }
33
33
  expect(content).to match(/zoo around/)
34
34
  expect(content).not_to match(/help \[COMMAND\]/)
35
35
  end
36
36
 
37
37
  it "shows information about a specific Thor group class" do
38
- content = capture(:stdout) { Thor::Runner.start(["help", "my_counter"]) }
38
+ content = capture(:stdout) { Thor::Runner.start(%w[help my_counter]) }
39
39
  expect(content).to match(/my_counter N/)
40
40
  end
41
41
 
42
42
  it "raises error if a class/command cannot be found" do
43
- content = capture(:stderr){ Thor::Runner.start(["help", "unknown"]) }
43
+ content = capture(:stderr) { Thor::Runner.start(%w[help unknown]) }
44
44
  expect(content.strip).to eq('Could not find command "unknown" in "default" namespace.')
45
45
  end
46
46
 
47
47
  it "raises error if a class/command cannot be found for a setup without thorfiles" do
48
48
  when_no_thorfiles_exist do
49
- Thor::Runner.should_receive :exit
50
- content = capture(:stderr){ Thor::Runner.start(["help", "unknown"]) }
49
+ expect(Thor::Runner).to receive :exit
50
+ content = capture(:stderr) { Thor::Runner.start(%w[help unknown]) }
51
51
  expect(content.strip).to eq('Could not find command "unknown".')
52
52
  end
53
53
  end
@@ -55,64 +55,65 @@ describe Thor::Runner do
55
55
 
56
56
  describe "#start" do
57
57
  it "invokes a command from Thor::Runner" do
58
- ARGV.replace ["list"]
58
+ ARGV.replace %w[list]
59
59
  expect(capture(:stdout) { Thor::Runner.start }).to match(/my_counter N/)
60
60
  end
61
61
 
62
62
  it "invokes a command from a specific Thor class" do
63
- ARGV.replace ["my_script:zoo"]
64
- expect(Thor::Runner.start).to be_true
63
+ ARGV.replace %w[my_script:zoo]
64
+ expect(Thor::Runner.start).to be true
65
65
  end
66
66
 
67
67
  it "invokes the default command from a specific Thor class if none is specified" do
68
- ARGV.replace ["my_script"]
68
+ ARGV.replace %w[my_script]
69
69
  expect(Thor::Runner.start).to eq("default command")
70
70
  end
71
71
 
72
- it "forwads arguments to the invoked command" do
73
- ARGV.replace ["my_script:animal", "horse"]
74
- expect(Thor::Runner.start).to eq(["horse"])
72
+ it "forwards arguments to the invoked command" do
73
+ ARGV.replace %w[my_script:animal horse]
74
+ expect(Thor::Runner.start).to eq(%w[horse])
75
75
  end
76
76
 
77
77
  it "invokes commands through shortcuts" do
78
- ARGV.replace ["my_script", "-T", "horse"]
79
- expect(Thor::Runner.start).to eq(["horse"])
78
+ ARGV.replace %w[my_script -T horse]
79
+ expect(Thor::Runner.start).to eq(%w[horse])
80
80
  end
81
81
 
82
82
  it "invokes a Thor::Group" do
83
- ARGV.replace ["my_counter", "1", "2", "--third", "3"]
83
+ ARGV.replace %w[my_counter 1 2 --third 3]
84
84
  expect(Thor::Runner.start).to eq([1, 2, 3, nil, nil, nil])
85
85
  end
86
86
 
87
87
  it "raises an error if class/command can't be found" do
88
- ARGV.replace ["unknown"]
89
- content = capture(:stderr){ Thor::Runner.start }
88
+ ARGV.replace %w[unknown]
89
+ content = capture(:stderr) { Thor::Runner.start }
90
90
  expect(content.strip).to eq('Could not find command "unknown" in "default" namespace.')
91
91
  end
92
92
 
93
93
  it "raises an error if class/command can't be found in a setup without thorfiles" do
94
94
  when_no_thorfiles_exist do
95
- ARGV.replace ["unknown"]
96
- Thor::Runner.should_receive :exit
97
- content = capture(:stderr){ Thor::Runner.start }
95
+ ARGV.replace %w[unknown]
96
+ expect(Thor::Runner).to receive :exit
97
+ content = capture(:stderr) { Thor::Runner.start }
98
98
  expect(content.strip).to eq('Could not find command "unknown".')
99
99
  end
100
100
  end
101
101
 
102
102
  it "does not swallow NoMethodErrors that occur inside the called method" do
103
- ARGV.replace ["my_script:call_unexistent_method"]
104
- expect{ Thor::Runner.start }.to raise_error(NoMethodError)
103
+ ARGV.replace %w[my_script:call_unexistent_method]
104
+ expect { Thor::Runner.start }.to raise_error(NoMethodError)
105
105
  end
106
106
 
107
107
  it "does not swallow Thor::Group InvocationError" do
108
- ARGV.replace ["whiny_generator"]
109
- expect{ Thor::Runner.start }.to raise_error(ArgumentError, /thor wrong_arity takes 1 argument, but it should not/)
108
+ ARGV.replace %w[whiny_generator]
109
+ expect { Thor::Runner.start }.to raise_error(ArgumentError, /thor wrong_arity takes 1 argument, but it should not/)
110
110
  end
111
111
 
112
112
  it "does not swallow Thor InvocationError" do
113
- ARGV.replace ["my_script:animal"]
113
+ ARGV.replace %w[my_script:animal]
114
114
  content = capture(:stderr) { Thor::Runner.start }
115
- expect(content.strip).to eq(%Q'ERROR: thor animal was called with no arguments\nUsage: "thor my_script:animal TYPE".')
115
+ expect(content.strip).to eq(%Q(ERROR: "thor animal" was called with no arguments
116
+ Usage: "thor my_script:animal TYPE"))
116
117
  end
117
118
  end
118
119
 
@@ -123,68 +124,68 @@ describe Thor::Runner do
123
124
  "random" => {
124
125
  :location => @location,
125
126
  :filename => "4a33b894ffce85d7b412fc1b36f88fe0",
126
- :namespaces => ["amazing"]
127
+ :namespaces => %w[amazing]
127
128
  }
128
129
  }
129
130
 
130
131
  root_file = File.join(Thor::Util.thor_root, "thor.yml")
131
132
 
132
133
  # Stub load and save to avoid thor.yaml from being overwritten
133
- YAML.stub!(:load_file).and_return(@original_yaml)
134
- File.stub!(:exists?).with(root_file).and_return(true)
135
- File.stub!(:open).with(root_file, "w")
134
+ allow(YAML).to receive(:load_file).and_return(@original_yaml)
135
+ allow(File).to receive(:exist?).with(root_file).and_return(true)
136
+ allow(File).to receive(:open).with(root_file, "w")
136
137
  end
137
138
 
138
139
  describe "list" do
139
140
  it "gives a list of the available commands" do
140
- ARGV.replace ["list"]
141
+ ARGV.replace %w[list]
141
142
  content = capture(:stdout) { Thor::Runner.start }
142
143
  expect(content).to match(/amazing:describe NAME\s+# say that someone is amazing/m)
143
144
  end
144
145
 
145
146
  it "gives a list of the available Thor::Group classes" do
146
- ARGV.replace ["list"]
147
+ ARGV.replace %w[list]
147
148
  expect(capture(:stdout) { Thor::Runner.start }).to match(/my_counter N/)
148
149
  end
149
150
 
150
151
  it "can filter a list of the available commands by --group" do
151
- ARGV.replace ["list", "--group", "standard"]
152
+ ARGV.replace %w[list --group standard]
152
153
  expect(capture(:stdout) { Thor::Runner.start }).to match(/amazing:describe NAME/)
153
154
  ARGV.replace []
154
155
  expect(capture(:stdout) { Thor::Runner.start }).not_to match(/my_script:animal TYPE/)
155
- ARGV.replace ["list", "--group", "script"]
156
+ ARGV.replace %w[list --group script]
156
157
  expect(capture(:stdout) { Thor::Runner.start }).to match(/my_script:animal TYPE/)
157
158
  end
158
159
 
159
160
  it "can skip all filters to show all commands using --all" do
160
- ARGV.replace ["list", "--all"]
161
+ ARGV.replace %w[list --all]
161
162
  content = capture(:stdout) { Thor::Runner.start }
162
163
  expect(content).to match(/amazing:describe NAME/)
163
164
  expect(content).to match(/my_script:animal TYPE/)
164
165
  end
165
166
 
166
167
  it "doesn't list superclass commands in the subclass" do
167
- ARGV.replace ["list"]
168
+ ARGV.replace %w[list]
168
169
  expect(capture(:stdout) { Thor::Runner.start }).not_to match(/amazing:help/)
169
170
  end
170
171
 
171
172
  it "presents commands in the default namespace with an empty namespace" do
172
- ARGV.replace ["list"]
173
+ ARGV.replace %w[list]
173
174
  expect(capture(:stdout) { Thor::Runner.start }).to match(/^thor :cow\s+# prints 'moo'/m)
174
175
  end
175
176
 
176
177
  it "runs commands with an empty namespace from the default namespace" do
177
- ARGV.replace [":command_conflict"]
178
+ ARGV.replace %w[:command_conflict]
178
179
  expect(capture(:stdout) { Thor::Runner.start }).to eq("command\n")
179
180
  end
180
181
 
181
182
  it "runs groups even when there is a command with the same name" do
182
- ARGV.replace ["command_conflict"]
183
+ ARGV.replace %w[command_conflict]
183
184
  expect(capture(:stdout) { Thor::Runner.start }).to eq("group\n")
184
185
  end
185
186
 
186
187
  it "runs commands with no colon in the default namespace" do
187
- ARGV.replace ["cow"]
188
+ ARGV.replace %w[cow]
188
189
  expect(capture(:stdout) { Thor::Runner.start }).to eq("moo\n")
189
190
  end
190
191
  end
@@ -192,21 +193,21 @@ describe Thor::Runner do
192
193
  describe "uninstall" do
193
194
  before do
194
195
  path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
195
- FileUtils.should_receive(:rm_rf).with(path)
196
+ expect(FileUtils).to receive(:rm_rf).with(path)
196
197
  end
197
198
 
198
199
  it "uninstalls existing thor modules" do
199
- silence(:stdout) { Thor::Runner.start(["uninstall", "random"]) }
200
+ silence(:stdout) { Thor::Runner.start(%w[uninstall random]) }
200
201
  end
201
202
  end
202
203
 
203
204
  describe "installed" do
204
205
  before do
205
- Dir.should_receive(:[]).and_return([])
206
+ expect(Dir).to receive(:[]).and_return([])
206
207
  end
207
208
 
208
209
  it "displays the modules installed in a pretty way" do
209
- stdout = capture(:stdout) { Thor::Runner.start(["installed"]) }
210
+ stdout = capture(:stdout) { Thor::Runner.start(%w[installed]) }
210
211
  expect(stdout).to match(/random\s*amazing/)
211
212
  expect(stdout).to match(/amazing:describe NAME\s+# say that someone is amazing/m)
212
213
  end
@@ -214,27 +215,31 @@ describe Thor::Runner do
214
215
 
215
216
  describe "install/update" do
216
217
  before do
217
- FileUtils.stub!(:mkdir_p)
218
- FileUtils.stub!(:touch)
219
- $stdin.stub!(:gets).and_return("Y")
218
+ allow(FileUtils).to receive(:mkdir_p)
219
+ allow(FileUtils).to receive(:touch)
220
+ allow(Thor::LineEditor).to receive(:readline).and_return("Y")
220
221
 
221
222
  path = File.join(Thor::Util.thor_root, Digest::MD5.hexdigest(@location + "random"))
222
- File.should_receive(:open).with(path, "w")
223
+ expect(File).to receive(:open).with(path, "w")
223
224
  end
224
225
 
225
226
  it "updates existing thor files" do
226
227
  path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
227
228
  if File.directory? path
228
- FileUtils.should_receive(:rm_rf).with(path)
229
+ expect(FileUtils).to receive(:rm_rf).with(path)
229
230
  else
230
- File.should_receive(:delete).with(path)
231
+ expect(File).to receive(:delete).with(path)
232
+ end
233
+ silence_warnings do
234
+ silence(:stdout) { Thor::Runner.start(%w[update random]) }
231
235
  end
232
- silence(:stdout) { Thor::Runner.start(["update", "random"]) }
233
236
  end
234
237
 
235
238
  it "installs thor files" do
236
- ARGV.replace ["install", @location]
237
- silence(:stdout) { Thor::Runner.start }
239
+ ARGV.replace %W[install #{@location}]
240
+ silence_warnings do
241
+ silence(:stdout) { Thor::Runner.start }
242
+ end
238
243
  end
239
244
  end
240
245
  end