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
|
require File.expand_path(File.dirname(__FILE__) + "/spec_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
capture(:stdout){ Thor::Runner.start(["help"]) }.should =~ /List the available thor tasks/
end
it "shows information about an specific Thor::Runner task" do
content = capture(:stdout){ Thor::Runner.start(["help", "list"]) }
content.should =~ /List the available thor tasks/
content.should_not =~ /help \[TASK\]/
end
it "shows information about a specific Thor class" do
content = capture(:stdout){ Thor::Runner.start(["help", "my_script"]) }
content.should =~ /zoo\s+# zoo around/m
end
it "shows information about an specific task from an specific Thor class" do
content = capture(:stdout){ Thor::Runner.start(["help", "my_script:zoo"]) }
content.should =~ /zoo around/
content.should_not =~ /help \[TASK\]/
end
it "shows information about a specific Thor group class" do
content = capture(:stdout){ Thor::Runner.start(["help", "my_counter"]) }
content.should =~ /my_counter N/
end
it "raises error if a class/task cannot be found" do
content = capture(:stderr){ Thor::Runner.start(["help", "unknown"]) }
content.strip.should == 'Could not find task "unknown" in "default" namespace.'
end
it "raises error if a class/task cannot be found for a setup without thorfiles" do
when_no_thorfiles_exist do
Thor::Runner.should_receive :exit
content = capture(:stderr){ Thor::Runner.start(["help", "unknown"]) }
content.strip.should == 'Could not find task "unknown".'
end
end
end
describe "#start" do
it "invokes a task from Thor::Runner" do
ARGV.replace ["list"]
capture(:stdout){ Thor::Runner.start }.should =~ /my_counter N/
end
it "invokes a task from a specific Thor class" do
ARGV.replace ["my_script:zoo"]
Thor::Runner.start.should be_true
end
it "invokes the default task from a specific Thor class if none is specified" do
ARGV.replace ["my_script"]
Thor::Runner.start.should == "default task"
end
it "forwads arguments to the invoked task" do
ARGV.replace ["my_script:animal", "horse"]
Thor::Runner.start.should == ["horse"]
end
it "invokes tasks through shortcuts" do
ARGV.replace ["my_script", "-T", "horse"]
Thor::Runner.start.should == ["horse"]
end
it "invokes a Thor::Group" do
ARGV.replace ["my_counter", "1", "2", "--third", "3"]
Thor::Runner.start.should == [1, 2, 3]
end
it "raises an error if class/task can't be found" do
ARGV.replace ["unknown"]
content = capture(:stderr){ Thor::Runner.start }
content.strip.should == 'Could not find task "unknown" in "default" namespace.'
end
it "raises an error if class/task can't be found in a setup without thorfiles" do
when_no_thorfiles_exist do
ARGV.replace ["unknown"]
Thor::Runner.should_receive :exit
content = capture(:stderr){ Thor::Runner.start }
content.strip.should == 'Could not find task "unknown".'
end
end
it "does not swallow NoMethodErrors that occur inside the called method" do
ARGV.replace ["my_script:call_unexistent_method"]
lambda { Thor::Runner.start }.should raise_error(NoMethodError)
end
it "does not swallow Thor::Group InvocationError" do
ARGV.replace ["whiny_generator"]
lambda { Thor::Runner.start }.should raise_error(ArgumentError, /thor wrong_arity takes 1 argument, but it should not/)
end
it "does not swallow Thor InvocationError" do
ARGV.replace ["my_script:animal"]
content = capture(:stderr) { Thor::Runner.start }
content.strip.should == 'thor animal requires at least 1 argument: "thor my_script:animal TYPE".'
end
end
describe "tasks" do
before do
@location = "#{File.dirname(__FILE__)}/fixtures/task.thor"
@original_yaml = {
"random" => {
:location => @location,
:filename => "4a33b894ffce85d7b412fc1b36f88fe0",
:namespaces => ["amazing"]
}
}
root_file = File.join(Thor::Util.thor_root, "thor.yml")
# Stub load and save to avoid thor.yaml from being overwritten
YAML.stub!(:load_file).and_return(@original_yaml)
File.stub!(:exists?).with(root_file).and_return(true)
File.stub!(:open).with(root_file, "w")
end
describe "list" do
it "gives a list of the available tasks" do
ARGV.replace ["list"]
content = capture(:stdout) { Thor::Runner.start }
content.should =~ /amazing:describe NAME\s+# say that someone is amazing/m
end
it "gives a list of the available Thor::Group classes" do
ARGV.replace ["list"]
capture(:stdout) { Thor::Runner.start }.should =~ /my_counter N/
end
it "can filter a list of the available tasks by --group" do
ARGV.replace ["list", "--group", "standard"]
capture(:stdout) { Thor::Runner.start }.should =~ /amazing:describe NAME/
ARGV.replace []
capture(:stdout) { Thor::Runner.start }.should_not =~ /my_script:animal TYPE/
ARGV.replace ["list", "--group", "script"]
capture(:stdout) { Thor::Runner.start }.should =~ /my_script:animal TYPE/
end
it "can skip all filters to show all tasks using --all" do
ARGV.replace ["list", "--all"]
content = capture(:stdout) { Thor::Runner.start }
content.should =~ /amazing:describe NAME/
content.should =~ /my_script:animal TYPE/
end
it "doesn't list superclass tasks in the subclass" do
ARGV.replace ["list"]
capture(:stdout) { Thor::Runner.start }.should_not =~ /amazing:help/
end
it "presents tasks in the default namespace with an empty namespace" do
ARGV.replace ["list"]
capture(:stdout) { Thor::Runner.start }.should =~ /^thor :cow\s+# prints 'moo'/m
end
it "runs tasks with an empty namespace from the default namespace" do
ARGV.replace [":task_conflict"]
capture(:stdout) { Thor::Runner.start }.should == "task\n"
end
it "runs groups even when there is a task with the same name" do
ARGV.replace ["task_conflict"]
capture(:stdout) { Thor::Runner.start }.should == "group\n"
end
it "runs tasks with no colon in the default namespace" do
ARGV.replace ["cow"]
capture(:stdout) { Thor::Runner.start }.should == "moo\n"
end
end
describe "uninstall" do
before do
path = File.join(Thor::Util.thor_root, @original_yaml["random"][:filename])
FileUtils.should_receive(:rm_rf).with(path)
end
it "uninstalls existing thor modules" do
silence(:stdout) { Thor::Runner.start(["uninstall", "random"]) }
end
end
describe "installed" do
before do
Dir.should_receive(:[]).and_return([])
end
it "displays the modules installed in a pretty way" do
stdout = capture(:stdout) { Thor::Runner.start(["installed"]) }
stdout.should =~ /random\s*amazing/
stdout.should =~ /amazing:describe NAME\s+# say that someone is amazing/m
end
end
describe "install/update" do
before do
FileUtils.stub!(:mkdir_p)
FileUtils.stub!(:touch)
$stdin.stub!(:gets).and_return("Y")
path = File.join(Thor::Util.thor_root, Digest::MD5.hexdigest(@location + "random"))
File.should_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
FileUtils.should_receive(:rm_rf).with(path)
else
File.should_receive(:delete).with(path)
end
silence(:stdout) { Thor::Runner.start(["update", "random"]) }
end
it "installs thor files" do
ARGV.replace ["install", @location]
silence(:stdout) { Thor::Runner.start }
end
end
end
end
|