rack-sprockets 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/.gitignore +5 -0
  2. data/Gemfile +4 -0
  3. data/Gemfile.lock +47 -0
  4. data/README.rdoc +2 -2
  5. data/Rakefile +5 -60
  6. data/demos/yui_compressed/Gemfile +5 -0
  7. data/demos/yui_compressed/Gemfile.lock +19 -0
  8. data/demos/yui_compressed/REAME.rdoc +13 -0
  9. data/demos/yui_compressed/app.rb +17 -0
  10. data/demos/yui_compressed/app/javascripts/alert_one.js +4 -0
  11. data/demos/yui_compressed/app/javascripts/alert_two.js +4 -0
  12. data/demos/yui_compressed/app/javascripts/app.js +16 -0
  13. data/demos/yui_compressed/public/javascripts/app.js +1 -0
  14. data/demos/yui_compressed/public/javascripts/uncompressed_app.js +12 -0
  15. data/lib/rack/.rb +1 -0
  16. data/lib/rack/sprockets/request.rb +42 -24
  17. data/lib/rack/sprockets/source.rb +27 -27
  18. data/lib/rack/sprockets/version.rb +4 -12
  19. data/rack-sprockets.gemspec +29 -0
  20. data/test/app_helper.rb +25 -0
  21. data/test/config_test.rb +80 -0
  22. data/test/env.rb +9 -0
  23. data/test/fixtures/mock_options.rb +9 -0
  24. data/test/fixtures/sinatra/app.rb +9 -0
  25. data/test/fixtures/sinatra/app/javascripts/alert_one.js +2 -0
  26. data/test/fixtures/sinatra/app/javascripts/alert_two.js +2 -0
  27. data/test/fixtures/sinatra/app/javascripts/app.js +10 -0
  28. data/test/fixtures/sinatra/app/javascripts/app_compiled.js +12 -0
  29. data/test/fixtures/sinatra/app/javascripts/nested/dependency.js +2 -0
  30. data/test/fixtures/sinatra/app/javascripts/nested/thing.js +11 -0
  31. data/test/fixtures/sinatra/app/javascripts/nested/thing_compiled.js +14 -0
  32. data/test/helper.rb +80 -0
  33. data/test/options_test.rb +78 -0
  34. data/test/request_test.rb +141 -0
  35. data/test/response_test.rb +41 -0
  36. data/test/sinatra_test.rb +42 -0
  37. data/test/source_test.rb +163 -0
  38. metadata +103 -40
@@ -1,13 +1,5 @@
1
- module RackSprockets
2
- module Version
3
-
4
- MAJOR = 1
5
- MINOR = 0
6
- TINY = 4
7
-
8
- def self.to_s # :nodoc:
9
- [MAJOR, MINOR, TINY].join('.')
10
- end
11
-
1
+ module Rack
2
+ module Sprockets
3
+ VERSION = "1.1.0"
12
4
  end
