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
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
describe Thor::Group do
describe "task" do
it "allows to use private methods from parent class as tasks" do
ChildGroup.start.should == ["bar", "foo", "baz"]
ChildGroup.new.baz("bar").should == "bar"
end
end
describe "#start" do
it "invokes all the tasks under the Thor group" do
MyCounter.start(["1", "2", "--third", "3"]).should == [ 1, 2, 3 ]
end
it "uses argument default value" do
MyCounter.start(["1", "--third", "3"]).should == [ 1, 2, 3 ]
end
it "invokes all the tasks in the Thor group and his parents" do
BrokenCounter.start(["1", "2", "--third", "3"]).should == [ nil, 2, 3, false, 5 ]
end
it "raises an error if a required argument is added after a non-required" do
lambda {
MyCounter.argument(:foo, :type => :string)
}.should raise_error(ArgumentError, 'You cannot have "foo" as required argument after the non-required argument "second".')
end
it "raises when an exception happens within the task call" do
lambda { BrokenCounter.start(["1", "2", "--fail"]) }.should raise_error
end
it "raises an error when a Thor group task expects arguments" do
lambda { WhinyGenerator.start }.should raise_error(ArgumentError, /thor wrong_arity takes 1 argument, but it should not/)
end
it "invokes help message if any of the shortcuts is given" do
MyCounter.should_receive(:help)
MyCounter.start(["-h"])
end
end
describe "#desc" do
it "sets the description for a given class" do
MyCounter.desc.should == "Description:\n This generator runs three tasks: one, two and three.\n"
end
it "can be inherited" do
BrokenCounter.desc.should == "Description:\n This generator runs three tasks: one, two and three.\n"
end
it "can be nil" do
WhinyGenerator.desc.should be_nil
end
end
describe "#help" do
before do
@content = capture(:stdout){ MyCounter.help(Thor::Base.shell.new) }
end
it "provides usage information" do
@content.should =~ /my_counter N \[N\]/
end
it "shows description" do
@content.should =~ /Description:/
@content.should =~ /This generator runs three tasks: one, two and three./
end
it "shows options information" do
@content.should =~ /Options/
@content.should =~ /\[\-\-third=THREE\]/
end
end
describe "#invoke" do
before do
@content = capture(:stdout){ E.start }
end
it "allows to invoke a class from the class binding" do
@content.should =~ /1\n2\n3\n4\n5\n/
end
it "shows invocation information to the user" do
@content.should =~ /invoke Defined/
end
it "uses padding on status generated by the invoked class" do
@content.should =~ /finished counting/
end
it "allows invocation to be configured with blocks" do
capture(:stdout) do
F.start.should == ["Valim, Jose"]
end
end
it "shows invoked options on help" do
content = capture(:stdout){ E.help(Thor::Base.shell.new) }
content.should =~ /Defined options:/
content.should =~ /\[--unused\]/
content.should =~ /# This option has no use/
end
end
describe "#invoke_from_option" do
describe "with default type" do
before do
@content = capture(:stdout){ G.start }
end
it "allows to invoke a class from the class binding by a default option" do
@content.should =~ /1\n2\n3\n4\n5\n/
end
it "does not invoke if the option is nil" do
capture(:stdout){ G.start(["--skip-invoked"]) }.should_not =~ /invoke/
end
it "prints a message if invocation cannot be found" do
content = capture(:stdout){ G.start(["--invoked", "unknown"]) }
content.should =~ /error unknown \[not found\]/
end
it "allows to invoke a class from the class binding by the given option" do
content = capture(:stdout){ G.start(["--invoked", "e"]) }
content.should =~ /invoke e/
end
it "shows invocation information to the user" do
@content.should =~ /invoke defined/
end
it "uses padding on status generated by the invoked class" do
@content.should =~ /finished counting/
end
it "shows invoked options on help" do
content = capture(:stdout){ G.help(Thor::Base.shell.new) }
content.should =~ /defined options:/
content.should =~ /\[--unused\]/
content.should =~ /# This option has no use/
end
end
describe "with boolean type" do
before do
@content = capture(:stdout){ H.start }
end
it "allows to invoke a class from the class binding by a default option" do
@content.should =~ /1\n2\n3\n4\n5\n/
end
it "does not invoke if the option is false" do
capture(:stdout){ H.start(["--no-defined"]) }.should_not =~ /invoke/
end
it "shows invocation information to the user" do
@content.should =~ /invoke defined/
end
it "uses padding on status generated by the invoked class" do
@content.should =~ /finished counting/
end
it "shows invoked options on help" do
content = capture(:stdout){ H.help(Thor::Base.shell.new) }
content.should =~ /defined options:/
content.should =~ /\[--unused\]/
content.should =~ /# This option has no use/
end
end
end
describe "edge-cases" do
it "can handle boolean options followed by arguments" do
klass = Class.new(Thor::Group) do
desc "say hi to name"
argument :name, :type => :string
class_option :loud, :type => :boolean
def hi
name.upcase! if options[:loud]
"Hi #{name}"
end
end
klass.start(["jose"]).should == ["Hi jose"]
klass.start(["jose", "--loud"]).should == ["Hi JOSE"]
klass.start(["--loud", "jose"]).should == ["Hi JOSE"]
end
it "provides extra args as `args`" do
klass = Class.new(Thor::Group) do
desc "say hi to name"
argument :name, :type => :string
class_option :loud, :type => :boolean
def hi
name.upcase! if options[:loud]
out = "Hi #{name}"
out << ": " << args.join(", ") unless args.empty?
out
end
end
klass.start(["jose"]).should == ["Hi jose"]
klass.start(["jose", "--loud"]).should == ["Hi JOSE"]
klass.start(["--loud", "jose"]).should == ["Hi JOSE"]
end
end
end
|