rake-pipeline 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,149 @@
1
+ require "rake-pipeline/middleware"
2
+ require "rake-pipeline/filters"
3
+ require "rack/test"
4
+
5
+ describe "Rake::Pipeline Middleware" do
6
+ include Rack::Test::Methods
7
+
8
+ ConcatFilter = Rake::Pipeline::SpecHelpers::Filters::ConcatFilter
9
+
10
+ class StripAssertsFilter < Rake::Pipeline::Filter
11
+ def generate_output(inputs, output)
12
+ inputs.each do |input|
13
+ output.write input.read.gsub(%r{^\s*assert\(.*\)\s*;?\s*$}m, '')
14
+ end
15
+ end
16
+ end
17
+
18
+ inputs = {
19
+ "app/javascripts/jquery.js" => "var jQuery = {};\n",
20
+
21
+ "app/javascripts/sproutcore.js" => <<-HERE.gsub(/^ {6}/, ''),
22
+ var SC = {};
23
+ assert(SC);
24
+ SC.hi = function() { console.log("hi"); };
25
+ HERE
26
+
27
+ "app/index.html" => "<html>HI</html>",
28
+ "app/javascripts/index.html" => "<html>JAVASCRIPT</html>",
29
+ "app/empty_dir" => nil
30
+ }
31
+
32
+ expected_output = <<-HERE.gsub(/^ {4}/, '')
33
+ var jQuery = {};
34
+ var SC = {};
35
+
36
+ SC.hi = function() { console.log("hi"); };
37
+ HERE
38
+
39
+ app = middleware = pipeline = nil
40
+
41
+ before do
42
+ app = lambda { |env| [404, {}, ['not found']] }
43
+
44
+ pipeline = Rake::Pipeline.build do
45
+ input tmp, "app/**/*"
46
+
47
+ match "*.js" do
48
+ filter(ConcatFilter) { "javascripts/application.js" }
49
+ filter(StripAssertsFilter) { |input| input }
50
+ end
51
+
52
+ # copy the rest
53
+ filter(ConcatFilter) { |input| input.sub(/^app\//, '') }
54
+
55
+ output "public"
56
+ end
57
+
58
+ middleware = Rake::Pipeline::Middleware.new(app, pipeline)
59
+
60
+ inputs.each do |name, string|
61
+ path = File.join(tmp, name)
62
+ if string
63
+ mkdir_p File.dirname(path)
64
+ File.open(path, "w") { |file| file.write(string) }
65
+ else
66
+ mkdir_p path
67
+ end
68
+ end
69
+
70
+ get "/javascripts/application.js"
71
+ end
72
+
73
+ let(:app) { middleware }
74
+
75
+ it "returns files relative to the output directory" do
76
+ last_response.should be_ok
77
+
78
+ last_response.body.should == expected_output
79
+ last_response.headers["Content-Type"].should == "application/javascript"
80
+ end
81
+
82
+ it "updates the output when files change" do
83
+ age_existing_files
84
+
85
+ File.open(File.join(tmp, "app/javascripts/jquery.js"), "w") do |file|
86
+ file.write "var jQuery = {};\njQuery.trim = function() {};\n"
87
+ end
88
+
89
+ expected = <<-HERE.gsub(/^ {6}/, '')
90
+ var jQuery = {};
91
+ jQuery.trim = function() {};
92
+ var SC = {};
93
+
94
+ SC.hi = function() { console.log("hi"); };
95
+ HERE
96
+
97
+ get "/javascripts/application.js"
98
+
99
+ last_response.body.should == expected
100
+ last_response.headers["Content-Type"].should == "application/javascript"
101
+ end
102
+
103
+ it "updates the output when new files are added" do
104
+ age_existing_files
105
+
106
+ File.open(File.join(tmp, "app/javascripts/history.js"), "w") do |file|
107
+ file.write "var History = {};\n"
108
+ end
109
+
110
+ expected = <<-HERE.gsub(/^ {6}/, '')
111
+ var History = {};
112
+ var jQuery = {};
113
+ var SC = {};
114
+
115
+ SC.hi = function() { console.log("hi"); };
116
+ HERE
117
+
118
+ get "/javascripts/application.js"
119
+
120
+ last_response.body.should == expected
121
+ last_response.headers["Content-Type"].should == "application/javascript"
122
+ end
123
+
124
+ it "returns index.html for directories" do
125
+ get "/"
126
+
127
+ last_response.body.should == "<html>HI</html>"
128
+ last_response.headers["Content-Type"].should == "text/html"
129
+
130
+ get "/javascripts"
131
+
132
+ last_response.body.should == "<html>JAVASCRIPT</html>"
133
+ last_response.headers["Content-Type"].should == "text/html"
134
+ end
135
+
136
+ it "ignores directories without index.html" do
137
+ get "/empty_dir"
138
+
139
+ last_response.body.should == "not found"
140
+ last_response.status.should == 404
141
+ end
142
+
143
+ it "falls back to the app" do
144
+ get "/zomg.notfound"
145
+
146
+ last_response.body.should == "not found"
147
+ last_response.status.should == 404
148
+ end
149
+ end
@@ -0,0 +1,160 @@
1
+ describe "Rake::Pipeline" do
2
+ ConcatFilter = Rake::Pipeline::SpecHelpers::Filters::ConcatFilter
3
+ StripAssertsFilter = Rake::Pipeline::SpecHelpers::Filters::StripAssertsFilter
4
+
5
+ let(:pipeline) { Rake::Pipeline.new }
6
+
7
+ it "accepts a input root" do
8
+ pipeline.input_root = "app/assets"
9
+ pipeline.input_root.should == File.expand_path("app/assets")
10
+ end
11
+
12
+ it "raises an exception on #relative_input_files if input_files are not provided" do
13
+ pipeline.input_root = "app/assets"
14
+ lambda { pipeline.input_files }.should raise_error(Rake::Pipeline::Error)
15
+ end
16
+
17
+ it "raises an exception on #relative_input_files if input_root is not provided" do
18
+ pipeline.input_glob = "app/assets/javascripts/**/*.js"
19
+ lambda { pipeline.input_files }.should raise_error(Rake::Pipeline::Error)
20
+ end
21
+
22
+ it "accepts a temporary directory" do
23
+ pipeline.tmpdir = "tmp"
24
+ pipeline.tmpdir.should == File.expand_path("tmp")
25
+ end
26
+
27
+ it "accepts an output directory" do
28
+ pipeline.output_root = "public"
29
+ pipeline.output_root.should == File.expand_path("public")
30
+ end
31
+
32
+ it "accepts a rake application" do
33
+ app = Rake::Application.new
34
+ pipeline.rake_application = app
35
+ pipeline.rake_application.should == app
36
+ end
37
+
38
+ it "defaults the rake application to Rake.application" do
39
+ pipeline.rake_application.should == Rake.application
40
+ end
41
+
42
+ it "can have filters added to it" do
43
+ filter = ConcatFilter.new
44
+ pipeline.add_filter filter
45
+ end
46
+
47
+ shared_examples_for "when working with input" do
48
+ def input_file(path, root=File.join(tmp, "app/assets"))
49
+ Rake::Pipeline::FileWrapper.new root, path
50
+ end
51
+
52
+ let(:files) do
53
+ %w(javascripts/jquery.js javascripts/sproutcore.js).map do |filename|
54
+ input_file(filename)
55
+ end
56
+ end
57
+
58
+ before do
59
+ Rake.application = Rake::Application.new
60
+
61
+ files.each do |file|
62
+ mkdir_p File.dirname(file.fullpath)
63
+
64
+ File.open(file.fullpath, "w") do |file|
65
+ file.write "// This is #{file.path}\n"
66
+ end
67
+ end
68
+
69
+ pipeline.input_root = "app/assets"
70
+ setup_input(pipeline)
71
+ pipeline.output_root = "public"
72
+ end
73
+
74
+ it "accepts a list of relative input files" do
75
+ pipeline.input_files.should == files
76
+ end
77
+
78
+ it "configures the filters with outputs and inputs with #rake_tasks" do
79
+ concat = ConcatFilter.new
80
+ concat.output_name_generator = proc { |input| "javascripts/application.js" }
81
+
82
+ strip_asserts = StripAssertsFilter.new
83
+ strip_asserts.output_name_generator = proc { |input| input }
84
+
85
+ pipeline.add_filters concat, strip_asserts
86
+ pipeline.setup
87
+
88
+ concat.input_files.should == pipeline.input_files
89
+ strip_asserts.input_files.each { |file| file.root.should == concat.output_root }
90
+
91
+ strip_asserts.input_files.should == [input_file("javascripts/application.js", concat.output_root)]
92
+ strip_asserts.output_root.should == File.expand_path(pipeline.output_root)
93
+ end
94
+
95
+ describe "generating rake tasks" do
96
+ tasks = nil
97
+
98
+ before do
99
+ concat = ConcatFilter.new
100
+ concat.output_name_generator = proc { |input| "javascripts/application.js" }
101
+ pipeline.add_filter concat
102
+ end
103
+
104
+ it "generates rake tasks in Rake.application" do
105
+ pipeline.setup
106
+ tasks = pipeline.rake_tasks
107
+
108
+ tasks.size.should == 1
109
+ task = tasks[0]
110
+ task.name.should == File.join(pipeline.output_root, "javascripts/application.js")
111
+
112
+ deps = task.prerequisites
113
+ deps.size.should == 2
114
+ deps[0].should == File.join(pipeline.input_root, "javascripts/jquery.js")
115
+ deps[1].should == File.join(pipeline.input_root, "javascripts/sproutcore.js")
116
+
117
+ Rake.application.tasks.size.should == 3
118
+ end
119
+
120
+ it "generates rake tasks is an alternate Rake::Application" do
121
+ app = Rake::Application.new
122
+ pipeline.rake_application = app
123
+ pipeline.setup
124
+ tasks = pipeline.rake_tasks
125
+
126
+ Rake.application.tasks.size.should == 0
127
+ end
128
+ end
129
+ end
130
+
131
+ describe "using a glob for input files" do
132
+ it_behaves_like "when working with input"
133
+
134
+ def setup_input(pipeline)
135
+ pipeline.input_glob = "javascripts/**/*.js"
136
+ end
137
+ end
138
+
139
+ describe "using a glob containing directories for input files" do
140
+ it_behaves_like "when working with input"
141
+
142
+ def setup_input(pipeline)
143
+ pipeline.input_glob = "**/*"
144
+ end
145
+ end
146
+
147
+ describe "using an array for input files" do
148
+ it_behaves_like "when working with input"
149
+
150
+ def setup_input(pipeline)
151
+ Dir.chdir("app/assets") do
152
+ files = Dir["javascripts/**/*.js"]
153
+ wrappers = files.map do |file|
154
+ Rake::Pipeline::FileWrapper.new(File.join(tmp, "app/assets"), file)
155
+ end
156
+ pipeline.input_files = wrappers
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,240 @@
1
+ require "rake-pipeline/filters"
2
+
3
+ describe "A realistic pipeline" do
4
+
5
+ INPUTS = {
6
+
7
+ "app/javascripts/jquery.js" => <<-HERE,
8
+ var jQuery = {};
9
+ HERE
10
+
11
+ "app/javascripts/sproutcore.js" => <<-HERE,
12
+ var SC = {};
13
+ assert(SC);
14
+ SC.hi = function() { console.log("hi"); };
15
+ HERE
16
+
17
+ "app/stylesheets/jquery.css" => <<-HERE,
18
+ #jquery {
19
+ color: red;
20
+ }
21
+ HERE
22
+
23
+ "app/stylesheets/sproutcore.css" => <<-HERE,
24
+ #sproutcore {
25
+ color: green;
26
+ }
27
+ HERE
28
+
29
+ "app/index.html" => <<-HERE
30
+ <html></html>
31
+ HERE
32
+
33
+ }
34
+
35
+ EXPECTED_JS_OUTPUT = <<-HERE
36
+ var jQuery = {};
37
+ var SC = {};
38
+
39
+ SC.hi = function() { console.log("hi"); };
40
+ HERE
41
+
42
+ EXPECTED_CSS_OUTPUT = <<-HERE
43
+ #jquery {
44
+ color: red;
45
+ }
46
+ #sproutcore {
47
+ color: green;
48
+ }
49
+ HERE
50
+
51
+ EXPECTED_HTML_OUTPUT = <<-HERE
52
+ <html></html>
53
+ HERE
54
+
55
+ before do
56
+ Rake.application = Rake::Application.new
57
+
58
+ INPUTS.each do |name, string|
59
+ mkdir_p File.dirname(File.join(tmp, name))
60
+ File.open(File.join(tmp, name), "w") { |file| file.write(string) }
61
+ end
62
+ end
63
+
64
+ def input_wrapper(path)
65
+ Rake::Pipeline::FileWrapper.new(tmp, path)
66
+ end
67
+
68
+ def output_should_exist(expected = EXPECTED_JS_OUTPUT)
69
+ output = File.join(tmp, "public/javascripts/application.js")
70
+ temp = File.join(tmp, "temporary")
71
+
72
+ File.exists?(output).should be_true
73
+ File.exists?(temp).should be_true
74
+
75
+ File.read(output).should == expected
76
+ end
77
+
78
+ concat_filter = Rake::Pipeline::ConcatFilter
79
+ strip_asserts_filter = Rake::Pipeline::SpecHelpers::Filters::StripAssertsFilter
80
+
81
+ it "can successfully apply filters" do
82
+ concat = concat_filter.new
83
+ concat.input_files = INPUTS.keys.select { |key| key =~ /javascript/ }.map { |file| input_wrapper(file) }
84
+ concat.output_root = File.join(tmp, "temporary", "concat_filter")
85
+ concat.output_name_generator = proc { |input| "javascripts/application.js" }
86
+
87
+ strip_asserts = strip_asserts_filter.new
88
+ strip_asserts.input_files = concat.output_files
89
+ strip_asserts.output_root = File.join(tmp, "public")
90
+ strip_asserts.output_name_generator = proc { |input| input }
91
+
92
+ concat.generate_rake_tasks
93
+ Rake::Task.define_task(:default => strip_asserts.generate_rake_tasks)
94
+ Rake.application[:default].invoke
95
+
96
+ output_should_exist
97
+ end
98
+
99
+ it "can be configured using the pipeline" do
100
+ pipeline = Rake::Pipeline.new
101
+ pipeline.input_root = File.expand_path(tmp)
102
+ pipeline.output_root = File.expand_path("public")
103
+ pipeline.input_glob = "app/javascripts/*.js"
104
+ pipeline.tmpdir = "temporary"
105
+
106
+ concat = concat_filter.new
107
+ concat.output_name_generator = proc { |input| "javascripts/application.js" }
108
+
109
+ strip_asserts = strip_asserts_filter.new
110
+ strip_asserts.output_name_generator = proc { |input| input }
111
+
112
+ pipeline.add_filters(concat, strip_asserts)
113
+ pipeline.invoke
114
+
115
+ output_should_exist
116
+ end
117
+
118
+ describe "using the pipeline DSL" do
119
+
120
+ attr_reader :pipeline
121
+
122
+ shared_examples_for "the pipeline DSL" do
123
+ it "can be configured using the pipeline DSL" do
124
+ pipeline.invoke
125
+ output_should_exist
126
+ end
127
+
128
+ it "can be configured using the pipeline DSL with an alternate Rake application" do
129
+ pipeline.rake_application = Rake::Application.new
130
+ pipeline.invoke
131
+ output_should_exist
132
+ end
133
+
134
+ it "can be invoked repeatedly to reflected updated changes" do
135
+ pipeline.invoke
136
+ age_existing_files
137
+
138
+ File.open(File.join(tmp, "app/javascripts/jquery.js"), "w") do |file|
139
+ file.write "var jQuery = {};\njQuery.trim = function() {};\n"
140
+ end
141
+
142
+ expected = <<-HERE.gsub(/^ {10}/, '')
143
+ var jQuery = {};
144
+ jQuery.trim = function() {};
145
+ var SC = {};
146
+
147
+ SC.hi = function() { console.log("hi"); };
148
+ HERE
149
+
150
+ pipeline.invoke
151
+
152
+ output_should_exist(expected)
153
+ end
154
+
155
+ it "can be restarted to reflect new files" do
156
+ pipeline.invoke
157
+ age_existing_files
158
+
159
+ File.open(File.join(tmp, "app/javascripts/history.js"), "w") do |file|
160
+ file.write "var History = {};\n"
161
+ end
162
+
163
+ pipeline.invoke_clean
164
+
165
+ expected = <<-HERE.gsub(/^ {10}/, '')
166
+ var History = {};
167
+ var jQuery = {};
168
+ var SC = {};
169
+
170
+ SC.hi = function() { console.log("hi"); };
171
+ HERE
172
+
173
+ output_should_exist(expected)
174
+ end
175
+ end
176
+
177
+ describe "the raw pipeline DSL" do
178
+ it_behaves_like "the pipeline DSL"
179
+
180
+ before do
181
+ @pipeline = Rake::Pipeline.build do
182
+ tmpdir "temporary"
183
+ input tmp, "app/javascripts/*.js"
184
+ filter(concat_filter) { "javascripts/application.js" }
185
+ filter(strip_asserts_filter) { |input| input }
186
+ output "public"
187
+ end
188
+ end
189
+ end
190
+
191
+ describe "the raw pipeline DSL" do
192
+ it_behaves_like "the pipeline DSL"
193
+
194
+ before do
195
+ @pipeline = Rake::Pipeline.build do
196
+ tmpdir "temporary"
197
+ input tmp, "app/javascripts/*.js"
198
+ filter concat_filter, "javascripts/application.js"
199
+ filter strip_asserts_filter
200
+ output "public"
201
+ end
202
+ end
203
+ end
204
+
205
+ describe "using the matcher spec" do
206
+
207
+ def output_should_exist(expected=EXPECTED_JS_OUTPUT)
208
+ super
209
+
210
+ css = File.join(tmp, "public/stylesheets/application.css")
211
+
212
+ File.exists?(css).should be_true
213
+ File.read(css).should == EXPECTED_CSS_OUTPUT
214
+
215
+ html = File.join(tmp, "public/index.html")
216
+ File.exists?(html).should be_true
217
+ File.read(html).should == EXPECTED_HTML_OUTPUT
218
+ end
219
+
220
+ it_behaves_like "the pipeline DSL"
221
+
222
+ before do
223
+ @pipeline = Rake::Pipeline.build do
224
+ tmpdir "temporary"
225
+ input File.join(tmp, "app"), "**/*.{js,css,html}"
226
+ output "public"
227
+
228
+ match "**/*.js" do
229
+ filter strip_asserts_filter
230
+ filter concat_filter, "javascripts/application.js"
231
+ end
232
+
233
+ match "**/*.css" do
234
+ filter concat_filter, "stylesheets/application.css"
235
+ end
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end