rack-pagespeed 0.1.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.
- data/Gemfile +13 -0
- data/Gemfile.lock +59 -0
- data/README.md +15 -0
- data/Rakefile +36 -0
- data/VERSION +1 -0
- data/lib/rack-pagespeed.rb +1 -0
- data/lib/rack/pagespeed.rb +46 -0
- data/lib/rack/pagespeed/config.rb +72 -0
- data/lib/rack/pagespeed/filters/all.rb +7 -0
- data/lib/rack/pagespeed/filters/base.rb +53 -0
- data/lib/rack/pagespeed/filters/combine_css.rb +73 -0
- data/lib/rack/pagespeed/filters/combine_javascripts.rb +69 -0
- data/lib/rack/pagespeed/filters/inline_css.rb +16 -0
- data/lib/rack/pagespeed/filters/inline_javascripts.rb +17 -0
- data/lib/rack/pagespeed/filters/minify_javascripts.rb +41 -0
- data/lib/rack/pagespeed/store/all.rb +6 -0
- data/lib/rack/pagespeed/store/disk.rb +18 -0
- data/lib/rack/pagespeed/store/memcached.rb +17 -0
- data/spec/config_spec.rb +187 -0
- data/spec/filters/combine_css_spec.rb +30 -0
- data/spec/filters/combine_javascripts_spec.rb +48 -0
- data/spec/filters/filter_spec.rb +57 -0
- data/spec/filters/inline_css_spec.rb +33 -0
- data/spec/filters/inline_javascript_spec.rb +30 -0
- data/spec/filters/minify_javascript_spec.rb +59 -0
- data/spec/fixtures/complex.html +33 -0
- data/spec/fixtures/foo.js +1 -0
- data/spec/fixtures/hh-reset.css +1 -0
- data/spec/fixtures/huge.css +1176 -0
- data/spec/fixtures/iphone.css +1 -0
- data/spec/fixtures/jquery-1.4.1.min.js +152 -0
- data/spec/fixtures/medialess1.css +2 -0
- data/spec/fixtures/medialess2.css +2 -0
- data/spec/fixtures/mylib.js +3 -0
- data/spec/fixtures/noexternalcss.html +11 -0
- data/spec/fixtures/noscripts.html +9 -0
- data/spec/fixtures/ohno.js +1 -0
- data/spec/fixtures/reset.css +1 -0
- data/spec/fixtures/screen.css +2 -0
- data/spec/fixtures/styles.html +10 -0
- data/spec/fixtures/zecoolwebsite/css/awesomebydesign.css +94 -0
- data/spec/fixtures/zecoolwebsite/css/reset.css +190 -0
- data/spec/fixtures/zecoolwebsite/img/bg-idevice.png +0 -0
- data/spec/fixtures/zecoolwebsite/img/bg.png +0 -0
- data/spec/fixtures/zecoolwebsite/img/bottom-left-arrow.png +0 -0
- data/spec/fixtures/zecoolwebsite/img/bottom-right-arrow.png +0 -0
- data/spec/fixtures/zecoolwebsite/img/consulting-arrow.png +0 -0
- data/spec/fixtures/zecoolwebsite/img/design-arrow.png +0 -0
- data/spec/fixtures/zecoolwebsite/img/prototyping-arrow.png +0 -0
- data/spec/fixtures/zecoolwebsite/img/top-left-arrow.png +0 -0
- data/spec/fixtures/zecoolwebsite/img/top-right-arrow.png +0 -0
- data/spec/fixtures/zecoolwebsite/img/webdev-arrow.png +0 -0
- data/spec/fixtures/zecoolwebsite/index.html +87 -0
- data/spec/fixtures/zecoolwebsite/js/awesomebydesign.js +103 -0
- data/spec/fixtures/zecoolwebsite/js/jquery-1.4.2.min.js +154 -0
- data/spec/fixtures/zecoolwebsite/js/modernizr-1.5.min.js +28 -0
- data/spec/fixtures/zecoolwebsite/js/sayhi.js +1 -0
- data/spec/integration/integration_spec.rb +54 -0
- data/spec/pagespeed_spec.rb +101 -0
- data/spec/spec_helper.rb +54 -0
- data/spec/store/disk_spec.rb +34 -0
- data/spec/store/memcached_spec.rb +29 -0
- metadata +344 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
class Rack::PageSpeed::Filters::InlineCSS < Rack::PageSpeed::Filters::Base
|
2
|
+
priority 10
|
3
|
+
|
4
|
+
def execute! document
|
5
|
+
nodes = document.css('link[rel="stylesheet"][href$=".css"]:not([href^="http"])')
|
6
|
+
return false unless nodes.count > 0
|
7
|
+
nodes.each do |node|
|
8
|
+
file = file_for node
|
9
|
+
next if file.stat.size > (@options[:max_size] or 2048)
|
10
|
+
inline = Nokogiri::XML::Node.new 'style', document
|
11
|
+
inline.content = file.read
|
12
|
+
node.before inline
|
13
|
+
node.remove
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Rack::PageSpeed::Filters::InlineJavaScripts < Rack::PageSpeed::Filter
|
2
|
+
name 'inline_javascripts'
|
3
|
+
priority 10
|
4
|
+
|
5
|
+
def execute! document
|
6
|
+
nodes = document.css('script[src$=".js"]:not([src^="http"])')
|
7
|
+
return false unless nodes.count > 0
|
8
|
+
nodes.each do |node|
|
9
|
+
file = file_for node
|
10
|
+
next if file.stat.size > (@options[:max_size] or 2048)
|
11
|
+
inline = Nokogiri::XML::Node.new 'script', document
|
12
|
+
inline.content = file.read
|
13
|
+
node.before inline
|
14
|
+
node.remove
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'jsmin'
|
2
|
+
begin
|
3
|
+
require 'md5'
|
4
|
+
rescue LoadError
|
5
|
+
require 'digest/md5'
|
6
|
+
end
|
7
|
+
|
8
|
+
class Rack::PageSpeed::Filters::MinifyJavaScripts < Rack::PageSpeed::Filters::Base
|
9
|
+
requires_store
|
10
|
+
name 'minify_javascripts'
|
11
|
+
priority 8
|
12
|
+
|
13
|
+
def execute! document
|
14
|
+
nodes = document.css('script')
|
15
|
+
return false unless nodes.count > 0
|
16
|
+
nodes.each do |node|
|
17
|
+
if !node['src']
|
18
|
+
node.content = JSMin.minify node.content
|
19
|
+
else
|
20
|
+
if match = %r(^/rack-pagespeed-(.*)).match(node['src'])
|
21
|
+
store = @options[:store]
|
22
|
+
store[match[1]] = JSMin.minify store[match[1]]
|
23
|
+
else
|
24
|
+
next unless local_script? node
|
25
|
+
file = file_for node
|
26
|
+
javascript = file.read
|
27
|
+
hash = Digest::MD5.hexdigest file.mtime.to_i.to_s + javascript
|
28
|
+
compressed = Nokogiri::XML::Node.new 'script', document
|
29
|
+
compressed['src'] = "/rack-pagespeed-#{hash}.js"
|
30
|
+
@options[:store]["#{hash}.js"] = JSMin.minify javascript
|
31
|
+
node.before compressed
|
32
|
+
node.remove
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def local_script? node
|
39
|
+
node['src'] and !(node['src'] =~ /^http/ or !(node['src'] =~ /.js$/))
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
|
3
|
+
class Rack::PageSpeed::Store::Disk
|
4
|
+
def initialize path = Dir.tmpdir
|
5
|
+
raise ArgumentError, "#{path} is not a directory" unless File.directory? path
|
6
|
+
@path = path
|
7
|
+
end
|
8
|
+
|
9
|
+
def [] key
|
10
|
+
path = "#{@path}/rack-pagespeed-#{key}"
|
11
|
+
File.read path if File.exists? path
|
12
|
+
end
|
13
|
+
|
14
|
+
def []= key, value
|
15
|
+
File.open("#{@path}/rack-pagespeed-#{key}", 'w') { |file| file << value }
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'memcached' # wanted to use Dalli, but it just ain't working here right now
|
2
|
+
|
3
|
+
class Rack::PageSpeed::Store::Memcached
|
4
|
+
def initialize address_port = nil
|
5
|
+
@client = Memcached.new address_port
|
6
|
+
@client.stats # let it raise errors if it can't connect
|
7
|
+
end
|
8
|
+
|
9
|
+
def [] key
|
10
|
+
@client.get key
|
11
|
+
end
|
12
|
+
|
13
|
+
def []= key, value
|
14
|
+
@client.set key, value
|
15
|
+
true
|
16
|
+
end
|
17
|
+
end
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe 'rack-pagespeed configuration' do
|
4
|
+
before do
|
5
|
+
class StripsNaked < Rack::PageSpeed::Filter; end
|
6
|
+
class MakesItLookGood < Rack::PageSpeed::Filter; end
|
7
|
+
end
|
8
|
+
|
9
|
+
context 'when instancing a new object' do
|
10
|
+
it 'creates methods for each filter class found in Rack::PageSpeed::Filters::Base.available_filters' do
|
11
|
+
Rack::PageSpeed::Config.new(:public => Dir.tmpdir).should respond_to :strips_naked
|
12
|
+
end
|
13
|
+
|
14
|
+
it "requires a :public parameter pointing to the app's public directory" do
|
15
|
+
expect { Rack::PageSpeed::Config.new("foo" => "bar") }.to raise_error(ArgumentError)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'sorts filter execution based on their specified order' do
|
20
|
+
before do
|
21
|
+
class Larry < Rack::PageSpeed::Filter; priority 3; end
|
22
|
+
class Moe < Rack::PageSpeed::Filter; priority 2; end
|
23
|
+
class Curly < Rack::PageSpeed::Filter; priority 1; end
|
24
|
+
@config = Rack::PageSpeed::Config.new :public => Fixtures.path do
|
25
|
+
curly
|
26
|
+
larry
|
27
|
+
moe
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "Larry is first" do
|
32
|
+
@config.filters.first.should be_a Larry
|
33
|
+
end
|
34
|
+
|
35
|
+
it "Moe is second" do
|
36
|
+
@config.filters[1].should be_a Moe
|
37
|
+
end
|
38
|
+
|
39
|
+
it "Curly is last" do
|
40
|
+
@config.filters.last.should be_a Curly
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'enabling filters, options hash based' do
|
45
|
+
context 'options[:filters]' do
|
46
|
+
before { File.stub(:directory?).and_return(true) }
|
47
|
+
|
48
|
+
it "if it's an array, it enables filters listed in it with their default options" do
|
49
|
+
config = Rack::PageSpeed::Config.new :filters => [:makes_it_look_good]
|
50
|
+
config.filters.first.should be_a MakesItLookGood
|
51
|
+
end
|
52
|
+
|
53
|
+
it "if it's a hash, it let's you pass options to the filters logically" do
|
54
|
+
config = Rack::PageSpeed::Config.new :filters => {:makes_it_look_good => {:test => 6000}}
|
55
|
+
filter = config.filters.first
|
56
|
+
filter.should be_a MakesItLookGood
|
57
|
+
filter.options[:test].should == 6000 # yeah, 2 assertions, bad, bad
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'raises a NoSuchFilterError when a non-existing filter is passed to :filters' do
|
62
|
+
expect { Rack::PageSpeed.new page, :filters => [:whoops!] }.to raise_error
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'enabling filters, block/DSL based' do
|
67
|
+
before { File.stub(:directory?).and_return(true) }
|
68
|
+
|
69
|
+
it "let's you invoke filter names in a DSL-like fashion through a block" do
|
70
|
+
config = Rack::PageSpeed::Config.new do
|
71
|
+
makes_it_look_good
|
72
|
+
strips_naked
|
73
|
+
end
|
74
|
+
config.filters.should include_an_instance_of MakesItLookGood
|
75
|
+
config.filters.should include_an_instance_of StripsNaked
|
76
|
+
end
|
77
|
+
|
78
|
+
# two specs below actually work with the optiosn hash based context too
|
79
|
+
it "won't add the same filter twice" do
|
80
|
+
config = Rack::PageSpeed::Config.new do
|
81
|
+
makes_it_look_good
|
82
|
+
makes_it_look_good
|
83
|
+
strips_naked
|
84
|
+
end
|
85
|
+
config.filters.count.should == 2
|
86
|
+
end
|
87
|
+
|
88
|
+
it "won't add a filter if it's call returns false" do
|
89
|
+
class NeedsStore < Rack::PageSpeed::Filter
|
90
|
+
requires_store
|
91
|
+
end
|
92
|
+
config = Rack::PageSpeed::Config.new do needs_store end
|
93
|
+
config.filters.should be_empty
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
context 'setting a storage mechanism' do
|
98
|
+
before { File.stub(:directory?).and_return(true) }
|
99
|
+
|
100
|
+
context 'through the hash options' do
|
101
|
+
context ':disk => "directory path" sets to disk storage, with a specific path' do
|
102
|
+
before { @config = Rack::PageSpeed::Config.new :store => { :disk => Fixtures.path } }
|
103
|
+
subject { @config.store }
|
104
|
+
specify { should be_a Rack::PageSpeed::Store::Disk }
|
105
|
+
specify { subject.instance_variable_get(:@path).should == Fixtures.path }
|
106
|
+
end
|
107
|
+
context ":disk sets to disk storage, in the system's temp dir" do
|
108
|
+
before { @config = Rack::PageSpeed::Config.new :store => :disk }
|
109
|
+
subject { @config.store }
|
110
|
+
specify { should be_a Rack::PageSpeed::Store::Disk }
|
111
|
+
specify { subject.instance_variable_get(:@path).should == Dir.tmpdir }
|
112
|
+
end
|
113
|
+
context 'sets to memcache storage if :memcache => "server address/port"' do
|
114
|
+
before { @config = Rack::PageSpeed::Config.new :store => { :memcached => 'localhost:11211' } }
|
115
|
+
subject { @config.store }
|
116
|
+
specify { should be_a Rack::PageSpeed::Store::Memcached }
|
117
|
+
specify { subject.instance_variable_get(:@client).servers.first.should =~ /localhost:11211/ }
|
118
|
+
end
|
119
|
+
context 'sets to memcache storage, 127.0.0.1:11211 if :memcache"' do
|
120
|
+
before { @config = Rack::PageSpeed::Config.new :store => :memcached }
|
121
|
+
subject { @config.store }
|
122
|
+
specify { should be_a Rack::PageSpeed::Store::Memcached }
|
123
|
+
specify { subject.instance_variable_get(:@client).servers.first.should =~ /127.0.0.1:11211/ }
|
124
|
+
end
|
125
|
+
context "raises NoSuchStorageMechanism for weird stuff" do
|
126
|
+
specify { expect { Rack::PageSpeed::Config.new :store => :poo }.to raise_error(Rack::PageSpeed::Config::NoSuchStorageMechanism) }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'through a block passed to the initializer' do
|
131
|
+
context 'to a simple Hash, if {} gets passed' do
|
132
|
+
before do
|
133
|
+
@config = Rack::PageSpeed::Config.new do
|
134
|
+
store({})
|
135
|
+
end
|
136
|
+
end
|
137
|
+
subject { @config.store }
|
138
|
+
specify { should == {} }
|
139
|
+
end
|
140
|
+
context 'to disk storage, in a specific path if :disk => "some directory path"' do
|
141
|
+
before do
|
142
|
+
@config = Rack::PageSpeed::Config.new do
|
143
|
+
store :disk => Fixtures.path
|
144
|
+
end
|
145
|
+
end
|
146
|
+
subject { @config.store }
|
147
|
+
specify { should be_a Rack::PageSpeed::Store::Disk }
|
148
|
+
specify { subject.instance_variable_get(:@path).should == Fixtures.path }
|
149
|
+
end
|
150
|
+
context ":disk sets to disk storage, in the system's temp dir" do
|
151
|
+
before do
|
152
|
+
@config = Rack::PageSpeed::Config.new do
|
153
|
+
store :disk
|
154
|
+
end
|
155
|
+
end
|
156
|
+
subject { @config.store }
|
157
|
+
specify { should be_a Rack::PageSpeed::Store::Disk }
|
158
|
+
specify { subject.instance_variable_get(:@path).should == Dir.tmpdir }
|
159
|
+
end
|
160
|
+
context 'sets to memcache storage if :memcache => "server address/port"' do
|
161
|
+
before do
|
162
|
+
@config = Rack::PageSpeed::Config.new do
|
163
|
+
store :memcached => 'localhost:11211'
|
164
|
+
end
|
165
|
+
end
|
166
|
+
subject { @config.store }
|
167
|
+
specify { should be_a Rack::PageSpeed::Store::Memcached }
|
168
|
+
specify { subject.instance_variable_get(:@client).servers.first.should =~ /localhost:11211/ }
|
169
|
+
end
|
170
|
+
context 'sets to memcache storage, localhost:11211 if :memcache"' do
|
171
|
+
before do
|
172
|
+
@config = Rack::PageSpeed::Config.new do
|
173
|
+
store :memcached
|
174
|
+
end
|
175
|
+
end
|
176
|
+
subject { @config.store }
|
177
|
+
specify { should be_a Rack::PageSpeed::Store::Memcached }
|
178
|
+
specify { subject.instance_variable_get(:@client).servers.first.should =~ /127.0.0.1:11211/ }
|
179
|
+
end
|
180
|
+
context "raises NoSuchStorageMechanism for weird stuff" do
|
181
|
+
specify do
|
182
|
+
expect { Rack::PageSpeed::Config.new do store :poo end }.to raise_error(Rack::PageSpeed::Config::NoSuchStorageMechanism)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe 'the combine_css filter' do
|
4
|
+
it "is called \"combine_css\" as far as Config is concerned" do
|
5
|
+
Rack::PageSpeed::Filters::CombineCSS.name.should == 'combine_css'
|
6
|
+
end
|
7
|
+
|
8
|
+
it "requires a store mechanism to be passed via :store when initializing" do
|
9
|
+
Rack::PageSpeed::Filters::CombineCSS.new.should be_false
|
10
|
+
end
|
11
|
+
|
12
|
+
it "is a priority 9 filter" do
|
13
|
+
Rack::PageSpeed::Filters::CombineCSS.priority.should == 9
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'execute!' do
|
17
|
+
before :each do
|
18
|
+
@filter = Rack::PageSpeed::Filters::CombineCSS.new :public => Fixtures.path, :store => {}
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'cuts down the number of scripts in the fixtures from 5 to 1' do
|
22
|
+
expect { @filter.execute! Fixtures.complex }.to change { Fixtures.complex.css('link[rel="stylesheet"][href$=".css"]:not([href^="http"])').count }.from(5).to(1)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "stores the nodes' contents in the store passed through the initializer" do
|
26
|
+
@filter.instance_variable_get(:@options)[:store].should_receive(:[]=)
|
27
|
+
@filter.execute! Fixtures.complex
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe 'the combine_javascripts filter' do
|
4
|
+
it "is called \"combine_javascripts\" as far as Config is concerned" do
|
5
|
+
Rack::PageSpeed::Filters::CombineJavaScripts.name.should == 'combine_javascripts'
|
6
|
+
end
|
7
|
+
|
8
|
+
it "is a priority 9 filter" do
|
9
|
+
Rack::PageSpeed::Filters::CombineJavaScripts.priority 9
|
10
|
+
end
|
11
|
+
|
12
|
+
context "requires a store mechanism to be passed via :store when initializing" do
|
13
|
+
specify { Rack::PageSpeed::Filters::CombineJavaScripts.new.should be_false }
|
14
|
+
specify { Rack::PageSpeed::Filters::CombineJavaScripts.new(:store => {}).should_not be_false }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'execute!' do
|
18
|
+
before :each do
|
19
|
+
@filter = Rack::PageSpeed::Filters::CombineJavaScripts.new :public => Fixtures.path, :store => {}
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'cuts down the number of scripts in the fixtures from 4 to 2' do
|
23
|
+
expect { @filter.execute! Fixtures.complex }.to change { Fixtures.complex.css('script[src$=".js"]:not([src^="http"])').count }.from(4).to(2)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "stores the nodes' contents in the store passed through the initializer" do
|
27
|
+
@filter.instance_variable_get(:@options)[:store].should_receive(:[]=).twice
|
28
|
+
@filter.execute! Fixtures.complex
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'yes, I test private methods, so what?' do
|
33
|
+
before do
|
34
|
+
@filter = Rack::PageSpeed::Filters::CombineJavaScripts.new :public => Fixtures.path, :store => {}
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns an array of arrays containing JS nodes that are next to each other in #group_siblings' do
|
38
|
+
nodes = Fixtures.complex.css('script[src$=".js"]:not([src^="http"]) + script[src$=".js"]:not([src^="http"])')
|
39
|
+
result = @filter.send :group_siblings, nodes
|
40
|
+
result.should == [[nodes[0].previous_element, nodes[0]], [nodes[1].previous_element, nodes[1]]]
|
41
|
+
end
|
42
|
+
|
43
|
+
it '#unique_id a key thats unique to the nodes combination of content + mtime' do
|
44
|
+
nodes = Fixtures.complex.css('script[src$=".js"]:not([src^="http"]) + script[src$=".js"]:not([src^="http"])')
|
45
|
+
@filter.send(:unique_id, nodes).should == Digest::MD5.hexdigest(nodes.map { |node| file = @filter.send(:file_for, node); file.mtime.to_i.to_s + file.read }.join)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe 'the base filter class' do
|
4
|
+
before { @base = Rack::PageSpeed::Filters::Base.new(:foo => 'bar') }
|
5
|
+
|
6
|
+
it 'when instancing, it takes an options hash as argument' do
|
7
|
+
@base.options[:foo].should == 'bar'
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'when subclassing, it adds the new class to the #available_filters list' do
|
11
|
+
class Moo < Rack::PageSpeed::Filters::Base; end
|
12
|
+
Rack::PageSpeed::Filters::Base.available_filters.should include(Moo)
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'the #name declaration, which can be used to declare a name which the filter can be called upon' do
|
16
|
+
it 'can be called from inside the class' do
|
17
|
+
class Boo < Rack::PageSpeed::Filters::Base
|
18
|
+
name 'mooers'
|
19
|
+
end
|
20
|
+
Boo.name.should == 'mooers'
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'defaults to the class name if not called' do
|
24
|
+
class BananaSmoothie < Rack::PageSpeed::Filters::Base; end
|
25
|
+
BananaSmoothie.name.should == 'banana_smoothie'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'the #priority declaration, which defines the order that the filter will be executed' do
|
30
|
+
it 'takes a number' do
|
31
|
+
class NiceFilter < Rack::PageSpeed::Filter
|
32
|
+
priority 1
|
33
|
+
end
|
34
|
+
NiceFilter.priority.should == 1
|
35
|
+
end
|
36
|
+
it 'takes a string' do
|
37
|
+
class NiceFilter < Rack::PageSpeed::Filter
|
38
|
+
priority '1'
|
39
|
+
end
|
40
|
+
NiceFilter.priority.should == 1
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context '#file_for returns a File object' do
|
45
|
+
before { @base.options.stub(:[]).with(:public).and_return(Fixtures.path) }
|
46
|
+
|
47
|
+
it 'for a script' do
|
48
|
+
script = Fixtures.complex.at_css('#mylib')
|
49
|
+
@base.send(:file_for, script).stat.size.should == File.size(File.join(Fixtures.path, 'mylib.js'))
|
50
|
+
end
|
51
|
+
|
52
|
+
it "for a stylesheet" do
|
53
|
+
style = Fixtures.complex.at_css('link')
|
54
|
+
@base.send(:file_for, style).stat.size.should == File.size(File.join(Fixtures.path, 'reset.css'))
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|