cobranding 1.2.2
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/License.txt +674 -0
- data/README.rdoc +69 -0
- data/Rakefile +37 -0
- data/lib/cobranding.rb +11 -0
- data/lib/cobranding/helper.rb +28 -0
- data/lib/cobranding/layout.rb +208 -0
- data/lib/cobranding/persistent_layout.rb +53 -0
- data/spec/helper_spec.rb +98 -0
- data/spec/layout_spec.rb +151 -0
- data/spec/persistent_layout_spec.rb +111 -0
- data/spec/spec_helper.rb +34 -0
- metadata +106 -0
data/spec/layout_spec.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Cobranding::Layout do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@context = Object.new
|
7
|
+
def @context.test_tag_for_cobranding
|
8
|
+
"Woo woo"
|
9
|
+
end
|
10
|
+
|
11
|
+
cache = ActiveSupport::Cache::MemoryStore.new
|
12
|
+
Rails.stub!(:cache).and_return(cache)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should be able to evaluate a template from HTML" do
|
16
|
+
layout = Cobranding::Layout.new("<html>Test</html>")
|
17
|
+
layout.evaluate(@context).should == "<html>Test</html>"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should replace {{}} markup with predefined method calls" do
|
21
|
+
layout = Cobranding::Layout.new("<html>Test {{test_tag}}</html>")
|
22
|
+
layout.evaluate(@context).should == "<html>Test Woo woo</html>"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should replace {{}} markup with predefined method calls using a custom suffix" do
|
26
|
+
def @context.test_tag_for_layout
|
27
|
+
"custom suffix"
|
28
|
+
end
|
29
|
+
layout = Cobranding::Layout.new("<html>Test {{test_tag}}</html>")
|
30
|
+
layout.evaluate(@context, :suffix => "_for_layout").should == "<html>Test custom suffix</html>"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should replace {{}} markup with predefined method calls using a custom prefix" do
|
34
|
+
def @context.cobranding_test_tag
|
35
|
+
"custom prefix"
|
36
|
+
end
|
37
|
+
layout = Cobranding::Layout.new("<html>Test {{test_tag}}</html>")
|
38
|
+
layout.evaluate(@context, :prefix => "cobranding_").should == "<html>Test custom prefix</html>"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should replace {{}} markup with predefined method calls using a custom prefix and suffix" do
|
42
|
+
def @context.cobranding_test_tag_for_layout
|
43
|
+
"custom prefix and suffix"
|
44
|
+
end
|
45
|
+
layout = Cobranding::Layout.new("<html>Test {{test_tag}}</html>")
|
46
|
+
layout.evaluate(@context, :prefix => "cobranding_", :suffix => "_for_layout").should == "<html>Test custom prefix and suffix</html>"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should ignore spaces in {{}} markup tags" do
|
50
|
+
layout = Cobranding::Layout.new("<html>Test {{ test_tag }}</html>")
|
51
|
+
layout.evaluate(@context).should == "<html>Test Woo woo</html>"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should ignore method calls that are not defined" do
|
55
|
+
layout = Cobranding::Layout.new("<html>Test {{no_tag}}</html>")
|
56
|
+
layout.evaluate(@context).should == "<html>Test </html>"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should not allow malicious markup tags" do
|
60
|
+
layout = Cobranding::Layout.new("<html>Test {{test_tag; File.read('/etc/passwd')}}</html>")
|
61
|
+
layout.evaluate(@context).should == "<html>Test {{test_tag; File.read('/etc/passwd')}}</html>"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should strip extra new lines since they are stupid" do
|
65
|
+
layout = Cobranding::Layout.new("<html>Test\r\n\t \n Newline\n\n\n</html>")
|
66
|
+
layout.evaluate(@context).should == "<html>Test\n Newline\n</html>"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should escape ERB code so evil things can't happen" do
|
70
|
+
layout = Cobranding::Layout.new("<html>Test <%= File.read('/etc/passwd') %></html>")
|
71
|
+
layout.evaluate(@context).should == "<html>Test <%= File.read('/etc/passwd') %></html>"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should be able to get a layout from a URL" do
|
75
|
+
stub_request(:get, "localhost/layout?site=1").to_return(:status => [200, "Success"], :body => "<html>{{test_tag}}</html>")
|
76
|
+
layout = Cobranding::Layout.get("http://localhost/layout", :params => {:site => 1})
|
77
|
+
layout.evaluate(@context).should == "<html>Woo woo</html>"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should be able to get a layout from URL components" do
|
81
|
+
stub_request(:get, "https://localhost:444/layout/path?site=1").to_return(:status => [200, "Success"], :body => "<html>{{test_tag}}</html>")
|
82
|
+
layout = Cobranding::Layout.get("path", :scheme => "https", :host => "localhost", :port => 444, :base => "/layout", :params => {:site => 1})
|
83
|
+
layout.evaluate(@context).should == "<html>Woo woo</html>"
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should be able to get a layout from a URL with a POST" do
|
87
|
+
stub_request(:post, "localhost/layout").with(:params => {"site" => "1"}, :headers => {'Content-Type'=>'application/x-www-form-urlencoded'}).to_return(:status => [200, "Success"], :body => "<html>{{test_tag}}</html>")
|
88
|
+
layout = Cobranding::Layout.get("http://localhost/layout", :method => :post, :site => 1)
|
89
|
+
layout.evaluate(@context).should == "<html>Woo woo</html>"
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should be able to get a layout from a URL without caching" do
|
93
|
+
stub_request(:get, "localhost/layout?site=1").to_return(:status => [200, "Success"], :body => "<html>{{test_tag}}</html>")
|
94
|
+
Rails.stub!(:cache).and_return(nil)
|
95
|
+
layout = Cobranding::Layout.get("http://localhost/layout", :params => {:site => 1})
|
96
|
+
layout.evaluate(@context).should == "<html>Woo woo</html>"
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should generate consistent cache keys" do
|
100
|
+
key_1 = Cobranding::Layout.cache_key("http://localhost/layout", :params => {:a => 1, :b => 2})
|
101
|
+
key_2 = Cobranding::Layout.cache_key("http://localhost/layout", :params => {"a" => "1", "b" => "2"})
|
102
|
+
key_3 = Cobranding::Layout.cache_key("http://localhost/layout?b=2&a=1")
|
103
|
+
key_4 = Cobranding::Layout.cache_key("http://localhost/layout?b=1&a=2")
|
104
|
+
key_5 = Cobranding::Layout.cache_key("http://localhost/layout_2", :params => {:a => 1, :b => 2})
|
105
|
+
key_1.should == key_2
|
106
|
+
key_1.should == key_3
|
107
|
+
key_1.should_not == key_4
|
108
|
+
key_1.should_not == key_5
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should read a layout from the cache if it is found" do
|
112
|
+
key = Cobranding::Layout.cache_key("http://localhost/layout")
|
113
|
+
cached_layout = Cobranding::Layout.new("<html>Cached</html>")
|
114
|
+
Rails.cache.write(key, cached_layout)
|
115
|
+
layout = Cobranding::Layout.get("http://localhost/layout", :ttl => 300)
|
116
|
+
layout.evaluate(@context).should == "<html>Cached</html>"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should not write a layout to the cache if :ttl is not specified" do
|
120
|
+
stub_request(:get, "http://localhost/layout?v=1").to_return(:status => 200, :body => "<html>{{test_tag}}</html>")
|
121
|
+
key = Cobranding::Layout.cache_key("http://localhost/layout", :params => {:v => 1})
|
122
|
+
layout = Cobranding::Layout.get("http://localhost/layout", :params => {:v => 1})
|
123
|
+
layout.evaluate(@context).should == "<html>Woo woo</html>"
|
124
|
+
cached_layout = Rails.cache.read(key)
|
125
|
+
cached_layout.should == nil
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should expand relative URL's in the HTML based on the request URL" do
|
129
|
+
html = "<a href=\"http://example.com/\"><img src=/logo.gif></a><A HREF='/test2'><IMG SRC=\"/images/new_logo.gif\" id=\"/logo\"></A>"
|
130
|
+
stub_request(:get, "http://localhost/layout").to_return(:status => 200, :body => html)
|
131
|
+
layout = Cobranding::Layout.get("http://localhost/layout")
|
132
|
+
layout.evaluate(@context).should == "<a href=\"http://example.com/\"><img src=http://localhost/logo.gif></a><A HREF='http://localhost/test2'><IMG SRC=\"http://localhost/images/new_logo.gif\" id=\"/logo\"></A>"
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should expand relative URL's in the HTML based on the :base_url option" do
|
136
|
+
html = "<a href=\"http://example.com/\"><img src=/logo.gif></a><A HREF='/test2'><IMG SRC=\"/images/new_logo.gif\" id=\"/logo\"></A>"
|
137
|
+
stub_request(:get, "http://localhost/layout").to_return(:status => 200, :body => html)
|
138
|
+
layout = Cobranding::Layout.get("http://localhost/layout", :base_url => "https://secure.example.com/")
|
139
|
+
layout.evaluate(@context).should == "<a href=\"http://example.com/\"><img src=https://secure.example.com/logo.gif></a><A HREF='https://secure.example.com/test2'><IMG SRC=\"https://secure.example.com/images/new_logo.gif\" id=\"/logo\"></A>"
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should process the layout HTML with a block in case it needs to be munged" do
|
143
|
+
html = 'this is <!--#include virtual="test_tag" --> stuff'
|
144
|
+
stub_request(:get, "http://localhost/layout").to_return(:status => 200, :body => html)
|
145
|
+
layout = Cobranding::Layout.get("http://localhost/layout") do |code|
|
146
|
+
code.gsub('i', '!')
|
147
|
+
code.gsub(/<!--#\s*include\s+virtual="([^"]+)"\s*-->/, '{{ \1 }}')
|
148
|
+
end
|
149
|
+
layout.evaluate(@context).should == "this is Woo woo stuff"
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require File.expand_path('../spec_helper', __FILE__)
|
2
|
+
|
3
|
+
describe Cobranding::PersistentLayout do
|
4
|
+
|
5
|
+
class Cobranding::PersistentLayout::Tester1
|
6
|
+
attr_accessor :src, :url
|
7
|
+
include Cobranding::PersistentLayout
|
8
|
+
end
|
9
|
+
|
10
|
+
class Cobranding::PersistentLayout::Tester2
|
11
|
+
attr_accessor :layout_src, :layout_url, :layout_url_options
|
12
|
+
include Cobranding::PersistentLayout
|
13
|
+
self.layout_src_attribute = :layout_src
|
14
|
+
self.layout_url_attribute = :layout_url
|
15
|
+
self.layout_url_options_attribute = :layout_url_options
|
16
|
+
end
|
17
|
+
|
18
|
+
class Cobranding::PersistentLayout::Tester3
|
19
|
+
attr_accessor :src, :url
|
20
|
+
include Cobranding::PersistentLayout
|
21
|
+
self.layout_preprocessor = lambda{|html| html.gsub('s', "$")}
|
22
|
+
end
|
23
|
+
|
24
|
+
class Cobranding::PersistentLayout::Tester4
|
25
|
+
attr_accessor :src, :url
|
26
|
+
include Cobranding::PersistentLayout
|
27
|
+
self.layout_preprocessor = :replace_i
|
28
|
+
|
29
|
+
def replace_i (html)
|
30
|
+
html.gsub('i', '!')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should fetch the layout and store the source into default fields" do
|
35
|
+
model = Cobranding::PersistentLayout::Tester1.new
|
36
|
+
model.url = "http://localhost/layout"
|
37
|
+
layout = Cobranding::Layout.new("<html/>")
|
38
|
+
Cobranding::Layout.should_receive(:get).with("http://localhost/layout", {}).and_return(layout)
|
39
|
+
model.fetch_layout
|
40
|
+
model.src.should == layout.src
|
41
|
+
model.layout.should == layout
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should fetch the layout and store the source into a specified fields" do
|
45
|
+
model = Cobranding::PersistentLayout::Tester2.new
|
46
|
+
model.layout_url = "http://localhost/layout"
|
47
|
+
model.layout_url_options = {"params" => {"v" => 1}}
|
48
|
+
layout = Cobranding::Layout.new("<html/>")
|
49
|
+
Cobranding::Layout.should_receive(:get).with("http://localhost/layout", {"params" => {"v" => 1}}).and_return(layout)
|
50
|
+
model.fetch_layout
|
51
|
+
model.layout_src.should == layout.src
|
52
|
+
model.layout.should == layout
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should create a layout from the compiled source in the field" do
|
56
|
+
model = Cobranding::PersistentLayout::Tester1.new
|
57
|
+
layout = Cobranding::Layout.new("<html/>")
|
58
|
+
model.src = layout.src
|
59
|
+
model.layout.src.should == layout.src
|
60
|
+
model.layout.object_id.should_not == layout.object_id
|
61
|
+
model.layout.object_id.should == model.layout.object_id
|
62
|
+
end
|
63
|
+
|
64
|
+
context "fetching with preprocessor" do
|
65
|
+
let(:url){ "http://localhost/layout" }
|
66
|
+
before :each do
|
67
|
+
stub_request(:get, url).to_return(:status => 200, :body => "This is a test")
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should not invoke a preprocessor if it isn't defined" do
|
71
|
+
model = Cobranding::PersistentLayout::Tester1.new
|
72
|
+
model.url = url
|
73
|
+
model.fetch_layout
|
74
|
+
model.src.should == Cobranding::Layout.new("This is a test").src
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should use a Proc as the layout preprocessor" do
|
78
|
+
model = Cobranding::PersistentLayout::Tester3.new
|
79
|
+
model.url = url
|
80
|
+
model.fetch_layout
|
81
|
+
model.src.should == Cobranding::Layout.new("Thi$ i$ a te$t").src
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should use an instance method as the layout preprocessor" do
|
85
|
+
model = Cobranding::PersistentLayout::Tester4.new
|
86
|
+
model.url = url
|
87
|
+
model.fetch_layout
|
88
|
+
model.src.should == Cobranding::Layout.new("Th!s !s a test").src
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "setting html with preprocessor" do
|
93
|
+
it "should not invoke a preprocessor if it isn't defined" do
|
94
|
+
model = Cobranding::PersistentLayout::Tester1.new
|
95
|
+
model.layout_html = "This is a test"
|
96
|
+
model.src.should == Cobranding::Layout.new("This is a test").src
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should use a Proc as the layout preprocessor" do
|
100
|
+
model = Cobranding::PersistentLayout::Tester3.new
|
101
|
+
model.layout_html = "This is a test"
|
102
|
+
model.src.should == Cobranding::Layout.new("Thi$ i$ a te$t").src
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should use an instance method as the layout preprocessor" do
|
106
|
+
model = Cobranding::PersistentLayout::Tester4.new
|
107
|
+
model.layout_html = "This is a test"
|
108
|
+
model.src.should == Cobranding::Layout.new("Th!s !s a test").src
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'logger'
|
3
|
+
require 'webmock/rspec'
|
4
|
+
rails_version = ENV["RAILS_VERSION"] || ">=3.0.5"
|
5
|
+
gem 'activesupport', rails_version
|
6
|
+
gem 'actionpack', rails_version
|
7
|
+
begin
|
8
|
+
require 'simplecov'
|
9
|
+
SimpleCov.start do
|
10
|
+
add_filter "/spec/"
|
11
|
+
end
|
12
|
+
rescue LoadError
|
13
|
+
# simplecov not installed
|
14
|
+
end
|
15
|
+
|
16
|
+
WebMock.disable_net_connect!
|
17
|
+
|
18
|
+
require File.expand_path('../../lib/cobranding', __FILE__)
|
19
|
+
|
20
|
+
|
21
|
+
module Rails
|
22
|
+
end
|
23
|
+
|
24
|
+
def Rails.env
|
25
|
+
"test"
|
26
|
+
end
|
27
|
+
|
28
|
+
def Rails.cache
|
29
|
+
@cache ||= ActiveSupport::Cache::MemoryStore.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def Rails.logger
|
33
|
+
@logger ||= Logger.new(StringIO.new)
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cobranding
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Brian Durand
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-06 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: actionpack
|
16
|
+
requirement: &70231273526100 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70231273526100
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rest-client
|
27
|
+
requirement: &70231273525080 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70231273525080
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &70231273524440 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.0.0
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70231273524440
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: webmock
|
49
|
+
requirement: &70231273539980 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70231273539980
|
58
|
+
description: Provides Rails view layouts from an HTTP service.
|
59
|
+
email:
|
60
|
+
- mdobrota@tribune.com
|
61
|
+
- ddpr@tribune.com
|
62
|
+
executables: []
|
63
|
+
extensions: []
|
64
|
+
extra_rdoc_files:
|
65
|
+
- README.rdoc
|
66
|
+
files:
|
67
|
+
- License.txt
|
68
|
+
- README.rdoc
|
69
|
+
- Rakefile
|
70
|
+
- lib/cobranding.rb
|
71
|
+
- lib/cobranding/helper.rb
|
72
|
+
- lib/cobranding/layout.rb
|
73
|
+
- lib/cobranding/persistent_layout.rb
|
74
|
+
- spec/helper_spec.rb
|
75
|
+
- spec/layout_spec.rb
|
76
|
+
- spec/persistent_layout_spec.rb
|
77
|
+
- spec/spec_helper.rb
|
78
|
+
homepage:
|
79
|
+
licenses: []
|
80
|
+
post_install_message:
|
81
|
+
rdoc_options:
|
82
|
+
- --line-numbers
|
83
|
+
- --inline-source
|
84
|
+
- --main
|
85
|
+
- README.rdoc
|
86
|
+
require_paths:
|
87
|
+
- lib
|
88
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
none: false
|
96
|
+
requirements:
|
97
|
+
- - ! '>='
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
requirements: []
|
101
|
+
rubyforge_project:
|
102
|
+
rubygems_version: 1.8.10
|
103
|
+
signing_key:
|
104
|
+
specification_version: 3
|
105
|
+
summary: Provides Rails view layouts from an HTTP service
|
106
|
+
test_files: []
|