shrinker 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.
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shrinker::Backend::Redis do
4
+ subject { Shrinker::Backend::Redis.new }
5
+
6
+ describe "with options" do
7
+ let(:options) do
8
+ {
9
+ :client => {
10
+ :login => 'login',
11
+ :password => 'somepassword',
12
+ :port => '2331',
13
+ :host => 'localhost'
14
+ }
15
+ }
16
+ end
17
+
18
+ subject { Shrinker::Backend::Redis.new(options) }
19
+
20
+ it "uses the options" do
21
+ Redis.should_receive(:new).with(options[:client])
22
+
23
+ subject.send(:client)
24
+ end
25
+ end
26
+
27
+ context "with a default client setup" do
28
+ let(:client) { Redis.new }
29
+ before { subject.stub(:client) { client} }
30
+
31
+ describe "#store" do
32
+ it "stores the raw_url with the token key" do
33
+ Shrinker::Serializer.should_receive(:to_json).with('someurl', {}).and_return("tobestored")
34
+
35
+ subject.store('someurl', 'token')
36
+
37
+ client.get("_shrinker::token").should == 'tobestored'
38
+ end
39
+
40
+ it "stores the raw_url with the attributes" do
41
+ Shrinker::Serializer.should_receive(:to_json).with('someurl', {:user_id => 123}).and_return("tobestored")
42
+
43
+ subject.store('someurl', 'token', :user_id => 123)
44
+ client.get("_shrinker::token").should == 'tobestored'
45
+ end
46
+
47
+ it "sets the ttl when present" do
48
+ Shrinker::Serializer.should_receive(:to_json).with('someurl', {}).and_return("tobestored")
49
+ subject.stub(:ttl) { 32 }
50
+ client.should_receive(:setex).with("_shrinker::token", 32, "tobestored")
51
+
52
+ subject.store('someurl', 'token')
53
+ end
54
+ end
55
+
56
+ describe "#fetch" do
57
+ it "fetches using the token key" do
58
+ client.set("_shrinker::token", '{"url": "someurl", "attributes": {}}')
59
+ subject.fetch("token").should == {'url' => "someurl", 'attributes' => {}}
60
+ end
61
+ end
62
+
63
+ describe "#used_token?" do
64
+ before { subject.send(:delete, 'token') }
65
+
66
+ it "returns true when the token is used" do
67
+ client.set("_shrinker::token", '{"url": "someurl", "attributes": {}}')
68
+
69
+ subject.used_token?('token').should be_true
70
+ end
71
+
72
+ it "returns false" do
73
+ subject.used_token?('token').should be_false
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shrinker::Config do
4
+
5
+ module Shrinker
6
+ module Backend
7
+ class FakeBackend < ::Shrinker::Backend::Abstract
8
+
9
+ end
10
+ end
11
+ end
12
+
13
+ let(:config) { Shrinker.config }
14
+
15
+ before do
16
+ config.reset!
17
+ end
18
+
19
+ after do
20
+ config.reset!
21
+ end
22
+
23
+ it 'should return the config object for manipulation' do
24
+ config.is_a?(Shrinker::Config).should be_true
25
+ Shrinker.configure.is_a?(Shrinker::Config).should be_true
26
+ end
27
+
28
+ it 'should yield to the config if a block is present' do
29
+ lambda{
30
+ Shrinker.configure do
31
+ raise self.class.name
32
+ end
33
+ }.should raise_error('Shrinker::Config')
34
+ end
35
+
36
+ it 'allows passing the backend' do
37
+ Shrinker.configure do
38
+ backend 'FakeBackend'
39
+ backend_options({:key => 'value'})
40
+ end
41
+
42
+ Shrinker::Backend::FakeBackend.should_receive(:new).with({:key => 'value'})
43
+ Shrinker.send(:backend)
44
+ end
45
+
46
+ describe "#merge!" do
47
+ it "merges a hash" do
48
+ config.merge!(backend_options: {something: true})
49
+ config.backend_options.should == {something: true}
50
+ end
51
+
52
+ it "merges an instance of Config" do
53
+ config.instance_eval do
54
+ expanded_pattern 'first_pattern'
55
+ shrinked_pattern 'shrinked_pattern'
56
+ end
57
+ other_config = Shrinker::Config.new
58
+ other_config.instance_eval do
59
+ expanded_pattern 'second_pattern'
60
+ end
61
+ config.merge!(other_config)
62
+ config.expanded_pattern.should == 'second_pattern'
63
+ config.shrinked_pattern.should == 'shrinked_pattern'
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shrinker::EasyUrl do
4
+ describe "#to_s" do
5
+ it "returns itself with no params" do
6
+ Shrinker::EasyUrl.new("test").to_s.should == 'test'
7
+ end
8
+
9
+ it "returns itself with params" do
10
+ Shrinker::EasyUrl.new("test?something=2").to_s.should == 'test?something=2'
11
+ end
12
+
13
+ it "returns itself without the params when deleting it" do
14
+ easy_url = Shrinker::EasyUrl.new("test?something=2")
15
+ easy_url.params.delete(:something)
16
+ easy_url.to_s.should == 'test'
17
+ end
18
+
19
+ it "keeps the other params when deleting some" do
20
+ easy_url = Shrinker::EasyUrl.new("test?something=2&else=3")
21
+ easy_url.params.delete(:something)
22
+ easy_url.params[:else].should == '3'
23
+ easy_url.to_s.should == 'test?else=3'
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+ require 'redis'
3
+
4
+ describe Shrinker::Extractor do
5
+ describe "#url" do
6
+ let(:config) do
7
+ config = Shrinker::Config.new
8
+ config.instance_eval do
9
+ backend 'Redis'
10
+ end
11
+ config
12
+ end
13
+
14
+ let(:client) { Redis.new }
15
+
16
+ before { client.set("_shrinker::token", '{"url": "someurl", "attributes": {"test": "ab"}}') }
17
+
18
+ it "returns an EasyUrl instance" do
19
+ easy_url = Shrinker::Extractor.unshrink("token", config)
20
+ easy_url.should be_instance_of(Shrinker::EasyUrl)
21
+ easy_url.to_s.should == "someurl"
22
+ easy_url.attributes.should == {"test" => 'ab'}
23
+ end
24
+
25
+ it "raise UrlNotFound when not existing" do
26
+ expect {
27
+ Shrinker::Extractor.unshrink("not-exiting", config)
28
+ }.to raise_error(Shrinker::UrlNotFound)
29
+ end
30
+ end
31
+
32
+ describe "#config" do
33
+ it "returns the default config by default" do
34
+ Shrinker::Extractor.new.send(:config).should == Shrinker.config
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,114 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shrinker::Parser::Mime do
4
+ let(:mime) do
5
+ <<-MYMIME
6
+ Date: Fri, 23 Nov 2012 16:19:10 -0800
7
+ To: someone@example.com
8
+ From: else@example.com
9
+ Subject: Email test
10
+ Content-type: multipart/mixed; boundary="theBoundaryString"
11
+
12
+ --theBoundaryString
13
+
14
+ Plain text message goes in this part. Notice that it
15
+ has a blank line before it starts, meaning that this
16
+ part has no additional headers.
17
+ Here is a link to http://my-example.com/test?params=1
18
+
19
+ --theBoundaryString
20
+ Content-Type: text/html
21
+ Content-Transfer-Encoding: 7bit
22
+ Content-Disposition: inline
23
+ Content-Base: "http://somewebsite.com/"
24
+
25
+ <body><font size=4>This</font> is a
26
+ <i>test</i>.
27
+ --theBoundaryString--
28
+ MYMIME
29
+ end
30
+
31
+ describe "#replace" do
32
+ let(:config) do
33
+ config = Shrinker::Config.new
34
+ config.instance_eval do
35
+ expanded_pattern /(www\.)?my-example.com/
36
+ shrinked_pattern 'goo.ln'
37
+ end
38
+ config
39
+ end
40
+
41
+ it "replace the content in the mime" do
42
+ Shrinker::Parser::Url.should_receive(:replace).with('my-example.com/test?params=1', {}, config).and_return("replace1")
43
+ Shrinker::Parser::Url.should_receive(:replace).with('somewebsite.com', {}, config).never
44
+
45
+ replaced_mime = Shrinker::Parser::Mime::replace(mime, {}, config)
46
+ replaced_mime.should include("Here is a link to http://replace1")
47
+ end
48
+
49
+ context "when mime is multipart" do
50
+ let(:mime) { File.read(File.join(FIXTURES_PATH, 'mime.txt')) }
51
+
52
+ it "replace only anchor tags when setting anchors_only_in_html to true" do
53
+ config.anchors_only_in_html true
54
+
55
+ Shrinker::Parser::Url.should_receive(:replace).with("my-example.com/a?something=true", {}, instance_of(Shrinker::Config)).and_return('replace1')
56
+ Shrinker::Parser::Url.should_receive(:replace).with("www.my-example.com/donec-lobortis-lacus-vel-urna-variuo--4?clicked=abcdef", {}, instance_of(Shrinker::Config)).and_return('replace2')
57
+ Shrinker::Parser::Url.should_receive(:replace).with('www.my-example.com/class-aptent-taciti-sociosqu-ad-litader.jpg', {}, instance_of(Shrinker::Config)).never
58
+ Shrinker::Parser::Url.should_receive(:replace).with('www.my-example.com/safe', {}, instance_of(Shrinker::Config)).never
59
+ Shrinker::Parser::Url.should_receive(:replace).with('my-example.com/none', {}, instance_of(Shrinker::Config)).never
60
+
61
+ replaced_mime = Shrinker::Parser::Mime::replace(mime, {}, config)
62
+ end
63
+
64
+ it "replace every urls when not setting anchors_only_in_html" do
65
+ Shrinker::Parser::Url.should_receive(:replace).with("my-example.com/a?something=true", {}, instance_of(Shrinker::Config)).and_return('replace1')
66
+ Shrinker::Parser::Url.should_receive(:replace).with("www.my-example.com/donec-lobortis-lacus-vel-urna-variuo--4?clicked=abcdef", {}, instance_of(Shrinker::Config)).and_return('replace2')
67
+ Shrinker::Parser::Url.should_receive(:replace).with('www.my-example.com/class-aptent-taciti-sociosqu-ad-litader.jpg', {}, instance_of(Shrinker::Config)).and_return('replace3')
68
+ Shrinker::Parser::Url.should_receive(:replace).with('www.my-example.com/safe', {}, instance_of(Shrinker::Config)).and_return('replace4')
69
+ Shrinker::Parser::Url.should_receive(:replace).with('my-example.com/none', {}, instance_of(Shrinker::Config)).and_return('replace5')
70
+
71
+ replaced_mime = Shrinker::Parser::Mime::replace(mime, {}, config)
72
+ end
73
+ end
74
+ end
75
+
76
+ context "for longer multipart mimes" do
77
+
78
+ let(:multipart_mime) { File.read(File.join(FIXTURES_PATH, 'multipart_mime.txt')) }
79
+ let(:config) do
80
+ config = Shrinker::Config.new
81
+ config.instance_eval do
82
+ backend 'Redis'
83
+ expanded_pattern /www.somwebsite.com/
84
+ exclude_path /core|assets/
85
+ shrinked_pattern 'goo.ln'
86
+ end
87
+ config
88
+ end
89
+
90
+ it "replace only anchor tags when setting anchors_only_in_html to true" do
91
+ config.anchors_only_in_html true
92
+
93
+ Shrinker::Parser::Url.should_receive(:replace).with("www.somwebsite.com/glencoe-il/t/office-help--0000", {}, instance_of(Shrinker::Config)).and_return('replace1')
94
+ Shrinker::Parser::Url.should_receive(:replace).with("www.somwebsite.com/notifications", {}, instance_of(Shrinker::Config)).and_return('replace2')
95
+ Shrinker::Parser::Url.should_receive(:replace).with("www.somwebsite.com/go/defdbf1191f17112776a6adb4c201b277af845278971e81b532089d1b96926300347343b15580afba7a7cc41567b9608161d", {}, instance_of(Shrinker::Config)).and_return('replace3')
96
+ Shrinker::Parser::Url.should_receive(:replace).with("www.somwebsite.com/go/5f25b2b15ec6b450c3c5af71102616e07413381a718f1b5d21e7ff9e26d6fc216e9c05ab2b8a40195a16c8603be5860170eb", {}, instance_of(Shrinker::Config)).and_return('replace4')
97
+ Shrinker::Parser::Url.should_receive(:replace).with('www.somwebsite.com/core/assets/email/somwebsite-sky-header.jpg', {}, instance_of(Shrinker::Config)).never
98
+
99
+ replaced_mime = Shrinker::Parser::Mime::replace(multipart_mime, {}, config)
100
+ end
101
+
102
+ it "replace every urls when not setting anchors_only_in_html" do
103
+ Shrinker::Parser::Url.should_receive(:replace).with("www.somwebsite.com/glencoe-il/t/office-help--0000", {}, instance_of(Shrinker::Config)).and_return('replace1')
104
+ Shrinker::Parser::Url.should_receive(:replace).with("www.somwebsite.com/notifications", {}, instance_of(Shrinker::Config)).and_return('replace2')
105
+ Shrinker::Parser::Url.should_receive(:replace).with("www.somwebsite.com/go/defdbf1191f17112776a6adb4c201b277af845278971e81b532089d1b96926300347343b15580afba7a7cc41567b9608161d", {}, instance_of(Shrinker::Config)).and_return('replace3')
106
+ Shrinker::Parser::Url.should_receive(:replace).with("www.somwebsite.com/go/5f25b2b15ec6b450c3c5af71102616e07413381a718f1b5d21e7ff9e26d6fc216e9c05ab2b8a40195a16c8603be5860170eb", {}, instance_of(Shrinker::Config)).and_return('replace4')
107
+ Shrinker::Parser::Url.should_receive(:replace).with('www.somwebsite.com/core/assets/email/somwebsite-sky-header.jpg', {}, instance_of(Shrinker::Config)).never
108
+
109
+ replaced_mime = Shrinker::Parser::Mime::replace(multipart_mime, {}, config)
110
+ end
111
+
112
+ end
113
+
114
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shrinker::Parser::Text do
4
+ describe "#replace" do
5
+
6
+ context "without protocol" do
7
+ let(:config) do
8
+ config = Shrinker::Config.new
9
+ config.instance_eval do
10
+ expanded_pattern /(www\.)?google.com/
11
+ shrinked_pattern 'goo.ln'
12
+ around_pattern /href="(?:https?:\/\/)?($url)"/
13
+ end
14
+ config
15
+ end
16
+
17
+ it "replaces proper occurences" do
18
+ content = <<-EV
19
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
20
+ Nunc quis rutrum <a href="http://www.google.com?something=true&else=false">dolor</a>.
21
+ <a href="www.google.com?params=abcdef" style="text-align:center;">http://google.com/safe</a>
22
+ Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
23
+ Curabitur ullamcorper nisl non dolor <a href="http://google.fr?something=true">venenatis</a> consequat.
24
+ Morbi odio libero, tincidunt quis tempus a, fringilla vitae augue.
25
+ <a href="http://google.com/somepath?something=true"></a>
26
+ Aenean placerat ullamcorper lorem vel feugiat.
27
+ EV
28
+
29
+ Shrinker::Parser::Url.should_receive(:replace).with('www.google.com?something=true&else=false', {}, config).and_return("replace1")
30
+ Shrinker::Parser::Url.should_receive(:replace).with('www.google.com?params=abcdef', {}, config).and_return("replace2")
31
+ Shrinker::Parser::Url.should_receive(:replace).with('google.com/safe', {}, config).never
32
+ Shrinker::Parser::Url.should_receive(:replace).with('google.fr?something=true', {}, config).never
33
+ Shrinker::Parser::Url.should_receive(:replace).with('google.com/somepath?something=true', {}, config).and_return("replace3")
34
+
35
+ replaced_text = Shrinker::Parser::Text::replace(content, {}, config)
36
+
37
+ expected_replaced_text = <<-EV
38
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
39
+ Nunc quis rutrum <a href="http://replace1">dolor</a>.
40
+ <a href="replace2" style="text-align:center;">http://google.com/safe</a>
41
+ Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
42
+ Curabitur ullamcorper nisl non dolor <a href="http://google.fr?something=true">venenatis</a> consequat.
43
+ Morbi odio libero, tincidunt quis tempus a, fringilla vitae augue.
44
+ <a href="http://replace3"></a>
45
+ Aenean placerat ullamcorper lorem vel feugiat.
46
+ EV
47
+
48
+ replaced_text.should == expected_replaced_text
49
+ end
50
+
51
+ it "does not do anything when there is no occurence" do
52
+ content = <<-EV
53
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
54
+ Curabitur ullamcorper nisl non dolor http://google.fr?something=true venenatis consequat.
55
+ Aenean placerat ullamcorper lorem vel feugiat.
56
+ EV
57
+
58
+ replaced_text = Shrinker::Parser::Text::replace(content, {}, config)
59
+ replaced_text.should == content
60
+ end
61
+ end
62
+
63
+ context "with protocol" do
64
+ let(:config) do
65
+ config = Shrinker::Config.new
66
+ config.instance_eval do
67
+ expanded_pattern /http:\/\/(www\.)?google.com/
68
+ shrinked_pattern 'https://goo.ln'
69
+ end
70
+ config
71
+ end
72
+
73
+ it "replaces proper occurences" do
74
+ content = <<-EV
75
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
76
+ Nunc quis rutrum http://www.google.com?something=true&else=false dolor.
77
+ Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
78
+ Curabitur ullamcorper nisl non dolor http://google.fr?something=true venenatis consequat.
79
+ Morbi odio libero, tincidunt quis tempus a, fringilla vitae augue.
80
+ https://google.com/somepath?something=true
81
+ Aenean placerat ullamcorper lorem vel feugiat.
82
+ EV
83
+
84
+ Shrinker::Parser::Url.should_receive(:replace).with('http://www.google.com?something=true&else=false', {}, config).and_return("https://replace1")
85
+ Shrinker::Parser::Url.should_receive(:replace).with('google.fr?something=true', {}, config).never
86
+ Shrinker::Parser::Url.should_receive(:replace).with('http://google.com/somepath?something=true', {}, config).never
87
+
88
+ replaced_text = Shrinker::Parser::Text::replace(content, {}, config)
89
+
90
+ expected_replaced_text = <<-EV
91
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
92
+ Nunc quis rutrum https://replace1 dolor.
93
+ Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
94
+ Curabitur ullamcorper nisl non dolor http://google.fr?something=true venenatis consequat.
95
+ Morbi odio libero, tincidunt quis tempus a, fringilla vitae augue.
96
+ https://google.com/somepath?something=true
97
+ Aenean placerat ullamcorper lorem vel feugiat.
98
+ EV
99
+
100
+ replaced_text.should == expected_replaced_text
101
+ end
102
+ end
103
+ end
104
+
105
+ describe "#config" do
106
+ it "returns the default config by default" do
107
+ Shrinker::Parser::Text.new.send(:config).should == Shrinker.config
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shrinker::Parser::Url do
4
+ describe "#replace" do
5
+ before { Shrinker::Token.stub(:fetch_unique_token).and_return("thetoken") }
6
+
7
+ context "without protocol" do
8
+ let(:config) do
9
+ config = Shrinker::Config.new
10
+ config.instance_eval do
11
+ backend 'Redis'
12
+ expanded_pattern /(www\.)?google.com/
13
+ exclude_path /images|assets/
14
+ shrinked_pattern 'goo.ln'
15
+ end
16
+ config
17
+ end
18
+
19
+ it "replace the link" do
20
+ Shrinker::Parser::Url::replace("www.google.com?something=else", {:user_id => 10}, config).should == "goo.ln/thetoken"
21
+ end
22
+
23
+ it "store the old link" do
24
+ Shrinker::Backend::Redis.any_instance.should_receive(:store).with("www.google.com?something=else", 'thetoken', {:user_id => 10})
25
+
26
+ Shrinker::Parser::Url::replace("www.google.com?something=else", {:user_id => 10}, config)
27
+ end
28
+
29
+ describe "does not do anything" do
30
+ before do
31
+ Shrinker::Backend::Redis.any_instance.should_receive(:store).never
32
+ end
33
+
34
+ it "returns the text if it does not match an url" do
35
+ Shrinker::Parser::Url::replace("sometext", {}, config).should == "sometext"
36
+ end
37
+
38
+ it "returns the text if it does not match the domain" do
39
+ Shrinker::Parser::Url::replace("www.google.fr", {}, config).should == "www.google.fr"
40
+ end
41
+
42
+ it "does not replace the link if there is a shrinker=false" do
43
+ Shrinker::Parser::Url::replace("www.google.com?shrinker=false&something=else", {}, config).should == "www.google.com?something=else"
44
+ end
45
+
46
+ it "does not replace the link if its excluded" do
47
+ Shrinker::Parser::Url::replace("www.google.com/assets/logo.png?something=else", {}, config).should == "www.google.com/assets/logo.png?something=else"
48
+ end
49
+ end
50
+ end
51
+
52
+ context "with full url dynamic pattern" do
53
+ let(:config) do
54
+ config = Shrinker::Config.new
55
+ config.instance_eval do
56
+ backend 'Redis'
57
+ expanded_pattern /(www\.)?google.com/
58
+ shrinked_pattern lambda{ |m| "#{m[0]}/x"}
59
+ end
60
+ config
61
+ end
62
+
63
+ it "replace the link" do
64
+ Shrinker::Parser::Url::replace("www.google.com?something=else", {:user_id => 10}, config).should == "www.google.com/x/thetoken"
65
+ end
66
+
67
+ it "store the old link" do
68
+ Shrinker::Backend::Redis.any_instance.should_receive(:store).with("www.google.com?something=else", 'thetoken', {:user_id => 10})
69
+
70
+ Shrinker::Parser::Url::replace("www.google.com?something=else", {:user_id => 10}, config)
71
+ end
72
+ end
73
+
74
+ context "with partial url dynamic pattern" do
75
+ let(:config) do
76
+ config = Shrinker::Config.new
77
+ config.instance_eval do
78
+ backend 'Redis'
79
+ expanded_pattern /(.+)\.google\.com/
80
+ shrinked_pattern lambda{ |m| "#{m[1]}.other.com"}
81
+ end
82
+ config
83
+ end
84
+
85
+ it "replace the link" do
86
+ Shrinker::Parser::Url::replace("xyz.google.com?something=else", {:user_id => 10}, config).should == "xyz.other.com/thetoken"
87
+ end
88
+
89
+ it "store the old link" do
90
+ Shrinker::Backend::Redis.any_instance.should_receive(:store).with("www.google.com?something=else", 'thetoken', {:user_id => 10})
91
+
92
+ Shrinker::Parser::Url::replace("www.google.com?something=else", {:user_id => 10}, config)
93
+ end
94
+ end
95
+
96
+ context "with protocol" do
97
+ let(:config) do
98
+ config = Shrinker::Config.new
99
+ config.instance_eval do
100
+ backend 'Redis'
101
+ expanded_pattern /http:\/\/(www\.)?google.com/
102
+ shrinked_pattern 'https://goo.ln'
103
+ end
104
+ config
105
+ end
106
+
107
+ it "replace the link" do
108
+ Shrinker::Parser::Url::replace("http://www.google.com?something=else", {:user_id => 10}, config).should == "https://goo.ln/thetoken"
109
+ end
110
+
111
+ it "store the old link" do
112
+ Shrinker::Backend::Redis.any_instance.should_receive(:store).with("http://www.google.com?something=else", 'thetoken', {:user_id => 10})
113
+
114
+ Shrinker::Parser::Url::replace("http://www.google.com?something=else", {:user_id => 10}, config)
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shrinker::Serializer do
4
+ describe "#hash" do
5
+ it "returns a hash containing the url" do
6
+ Shrinker::Serializer::to_hash('someurl').should == {:url => 'someurl', :attributes => {}}
7
+ end
8
+
9
+ it "returns a hash containing the attributes" do
10
+ Shrinker::Serializer::to_hash('someurl', {:user_id => 12}).should == {:url => 'someurl', :attributes => {:user_id => 12}}
11
+ end
12
+ end
13
+
14
+ describe "#json" do
15
+ it "returns a json containing the url" do
16
+ Shrinker::Serializer::to_json('someurl').should == {:url => 'someurl', :attributes => {}}.to_json
17
+ end
18
+
19
+ it "returns a json containing the attributes" do
20
+ Shrinker::Serializer::to_json('someurl', {:user_id => 12}).should == {:url => 'someurl', :attributes => {:user_id => 12}}.to_json
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shrinker do
4
+ describe ".unshrink" do
5
+ it "delegates the method to the Extractor" do
6
+ Shrinker::Extractor.should_receive(:unshrink).with('token', Shrinker.config)
7
+
8
+ Shrinker.unshrink('token')
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shrinker::Token do
4
+ describe "#generate" do
5
+ it "allows passing a prefix" do
6
+ Shrinker::Token.stub(:rand).and_return('random')
7
+ Digest::MD5.should_receive(:hexdigest).with("something__random").and_return("abcdefghijklmnopqrstuvwxyz")
8
+
9
+ Shrinker::Token.generate(prefix: 'something').should == "opqrstuvwxyz"
10
+ end
11
+ end
12
+
13
+ describe "#fetch_uniq_token" do
14
+ let(:backend) { stub }
15
+
16
+ it "returns an unique token" do
17
+ backend.stub(:used_token?).and_return(true, false)
18
+
19
+ Shrinker::Token.should_receive(:generate).twice.and_return('abcdef')
20
+
21
+ Shrinker::Token.fetch_unique_token(backend).should == 'abcdef'
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ require 'shrinker'
2
+
3
+ FIXTURES_PATH = File.expand_path('../support/fixtures', __FILE__)
@@ -0,0 +1,41 @@
1
+ Date: Tue, 27 Nov 2012 21:23:03 +0000
2
+ From: Someone <someone@example.com>
3
+ To: someone@example.com
4
+ Message-ID: <50b52f37d9dfb_805540b019a86752@example.mail>
5
+ Subject: The subject
6
+ Mime-Version: 1.0
7
+ Content-Type: text/html;
8
+ charset=UTF-8
9
+ Content-Transfer-Encoding: quoted-printable
10
+
11
+ <!DOCTYPE html>
12
+ <html>
13
+ =C2=A0=C2=A0<head>
14
+ \ <meta content=3D"text/html; charset=3DUTF-8" http-equiv=3D"Content-Ty=
15
+ pe" />
16
+ =C2=A0=C2=A0</head>
17
+ =C2=A0=C2=A0<body>
18
+
19
+ <div style=3D"font-family: 'Helvetica Neue', Arial, Helvetica, sans-ser=
20
+ if; color: #462815; margin: 10px auto; position: relative; width: 600px; =
21
+ background-color: white;">
22
+ <img alt=3D"Quisque tincidunt mattis risus" border=
23
+ "0" src=3D"https://www.my-example.com/class-aptent-taciti-sociosqu-ad-lit=
24
+ ader.jpg" />
25
+ <a href=3D"my-example.com/a?something=3Dtrue">my-example.com/none</a>
26
+ <br/>
27
+
28
+ <br/>
29
+ <a href=3D"https://www.my-example.com/donec-lobortis-lacus-vel-urna-variu=
30
+ o--4?clicked=3Dabcdef">https://www.my-example.com/safe</a>
31
+
32
+ <br/><br/>
33
+ Khufu hidden vcjjxnb. Cnvxjcmcjahrajcb zings
34
+ non magna imperdiet aliquam.<br/><br/>
35
+ <br/>
36
+ <br/>
37
+
38
+ </div>
39
+
40
+ =C2=A0=C2=A0</body>
41
+ </html>=