templater 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,72 @@
1
+ module Templater
2
+
3
+ module Manifold
4
+
5
+ attr_accessor :generators
6
+
7
+ # Add a generator to this manifold
8
+ #
9
+ # === Parameters
10
+ # name<Symbol>:: The name given to this generator in the manifold
11
+ # generator<Templater::Generator>:: The generator class
12
+ def add(name, generator)
13
+ @generators ||={}
14
+ @generators[name.to_sym] = generator
15
+ generator.manifold = self
16
+ (class << self; self; end).module_eval <<-MODULE
17
+ def #{name}
18
+ generator(:#{name})
19
+ end
20
+ MODULE
21
+ end
22
+
23
+ # Remove the generator with the given name from the manifold
24
+ #
25
+ # === Parameters
26
+ # name<Symbol>:: The name of the generator to be removed.
27
+ def remove(name)
28
+ @generators.delete(name.to_sym)
29
+ (class << self; self; end).module_eval <<-MODULE
30
+ undef #{name}
31
+ MODULE
32
+ end
33
+
34
+ # Finds the class of a generator, given its name in the manifold.
35
+ #
36
+ # === Parameters
37
+ # name<Symbol>:: The name of the generator to find
38
+ #
39
+ # === Returns
40
+ # Templater::Generator:: The found generator class
41
+ def generator(name)
42
+ @generators ||= {}
43
+ @generators[name.to_sym]
44
+ end
45
+
46
+ # A Shortcut method for invoking the command line interface provided with Templater.
47
+ #
48
+ # === Parameters
49
+ # destination_root<String>:: Where the generated files should be put, this would usually be Dir.pwd
50
+ # name<String>:: The name of the executable running this generator (such as 'merb-gen')
51
+ # version<String>:: The version number of the executable.
52
+ # args<Array[String]>:: An array of arguments to pass into the generator. This would usually be ARGV
53
+ def run_cli(destination_root, name, version, args)
54
+ Templater::CLI::Manifold.run(destination_root, self, name, version, args)
55
+ end
56
+
57
+ # If the argument is omitted, simply returns the description for this manifold, otherwise
58
+ # sets the description to the passed string.
59
+ #
60
+ # === Parameters
61
+ # text<String>:: A description
62
+ #
63
+ # === Returns
64
+ # String:: The description for this manifold
65
+ def desc(text = nil)
66
+ @text = text if text
67
+ return @text.realign_indentation
68
+ end
69
+
70
+ end
71
+
72
+ end
@@ -0,0 +1,66 @@
1
+ module Templater
2
+
3
+ class Proxy #:nodoc:
4
+
5
+ def initialize(name, source, destination, &block)
6
+ @block, @source, @destination = block, source, destination
7
+ @name = name.to_sym
8
+ end
9
+
10
+ def source(source)
11
+ @source = source
12
+ end
13
+
14
+ def destination(dest)
15
+ @destination = dest
16
+ end
17
+
18
+ def method_missing(method, *args, &block)
19
+ if @generator
20
+ @generator.send(method, *args, &block)
21
+ else
22
+ super
23
+ end
24
+ end
25
+
26
+ protected
27
+
28
+ def get_source
29
+ ::File.expand_path(@source.to_s, @generator.source_root)
30
+ end
31
+
32
+ def get_destination
33
+ ::File.expand_path(convert_encoded_instructions(@destination.to_s), @generator.destination_root)
34
+ end
35
+
36
+ def convert_encoded_instructions(filename)
37
+ filename.gsub(/%.*?%/) do |string|
38
+ instruction = string.match(/%(.*?)%/)[1]
39
+ @generator.respond_to?(instruction) ? @generator.send(instruction) : string
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ class TemplateProxy < Proxy #:nodoc:
46
+
47
+ def to_template(generator)
48
+ @generator = generator
49
+ instance_eval(&@block) if @block
50
+ Templater::Template.new(generator, @name, get_source, get_destination, true)
51
+ end
52
+
53
+ end
54
+
55
+ class FileProxy < Proxy #:nodoc:
56
+
57
+ def to_file(generator)
58
+ @generator = generator
59
+ instance_eval(&@block) if @block
60
+ @generator = nil
61
+ Templater::File.new(@name, ::File.join(generator.source_root, @source.to_s), ::File.join(generator.destination_root, @destination.to_s))
62
+ end
63
+
64
+ end
65
+
66
+ end
@@ -0,0 +1,67 @@
1
+ module Templater
2
+ class Template
3
+
4
+ attr_accessor :context, :name, :source, :destination, :options
5
+
6
+ # Builds a new template, given the context (e.g. binding) in which the template will be rendered
7
+ # (usually a generator), the name of the template and its source and destination.
8
+ #
9
+ # === Parameters
10
+ # context<Object>:: Context for rendering
11
+ # name<Symbol>:: The name of this template
12
+ # source<String>:: Full path to the source of this template
13
+ # destination<String>:: Full path to the destination of this template
14
+ # render<Boolean>:: If set to false, will do a copy instead of rendering.
15
+ def initialize(context, name, source, destination, render = true)
16
+ @context = context
17
+ @name = name
18
+ @source = source
19
+ @destination = destination
20
+ @options = { :render => render }
21
+ end
22
+
23
+ # Returns the destination path relative to Dir.pwd. This is useful for prettier output in interfaces
24
+ # where the destination root is Dir.pwd.
25
+ #
26
+ # === Returns
27
+ # String:: The destination relative to Dir.pwd
28
+ def relative_destination
29
+ @destination.sub(::Dir.pwd + '/', '')
30
+ end
31
+
32
+ # Renders the template using ERB and returns the result as a String.
33
+ #
34
+ # === Returns
35
+ # String:: The rendered template.
36
+ def render
37
+ ERB.new(::File.read(source), nil, '-').result(context.send(:binding))
38
+ end
39
+
40
+ # Checks if the destination file already exists.
41
+ #
42
+ # === Returns
43
+ # Boolean:: true if the file exists, false otherwise.
44
+ def exists?
45
+ ::File.exists?(destination)
46
+ end
47
+
48
+ # Checks if the content of the file at the destination is identical to the rendered result.
49
+ #
50
+ # === Returns
51
+ # Boolean:: true if it is identical, false otherwise.
52
+ def identical?
53
+ ::File.read(destination) == render if ::File.exists?(destination)
54
+ end
55
+
56
+ # Renders the template and copies it to the destination.
57
+ def invoke!
58
+ ::FileUtils.mkdir_p(::File.dirname(destination))
59
+ if options[:render]
60
+ ::File.open(destination, 'w') {|f| f.write render }
61
+ else
62
+ ::FileUtils.copy_file(source, destination)
63
+ end
64
+ end
65
+
66
+ end
67
+ end
@@ -0,0 +1,39 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe String, '#strip_indentation!' do
4
+
5
+ it "should remove unneccessary whitespace from the beginning of a line" do
6
+
7
+ a_string = <<-STRING
8
+ here be something
9
+ STRING
10
+
11
+ a_string.realign_indentation.should == <<-STRING
12
+ here be something
13
+ STRING
14
+
15
+ end
16
+
17
+ it "should remove unneccessary whitespace from the beginning of all lines, but keep indentation" do
18
+
19
+ a_string = <<-STRING
20
+ here be something
21
+ indented
22
+ more
23
+ blah
24
+ test
25
+ gurr
26
+ STRING
27
+
28
+ a_string.realign_indentation.should == <<-STRING
29
+ here be something
30
+ indented
31
+ more
32
+ blah
33
+ test
34
+ gurr
35
+ STRING
36
+
37
+ end
38
+
39
+ end
data/spec/file_spec.rb ADDED
@@ -0,0 +1,74 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Templater::File, '.new' do
4
+ it "should set name, source and destination" do
5
+ file = Templater::File.new(:monkey, '/path/to/source', '/path/to/destination')
6
+ file.name.should == :monkey
7
+ file.source.should == '/path/to/source'
8
+ file.destination.should == '/path/to/destination'
9
+ end
10
+ end
11
+
12
+ describe Templater::File, '#relative_destination' do
13
+ it "should get the destination relative to the pwd" do
14
+ Dir.stub!(:pwd).and_return('/path/to')
15
+ file = Templater::File.new(:monkey, '/path/to/source', '/path/to/destination/with/some/more/subdirs')
16
+ file.relative_destination.should == 'destination/with/some/more/subdirs'
17
+ end
18
+ end
19
+
20
+ describe Templater::File, '#render' do
21
+ it "should output the file" do
22
+ file = Templater::File.new(:monkey, template_path('simple_erb.rbt'), '/path/to/destination')
23
+ file.render.should == "test<%= 1+1 %>test"
24
+ end
25
+ end
26
+
27
+ describe Templater::File, '#exists?' do
28
+
29
+ it "should exist if the destination file exists" do
30
+ file = Templater::File.new(:monkey, template_path('simple.rbt'), result_path('erb.rbs'))
31
+ file.should be_exists
32
+ end
33
+
34
+ it "should not exist if the destination file does not exist" do
35
+ file = Templater::File.new(:monkey, template_path('simple.rbt'), result_path('some_weird_file.rbs'))
36
+ file.should_not be_exists
37
+ end
38
+
39
+ end
40
+
41
+ describe Templater::File, '#identical' do
42
+
43
+ it "should not be identical if the destination file doesn't exist" do
44
+ file = Templater::File.new(:monkey, template_path('simple_erb.rbt'), result_path('some_weird_file.rbs'))
45
+ file.should_not be_identical
46
+ end
47
+
48
+ it "should not be identical if the destination file is not identical to the source file" do
49
+ file = Templater::File.new(:monkey, template_path('simple_erb.rbt'), result_path('simple_erb.rbs'))
50
+ file.should be_exists
51
+ file.should_not be_identical
52
+ end
53
+
54
+ it "should be identical if the destination file is identical to the source file" do
55
+ file= Templater::File.new(:monkey, template_path('simple_erb.rbt'), result_path('file.rbs'))
56
+ file.should be_exists
57
+ file.should be_identical
58
+ end
59
+ end
60
+
61
+ describe Templater::File, '#invoke!' do
62
+
63
+ it "should copy the source file to the destination" do
64
+ file = Templater::File.new(:monkey, template_path('simple_erb.rbt'), result_path('path/to/subdir/test2.rbs'))
65
+
66
+ file.invoke!
67
+
68
+ File.exists?(result_path('path/to/subdir/test2.rbs')).should be_true
69
+ FileUtils.identical?(template_path('simple_erb.rbt'), result_path('path/to/subdir/test2.rbs')).should be_true
70
+
71
+ # cleanup
72
+ FileUtils.rm_rf(result_path('path'))
73
+ end
74
+ end
@@ -0,0 +1,1011 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe Templater::Generator, '#desc' do
4
+
5
+ it "should append text when called with an argument, and return it when called with no argument" do
6
+ @generator_class = Class.new(Templater::Generator)
7
+
8
+ @generator_class.desc "some text"
9
+ @generator_class.desc.should == "some text"
10
+ end
11
+
12
+ end
13
+
14
+ describe Templater::Generator, '.argument' do
15
+
16
+ before do
17
+ @generator_class = Class.new(Templater::Generator)
18
+ end
19
+
20
+ it "should create accessors" do
21
+ @generator_class.argument(0, :monkey)
22
+
23
+ instance = @generator_class.new('/tmp')
24
+ instance.monkey = 'a test'
25
+ instance.monkey.should == 'a test'
26
+ end
27
+
28
+ it "should pass an initial value to the argument" do
29
+ @generator_class.argument(0, :monkey)
30
+
31
+ instance = @generator_class.new('/tmp', {}, 'i am a monkey')
32
+ instance.monkey.should == 'i am a monkey'
33
+ end
34
+
35
+ it "should create multiple accessors" do
36
+ @generator_class.argument(0, :monkey)
37
+ @generator_class.argument(1, :llama)
38
+ @generator_class.argument(2, :herd)
39
+
40
+ instance = @generator_class.new('/tmp')
41
+ instance.monkey = 'a monkey'
42
+ instance.monkey.should == 'a monkey'
43
+ instance.llama = 'a llama'
44
+ instance.llama.should == 'a llama'
45
+ instance.herd = 'a herd'
46
+ instance.herd.should == 'a herd'
47
+ end
48
+
49
+ it "should pass an initial value to multiple accessors" do
50
+ @generator_class.argument(0, :monkey)
51
+ @generator_class.argument(1, :llama)
52
+ @generator_class.argument(2, :herd)
53
+
54
+ instance = @generator_class.new('/tmp', {}, 'a monkey', 'a llama', 'a herd')
55
+ instance.monkey.should == 'a monkey'
56
+ instance.llama.should == 'a llama'
57
+ instance.herd.should == 'a herd'
58
+ end
59
+
60
+ it "should set a default value for an argument" do
61
+ @generator_class.argument(0, :monkey, :default => 'a revision')
62
+
63
+ instance = @generator_class.new('/tmp')
64
+ instance.monkey.should == 'a revision'
65
+ end
66
+
67
+ it "should allow some syntactic sugar declaration" do
68
+ @generator_class.first_argument(:monkey)
69
+ @generator_class.second_argument(:llama)
70
+ @generator_class.third_argument(:herd)
71
+ @generator_class.fourth_argument(:elephant)
72
+
73
+ instance = @generator_class.new('/tmp', {}, 'a monkey', 'a llama', 'a herd', 'an elephant')
74
+ instance.monkey.should == 'a monkey'
75
+ instance.llama.should == 'a llama'
76
+ instance.herd.should == 'a herd'
77
+ instance.elephant.should == 'an elephant'
78
+ end
79
+
80
+ it "should whine when there are too many arguments" do
81
+ @generator_class.argument(0, :monkey)
82
+ @generator_class.argument(1, :llama)
83
+
84
+ lambda { @generator_class.new('/tmp', {}, 'a monkey', 'a llama', 'a herd') }.should raise_error(Templater::TooManyArgumentsError)
85
+ end
86
+
87
+ it "should assign arguments if an argument is required and that requirement is fullfilled" do
88
+ @generator_class.argument(0, :monkey, :required => true)
89
+ @generator_class.argument(1, :elephant, :required => true)
90
+ @generator_class.argument(2, :llama)
91
+
92
+ instance = @generator_class.new('/tmp', {}, 'enough', 'arguments')
93
+ instance.monkey.should == "enough"
94
+ instance.elephant.should == "arguments"
95
+ instance.llama.should be_nil
96
+ end
97
+
98
+ it "should raise an error when a required argument is not passed" do
99
+ @generator_class.argument(0, :monkey, :required => true)
100
+ @generator_class.argument(1, :elephant, :required => true)
101
+ @generator_class.argument(2, :llama)
102
+
103
+ lambda { @generator_class.new('/tmp', {}, 'too few arguments') }.should raise_error(Templater::TooFewArgumentsError)
104
+ end
105
+
106
+ it "should raise an error if nil is assigned to a require argument" do
107
+ @generator_class.argument(0, :monkey, :required => true)
108
+
109
+ instance = @generator_class.new('/tmp', {}, 'test')
110
+
111
+ lambda { instance.monkey = nil }.should raise_error(Templater::TooFewArgumentsError)
112
+ end
113
+
114
+ it "should assign an argument when a block appended to an argument does not throw :invalid" do
115
+ @generator_class.argument(0, :monkey) do
116
+ 1 + 1
117
+ end
118
+ @generator_class.argument(1, :elephant) do
119
+ false
120
+ end
121
+ @generator_class.argument(2, :llama)
122
+
123
+ instance = @generator_class.new('/tmp', {}, 'blah', 'urgh')
124
+ instance.monkey.should == 'blah'
125
+ instance.elephant.should == 'urgh'
126
+
127
+ instance.monkey = :harr
128
+ instance.monkey.should == :harr
129
+ end
130
+
131
+ it "should raise an error with the throw message, when a block is appended to an argument and throws :invalid" do
132
+ @generator_class.argument(0, :monkey) do
133
+ throw :invalid, 'this is not a valid monkey, bad monkey!'
134
+ end
135
+
136
+ lambda { @generator_class.new('/tmp', {}, 'blah') }.should raise_error(Templater::ArgumentError, 'this is not a valid monkey, bad monkey!')
137
+
138
+ instance = @generator_class.new('/tmp')
139
+
140
+ lambda { instance.monkey = :anything }.should raise_error(Templater::ArgumentError, 'this is not a valid monkey, bad monkey!')
141
+ end
142
+
143
+ end
144
+
145
+ describe Templater::Generator, '.argument as hash' do
146
+
147
+ before do
148
+ @generator_class = Class.new(Templater::Generator)
149
+ @generator_class.argument(0, :monkey)
150
+ @generator_class.argument(1, :llama, :as => :hash)
151
+ end
152
+
153
+ it "should allow assignment of hashes" do
154
+ instance = @generator_class.new('/tmp', {}, 'a monkey', { :hash => 'blah' })
155
+
156
+ instance.monkey.should == 'a monkey'
157
+ instance.llama[:hash].should == 'blah'
158
+
159
+ instance.llama = { :me_s_a => :hash }
160
+ instance.llama[:me_s_a].should == :hash
161
+ end
162
+
163
+ it "should convert a key/value pair to a hash" do
164
+ instance = @generator_class.new('/tmp', {}, 'a monkey', 'test:unit')
165
+ instance.llama['test'].should == 'unit'
166
+ end
167
+
168
+ it "should consume the remaining arguments and convert them to a hash if they are key/value pairs" do
169
+ instance = @generator_class.new('/tmp', {}, 'a monkey', 'test:unit', 'john:silver', 'river:road')
170
+ instance.llama['test'].should == 'unit'
171
+ instance.llama['john'].should == 'silver'
172
+ instance.llama['river'].should == 'road'
173
+ end
174
+
175
+ it "should raise an error if one of the remaining arguments is not a key/value pair" do
176
+ lambda { @generator_class.new('/tmp', {}, 'a monkey', 'a:llama', 'duck:llama', 'not_a_pair', 'pair:blah') }.should raise_error(Templater::MalformattedArgumentError)
177
+ end
178
+
179
+ it "should raise error if the argument is neither a hash nor a key/value pair" do
180
+ lambda { @generator_class.new('/tmp', {}, 'a monkey', 23) }.should raise_error(Templater::MalformattedArgumentError)
181
+ instance = @generator_class.new('/tmp')
182
+ lambda { instance.llama = :not_a_hash }.should raise_error(Templater::MalformattedArgumentError)
183
+ end
184
+
185
+ end
186
+
187
+ describe Templater::Generator, '.argument as array' do
188
+
189
+ before do
190
+ @generator_class = Class.new(Templater::Generator)
191
+ @generator_class.argument(0, :monkey)
192
+ @generator_class.argument(1, :llama, :as => :array)
193
+ end
194
+
195
+ it "should allow assignment of arrays" do
196
+ instance = @generator_class.new('/tmp', {}, 'a monkey', %w(an array))
197
+
198
+ instance.monkey.should == 'a monkey'
199
+ instance.llama[0].should == 'an'
200
+ instance.llama[1].should == 'array'
201
+
202
+ instance.llama = %w(another donkey)
203
+ instance.llama[0].should == 'another'
204
+ instance.llama[1].should == 'donkey'
205
+ end
206
+
207
+ it "should convert a single argument to an array" do
208
+ instance = @generator_class.new('/tmp', {}, 'a monkey', 'test')
209
+ instance.llama[0].should == 'test'
210
+ end
211
+
212
+ it "should consume the remaining arguments and convert them to an array" do
213
+ instance = @generator_class.new('/tmp', {}, 'a monkey', 'test', 'silver', 'river')
214
+ instance.llama[0].should == 'test'
215
+ instance.llama[1].should == 'silver'
216
+ instance.llama[2].should == 'river'
217
+ end
218
+
219
+ it "should raise error if the argument is not an array" do
220
+ instance = @generator_class.new('/tmp')
221
+ lambda { instance.llama = :not_an_array }.should raise_error(Templater::MalformattedArgumentError)
222
+ end
223
+
224
+ end
225
+
226
+ describe Templater::Generator, '.template' do
227
+
228
+ before do
229
+ @generator_class = Class.new(Templater::Generator)
230
+ end
231
+
232
+ it "should add a template with source and destination" do
233
+ @generator_class.template(:my_template, 'path/to/source.rbt', 'path/to/destination.rb')
234
+ @instance = @generator_class.new('/tmp/destination')
235
+
236
+ @instance.stub!(:source_root).and_return('/tmp/source')
237
+
238
+ @instance.template(:my_template).source.should == '/tmp/source/path/to/source.rbt'
239
+ @instance.template(:my_template).destination.should == '/tmp/destination/path/to/destination.rb'
240
+ @instance.template(:my_template).should be_an_instance_of(Templater::Template)
241
+ end
242
+
243
+ it "should add a template with absolute source and destination" do
244
+ @generator_class.template(:my_template, '/path/to/source.rbt', '/path/to/destination.rb')
245
+ @instance = @generator_class.new('/tmp/destination')
246
+
247
+ @instance.stub!(:source_root).and_return('/tmp/source')
248
+
249
+ @instance.template(:my_template).source.should == '/path/to/source.rbt'
250
+ @instance.template(:my_template).destination.should == '/path/to/destination.rb'
251
+ @instance.template(:my_template).should be_an_instance_of(Templater::Template)
252
+ end
253
+
254
+ it "should add a template with destination and infer the source" do
255
+ @generator_class.template(:my_template, 'path/to/destination.rb')
256
+ @instance = @generator_class.new('/tmp/destination')
257
+
258
+ @instance.stub!(:source_root).and_return('/tmp/source')
259
+
260
+ @instance.template(:my_template).source.should == '/tmp/source/path/to/destination.rbt'
261
+ @instance.template(:my_template).destination.should == '/tmp/destination/path/to/destination.rb'
262
+ @instance.template(:my_template).should be_an_instance_of(Templater::Template)
263
+ end
264
+
265
+ it "should add a template with a block" do
266
+ @generator_class.template(:my_template) do
267
+ source 'blah.rbt'
268
+ destination "gurr#{Process.pid.to_s}.rb"
269
+ end
270
+ @instance = @generator_class.new('/tmp/destination')
271
+
272
+ @instance.stub!(:source_root).and_return('/tmp/source')
273
+
274
+ @instance.template(:my_template).source.should == '/tmp/source/blah.rbt'
275
+ @instance.template(:my_template).destination.should == "/tmp/destination/gurr#{Process.pid.to_s}.rb"
276
+ @instance.template(:my_template).should be_an_instance_of(Templater::Template)
277
+ end
278
+
279
+ it "should add a template and convert an with an instruction encoded in the destination, but not one encoded in the source" do
280
+ @generator_class.template(:my_template, 'template/%some_method%.rbt', 'template/%another_method%.rb')
281
+ @instance = @generator_class.new('/tmp/destination')
282
+
283
+ @instance.stub!(:source_root).and_return('/tmp/source')
284
+ @instance.should_not_receive(:some_method)
285
+ @instance.should_receive(:another_method).at_least(:once).and_return('beast')
286
+
287
+ @instance.template(:my_template).source.should == '/tmp/source/template/%some_method%.rbt'
288
+ @instance.template(:my_template).destination.should == "/tmp/destination/template/beast.rb"
289
+ @instance.template(:my_template).should be_an_instance_of(Templater::Template)
290
+ end
291
+
292
+ it "should add a template and leave an encoded instruction be if it doesn't exist as a method" do
293
+ @generator_class.template(:my_template, 'template/blah.rbt', 'template/%some_method%.rb')
294
+ @instance = @generator_class.new('/tmp/destination')
295
+
296
+ @instance.stub!(:source_root).and_return('/tmp/source')
297
+
298
+ @instance.template(:my_template).destination.should == "/tmp/destination/template/%some_method%.rb"
299
+ @instance.template(:my_template).should be_an_instance_of(Templater::Template)
300
+ end
301
+
302
+ end
303
+
304
+ describe Templater::Generator, '.file' do
305
+
306
+ before do
307
+ @generator_class = Class.new(Templater::Generator)
308
+ end
309
+
310
+ it "should add a file with source and destination" do
311
+ @generator_class.file(:my_template, 'path/to/source.rbt', 'path/to/destination.rb')
312
+ @instance = @generator_class.new('/tmp/destination')
313
+
314
+ @instance.stub!(:source_root).and_return('/tmp/source')
315
+
316
+ @instance.file(:my_template).source.should == '/tmp/source/path/to/source.rbt'
317
+ @instance.file(:my_template).destination.should == '/tmp/destination/path/to/destination.rb'
318
+ @instance.file(:my_template).should be_an_instance_of(Templater::File)
319
+ end
320
+
321
+ it "should add a file with source and infer destination " do
322
+ @generator_class.file(:my_template, 'path/to/file.rb')
323
+ @instance = @generator_class.new('/tmp/destination')
324
+
325
+ @instance.stub!(:source_root).and_return('/tmp/source')
326
+
327
+ @instance.file(:my_template).source.should == '/tmp/source/path/to/file.rb'
328
+ @instance.file(:my_template).destination.should == '/tmp/destination/path/to/file.rb'
329
+ @instance.file(:my_template).should be_an_instance_of(Templater::File)
330
+ end
331
+
332
+ end
333
+
334
+ describe Templater::Generator, '.invoke' do
335
+
336
+ before do
337
+ @generator_class = Class.new(Templater::Generator)
338
+ @generator_class.first_argument :test1
339
+ @generator_class.second_argument :test2
340
+
341
+ @invoked_generator = mock('an invoked generator')
342
+ @invoked_instance = mock('an instance of the invoked generator')
343
+ @invoked_generator.stub!(:new).and_return(@invoked_instance)
344
+
345
+ @manifold = mock('a manifold')
346
+ @manifold.stub!(:generator).with(:test).and_return(@invoked_generator)
347
+ end
348
+
349
+ it "should add nothing if there is no manifold" do
350
+ @generator_class.invoke(:test)
351
+ @instance = @generator_class.new('/tmp', {}, 'test', 'argument')
352
+
353
+ @instance.invocations.should be_empty
354
+ end
355
+
356
+ describe "with no block" do
357
+
358
+ before(:each) do
359
+ @generator_class.stub!(:manifold).and_return(@manifold)
360
+ end
361
+
362
+ it "should return the instantiaded template" do
363
+ @generator_class.invoke(:test)
364
+ @instance = @generator_class.new('/tmp', {}, 'test', 'argument')
365
+
366
+ @instance.invocations.first.should == @invoked_instance
367
+ end
368
+
369
+ it "should ask the manifold for the generator" do
370
+ @generator_class.should_receive(:manifold).at_least(:once).and_return(@manifold)
371
+ @manifold.should_receive(:generator).with(:test).and_return(@invoked_generator)
372
+ @generator_class.invoke(:test)
373
+ @instance = @generator_class.new('/tmp', {}, 'test', 'argument')
374
+
375
+ @instance.invocations.first.should == @invoked_instance
376
+ end
377
+
378
+ it "should instantiate the generator with the correct arguments" do
379
+ @invoked_generator.should_receive(:new).with('/tmp', {}, 'test', 'argument').and_return(@invoked_instance)
380
+ @generator_class.invoke(:test)
381
+ @instance = @generator_class.new('/tmp', {}, 'test', 'argument')
382
+
383
+ @instance.invocations.first.should == @invoked_instance
384
+ end
385
+
386
+ end
387
+
388
+ describe "with a block" do
389
+
390
+ before(:each) do
391
+ @generator_class.stub!(:manifold).and_return(@manifold)
392
+ end
393
+
394
+ it "should pass the generator class to the block and return the result of it" do
395
+ @generator_class.invoke(:test) do |generator|
396
+ generator.new(destination_root, options, 'blah', 'monkey', some_method)
397
+ end
398
+ @instance = @generator_class.new('/tmp', {}, 'test', 'argument')
399
+
400
+ @instance.should_receive(:some_method).and_return('da')
401
+ @invoked_generator.should_receive(:new).with('/tmp', {}, 'blah', 'monkey', 'da').and_return(@invoked_instance)
402
+
403
+ @instance.invocations.first.should == @invoked_instance
404
+ end
405
+
406
+ it "should ask the manifold for the generator" do
407
+ @generator_class.should_receive(:manifold).at_least(:once).and_return(@manifold)
408
+ @manifold.should_receive(:generator).with(:test).and_return(@invoked_generator)
409
+
410
+ @generator_class.invoke(:test) do |generator|
411
+ generator.new(destination_root, options, 'blah', 'monkey')
412
+ end
413
+
414
+ @instance = @generator_class.new('/tmp', {}, 'test', 'argument')
415
+ @instance.invocations.first.should == @invoked_instance
416
+ end
417
+
418
+ end
419
+
420
+ end
421
+
422
+ describe Templater::Generator, '.template_list' do
423
+
424
+ it "should add a series of templates given a list as heredoc" do
425
+ @generator_class = Class.new(Templater::Generator)
426
+
427
+ @generator_class.should_receive(:template).with(:app_model_rb, 'app/model.rb')
428
+ @generator_class.should_receive(:template).with(:spec_model_rb, 'spec/model.rb')
429
+ @generator_class.should_receive(:template).with(:donkey_poo_css, 'donkey/poo.css')
430
+ @generator_class.should_receive(:template).with(:john_smith_file_rb, 'john/smith/file.rb')
431
+
432
+ @generator_class.template_list <<-LIST
433
+ app/model.rb
434
+ spec/model.rb
435
+ donkey/poo.css
436
+ john/smith/file.rb
437
+ LIST
438
+ end
439
+
440
+ it "should add a series of templates given a list as array" do
441
+ @generator_class = Class.new(Templater::Generator)
442
+
443
+ @generator_class.should_receive(:template).with(:app_model_rb, 'app/model.rb')
444
+ @generator_class.should_receive(:template).with(:spec_model_rb, 'spec/model.rb')
445
+ @generator_class.should_receive(:template).with(:donkey_poo_css, 'donkey/poo.css')
446
+ @generator_class.should_receive(:template).with(:john_smith_file_rb, 'john/smith/file.rb')
447
+
448
+ @generator_class.template_list(%w(app/model.rb spec/model.rb donkey/poo.css john/smith/file.rb))
449
+ end
450
+
451
+ end
452
+
453
+ describe Templater::Generator, '.file_list' do
454
+
455
+ it "should add a series of files given a list as heredoc" do
456
+ @generator_class = Class.new(Templater::Generator)
457
+
458
+ @generator_class.should_receive(:file).with(:app_model_rb, 'app/model.rb')
459
+ @generator_class.should_receive(:file).with(:spec_model_rb, 'spec/model.rb')
460
+ @generator_class.should_receive(:file).with(:donkey_poo_css, 'donkey/poo.css')
461
+ @generator_class.should_receive(:file).with(:john_smith_file_rb, 'john/smith/file.rb')
462
+
463
+ @generator_class.file_list <<-LIST
464
+ app/model.rb
465
+ spec/model.rb
466
+ donkey/poo.css
467
+ john/smith/file.rb
468
+ LIST
469
+ end
470
+
471
+ it "should add a series of files given a list as array" do
472
+ @generator_class = Class.new(Templater::Generator)
473
+
474
+ @generator_class.should_receive(:file).with(:app_model_rb, 'app/model.rb')
475
+ @generator_class.should_receive(:file).with(:spec_model_rb, 'spec/model.rb')
476
+ @generator_class.should_receive(:file).with(:donkey_poo_css, 'donkey/poo.css')
477
+ @generator_class.should_receive(:file).with(:john_smith_file_rb, 'john/smith/file.rb')
478
+
479
+ @generator_class.file_list(%w(app/model.rb spec/model.rb donkey/poo.css john/smith/file.rb))
480
+ end
481
+
482
+ end
483
+
484
+ describe Templater::Generator, '.glob!' do
485
+
486
+ before do
487
+ @generator_class = Class.new(Templater::Generator)
488
+ @generator_class.stub!(:source_root).and_return(template_path('glob'))
489
+ end
490
+
491
+ it "should add templates and files in the source_root based on if their extensions are in the template_extensions array" do
492
+ @generator_class.glob!()
493
+
494
+ @instance = @generator_class.new('/tmp/destination')
495
+
496
+ @instance.template(:arg_js).source.should == template_path('glob/arg.js')
497
+ @instance.template(:arg_js).destination.should == "/tmp/destination/arg.js"
498
+
499
+ @instance.template(:test_rb).source.should == template_path('glob/test.rb')
500
+ @instance.template(:test_rb).destination.should == "/tmp/destination/test.rb"
501
+
502
+ @instance.file(:subfolder_jessica_alba_jpg).source.should == template_path('glob/subfolder/jessica_alba.jpg')
503
+ @instance.file(:subfolder_jessica_alba_jpg).destination.should == '/tmp/destination/subfolder/jessica_alba.jpg'
504
+ end
505
+
506
+ it "should add templates and files with a different template_extensions array" do
507
+ @generator_class.glob!(nil, %w(jpg))
508
+
509
+ @instance = @generator_class.new('/tmp/destination')
510
+
511
+ @instance.file(:arg_js).source.should == template_path('glob/arg.js')
512
+ @instance.file(:arg_js).destination.should == "/tmp/destination/arg.js"
513
+
514
+ @instance.file(:test_rb).source.should == template_path('glob/test.rb')
515
+ @instance.file(:test_rb).destination.should == "/tmp/destination/test.rb"
516
+
517
+ @instance.template(:subfolder_jessica_alba_jpg).source.should == template_path('glob/subfolder/jessica_alba.jpg')
518
+ @instance.template(:subfolder_jessica_alba_jpg).destination.should == '/tmp/destination/subfolder/jessica_alba.jpg'
519
+ end
520
+
521
+ it "should glob in a subdirectory" do
522
+ @generator_class.stub!(:source_root).and_return(template_path(""))
523
+ @generator_class.glob!('glob', %w(jpg))
524
+
525
+ @instance = @generator_class.new('/tmp/destination')
526
+
527
+ @instance.file(:glob_arg_js).source.should == template_path('glob/arg.js')
528
+ @instance.file(:glob_arg_js).destination.should == "/tmp/destination/glob/arg.js"
529
+
530
+ @instance.file(:glob_test_rb).source.should == template_path('glob/test.rb')
531
+ @instance.file(:glob_test_rb).destination.should == "/tmp/destination/glob/test.rb"
532
+
533
+ @instance.template(:glob_subfolder_jessica_alba_jpg).source.should == template_path('glob/subfolder/jessica_alba.jpg')
534
+ @instance.template(:glob_subfolder_jessica_alba_jpg).destination.should == '/tmp/destination/glob/subfolder/jessica_alba.jpg'
535
+ end
536
+
537
+ it "should add only the given templates and files" do
538
+ @generator_class.glob!()
539
+
540
+ @instance = @generator_class.new('/tmp/destination')
541
+
542
+ @instance.templates.map { |t| t.name }.should == [
543
+ :arg_js,
544
+ :subfolder_monkey_rb,
545
+ :test_rb,
546
+ ]
547
+ @instance.files.map { |f| f.name }.should == [
548
+ :readme,
549
+ :subfolder_jessica_alba_jpg
550
+ ]
551
+ end
552
+
553
+ end
554
+
555
+ describe Templater::Generator, '.option' do
556
+
557
+ before do
558
+ @generator_class = Class.new(Templater::Generator)
559
+ end
560
+
561
+ it "should add accessors" do
562
+ @generator_class.option(:test)
563
+
564
+ instance = @generator_class.new('/tmp')
565
+
566
+ instance.test = "monkey"
567
+ instance.test.should == "monkey"
568
+
569
+ end
570
+
571
+ it "should preset a default value" do
572
+ @generator_class.option(:test, :default => 'elephant')
573
+
574
+ instance = @generator_class.new('/tmp')
575
+
576
+ instance.test.should == "elephant"
577
+ end
578
+
579
+ it "should allow overwriting of default values" do
580
+ @generator_class.option(:test, :default => 'elephant')
581
+
582
+ instance = @generator_class.new('/tmp')
583
+
584
+ instance.test.should == "elephant"
585
+ instance.test = "monkey"
586
+ instance.test.should == "monkey"
587
+ end
588
+
589
+ it "should allow passing in of options on generator creation" do
590
+ @generator_class.option(:test, :default => 'elephant')
591
+
592
+ instance = @generator_class.new('/tmp', { :test => 'freebird' })
593
+
594
+ instance.test.should == "freebird"
595
+ instance.test = "monkey"
596
+ instance.test.should == "monkey"
597
+ end
598
+ end
599
+
600
+ describe Templater::Generator, '.generators' do
601
+
602
+ before do
603
+ @generator_class = Class.new(Templater::Generator)
604
+
605
+ @g1 = Class.new(Templater::Generator)
606
+ @g2 = Class.new(Templater::Generator)
607
+ @g3 = Class.new(Templater::Generator)
608
+ @g4 = Class.new(Templater::Generator)
609
+
610
+ @manifold = mock('a manifold')
611
+ @manifold.stub!(:generator).with(:monkey).and_return(@g1)
612
+ @manifold.stub!(:generator).with(:blah).and_return(@g2)
613
+ @manifold.stub!(:generator).with(:duck).and_return(@g3)
614
+ @manifold.stub!(:generator).with(:llama).and_return(@g4)
615
+ @manifold.stub!(:generator).with(:i_dont_exist).and_return(nil)
616
+
617
+ @generator_class.manifold = @manifold
618
+ @g1.manifold = @manifold
619
+ @g2.manifold = @manifold
620
+ @g3.manifold = @manifold
621
+ @g4.manifold = @manifold
622
+ end
623
+
624
+ it "should return [self] when no manifold or invocations exist" do
625
+ @generator_class.manifold = nil
626
+ @generator_class.generators.should == [@generator_class]
627
+ end
628
+
629
+ it "should return [self] when only invocations exist" do
630
+ @generator_class.manifold = nil
631
+ @generator_class.invoke(:monkey)
632
+ @generator_class.invoke(:blah)
633
+ @generator_class.generators.should == [@generator_class]
634
+ end
635
+
636
+ it "should return a list of invoked generators" do
637
+ @generator_class.invoke(:monkey)
638
+ @generator_class.invoke(:blah)
639
+
640
+ @generator_class.generators.should == [@generator_class, @g1, @g2]
641
+ end
642
+
643
+ it "should return a list of invoked generators recursively" do
644
+ @generator_class.invoke(:monkey)
645
+ @generator_class.invoke(:blah)
646
+ @g1.invoke(:duck)
647
+ @g3.invoke(:llama)
648
+
649
+ @generator_class.generators.should == [@generator_class, @g1, @g3, @g4, @g2]
650
+ end
651
+
652
+ it "should ignore invocations that do not exist in the manifold" do
653
+ @generator_class.invoke(:monkey)
654
+ @generator_class.invoke(:blah)
655
+ @g1.invoke(:duck)
656
+ @g3.invoke(:i_dont_exist)
657
+
658
+ @generator_class.generators.should == [@generator_class, @g1, @g3, @g2]
659
+ end
660
+ end
661
+
662
+ describe Templater::Generator, '.source_root' do
663
+ it "should raise an error, complaining that source_root must be overridden" do
664
+ @generator_class = Class.new(Templater::Generator)
665
+ lambda { @generator_class.source_root }.should raise_error(Templater::SourceNotSpecifiedError)
666
+ end
667
+ end
668
+
669
+ describe Templater::Generator, '#template' do
670
+
671
+ before do
672
+ @generator_class = Class.new(Templater::Generator)
673
+ @generator_class.class_eval do
674
+ def source_root
675
+ '/tmp/source'
676
+ end
677
+ end
678
+ end
679
+
680
+ it "should find a template by name" do
681
+ @generator_class.template(:blah1, 'blah.rb')
682
+ @generator_class.template(:blah2, 'blah2.rb')
683
+
684
+ instance = @generator_class.new('/tmp')
685
+
686
+ instance.template(:blah1).name.should == :blah1
687
+ instance.template(:blah1).source.should == '/tmp/source/blah.rbt'
688
+ instance.template(:blah1).destination.should == '/tmp/blah.rb'
689
+ end
690
+
691
+ it "should not return a template with an option that does not match." do
692
+ @generator_class.option :framework, :default => :rails
693
+
694
+ @generator_class.template(:merb, 'blah.rb', :framework => :merb)
695
+ @generator_class.template(:rails, 'blah2.rb', :framework => :rails)
696
+ @generator_class.template(:none, 'blah2.rb')
697
+
698
+ instance = @generator_class.new('/tmp')
699
+
700
+ instance.template(:rails).name.should == :rails
701
+ instance.template(:merb).should be_nil
702
+ instance.template(:none).name.should == :none
703
+
704
+ instance.framework = :merb
705
+ instance.template(:rails).should be_nil
706
+ instance.template(:merb).name.should == :merb
707
+ instance.template(:none).name.should == :none
708
+
709
+ instance.framework = nil
710
+ instance.template(:rails).should be_nil
711
+ instance.template(:merb).should be_nil
712
+ instance.template(:none).name.should == :none
713
+ end
714
+ end
715
+
716
+ describe Templater::Generator, '#templates' do
717
+
718
+ before do
719
+ @generator_class = Class.new(Templater::Generator)
720
+ @generator_class.class_eval do
721
+ def source_root
722
+ '/tmp/source'
723
+ end
724
+ end
725
+ end
726
+
727
+ it "should return all templates" do
728
+ @generator_class.template(:blah1, 'blah.rb')
729
+ @generator_class.template(:blah2, 'blah2.rb')
730
+
731
+ instance = @generator_class.new('/tmp')
732
+
733
+ instance.templates[0].name.should == :blah1
734
+ instance.templates[1].name.should == :blah2
735
+ end
736
+
737
+ it "should not return templates with an option that does not match." do
738
+ @generator_class.option :framework, :default => :rails
739
+
740
+ @generator_class.template(:merb, 'blah.rb', :framework => :merb)
741
+ @generator_class.template(:rails, 'blah2.rb', :framework => :rails)
742
+ @generator_class.template(:none, 'blah2.rb')
743
+
744
+ instance = @generator_class.new('/tmp')
745
+
746
+ instance.templates[0].name.should == :rails
747
+ instance.templates[1].name.should == :none
748
+
749
+ instance.framework = :merb
750
+ instance.templates[0].name.should == :merb
751
+ instance.templates[1].name.should == :none
752
+
753
+ instance.framework = :rails
754
+ instance.templates[0].name.should == :rails
755
+ instance.templates[1].name.should == :none
756
+
757
+ instance.framework = nil
758
+ instance.templates[0].name.should == :none
759
+ end
760
+ end
761
+
762
+ describe Templater::Generator, '#file' do
763
+
764
+ before do
765
+ @generator_class = Class.new(Templater::Generator)
766
+ @generator_class.class_eval do
767
+ def source_root
768
+ '/tmp/source'
769
+ end
770
+ end
771
+ end
772
+
773
+ it "should find a file by name" do
774
+ @generator_class.file(:blah1, 'blah.rb')
775
+ @generator_class.file(:blah2, 'blah2.rb')
776
+
777
+ instance = @generator_class.new('/tmp')
778
+
779
+ instance.file(:blah1).name.should == :blah1
780
+ instance.file(:blah1).source.should == '/tmp/source/blah.rb'
781
+ instance.file(:blah1).destination.should == '/tmp/blah.rb'
782
+ end
783
+
784
+ it "should not return a file with an option that does not match." do
785
+ @generator_class.option :framework, :default => :rails
786
+
787
+ @generator_class.file(:merb, 'blah.rb', :framework => :merb)
788
+ @generator_class.file(:rails, 'blah2.rb', :framework => :rails)
789
+ @generator_class.file(:none, 'blah2.rb')
790
+
791
+ instance = @generator_class.new('/tmp')
792
+
793
+ instance.file(:rails).name.should == :rails
794
+ instance.file(:merb).should be_nil
795
+ instance.file(:none).name.should == :none
796
+
797
+ instance.framework = :merb
798
+ instance.file(:rails).should be_nil
799
+ instance.file(:merb).name.should == :merb
800
+ instance.file(:none).name.should == :none
801
+
802
+ instance.framework = nil
803
+ instance.file(:rails).should be_nil
804
+ instance.file(:merb).should be_nil
805
+ instance.file(:none).name.should == :none
806
+ end
807
+ end
808
+
809
+ describe Templater::Generator, '#files' do
810
+
811
+ before do
812
+ @generator_class = Class.new(Templater::Generator)
813
+ @generator_class.class_eval do
814
+ def source_root
815
+ '/tmp/source'
816
+ end
817
+ end
818
+ end
819
+
820
+ it "should return all files" do
821
+ @generator_class.file(:blah1, 'blah.rb')
822
+ @generator_class.file(:blah2, 'blah2.rb')
823
+
824
+ instance = @generator_class.new('/tmp')
825
+
826
+ instance.files[0].name.should == :blah1
827
+ instance.files[1].name.should == :blah2
828
+ end
829
+
830
+ it "should not return files with an option that does not match." do
831
+ @generator_class.option :framework, :default => :rails
832
+
833
+ @generator_class.file(:merb, 'blah.rb', :framework => :merb)
834
+ @generator_class.file(:rails, 'blah2.rb', :framework => :rails)
835
+ @generator_class.file(:none, 'blah2.rb')
836
+
837
+ instance = @generator_class.new('/tmp')
838
+
839
+ instance.files[0].name.should == :rails
840
+ instance.files[1].name.should == :none
841
+
842
+ instance.framework = :merb
843
+ instance.files[0].name.should == :merb
844
+ instance.files[1].name.should == :none
845
+
846
+ instance.framework = :rails
847
+ instance.files[0].name.should == :rails
848
+ instance.files[1].name.should == :none
849
+
850
+ instance.framework = nil
851
+ instance.files[0].name.should == :none
852
+ end
853
+ end
854
+
855
+ describe Templater::Generator, '#invocations' do
856
+
857
+ before do
858
+ @generator_class = Class.new(Templater::Generator)
859
+ @generator_class.class_eval do
860
+ def source_root
861
+ '/tmp/source'
862
+ end
863
+ end
864
+
865
+ @generator1 = mock('a generator for merb')
866
+ @instance1 = mock('an instance of the generator for merb')
867
+ @generator1.stub!(:new).and_return(@instance1)
868
+ @generator2 = mock('a generator for rails')
869
+ @instance2 = mock('an instance of the generator for rails')
870
+ @generator2.stub!(:new).and_return(@instance2)
871
+ @generator3 = mock('a generator for both')
872
+ @instance3 = mock('an instance of the generator for both')
873
+ @generator3.stub!(:new).and_return(@instance3)
874
+
875
+ @manifold = mock('a manifold')
876
+ @manifold.stub!(:generator).with(:merb).and_return(@generator1)
877
+ @manifold.stub!(:generator).with(:rails).and_return(@generator2)
878
+ @manifold.stub!(:generator).with(:both).and_return(@generator3)
879
+
880
+ @generator_class.stub!(:manifold).and_return(@manifold)
881
+ end
882
+
883
+ it "should return all invocations" do
884
+ @generator_class.invoke(:merb)
885
+ @generator_class.invoke(:rails)
886
+
887
+ instance = @generator_class.new('/tmp')
888
+
889
+ instance.invocations[0].should == @instance1
890
+ instance.invocations[1].should == @instance2
891
+ end
892
+
893
+ it "should not return templates with an option that does not match." do
894
+ @generator_class.option :framework, :default => :rails
895
+
896
+ @generator_class.invoke(:merb, :framework => :merb)
897
+ @generator_class.invoke(:rails, :framework => :rails)
898
+ @generator_class.invoke(:both)
899
+
900
+ instance = @generator_class.new('/tmp')
901
+
902
+ instance.invocations[0].should == @instance2
903
+ instance.invocations[1].should == @instance3
904
+
905
+ instance.framework = :merb
906
+ instance.invocations[0].should == @instance1
907
+ instance.invocations[1].should == @instance3
908
+
909
+ instance.framework = :rails
910
+ instance.invocations[0].should == @instance2
911
+ instance.invocations[1].should == @instance3
912
+
913
+ instance.framework = nil
914
+ instance.invocations[0].should == @instance3
915
+ end
916
+ end
917
+
918
+ describe Templater::Generator, '#actions' do
919
+
920
+ before do
921
+ @generator_class = Class.new(Templater::Generator)
922
+ @generator_class.class_eval do
923
+ def source_root
924
+ '/tmp/source'
925
+ end
926
+ end
927
+
928
+ @generator1 = mock('a generator')
929
+ @instance1 = mock('an instance of the generator')
930
+ @generator1.stub!(:new).and_return(@instance1)
931
+ @generator2 = mock('another generator')
932
+ @instance2 = mock('an instance of another generator')
933
+ @generator2.stub!(:new).and_return(@instance2)
934
+
935
+ @manifold = mock('a manifold')
936
+ @manifold.stub!(:generator).with(:one).and_return(@generator1)
937
+ @manifold.stub!(:generator).with(:two).and_return(@generator2)
938
+ @manifold.stub!(:generator).with(:three).and_return(@generator3)
939
+
940
+ @generator_class.stub!(:manifold).and_return(@manifold)
941
+ end
942
+
943
+ it "should return all templates and files" do
944
+ instance = @generator_class.new('/tmp')
945
+ instance.should_receive(:templates).at_least(:once).and_return(['template1', 'template2'])
946
+ instance.should_receive(:files).at_least(:once).and_return(['file1', 'file2'])
947
+
948
+ instance.actions.should include('template1')
949
+ instance.actions.should include('template2')
950
+ instance.actions.should include('file1')
951
+ instance.actions.should include('file2')
952
+ end
953
+
954
+ it "should return all templates and files recursively for all invocations" do
955
+ instance = @generator_class.new('/tmp')
956
+ instance.should_receive(:templates).at_least(:once).and_return(['template1', 'template2'])
957
+ instance.should_receive(:files).at_least(:once).and_return(['file1', 'file2'])
958
+ instance.should_receive(:invocations).at_least(:once).and_return([@instance1, @instance2])
959
+
960
+ @instance1.should_receive(:actions).at_least(:once).and_return(['subtemplate1', 'subfile1'])
961
+ @instance2.should_receive(:actions).at_least(:once).and_return(['subtemplate2', 'subfile2'])
962
+
963
+ instance.actions.should include('template1')
964
+ instance.actions.should include('template2')
965
+ instance.actions.should include('subtemplate1')
966
+ instance.actions.should include('subtemplate2')
967
+ instance.actions.should include('file1')
968
+ instance.actions.should include('file2')
969
+ instance.actions.should include('subfile1')
970
+ instance.actions.should include('subfile2')
971
+ end
972
+
973
+ end
974
+
975
+ describe Templater::Generator, '#invoke!' do
976
+
977
+ before do
978
+ @generator_class = Class.new(Templater::Generator)
979
+ end
980
+
981
+ it "should invoke all templates" do
982
+ template1 = mock('a template')
983
+ template2 = mock('another template')
984
+
985
+ instance = @generator_class.new('/tmp')
986
+
987
+ instance.should_receive(:templates).and_return([template1, template2])
988
+ template1.should_receive(:invoke!)
989
+ template2.should_receive(:invoke!)
990
+
991
+ instance.invoke!
992
+ end
993
+ end
994
+
995
+ describe Templater::Generator, '#destination_root' do
996
+ it "should be remembered" do
997
+ @generator_class = Class.new(Templater::Generator)
998
+ instance = @generator_class.new('/path/to/destination')
999
+ instance.destination_root.should == '/path/to/destination'
1000
+ end
1001
+ end
1002
+
1003
+ describe Templater::Generator, '#source_root' do
1004
+ it "try to retrieve the source root from the class" do
1005
+ @generator_class = Class.new(Templater::Generator)
1006
+ @generator_class.should_receive(:source_root).and_return('/tmp/source')
1007
+
1008
+ instance = @generator_class.new('/tmp')
1009
+ instance.source_root.should == '/tmp/source'
1010
+ end
1011
+ end