rack-less 1.5.0 → 2.0.0

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.
Files changed (37) hide show
  1. data/.bundle/config +2 -0
  2. data/.gitignore +5 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +53 -0
  5. data/Rakefile +5 -43
  6. data/lib/rack/less.rb +6 -12
  7. data/lib/rack/less/config.rb +13 -25
  8. data/lib/rack/less/request.rb +36 -22
  9. data/lib/rack/less/source.rb +7 -7
  10. data/lib/rack/less/version.rb +3 -11
  11. data/rack-less.gemspec +29 -0
  12. data/test/app_helper.rb +25 -0
  13. data/test/config_test.rb +215 -0
  14. data/test/env.rb +9 -0
  15. data/test/fixtures/mock_options.rb +9 -0
  16. data/test/fixtures/sinatra/app.rb +9 -0
  17. data/test/fixtures/sinatra/app/stylesheets/all_compiled.css +7 -0
  18. data/test/fixtures/sinatra/app/stylesheets/all_one.less +10 -0
  19. data/test/fixtures/sinatra/app/stylesheets/all_two.less +4 -0
  20. data/test/fixtures/sinatra/app/stylesheets/css.css +4 -0
  21. data/test/fixtures/sinatra/app/stylesheets/css_compiled.css +4 -0
  22. data/test/fixtures/sinatra/app/stylesheets/nested/file.css +10 -0
  23. data/test/fixtures/sinatra/app/stylesheets/nested/file_compiled.css +2 -0
  24. data/test/fixtures/sinatra/app/stylesheets/nested/really/really.less +10 -0
  25. data/test/fixtures/sinatra/app/stylesheets/nested/really/really_compiled.css +2 -0
  26. data/test/fixtures/sinatra/app/stylesheets/normal.less +10 -0
  27. data/test/fixtures/sinatra/app/stylesheets/normal_compiled.css +2 -0
  28. data/test/fixtures/sinatra/app/stylesheets/some-styles.less +8 -0
  29. data/test/fixtures/sinatra/app/stylesheets/some_styles.less +8 -0
  30. data/test/fixtures/sinatra/app/stylesheets/styles1.less +8 -0
  31. data/test/helper.rb +77 -0
  32. data/test/options_test.rb +60 -0
  33. data/test/request_test.rb +142 -0
  34. data/test/response_test.rb +41 -0
  35. data/test/sinatra_test.rb +54 -0
  36. data/test/source_test.rb +158 -0
  37. metadata +93 -57
