rack-pagespeed-fork 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +20 -0
- data/README.md +3 -0
- data/Rakefile +41 -0
- data/VERSION +1 -0
- data/lib/rack-pagespeed.rb +1 -0
- data/lib/rack/pagespeed.rb +50 -0
- data/lib/rack/pagespeed/config.rb +79 -0
- data/lib/rack/pagespeed/filters/all.rb +8 -0
- data/lib/rack/pagespeed/filters/base.rb +64 -0
- data/lib/rack/pagespeed/filters/combine_css.rb +81 -0
- data/lib/rack/pagespeed/filters/combine_javascripts.rb +77 -0
- data/lib/rack/pagespeed/filters/inline_css.rb +16 -0
- data/lib/rack/pagespeed/filters/inline_images.rb +17 -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/disk.rb +20 -0
- data/lib/rack/pagespeed/store/memcached.rb +21 -0
- data/lib/rack/pagespeed/store/redis.rb +19 -0
- data/rack-pagespeed-fork.gemspec +103 -0
- data/spec/config_spec.rb +110 -0
- data/spec/filters/combine_css_spec.rb +30 -0
- data/spec/filters/combine_javascripts_spec.rb +58 -0
- data/spec/filters/filter_spec.rb +62 -0
- data/spec/filters/inline_css_spec.rb +33 -0
- data/spec/filters/inline_images_spec.rb +28 -0
- data/spec/filters/inline_javascript_spec.rb +30 -0
- data/spec/filters/minify_javascript_spec.rb +59 -0
- data/spec/fixtures/all-small-dog-breeds.jpg +0 -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/mock_store.rb +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/pagespeed_spec.rb +106 -0
- data/spec/spec_helper.rb +60 -0
- data/spec/store/disk_spec.rb +34 -0
- data/spec/store/memcached_spec.rb +23 -0
- data/spec/store/redis_spec.rb +22 -0
- metadata +178 -0
@@ -0,0 +1,16 @@
|
|
1
|
+
class Rack::PageSpeed::Filters::InlineCSS < Rack::PageSpeed::Filter
|
2
|
+
priority 10
|
3
|
+
|
4
|
+
def execute! document
|
5
|
+
nodes = document.css('link[rel="stylesheet"][href]')
|
6
|
+
return false unless nodes.count > 0
|
7
|
+
nodes.each do |node|
|
8
|
+
file = file_for node
|
9
|
+
next if !file or 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::InlineImages < Rack::PageSpeed::Filter
|
2
|
+
priority 8
|
3
|
+
|
4
|
+
def execute! document
|
5
|
+
nodes = document.css('img')
|
6
|
+
return false unless nodes.count > 0
|
7
|
+
nodes.each do |node|
|
8
|
+
file = file_for node
|
9
|
+
next if !file or file.stat.size > (@options[:max_size] or 1024)
|
10
|
+
img = node.clone
|
11
|
+
img['src'] = "data:#{Rack::Mime.mime_type(File.extname(file.path))};base64,#{[file.read].pack('m')}"
|
12
|
+
img['alt'] = node['alt'] if node['alt']
|
13
|
+
node.before img
|
14
|
+
node.remove
|
15
|
+
end
|
16
|
+
end
|
17
|
+
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]')
|
7
|
+
return false unless nodes.count > 0
|
8
|
+
nodes.each do |node|
|
9
|
+
file = file_for node
|
10
|
+
next if !file or 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 2
|
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.name == 'script' and file_for(node)
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
|
3
|
+
module Rack::PageSpeed::Store; end
|
4
|
+
|
5
|
+
class Rack::PageSpeed::Store::Disk
|
6
|
+
def initialize path = Dir.tmpdir
|
7
|
+
raise ArgumentError, "#{path} is not a directory" unless File.directory? path
|
8
|
+
@path = path
|
9
|
+
end
|
10
|
+
|
11
|
+
def [] key
|
12
|
+
path = "#{@path}/rack-pagespeed-#{key}"
|
13
|
+
File.read path if File.exists? path
|
14
|
+
end
|
15
|
+
|
16
|
+
def []= key, value
|
17
|
+
File.open("#{@path}/rack-pagespeed-#{key}", 'w') { |file| file << value }
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
begin
|
2
|
+
require 'dalli'
|
3
|
+
rescue LoadError
|
4
|
+
raise LoadError, ":memcached store requires the dalli gem to be installed."
|
5
|
+
end
|
6
|
+
|
7
|
+
class Rack::PageSpeed::Store::Memcached
|
8
|
+
def initialize *args
|
9
|
+
@client = Dalli::Client.new *args
|
10
|
+
# @client.stats # let it raise errors if it can't connect
|
11
|
+
end
|
12
|
+
|
13
|
+
def [] key
|
14
|
+
@client.get key
|
15
|
+
end
|
16
|
+
|
17
|
+
def []= key, value
|
18
|
+
@client.set key, value
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
begin
|
2
|
+
require 'redis'
|
3
|
+
rescue LoadError
|
4
|
+
raise LoadError, ":redis store requires the redis gem to be installed."
|
5
|
+
end
|
6
|
+
|
7
|
+
class Rack::PageSpeed::Store::Redis
|
8
|
+
def initialize *args
|
9
|
+
@client = Redis.new *args
|
10
|
+
end
|
11
|
+
|
12
|
+
def [] key
|
13
|
+
@client.get key
|
14
|
+
end
|
15
|
+
|
16
|
+
def []= key, value
|
17
|
+
@client.set key, value
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
# stub: rack-pagespeed-fork 0.1.0 ruby lib
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "rack-pagespeed-fork"
|
9
|
+
s.version = "0.1.0"
|
10
|
+
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
|
+
s.require_paths = ["lib"]
|
13
|
+
s.authors = ["Will Jordan", "Julio Cesar Ody"]
|
14
|
+
s.date = "2014-10-08"
|
15
|
+
s.description = "Web page speed optimizations at the Rack level - fork"
|
16
|
+
s.email = "will@code.org"
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"README.md"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
"Gemfile",
|
22
|
+
"README.md",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"lib/rack-pagespeed.rb",
|
26
|
+
"lib/rack/pagespeed.rb",
|
27
|
+
"lib/rack/pagespeed/config.rb",
|
28
|
+
"lib/rack/pagespeed/filters/all.rb",
|
29
|
+
"lib/rack/pagespeed/filters/base.rb",
|
30
|
+
"lib/rack/pagespeed/filters/combine_css.rb",
|
31
|
+
"lib/rack/pagespeed/filters/combine_javascripts.rb",
|
32
|
+
"lib/rack/pagespeed/filters/inline_css.rb",
|
33
|
+
"lib/rack/pagespeed/filters/inline_images.rb",
|
34
|
+
"lib/rack/pagespeed/filters/inline_javascripts.rb",
|
35
|
+
"lib/rack/pagespeed/filters/minify_javascripts.rb",
|
36
|
+
"lib/rack/pagespeed/store/disk.rb",
|
37
|
+
"lib/rack/pagespeed/store/memcached.rb",
|
38
|
+
"lib/rack/pagespeed/store/redis.rb",
|
39
|
+
"rack-pagespeed-fork.gemspec",
|
40
|
+
"spec/config_spec.rb",
|
41
|
+
"spec/filters/combine_css_spec.rb",
|
42
|
+
"spec/filters/combine_javascripts_spec.rb",
|
43
|
+
"spec/filters/filter_spec.rb",
|
44
|
+
"spec/filters/inline_css_spec.rb",
|
45
|
+
"spec/filters/inline_images_spec.rb",
|
46
|
+
"spec/filters/inline_javascript_spec.rb",
|
47
|
+
"spec/filters/minify_javascript_spec.rb",
|
48
|
+
"spec/fixtures/all-small-dog-breeds.jpg",
|
49
|
+
"spec/fixtures/complex.html",
|
50
|
+
"spec/fixtures/foo.js",
|
51
|
+
"spec/fixtures/hh-reset.css",
|
52
|
+
"spec/fixtures/huge.css",
|
53
|
+
"spec/fixtures/iphone.css",
|
54
|
+
"spec/fixtures/jquery-1.4.1.min.js",
|
55
|
+
"spec/fixtures/medialess1.css",
|
56
|
+
"spec/fixtures/medialess2.css",
|
57
|
+
"spec/fixtures/mock_store.rb",
|
58
|
+
"spec/fixtures/mylib.js",
|
59
|
+
"spec/fixtures/noexternalcss.html",
|
60
|
+
"spec/fixtures/noscripts.html",
|
61
|
+
"spec/fixtures/ohno.js",
|
62
|
+
"spec/fixtures/reset.css",
|
63
|
+
"spec/fixtures/screen.css",
|
64
|
+
"spec/fixtures/styles.html",
|
65
|
+
"spec/pagespeed_spec.rb",
|
66
|
+
"spec/spec_helper.rb",
|
67
|
+
"spec/store/disk_spec.rb",
|
68
|
+
"spec/store/memcached_spec.rb",
|
69
|
+
"spec/store/redis_spec.rb"
|
70
|
+
]
|
71
|
+
s.homepage = "http://github.com/wjordan/rack-pagespeed"
|
72
|
+
s.licenses = ["MIT"]
|
73
|
+
s.rubygems_version = "2.4.2"
|
74
|
+
s.summary = "Web page speed optimizations at the Rack level - fork"
|
75
|
+
|
76
|
+
if s.respond_to? :specification_version then
|
77
|
+
s.specification_version = 4
|
78
|
+
|
79
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
80
|
+
s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
|
81
|
+
s.add_runtime_dependency(%q<jsmin>, [">= 0"])
|
82
|
+
s.add_runtime_dependency(%q<mime-types>, [">= 0"])
|
83
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0"])
|
84
|
+
s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
|
85
|
+
s.add_development_dependency(%q<rspec>, ["= 2.6.0"])
|
86
|
+
else
|
87
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
88
|
+
s.add_dependency(%q<jsmin>, [">= 0"])
|
89
|
+
s.add_dependency(%q<mime-types>, [">= 0"])
|
90
|
+
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
91
|
+
s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
|
92
|
+
s.add_dependency(%q<rspec>, ["= 2.6.0"])
|
93
|
+
end
|
94
|
+
else
|
95
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
96
|
+
s.add_dependency(%q<jsmin>, [">= 0"])
|
97
|
+
s.add_dependency(%q<mime-types>, [">= 0"])
|
98
|
+
s.add_dependency(%q<bundler>, ["~> 1.0"])
|
99
|
+
s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
|
100
|
+
s.add_dependency(%q<rspec>, ["= 2.6.0"])
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,110 @@
|
|
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
|
+
before { File.stub(:directory?).and_return(true) }
|
46
|
+
|
47
|
+
it "if it's an array, it enables filters listed in it with their default options" do
|
48
|
+
config = Rack::PageSpeed::Config.new :filters => [:makes_it_look_good]
|
49
|
+
config.filters.first.should be_a MakesItLookGood
|
50
|
+
end
|
51
|
+
|
52
|
+
it "if it's a hash, it let's you pass options to the filters" do
|
53
|
+
config = Rack::PageSpeed::Config.new :filters => {:makes_it_look_good => {:test => 6000}}
|
54
|
+
filter = config.filters.first
|
55
|
+
filter.should be_a MakesItLookGood
|
56
|
+
filter.options[:test].should == 6000 # yeah, 2 assertions, bad, bad
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'raises a NoSuchFilter error when a non-existing filter is passed to :filters' do
|
60
|
+
expect { Rack::PageSpeed::Config.new :filters => [:whoops!] }.to raise_error(Rack::PageSpeed::Config::NoSuchFilter)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'enabling filters, block/DSL based' do
|
65
|
+
before { File.stub(:directory?).and_return(true) }
|
66
|
+
|
67
|
+
it "let's you invoke filter names in a DSL-like fashion through a block" do
|
68
|
+
config = Rack::PageSpeed::Config.new do
|
69
|
+
makes_it_look_good
|
70
|
+
strips_naked
|
71
|
+
end
|
72
|
+
config.filters.should include_an_instance_of MakesItLookGood
|
73
|
+
config.filters.should include_an_instance_of StripsNaked
|
74
|
+
end
|
75
|
+
|
76
|
+
# two specs below actually work with the optiosn hash based context too
|
77
|
+
it "won't add the same filter twice" do
|
78
|
+
config = Rack::PageSpeed::Config.new do
|
79
|
+
makes_it_look_good
|
80
|
+
makes_it_look_good
|
81
|
+
strips_naked
|
82
|
+
end
|
83
|
+
config.filters.count.should == 2
|
84
|
+
end
|
85
|
+
|
86
|
+
it "calling a filter that requires storage without specifying one raises an error" do
|
87
|
+
class NeedsStore < Rack::PageSpeed::Filter
|
88
|
+
requires_store
|
89
|
+
end
|
90
|
+
expect { Rack::PageSpeed::Config.new do needs_store end }.to raise_error
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'raises a NoSuchFilter error when a non-existing filter is called ' do
|
94
|
+
expect { Rack::PageSpeed::Config.new do whateva :foo => 'bar' end }.to raise_error(Rack::PageSpeed::Config::NoSuchFilter)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'setting a storage mechanism' do
|
99
|
+
before { File.stub(:directory?).and_return(true) }
|
100
|
+
|
101
|
+
it 'loads the appropriate class on request' do
|
102
|
+
::File.stub(:join).and_return(File.dirname(__FILE__) + '/fixtures/mock_store.rb')
|
103
|
+
expect {
|
104
|
+
Rack::PageSpeed::Config.new do
|
105
|
+
store :mock
|
106
|
+
end
|
107
|
+
}.to change { Rack::PageSpeed::Store.const_defined?('Mock') }.from(false).to(true)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
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
|
+
expect { Rack::PageSpeed::Filters::CombineCSS.new }.to raise_error
|
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,58 @@
|
|
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 { expect { Rack::PageSpeed::Filters::CombineJavaScripts.new }.to raise_error }
|
14
|
+
specify { expect { Rack::PageSpeed::Filters::CombineJavaScripts.new(:store => {}) }.to_not raise_error }
|
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
|
+
context 'the #unique_id method' do
|
44
|
+
it "generates a hash thats unique to the nodes' combination of content + mtime in the absence of @options[:hash]" do
|
45
|
+
nodes = Fixtures.complex.css('script[src$=".js"]:not([src^="http"]) + script[src$=".js"]:not([src^="http"])')
|
46
|
+
@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)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "uses values for hashes estipulated in @options[:hash] if any" do
|
50
|
+
nodes = []
|
51
|
+
nodes << Fixtures.complex.at_css('script[src="ohno.js"]')
|
52
|
+
nodes << Fixtures.complex.at_css('script[src="foo.js"]')
|
53
|
+
filter = Rack::PageSpeed::Filters::CombineJavaScripts.new :store => {}, :hash => { %W(ohno.js foo.js) => "romanking" }
|
54
|
+
filter.send(:unique_id, nodes).should == "romanking"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|