13
- end
5
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rack/sprockets/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rack-sprockets"
7
+ s.version = Rack::Sprockets::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Kelly Redding"]
10
+ s.email = ["kelly@kelredd.com"]
11
+ s.homepage = "http://github.com/kelredd/rack-sprockets"
12
+ s.summary = %q{Sprockets javascript preprocessing for Rack apps.}
13
+ s.description = %q{Use rack middleware to handle sprockets preprocessing. Processing happens on requests to sprockets resources. This allows you to develop, check in, and deploy unprocessed sprockets resources and leave the processing to the middleware. Allows for optimizing by environment: never-cache, always-reprocess in development; cache, process-once in production (for example).}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_development_dependency("bundler", ["~> 1.0"])
21
+ s.add_development_dependency("test-belt", ["= 0.2.1"]) # locked to a specific version for test stability
22
+ s.add_development_dependency("sinatra", [">= 0.9.4"])
23
+ s.add_development_dependency("rack-test", [">= 0.5.3"])
24
+ s.add_development_dependency("webrat", [">= 0.6.0"])
25
+ s.add_development_dependency("yui-compressor", [">=0.9.1"])
26
+
27
+ s.add_dependency("rack", ["~> 1.0"])
28
+ s.add_dependency("sprockets", ["~> 1.0"])
29
+ end
@@ -0,0 +1,25 @@
1
+ require 'rack/test'
2
+ require 'webrat'
3
+
4
+ class Test::Unit::TestCase
5
+ include Rack::Test::Methods
6
+ include Webrat::Methods
7
+ include Webrat::Matchers
8
+
9
+ Webrat.configure do |config|
10
+ config.mode = :rack
11
+ end
12
+
13
+ class << self
14
+
15
+ def should_respond_with_compiled_js
16
+ should "return compiled js" do
17
+ assert_equal 200, @response.status, "status is not '#{Rack::Utils::HTTP_STATUS_CODES[200]}'"
18
+ assert @response.headers["Content-Type"].include?(Rack::Sprockets::MIME_TYPE), "content type is not '#{Rack::Sprockets::MIME_TYPE}'"
19
+ assert_equal @compiled.strip, @response.body.strip, "the compiled js is incorrect"
20
+ end
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,80 @@
1
+ require 'test/helper'
2
+ require 'rack/sprockets/config'
3
+
4
+ class ConfigTest < Test::Unit::TestCase
5
+ context 'Rack::Sprockets::Config' do
6
+ setup do
7
+ @config = Rack::Sprockets::Config.new
8
+ end
9
+
10
+ { :cache => false,
11
+ :compress => false
12
+ }.each do |k,v|
13
+ should "have an accessor for #{k}" do
14
+ assert_respond_to @config, k, "no reader for #{k}"
15
+ assert_respond_to @config, "#{k}=".to_sym, "no writer for #{k}"
16
+ end
17
+
18
+ should "default #{k} correctly" do
19
+ assert_equal v, @config.send(k)
20
+ end
21
+ end
22
+
23
+ should "provide boolean readers" do
24
+ assert_respond_to @config, :cache?, "no reader for :cache?"
25
+ assert_equal !!@config.cache, @config.cache?
26
+ assert_respond_to @config, :compress?, "no reader for :compress?"
27
+ assert_equal !!@config.compress, @config.compress?
28
+ end
29
+
30
+ should "allow init with setting hash" do
31
+ settings = {
32
+ :cache => true,
33
+ :compress => true
34
+ }
35
+ config = Rack::Sprockets::Config.new settings
36
+
37
+ assert_equal true, config.cache
38
+ assert_equal true, config.compress
39
+ end
40
+
41
+ should "be accessible at Rack::Sprockets class level" do
42
+ assert_respond_to Rack::Sprockets, :configure
43
+ assert_respond_to Rack::Sprockets, :config
44
+ assert_respond_to Rack::Sprockets, :config=
45
+ end
46
+
47
+ context "given a new configuration" do
48
+ setup do
49
+ @old_config = Rack::Sprockets.config
50
+ @settings = {
51
+ :cache => true,
52
+ :compress => true,
53
+ }
54
+ @traditional_config = Rack::Sprockets::Config.new @settings
55
+ end
56
+ teardown do
57
+ Rack::Sprockets.config = @old_config
58
+ end
59
+
60
+ should "allow Rack::Sprockets to directly apply settings" do
61
+ Rack::Sprockets.config = @traditional_config.dup
62
+
63
+ assert_equal @traditional_config.cache, Rack::Sprockets.config.cache
64
+ assert_equal @traditional_config.compress, Rack::Sprockets.config.compress
65
+ end
66
+
67
+ should "allow Rack::Sprockets to apply settings using a block" do
68
+ Rack::Sprockets.configure do |config|
69
+ config.cache = true
70
+ config.compress = true
71
+ end
72
+
73
+ assert_equal @traditional_config.cache, Rack::Sprockets.config.cache
74
+ assert_equal @traditional_config.compress, Rack::Sprockets.config.compress
75
+ end
76
+
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,9 @@
1
+ # Add test and lib paths to the $LOAD_PATH
2
+ [ File.dirname(__FILE__),
3
+ File.join(File.dirname(__FILE__), '..', 'lib')
4
+ ].each do |path|
5
+ full_path = File.expand_path(path)
6
+ $LOAD_PATH.unshift(full_path) unless $LOAD_PATH.include?(full_path)
7
+ end
8
+
9
+ require 'rack/sprockets'
@@ -0,0 +1,9 @@
1
+ class MockOptions
2
+ include Rack::Sprockets::Options
3
+
4
+ def initialize
5
+ @env = nil
6
+ initialize_options
7
+ end
8
+ end
9
+
@@ -0,0 +1,9 @@
1
+ require 'sinatra/base'
2
+
3
+ class SinatraApp < Sinatra::Base
4
+
5
+ configure do
6
+ set :root, File.expand_path(File.dirname(__FILE__))
7
+ end
8
+
9
+ end
@@ -0,0 +1,2 @@
1
+ var one_message = 'alert one';
2
+ alert(one_message);
@@ -0,0 +1,2 @@
1
+ var two_message = 'alert 2';
2
+ alert(two_message);
@@ -0,0 +1,10 @@
1
+ //= require <alert_one>
2
+ //= require <alert_two>
3
+
4
+ var app_message = 'full app';
5
+ alert(app_message);
6
+
7
+ function () {
8
+ var foo = {};
9
+ foo["bar"] = "baz";
10
+ }
@@ -0,0 +1,12 @@
1
+ var one_message = 'alert one';
2
+ alert(one_message);
3
+ var two_message = 'alert 2';
4
+ alert(two_message);
5
+
6
+ var app_message = 'full app';
7
+ alert(app_message);
8
+
9
+ function () {
10
+ var foo = {};
11
+ foo["bar"] = "baz";
12
+ }
@@ -0,0 +1,2 @@
1
+ var dependency_msg = 'dependent';
2
+ alert(dependency_msg);
@@ -0,0 +1,11 @@
1
+ //= require <alert_one>
2
+ //= require <alert_two>
3
+ //= require <nested/dependency>
4
+
5
+ var thing_message = 'thing';
6
+ alert(thing_message);
7
+
8
+ function () {
9
+ var ahh = {};
10
+ ahh["boo"] = "poo";
11
+ }
@@ -0,0 +1,14 @@
1
+ var one_message = 'alert one';
2
+ alert(one_message);
3
+ var two_message = 'alert 2';
4
+ alert(two_message);
5
+ var dependency_msg = 'dependent';
6
+ alert(dependency_msg);
7
+
8
+ var thing_message = 'thing';
9
+ alert(thing_message);
10
+
11
+ function () {
12
+ var ahh = {};
13
+ ahh["boo"] = "poo";
14
+ }
@@ -0,0 +1,80 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup
4
+
5
+ require 'test_belt'
6
+ require 'test/env'
7
+
8
+ class Test::Unit::TestCase
9
+
10
+ def file_path(*segments)
11
+ segs = segments.unshift([File.dirname(__FILE__), '..']).flatten
12
+ File.expand_path(segs.join(File::SEPARATOR))
13
+ end
14
+
15
+ def env_defaults
16
+ Rack::Sprockets::Base.defaults.merge({
17
+ Rack::Sprockets::Base.option_name(:root) => file_path('test','fixtures','sinatra')
18
+ })
19
+ end
20
+
21
+ def self.should_compile_source(name, desc)
22
+ context desc do
23
+ setup do
24
+ @compiled = File.read(File.join(@source_folder, "#{name}_compiled.js"))
25
+ @source = Rack::Sprockets::Source.new(name, {
26
+ :folder => @source_folder,
27
+ :secretary => @secretary
28
+ })
29
+ end
30
+
31
+ should "compile to Javascript" do
32
+ assert_equal @compiled.strip, @source.compiled.strip, '.compiled is incorrect'
33
+ assert_equal @compiled.strip, @source.to_js.strip, '.to_js is incorrect'
34
+ assert_equal @compiled.strip, @source.js.strip, '.js is incorrect'
35
+ end
36
+ end
37
+ end
38
+
39
+ def sprockets_request(method, path_info)
40
+ Rack::Sprockets::Request.new(@defaults.merge({
41
+ 'REQUEST_METHOD' => method,
42
+ 'PATH_INFO' => path_info
43
+ }))
44
+ end
45
+
46
+ def sprockets_response(js)
47
+ Rack::Sprockets::Response.new(@defaults, js)
48
+ end
49
+
50
+ def self.should_not_be_a_valid_rack_sprockets_request(args)
51
+ context "to #{args[:method].upcase} #{args[:resource]} (#{args[:description]})" do
52
+ setup do
53
+ @request = sprockets_request(args[:method], args[:resource])
54
+ end
55
+
56
+ should "not be a valid endpoint for Rack::Sprockets" do
57
+ not_valid = !@request.get?
58
+ not_valid ||= !@request.for_js?
59
+ not_valid ||= @request.source.files.empty?
60
+ assert not_valid, 'request is a GET for .js format and has source'
61
+ assert !@request.for_sprockets?, 'the request is for sprockets'
62
+ end
63
+ end
64
+ end
65
+ def self.should_be_a_valid_rack_sprockets_request(args)
66
+ context "to #{args[:method].upcase} #{args[:resource]} (#{args[:description]})" do
67
+ setup do
68
+ @request = sprockets_request(args[:method], args[:resource])
69
+ end
70
+
71
+ should "be a valid endpoint for Rack::Sprockets" do
72
+ assert @request.get?, 'the request is not a GET'
73
+ assert @request.for_js?, 'the request is not for js'
74
+ assert !@request.source.files.empty?, 'the request resource has no source'
75
+ assert @request.for_sprockets?, 'the request is not for sprockets'
76
+ end
77
+ end
78
+ end
79
+
80
+ end
@@ -0,0 +1,78 @@
1
+ require 'test/helper'
2
+ require 'rack/sprockets/options'
3
+ require 'fixtures/mock_options'
4
+
5
+ class OptionsTest < Test::Unit::TestCase
6
+ context 'Rack::Sprockets::Options' do
7
+ setup { @options = MockOptions.new }
8
+
9
+ should "use a namespace" do
10
+ assert_equal 'rack-sprockets', Rack::Sprockets::Options::RACK_ENV_NS
11
+ end
12
+
13
+ should "provide an option_name helper" do
14
+ assert_respond_to MockOptions, :option_name
15
+ end
16
+
17
+ should "provide defaults" do
18
+ assert_respond_to MockOptions, :defaults
19
+ end
20
+
21
+ should "allow access to the options" do
22
+ assert_respond_to @options, :options, 'no #options accessor'
23
+ assert_kind_of Hash, @options.options, '#options is not a Hash'
24
+ assert_equal MockOptions.defaults[MockOptions.option_name(:source)], @options.options(:source)
25
+ end
26
+
27
+ { :root => ".",
28
+ :public => 'public',
29
+ :source => 'app/javascripts',
30
+ :hosted_at => '/javascripts',
31
+ :load_path => ["app/javascripts/", "vendor/javascripts/"],
32
+ :expand_paths => true
33
+ }.each do |k,v|
34
+ should "default #{k} correctly" do
35
+ assert_equal v, @options.options[MockOptions.option_name(k)]
36
+ end
37
+ end
38
+
39
+ context '#set' do
40
+ should "set a Symbol option as #{Rack::Sprockets::Options::RACK_ENV_NS}.symbol" do
41
+ @options.set :foo, 'bar'
42
+ assert_equal 'bar', @options.options[MockOptions.option_name(:foo)]
43
+ end
44
+ should 'set a String option as string' do
45
+ @options.set 'foo.bar', 'baz'
46
+ assert_equal 'baz', @options.options['foo.bar']
47
+ end
48
+ should 'set all key/value pairs when given a Hash' do
49
+ @options.set :foo => 'bar', 'foo.bar' => 'baz'
50
+ assert_equal 'bar', @options.options[MockOptions.option_name(:foo)]
51
+ assert_equal 'baz', @options.options['foo.bar']
52
+ end
53
+ end
54
+
55
+ should 'allow setting multiple options via assignment' do
56
+ @options.options = { :foo => 'bar', 'foo.bar' => 'baz' }
57
+ assert_equal 'bar', @options.options[MockOptions.option_name(:foo)]
58
+ assert_equal 'baz', @options.options['foo.bar']
59
+ end
60
+
61
+ context "when writing to collection options" do
62
+ setup do
63
+ @option = Rack::Sprockets::Options::COLLECTION_OPTS.first
64
+ end
65
+
66
+ should "force the option to an array value" do
67
+ @options.set @option, ["blah", "whatever"]
68
+ assert_kind_of Array, @options.options[@option]
69
+ assert_equal 2, @options.options[@option].length
70
+
71
+ @options.set @option, "something"
72
+ assert_kind_of Array, @options.options[@option]
73
+ assert_equal 1, @options.options[@option].length
74
+ end
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,141 @@
1
+ require 'test/helper'
2
+ require 'rack/sprockets/base'
3
+ require 'rack/sprockets/request'
4
+
5
+ class RequestTest < Test::Unit::TestCase
6
+
7
+ context 'Rack::Sprockets::Request' do
8
+ setup do
9
+ @defaults = env_defaults
10
+ end
11
+
12
+ context "basic object" do
13
+ should "have some attributes" do
14
+ [ :options,
15
+ :hosted_at_option,
16
+ :request_method,
17
+ :path_info,
18
+ :path_info_resource,
19
+ :path_info_format,
20
+ :source,
21
+ :hosted_at?,
22
+ :cached?,
23
+ :for_js?,
24
+ :for_sprockets?
25
+ ].each do |a|
26
+ assert_respond_to sprockets_request("GET", "/foo.js"), a, "request does not respond to #{a.inspect}"
27
+ end
28
+ end
29
+
30
+ should "sanitize the :hosted_at options" do
31
+ req = sprockets_request("GET", "/something.js")
32
+ req.options = {:hosted_at => "/here"}
33
+ assert_equal "/here", req.hosted_at_option
34
+
35
+ req = sprockets_request("GET", "/something.js")
36
+ req.options = {:hosted_at => "//there"}
37
+ assert_equal "/there", req.hosted_at_option
38
+
39
+ req = sprockets_request("GET", "/something.js")
40
+ req.options = {:hosted_at => "/where/"}
41
+ assert_equal "/where", req.hosted_at_option
42
+
43
+ req = sprockets_request("GET", "/something.js")
44
+ req.options = {:hosted_at => "what/"}
45
+ assert_equal "/what", req.hosted_at_option
46
+
47
+ req = sprockets_request("GET", "/something.js")
48
+ req.options = {:hosted_at => "why//"}
49
+ assert_equal "/why", req.hosted_at_option
50
+ end
51
+
52
+ should "know it's resource" do
53
+ assert_equal '/something', sprockets_request("GET", "/javascripts/something.js").path_info_resource
54
+ assert_equal '/something.awesome', sprockets_request("GET", "/javascripts/something.awesome.js").path_info_resource
55
+ assert_equal '/nested/something', sprockets_request("GET", "/javascripts/nested/something.js").path_info_resource
56
+ assert_equal '/something', sprockets_request("GET", "/something.js").path_info_resource
57
+ assert_equal '/something', sprockets_request("GET", "///something.js").path_info_resource
58
+ assert_equal '/nested/something', sprockets_request("GET", "/nested/something.js").path_info_resource
59
+ assert_equal '/nested/something', sprockets_request("GET", "/nested///something.js").path_info_resource
60
+ end
61
+
62
+ should "know it's resource format" do
63
+ assert_equal '.js', sprockets_request("GET", "/foo.js").path_info_format
64
+ assert_equal '.js', sprockets_request("GET", "/foo/bar.js").path_info_format
65
+ end
66
+ end
67
+
68
+ context "#source " do
69
+ should "match :compress settings with Rack::Sprockets:Config" do
70
+ req = sprockets_request("GET", "/javascripts/app.js")
71
+ assert_equal Rack::Sprockets.config.compress?, req.source.compress?
72
+ end
73
+
74
+ should "set it's cache value to nil when Rack::Sprockets not configured to cache" do
75
+ Rack::Sprockets.config = Rack::Sprockets::Config.new
76
+ req = sprockets_request("GET", "/javascripts/app.js")
77
+
78
+ assert_equal false, req.source.cache?
79
+ assert_equal nil, req.source.cache
80
+ end
81
+
82
+ should "set it's cache to the appropriate path when Rack::Sprockets configured to cache" do
83
+ Rack::Sprockets.config = Rack::Sprockets::Config.new :cache => true
84
+ req = sprockets_request("GET", "/javascripts/app.js")
85
+ cache_path = File.join(req.options(:root), req.options(:public), req.options(:hosted_at))
86
+
87
+ assert_equal true, req.source.cache?
88
+ assert_equal cache_path, req.source.cache
89
+ end
90
+ end
91
+
92
+ should_not_be_a_valid_rack_sprockets_request({
93
+ :method => "POST",
94
+ :resource => "/foo.html",
95
+ :description => "a non-js resource"
96
+ })
97
+
98
+ should_not_be_a_valid_rack_sprockets_request({
99
+ :method => "POST",
100
+ :resource => "/foo.css",
101
+ :description => "a css resource"
102
+ })
103
+
104
+ should_not_be_a_valid_rack_sprockets_request({
105
+ :method => "GET",
106
+ :resource => "/foo.html",
107
+ :description => "a non-js resource"
108
+ })
109
+
110
+ should_not_be_a_valid_rack_sprockets_request({
111
+ :method => "GET",
112
+ :resource => "/foo.js",
113
+ :description => "a js resource hosted somewhere other than where Rack::Sprockets expects them"
114
+ })
115
+
116
+ should_not_be_a_valid_rack_sprockets_request({
117
+ :method => "GET",
118
+ :resource => "/javascripts/foo.js",
119
+ :description => "a js resource hosted where Rack::Sprockets expects them but does not match any source"
120
+ })
121
+
122
+ should_be_a_valid_rack_sprockets_request({
123
+ :method => "GET",
124
+ :resource => "/javascripts/app.js",
125
+ :description => "a js resource hosted where Rack::Sprockets expects them that matches source"
126
+ })
127
+
128
+ should_not_be_a_valid_rack_sprockets_request({
129
+ :method => "GET",
130
+ :resource => "/javascripts/nested/foo.js",
131
+ :description => "a nested js resource hosted where Rack::Sprockets expects them but does not match any source"
132
+ })
133
+
134
+ should_be_a_valid_rack_sprockets_request({
135
+ :method => "GET",
136
+ :resource => "/javascripts/nested/thing.js",
137
+ :description => "a nested js resource hosted where Rack::Sprockets expects them that matches source"
138
+ })
139
+ end
140
+
141
+ end