@@ -0,0 +1,60 @@
1
+ require "test/helper"
2
+ require 'rack/less/options'
3
+ require 'fixtures/mock_options'
4
+
5
+ class OptionsTest < Test::Unit::TestCase
6
+ context 'Rack::Less::Options' do
7
+ setup { @options = MockOptions.new }
8
+
9
+ should "use a namespace" do
10
+ assert_equal 'rack-less', Rack::Less::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
+ :source => 'app/stylesheets',
29
+ :public => 'public',
30
+ :hosted_at => '/stylesheets'
31
+ }.each do |k,v|
32
+ should "default #{k} correctly" do
33
+ assert_equal v, @options.options[MockOptions.option_name(k)]
34
+ end
35
+ end
36
+
37
+ context '#set' do
38
+ should "set a Symbol option as #{Rack::Less::Options::RACK_ENV_NS}.symbol" do
39
+ @options.set :foo, 'bar'
40
+ assert_equal 'bar', @options.options[MockOptions.option_name(:foo)]
41
+ end
42
+ should 'set a String option as string' do
43
+ @options.set 'foo.bar', 'baz'
44
+ assert_equal 'baz', @options.options['foo.bar']
45
+ end
46
+ should 'set all key/value pairs when given a Hash' do
47
+ @options.set :foo => 'bar', 'foo.bar' => 'baz'
48
+ assert_equal 'bar', @options.options[MockOptions.option_name(:foo)]
49
+ assert_equal 'baz', @options.options['foo.bar']
50
+ end
51
+ end
52
+
53
+ should 'allow setting multiple options via assignment' do
54
+ @options.options = { :foo => 'bar', 'foo.bar' => 'baz' }
55
+ assert_equal 'bar', @options.options[MockOptions.option_name(:foo)]
56
+ assert_equal 'baz', @options.options['foo.bar']
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,142 @@
1
+ require "test/helper"
2
+ require 'rack/less/request'
3
+
4
+ class RequestTest < Test::Unit::TestCase
5
+
6
+ context 'Rack::Less::Request' do
7
+ setup do
8
+ @defaults = env_defaults
9
+ end
10
+
11
+ context "basic object" do
12
+ should "have some attributes" do
13
+ [ :options,
14
+ :hosted_at_option,
15
+ :request_method,
16
+ :path_info,
17
+ :path_info_format,
18
+ :path_info_resource,
19
+ :source,
20
+ :hosted_at?,
21
+ :cached?,
22
+ :for_css?,
23
+ :for_less?
24
+ ].each do |a|
25
+ assert_respond_to less_request("GET", "/foo.css"), a, "request does not respond to #{a.inspect}"
26
+ end
27
+ end
28
+
29
+ should "know it's resource format" do
30
+ assert_equal '.css', less_request("GET", "/foo.css").path_info_format
31
+ assert_equal '.css', less_request("GET", "/foo/bar.css").path_info_format
32
+ assert_equal '', less_request("GET", "/foo/bar").path_info_format
33
+ end
34
+
35
+ should "sanitize the :hosted_at options" do
36
+ req = less_request("GET", "/something.css")
37
+ req.options = {:hosted_at => "/here"}
38
+ assert_equal "/here", req.hosted_at_option
39
+
40
+ req = less_request("GET", "/something.css")
41
+ req.options = {:hosted_at => "//there"}
42
+ assert_equal "/there", req.hosted_at_option
43
+
44
+ req = less_request("GET", "/something.css")
45
+ req.options = {:hosted_at => "/where/"}
46
+ assert_equal "/where", req.hosted_at_option
47
+
48
+ req = less_request("GET", "/something.css")
49
+ req.options = {:hosted_at => "what/"}
50
+ assert_equal "/what", req.hosted_at_option
51
+
52
+ req = less_request("GET", "/something.css")
53
+ req.options = {:hosted_at => "why//"}
54
+ assert_equal "/why", req.hosted_at_option
55
+ end
56
+
57
+ should "know it's resource" do
58
+ assert_equal '/something', less_request("GET", "/stylesheets/something.css").path_info_resource
59
+ assert_equal '/something.awesome', less_request("GET", "/stylesheets/something.awesome.css").path_info_resource
60
+ assert_equal '/nested/something', less_request("GET", "/stylesheets/nested/something.css").path_info_resource
61
+ assert_equal '/something/really/awesome', less_request("GET", "/stylesheets/something/really/awesome.css").path_info_resource
62
+ assert_equal '/something', less_request("GET", "/something.css").path_info_resource
63
+ assert_equal '/something', less_request("GET", "///something.css").path_info_resource
64
+ assert_equal '/nested/something', less_request("GET", "/nested/something.css").path_info_resource
65
+ assert_equal '/nested/something', less_request("GET", "/nested///something.css").path_info_resource
66
+ end
67
+ end
68
+
69
+ context "#source " do
70
+ should "match :compress settings with Rack::Less:Config" do
71
+ req = less_request("GET", "/stylesheets/normal.css")
72
+ assert_equal Rack::Less.config.compress?, req.source.compress?
73
+ end
74
+
75
+ should "set it's cache value to nil when Rack::Less not configured to cache" do
76
+ Rack::Less.config = Rack::Less::Config.new
77
+ req = less_request("GET", "/stylesheets/normal.css")
78
+
79
+ assert_equal false, req.source.cache?
80
+ assert_equal nil, req.source.cache
81
+ end
82
+
83
+ should "set it's cache to the appropriate path when Rack::Less configured to cache" do
84
+ Rack::Less.config = Rack::Less::Config.new :cache => true
85
+ req = less_request("GET", "/stylesheets/normal.css")
86
+ cache_path = File.join(req.options(:root), req.options(:public), req.hosted_at_option)
87
+
88
+ assert_equal true, req.source.cache?
89
+ assert_equal cache_path, req.source.cache
90
+ end
91
+ end
92
+
93
+ should_not_be_a_valid_rack_less_request({
94
+ :method => "POST",
95
+ :resource => "/foo.html",
96
+ :description => "a non-css resource"
97
+ })
98
+
99
+ should_not_be_a_valid_rack_less_request({
100
+ :method => "POST",
101
+ :resource => "/foo.css",
102
+ :description => "a css resource"
103
+ })
104
+
105
+ should_not_be_a_valid_rack_less_request({
106
+ :method => "GET",
107
+ :resource => "/foo.css",
108
+ :description => "a css resource hosted somewhere other than where Rack::Less expects them"
109
+ })
110
+
111
+ should_not_be_a_valid_rack_less_request({
112
+ :method => "GET",
113
+ :resource => "/stylesheets/foo.css",
114
+ :description => "a css resource hosted where Rack::Less expects them but does not match any source"
115
+ })
116
+
117
+ should_be_a_valid_rack_less_request({
118
+ :method => "GET",
119
+ :resource => "/stylesheets/normal.css",
120
+ :description => "a css resource hosted where Rack::Less expects them that matches source"
121
+ })
122
+
123
+ should_be_a_valid_rack_less_request({
124
+ :method => "GET",
125
+ :resource => "/stylesheets/some-styles.css",
126
+ :description => "a proper css resource with a '-' in the name"
127
+ })
128
+
129
+ should_be_a_valid_rack_less_request({
130
+ :method => "GET",
131
+ :resource => "/stylesheets/some_styles.css",
132
+ :description => "a proper css resource with a '_' in the name"
133
+ })
134
+
135
+ should_be_a_valid_rack_less_request({
136
+ :method => "GET",
137
+ :resource => "/stylesheets/styles1.css",
138
+ :description => "a proper css resource with a number in the name"
139
+ })
140
+ end
141
+
142
+ end
@@ -0,0 +1,41 @@
1
+ require "test/helper"
2
+ require 'rack/less/response'
3
+
4
+ class RequestTest < Test::Unit::TestCase
5
+
6
+ context 'Rack::Less::Response' do
7
+ setup do
8
+ @defaults = env_defaults
9
+ @css = File.read(file_path('test','fixtures','sinatra','app','stylesheets', 'css_compiled.css'))
10
+ @response = less_response(@css)
11
+ end
12
+
13
+ should "have some attributes" do
14
+ [ :options,
15
+ :status,
16
+ :headers,
17
+ :body,
18
+ :content_length,
19
+ :content_type,
20
+ :to_rack
21
+ ].each do |a|
22
+ assert_respond_to @response, a, "request does not respond to #{a.inspect}"
23
+ end
24
+ end
25
+
26
+ should "set it's status to '#{Rack::Utils::HTTP_STATUS_CODES[200]}'" do
27
+ assert_equal 200, @response.status
28
+ end
29
+
30
+ should "set it's Content-Type to '#{Rack::Less::MIME_TYPE}'" do
31
+ assert_equal Rack::Less::MIME_TYPE, @response.content_type, 'the content_type accessor is incorrect'
32
+ assert_equal Rack::Less::MIME_TYPE, @response.headers['Content-Type'], 'the Content-Type header is incorrect'
33
+ end
34
+
35
+ should "set it's Content-Length appropriately" do
36
+ assert_equal Rack::Less::Response.content_length(@css), @response.content_length, 'the content_length accessor is incorrect'
37
+ assert_equal Rack::Less::Response.content_length(@css), @response.headers['Content-Length'].to_i
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,54 @@
1
+ require "test/helper"
2
+ require "test/app_helper"
3
+ require 'test/fixtures/sinatra/app'
4
+
5
+ class SinatraTest < Test::Unit::TestCase
6
+
7
+ def app
8
+ @app ||= SinatraApp
9
+ end
10
+ def default_value(name)
11
+ Rack::Less::Base.defaults["#{Rack::Less::Options::RACK_ENV_NS}.#{name}"]
12
+ end
13
+
14
+ context "A Sinatra app using Rack::Less" do
15
+
16
+ context "requesting valid LESS" do
17
+ setup do
18
+ app.use Rack::Less,
19
+ :root => file_path('test','fixtures','sinatra')
20
+
21
+ @compiled = File.read(file_path('test','fixtures','sinatra','app','stylesheets', 'normal_compiled.css'))
22
+ @response = visit "/stylesheets/normal.css"
23
+ end
24
+
25
+ should_respond_with_compiled_css
26
+ end
27
+
28
+ context "requesting a nested valid LESS" do
29
+ setup do
30
+ app.use Rack::Less,
31
+ :root => file_path('test','fixtures','sinatra')
32
+
33
+ @compiled = File.read(file_path('test','fixtures','sinatra','app','stylesheets', 'nested', 'file_compiled.css'))
34
+ @response = visit "/stylesheets/nested/file.css"
35
+ end
36
+
37
+ should_respond_with_compiled_css
38
+ end
39
+
40
+ context "requesting a really nested valid LESS" do
41
+ setup do
42
+ app.use Rack::Less,
43
+ :root => file_path('test','fixtures','sinatra')
44
+
45
+ @compiled = File.read(file_path('test','fixtures','sinatra','app','stylesheets', 'nested', 'really', 'really_compiled.css'))
46
+ @response = visit "/stylesheets/nested/really/really.css"
47
+ end
48
+
49
+ should_respond_with_compiled_css
50
+ end
51
+
52
+ end
53
+
54
+ end
@@ -0,0 +1,158 @@
1
+ require "test/helper"
2
+ require 'rack/less/source'
3
+
4
+ class SourceTest < Test::Unit::TestCase
5
+ context 'Rack::Less::Source' do
6
+ setup do
7
+ @source_folder = file_path('test','fixtures','sinatra','app','stylesheets')
8
+ @cache = file_path('test','fixtures','sinatra','public','stylesheets')
9
+ end
10
+
11
+ should "require an existing :folder" do
12
+ assert_raise ArgumentError do
13
+ Rack::Less::Source.new('foo')
14
+ end
15
+ assert_raise ArgumentError do
16
+ Rack::Less::Source.new('foo', :folder => file_path('does','not','exist'))
17
+ end
18
+ assert_nothing_raised do
19
+ Rack::Less::Source.new('foo', :folder => @source_folder)
20
+ end
21
+ end
22
+
23
+ should "accept both .less and .css extensions, prefering .less over .css though" do
24
+ assert_equal [:less, :css], Rack::Less::Source::PREFERRED_EXTENSIONS
25
+ end
26
+
27
+ context "object" do
28
+ setup do
29
+ @basic = Rack::Less::Source.new('basic', :folder => @source_folder)
30
+ @nested = Rack::Less::Source.new('this/source/is/nested', :folder => @source_folder)
31
+ @ugly = Rack::Less::Source.new('//this/source/is/ugly', :folder => @source_folder)
32
+ @compressed = Rack::Less::Source.new('compressed', {
33
+ :folder => @source_folder,
34
+ :compress => true
35
+ })
36
+ @cached = Rack::Less::Source.new('cached', {
37
+ :folder => @source_folder,
38
+ :cache => @cache,
39
+ :compress => false
40
+ })
41
+ end
42
+
43
+ should "have accessors for path and cache values" do
44
+ assert_respond_to @basic, :css_resource
45
+ assert_equal 'basic', @basic.css_resource
46
+ assert_respond_to @basic, :cache
47
+ assert_equal 'this/source/is/nested', @nested.css_resource
48
+ assert_equal 'this/source/is/ugly', @ugly.css_resource
49
+ end
50
+
51
+ should "have an option for using compression" do
52
+ assert_equal false, @basic.compress?, 'the basic app should not compress'
53
+ assert_equal true, @compressed.compress?, 'the compressed app should compress'
54
+ assert_equal false, @cached.compress?, 'the cached app should not compress'
55
+ end
56
+
57
+ should "have an option for caching output to files" do
58
+ assert_equal false, @basic.cache?, 'the basic app should not cache'
59
+ assert_equal true, @cached.cache?, 'the cached app should cache'
60
+ end
61
+
62
+ should "have a source files list" do
63
+ assert_respond_to @basic, :files, 'engine does not respond to :files'
64
+ assert_kind_of Array, @basic.files, 'the engine files is not an Array'
65
+ end
66
+
67
+ should "have compiled css" do
68
+ assert_respond_to @basic, :to_css, 'engine does not respond to :to_css'
69
+ assert_respond_to @basic, :css, 'engine does not respond to :css'
70
+ end
71
+ end
72
+
73
+ context "with no corresponding source" do
74
+ setup do
75
+ @none = Rack::Less::Source.new('none', :folder => @source_folder)
76
+ end
77
+
78
+ should "have an empty file list" do
79
+ assert @none.files.empty?, 'engine file list is not empty'
80
+ end
81
+
82
+ should "generate no css" do
83
+ assert @none.to_css.empty?, 'engine generated css when it should not have'
84
+ end
85
+ end
86
+
87
+ should_compile_source('normal', "needing to be compiled")
88
+ should_compile_source('nested/file', "that is nested, needing to be compiled")
89
+ should_compile_source('css', "that is a CSS stylesheet")
90
+
91
+
92
+ context "with whitespace compression" do
93
+ setup do
94
+ @compiled = File.read(File.join(@source_folder, "normal_compiled.css"))
95
+ @compressed_normal = Rack::Less::Source.new('normal', {
96
+ :folder => @source_folder,
97
+ :compress => :whitespace
98
+ })
99
+ end
100
+
101
+ should "compress the compiled css" do
102
+ assert_equal @compiled.strip.delete("\n"), @compressed_normal.to_css, "the compiled css is compressed incorrectly"
103
+ end
104
+ end
105
+
106
+ context "with yui compression" do
107
+ setup do
108
+ @compiled = File.read(File.join(@source_folder, "normal_compiled.css"))
109
+ @compressed_normal = Rack::Less::Source.new('normal', {
110
+ :folder => @source_folder,
111
+ :compress => :yui
112
+ })
113
+ end
114
+
115
+ should "compress the compiled css" do
116
+ comp = YUI::CssCompressor.new(Rack::Less::Source::YUI_OPTS).compress(@compiled.strip)
117
+ assert_equal comp, @compressed_normal.to_css, "the compiled css is compressed incorrectly"
118
+ end
119
+ end
120
+
121
+ context "with caching" do
122
+ setup do
123
+ FileUtils.rm_rf(File.dirname(@cache)) if File.exists?(File.dirname(@cache))
124
+ @expected = Rack::Less::Source.new('normal', {
125
+ :folder => @source_folder,
126
+ :cache => @cache
127
+ }).to_css
128
+ @cached_file = File.join(@cache, "normal.css")
129
+ end
130
+ teardown do
131
+ FileUtils.rm_rf(File.dirname(@cache)) if File.exists?(File.dirname(@cache))
132
+ end
133
+
134
+ should "store the compiled css to a file in the cache" do
135
+ assert File.exists?(@cache), 'the cache folder does not exist'
136
+ assert File.exists?(@cached_file), 'the css was not cached to a file'
137
+ assert_equal @expected.strip, File.read(@cached_file).strip, "the compiled css is incorrect"
138
+ end
139
+ end
140
+
141
+ context "that is a combination of multiple files" do
142
+ setup do
143
+ @compiled = File.read(File.join(@source_folder, "all_compiled.css"))
144
+ @combinations_before = Rack::Less.config.combinations
145
+ Rack::Less.config.combinations = {'all' => ['all_one', 'all_two']}
146
+ @all = Rack::Less::Source.new('all', :folder => @source_folder)
147
+ end
148
+ teardown do
149
+ Rack::Less.config.combinations = @combinations_before
150
+ end
151
+
152
+ should "combine the compiled css" do
153
+ assert_equal @compiled.strip, @all.to_css.strip, "the compiled css is combined incorrectly"
154
+ end
155
+ end
156
+
157
+ end
158
+ end