1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
|
require "helper"
require "thor/runner"
describe Thor::Runner do
def when_no_thorfiles_exist
old_dir = Dir.pwd
Dir.chdir ".."
delete = Thor::Base.subclasses.select { |e| e.namespace == "default" }
delete.each { |e| Thor::Base.subclasses.delete e }
yield
Thor::Base.subclasses.concat delete
Dir.chdir old_dir
end
describe "#help" do
it "shows information about Thor::Runner itself" do
expect(capture(:stdout) { Thor::Runner.start(%w[help]) }).to match(/List the available thor commands/)
end
it "shows information about a specific Thor::Runner command" do
content = capture(:stdout) { Thor::Runner.start(%w[help list]) }
expect(content).to match(/List the available thor commands/)
expect(content).not_to match(/help \[COMMAND\]/)
end
it "shows information about a specific Thor class" do
content = capture(:stdout) { Thor::Runner.start(%w[help my_script]) }
expect(content).to match(/zoo\s+# zoo around/m)
end
it "shows information about a specific command from a specific Thor class" do
content = capture(:stdout) { Thor::Runner.start(%w[help my_script:zoo]) }
expect(content).to match(/zoo around/)
expect(content).not_to match(/help \[COMMAND\]/)
end
it "shows information about a specific Thor group class" do
content = capture(:stdout) { Thor::Runner.start(%w[help my_counter]) }
expect(content).to match(/my_counter N/)
end
it "raises error if a class/command cannot be found" do
content = capture(:stderr) { Thor::Runner.start(%w[help unknown]) }
expect(content.strip).to eq('Could not find command "unknown" in "default" namespace.')
end
it "raises error if a class/command cannot be found for a setup without thorfiles" do
when_no_thorfiles_exist do
expect(Thor::Runner).to receive :exit
content = capture(:stderr) { Thor::Runner.start(%w[help unknown]) }
expect(content.strip).to eq('Could not find command "unknown".')
end
end
end
describe "#start" do
it "invokes a command from Thor::Runner" do
ARGV.replace %w[list]
expect(capture(:stdout) { Thor::Runner.start }).to match(/my_counter N/)
end
it "invokes a command from a specific Thor class" do
ARGV.replace %w[my_script:zoo]
expect(Thor::Runner.start).to be true
end
it "invokes the default command from a specific Thor class if none is specified" do
ARGV.replace %w[my_script]
expect(Thor::Runner.start).to eq("default command")
end
it "forwards arguments to the invoked command" do
ARGV.replace %w[my_script:animal horse]
expect(Thor::Runner.start).to eq(%w[horse])
end
it "invokes commands through shortcuts" do
ARGV.replace %w[my_script -T horse]
expect(Thor::Runner.start).to eq(%w[horse])
end
it "invokes a Thor::Group" do
ARGV.replace %w[my_counter 1 2 --third 3]
expect(Thor::Runner.start).to eq([1, 2, 3, nil, nil, nil])
end
it "raises an error if class/command can't be found" do
ARGV.replace %w[unknown]
content = capture(:stderr) { Thor::Runner.start }
expect(content.strip).to eq('Could not find command "unknown" in "default" namespace.')
end
it "raises an error if class/command can't be found in a setup without thorfiles" do
when_no_thorfiles_exist do
ARGV.replace %w[unknown]
expect(Thor::Runner).to receive :exit
content = capture(:stderr) { Thor::Runner.start }
expect(content.strip).to eq('Could not find command "unknown".')
end
end
it "does not swallow NoMethodErrors that occur inside the called method" do
ARGV.replace %w[my_script:call_unexistent_method]
expect { Thor::Runner.start }.to raise_error(NoMethodError)
end
it "does not swallow Thor::Group InvocationError" do
ARGV.replace %w[whiny_generator]
expect { Thor::Runner.start }.to raise_error(ArgumentError, /thor wrong_arity takes 1 argument, but it should not/)
end
it "does not swallow Thor InvocationError" do
ARGV.replace %w[my_script:animal]
content = capture(:stderr) { Thor::Runner.start }
expect(content.strip).to eq(%Q(ERROR: "thor animal" was called with no arguments
Usage: "thor my_script:animal TYPE"))
end
end
describe "commands" do
before do
@location = "#{File.dirname(__FILE__)}/fixtures/command.thor"
@original_yaml = {
"random" => {
:location => @location,
:filename => "4a33b894ffce85d7b412fc1b36f88fe0",
:namespaces => %w[amazing]
}
}
root_file = File.join(Thor::Util.thor_root, "thor.yml")
# Stub load and save to avoid thor.yaml from being overwritten
allow(YAML).to receive(:load_file).and_return(@original_yaml)
allow(File).to receive(:exist?).with(root_file).and_return(true)
allow(File).to receive(:open).with(root_file, "w")
end
describe "list" do
it "gives a list of the available commands" do
ARGV.replace %w[list]
content = capture(:stdout) { Thor::Runner.start }
expect(content).to match(/amazing:describe NAME\s+# say that someone is amazing/m)
end
it "gives a list of the available Thor::Group classes" do
ARGV.replace %w[list]
expect(capture(:stdout) { Thor::Runner.start }).to match(/my_counter N/)
end
it "can filter a list of the available commands by --group" do
ARGV.replace %w[list --group standard]
expect(capture(:stdout) { Thor::Runner.start }).to match(/amazing:describe NAME/)
ARGV.replace []
expect(capture(:stdout) { Thor::Runner.start }).not_to match(/my_script:animal TYPE/)
ARGV.replace %w[list --group script]
expect(capture(:stdout) { Thor::Runner.start }).to match(/my_script:animal TYPE/)
end
it "can skip all filters to show all commands using --all" do
ARGV.replace %w[list --all]
content = capture(:stdout) { Thor::Runner.start }
expect(content).to match(/amazing:describe NAME/)
expect(content).to match(/my_script:animal TYPE/)
end
it "doesn't list superclass commands in the subclass" do
ARGV.replace %w[list]
expect(capture(:stdout) { Thor::Runner.start }).not_to match(/amazing:help/)
end
it "presents commands in the default namespace with an empty namespace" do
ARGV.replace %w[list]
expect(capture(:stdout) { Thor::Runner.start }).to match(/^thor :cow\s+# prints 'moo'/m)
end
it "runs commands with an empty namespace from the default namespace" do
ARGV.replace %w[:command_conflict]
expect(capture(:stdout) { Thor::Runner.start }).to eq("command\n")
end
it "runs groups even when there is a command with the same name" do
ARGV.replace %w[command_conflict]
expect(capture(:stdout) { Thor::Runner.start }).to eq("group\n")
end
it "runs commands with no colon in the default namespace" do
ARGV.replace %w[cow]
expect(capture(:stdout) { Thor::Runner.start }).to eq("moo\n")
end
end
describe "uninstall" do
before do
path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
expect(FileUtils).to receive(:rm_rf).with(path)
end
it "uninstalls existing thor modules" do
silence(:stdout) { Thor::Runner.start(%w[uninstall random]) }
end
end
describe "installed" do
before do
expect(Dir).to receive(:[]).and_return([])
end
it "displays the modules installed in a pretty way" do
stdout = capture(:stdout) { Thor::Runner.start(%w[installed]) }
expect(stdout).to match(/random\s*amazing/)
expect(stdout).to match(/amazing:describe NAME\s+# say that someone is amazing/m)
end
end
describe "install/update" do
before do
allow(FileUtils).to receive(:mkdir_p)
allow(FileUtils).to receive(:touch)
allow(Thor::LineEditor).to receive(:readline).and_return("Y")
path = File.join(Thor::Util.thor_root, Digest::MD5.hexdigest(@location + "random"))
expect(File).to receive(:open).with(path, "w")
end
it "updates existing thor files" do
path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
if File.directory? path
expect(FileUtils).to receive(:rm_rf).with(path)
else
expect(File).to receive(:delete).with(path)
end
silence_warnings do
silence(:stdout) { Thor::Runner.start(%w[update random]) }
end
end
it "installs thor files" do
ARGV.replace %W[install #{@location}]
silence_warnings do
silence(:stdout) { Thor::Runner.start }
end
end
end
end
end
|