templater 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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