thor 0.18.1 → 0.19.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.
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