rack-pagespeed-fork 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.
- 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
|