Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 217 lines (175 sloc) 6.644 kb
d73796e @josevalim Generators first scratch.
josevalim authored
1 require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
50a6f71 @josevalim Thor::Generator is now Thor::Group.
josevalim authored
3 describe Thor::Group do
d54bced @drogus Allow to use private methods from superclass as tasks
drogus authored
4 describe "task" do
5 it "allows to use private methods from parent class as tasks" do
35b14a9 @sferik Add rcov to bundle
sferik authored
6 ChildGroup.start.should == ["bar", "foo", "baz"]
7 ChildGroup.new.baz("bar").should == "bar"
d54bced @drogus Allow to use private methods from superclass as tasks
drogus authored
8 end
9 end
10
76383c7 @josevalim More specs, more documentation.
josevalim authored
11 describe "#start" do
50a6f71 @josevalim Thor::Generator is now Thor::Group.
josevalim authored
12 it "invokes all the tasks under the Thor group" do
35b14a9 @sferik Add rcov to bundle
sferik authored
13 MyCounter.start(["1", "2", "--third", "3"]).should == [ 1, 2, 3 ]
76383c7 @josevalim More specs, more documentation.
josevalim authored
14 end
15
bb35d61 @josevalim Arguments can be optional too (the main difference from options then is ...
josevalim authored
16 it "uses argument default value" do
35b14a9 @sferik Add rcov to bundle
sferik authored
17 MyCounter.start(["1", "--third", "3"]).should == [ 1, 2, 3 ]
bb35d61 @josevalim Arguments can be optional too (the main difference from options then is ...
josevalim authored
18 end
19
50a6f71 @josevalim Thor::Generator is now Thor::Group.
josevalim authored
20 it "invokes all the tasks in the Thor group and his parents" do
35b14a9 @sferik Add rcov to bundle
sferik authored
21 BrokenCounter.start(["1", "2", "--third", "3"]).should == [ nil, 2, 3, false, 5 ]
76383c7 @josevalim More specs, more documentation.
josevalim authored
22 end
23
bb35d61 @josevalim Arguments can be optional too (the main difference from options then is ...
josevalim authored
24 it "raises an error if a required argument is added after a non-required" do
25 lambda {
26 MyCounter.argument(:foo, :type => :string)
35b14a9 @sferik Add rcov to bundle
sferik authored
27 }.should raise_error(ArgumentError, 'You cannot have "foo" as required argument after the non-required argument "second".')
76383c7 @josevalim More specs, more documentation.
josevalim authored
28 end
29
30 it "raises when an exception happens within the task call" do
35b14a9 @sferik Add rcov to bundle
sferik authored
31 lambda { BrokenCounter.start(["1", "2", "--fail"]) }.should raise_error
76383c7 @josevalim More specs, more documentation.
josevalim authored
32 end
33
50a6f71 @josevalim Thor::Generator is now Thor::Group.
josevalim authored
34 it "raises an error when a Thor group task expects arguments" do
a24b669 @wycats More friendly error messages (ht: @tomdale)
wycats authored
35 lambda { WhinyGenerator.start }.should raise_error(ArgumentError, /thor wrong_arity takes 1 argument, but it should not/)
76383c7 @josevalim More specs, more documentation.
josevalim authored
36 end
ebfaf3b @josevalim Spec'ing that help is called on generators when -h is supplied.
josevalim authored
37
38 it "invokes help message if any of the shortcuts is given" do
a72d0f4 @josevalim Bye bye RR. Hello Rspec mocks.
josevalim authored
39 MyCounter.should_receive(:help)
ebfaf3b @josevalim Spec'ing that help is called on generators when -h is supplied.
josevalim authored
40 MyCounter.start(["-h"])
41 end
76383c7 @josevalim More specs, more documentation.
josevalim authored
42 end
1754f44 @josevalim Improving #help coverage.
josevalim authored
43
413b830 @josevalim USAGE file is automatically used as description if it exists in the dest...
josevalim authored
44 describe "#desc" do
45 it "sets the description for a given class" do
35b14a9 @sferik Add rcov to bundle
sferik authored
46 MyCounter.desc.should == "Description:\n This generator runs three tasks: one, two and three.\n"
413b830 @josevalim USAGE file is automatically used as description if it exists in the dest...
josevalim authored
47 end
48
49 it "can be inherited" do
35b14a9 @sferik Add rcov to bundle
sferik authored
50 BrokenCounter.desc.should == "Description:\n This generator runs three tasks: one, two and three.\n"
413b830 @josevalim USAGE file is automatically used as description if it exists in the dest...
josevalim authored
51 end
52
51c5a4e @josevalim Remove USAGE file check. It was ported to Rails since it's rails specifi...
josevalim authored
53 it "can be nil" do
35b14a9 @sferik Add rcov to bundle
sferik authored
54 WhinyGenerator.desc.should be_nil
413b830 @josevalim USAGE file is automatically used as description if it exists in the dest...
josevalim authored
55 end
56 end
57
1754f44 @josevalim Improving #help coverage.
josevalim authored
58 describe "#help" do
59 before(:each) do
68f8ed5 @josevalim Shells should be instantiated and can be given as arguments to start.
josevalim authored
60 @content = capture(:stdout){ MyCounter.help(Thor::Base.shell.new) }
1754f44 @josevalim Improving #help coverage.
josevalim authored
61 end
62
63 it "provides usage information" do
35b14a9 @sferik Add rcov to bundle
sferik authored
64 @content.should =~ /my_counter N \[N\]/
1754f44 @josevalim Improving #help coverage.
josevalim authored
65 end
66
2212ae3 @josevalim Add description to Thor::Group.
josevalim authored
67 it "shows description" do
35b14a9 @sferik Add rcov to bundle
sferik authored
68 @content.should =~ /Description:/
69 @content.should =~ /This generator runs three tasks: one, two and three./
2212ae3 @josevalim Add description to Thor::Group.
josevalim authored
70 end
71
40d6950 @josevalim Use padding in options that does not have aliases.
josevalim authored
72 it "shows options information" do
35b14a9 @sferik Add rcov to bundle
sferik authored
73 @content.should =~ /Options/
74 @content.should =~ /\[\-\-third=THREE\]/
1754f44 @josevalim Improving #help coverage.
josevalim authored
75 end
76 end
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
77
78 describe "#invoke" do
79 before(:each) do
80 @content = capture(:stdout){ E.start }
81 end
82
83 it "allows to invoke a class from the class binding" do
35b14a9 @sferik Add rcov to bundle
sferik authored
84 @content.should =~ /1\n2\n3\n4\n5\n/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
85 end
86
87 it "shows invocation information to the user" do
35b14a9 @sferik Add rcov to bundle
sferik authored
88 @content.should =~ /invoke Defined/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
89 end
90
91 it "uses padding on status generated by the invoked class" do
35b14a9 @sferik Add rcov to bundle
sferik authored
92 @content.should =~ /finished counting/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
93 end
94
95 it "allows invocation to be configured with blocks" do
96 capture(:stdout) do
35b14a9 @sferik Add rcov to bundle
sferik authored
97 F.start.should == ["Valim, Jose"]
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
98 end
99 end
100
101 it "shows invoked options on help" do
102 content = capture(:stdout){ E.help(Thor::Base.shell.new) }
35b14a9 @sferik Add rcov to bundle
sferik authored
103 content.should =~ /Defined options:/
104 content.should =~ /\[--unused\]/
105 content.should =~ /# This option has no use/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
106 end
107 end
108
109 describe "#invoke_from_option" do
110 describe "with default type" do
111 before(:each) do
112 @content = capture(:stdout){ G.start }
113 end
114
115 it "allows to invoke a class from the class binding by a default option" do
35b14a9 @sferik Add rcov to bundle
sferik authored
116 @content.should =~ /1\n2\n3\n4\n5\n/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
117 end
118
119 it "does not invoke if the option is nil" do
35b14a9 @sferik Add rcov to bundle
sferik authored
120 capture(:stdout){ G.start(["--skip-invoked"]) }.should_not =~ /invoke/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
121 end
122
123 it "prints a message if invocation cannot be found" do
124 content = capture(:stdout){ G.start(["--invoked", "unknown"]) }
35b14a9 @sferik Add rcov to bundle
sferik authored
125 content.should =~ /error unknown \[not found\]/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
126 end
127
128 it "allows to invoke a class from the class binding by the given option" do
129 content = capture(:stdout){ G.start(["--invoked", "e"]) }
35b14a9 @sferik Add rcov to bundle
sferik authored
130 content.should =~ /invoke e/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
131 end
132
133 it "shows invocation information to the user" do
35b14a9 @sferik Add rcov to bundle
sferik authored
134 @content.should =~ /invoke defined/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
135 end
136
137 it "uses padding on status generated by the invoked class" do
35b14a9 @sferik Add rcov to bundle
sferik authored
138 @content.should =~ /finished counting/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
139 end
140
141 it "shows invoked options on help" do
142 content = capture(:stdout){ G.help(Thor::Base.shell.new) }
35b14a9 @sferik Add rcov to bundle
sferik authored
143 content.should =~ /defined options:/
144 content.should =~ /\[--unused\]/
145 content.should =~ /# This option has no use/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
146 end
147 end
148
149 describe "with boolean type" do
150 before(:each) do
151 @content = capture(:stdout){ H.start }
152 end
153
154 it "allows to invoke a class from the class binding by a default option" do
35b14a9 @sferik Add rcov to bundle
sferik authored
155 @content.should =~ /1\n2\n3\n4\n5\n/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
156 end
157
158 it "does not invoke if the option is false" do
35b14a9 @sferik Add rcov to bundle
sferik authored
159 capture(:stdout){ H.start(["--no-defined"]) }.should_not =~ /invoke/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
160 end
161
162 it "shows invocation information to the user" do
35b14a9 @sferik Add rcov to bundle
sferik authored
163 @content.should =~ /invoke defined/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
164 end
165
166 it "uses padding on status generated by the invoked class" do
35b14a9 @sferik Add rcov to bundle
sferik authored
167 @content.should =~ /finished counting/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
168 end
169
170 it "shows invoked options on help" do
171 content = capture(:stdout){ H.help(Thor::Base.shell.new) }
35b14a9 @sferik Add rcov to bundle
sferik authored
172 content.should =~ /defined options:/
173 content.should =~ /\[--unused\]/
174 content.should =~ /# This option has no use/
364d6e3 @josevalim Added more specs to class method invocations.
josevalim authored
175 end
176 end
177 end
0cfe4af @wycats Changes in semantics:
wycats authored
178
179 describe "edge-cases" do
180 it "can handle boolean options followed by arguments" do
181 klass = Class.new(Thor::Group) do
182 desc "say hi to name"
183 argument :name, :type => :string
184 class_option :loud, :type => :boolean
185
186 def hi
187 name.upcase! if options[:loud]
188 "Hi #{name}"
189 end
190 end
191
192 klass.start(["jose"]).should == ["Hi jose"]
193 klass.start(["jose", "--loud"]).should == ["Hi JOSE"]
194 klass.start(["--loud", "jose"]).should == ["Hi JOSE"]
195 end
196
197 it "provides extra args as `args`" do
198 klass = Class.new(Thor::Group) do
199 desc "say hi to name"
200 argument :name, :type => :string
201 class_option :loud, :type => :boolean
202
203 def hi
204 name.upcase! if options[:loud]
205 out = "Hi #{name}"
206 out << ": " << args.join(", ") unless args.empty?
207 out
208 end
209 end
210
211 klass.start(["jose"]).should == ["Hi jose"]
212 klass.start(["jose", "--loud"]).should == ["Hi JOSE"]
213 klass.start(["--loud", "jose"]).should == ["Hi JOSE"]
214 end
215 end
d73796e @josevalim Generators first scratch.
josevalim authored
216 end
Something went wrong with that request. Please try again.