tg-firefly 0.9.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,21 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Base62 encoding/decoding" do
4
+ [
5
+ [ 1, "1"],
6
+ [ 10, "a"],
7
+ [ 61, "Z"],
8
+ [ 62, "10"],
9
+ [ 63, "11"],
10
+ [ 124, "20"],
11
+ [200000000, "dxb8s"]
12
+ ].each do |input, output|
13
+ it "should encode #{input} correctly to #{output}" do
14
+ Firefly::Base62.encode(input).should eql(output)
15
+ end
16
+
17
+ it "should decode correctly" do
18
+ Firefly::Base62.decode(output).should eql(input)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "CodeFactory" do
4
+
5
+ describe "next!" do
6
+ it "should return the next sequential code_count" do
7
+ Firefly::CodeFactory.order = :sequential
8
+ current_count = Firefly::CodeFactory.first.count
9
+ expected_code = Firefly::Base62.encode(current_count + 1)
10
+ Firefly::CodeFactory.next_code!.should eql(expected_code)
11
+ end
12
+
13
+ it "should return the next random code_count" do
14
+ Firefly::CodeFactory.order = :random
15
+ current_count = Firefly::CodeFactory.first.count
16
+ expected_code = Firefly::Base62.encode(current_count + 1)
17
+ Firefly::CodeFactory.next_code!.should_not eql(expected_code)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,74 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Firefly" do
4
+ include Rack::Test::Methods
5
+
6
+ def app
7
+ self.class.class_variable_get(:@@app) # ruby 1.9.3 warning
8
+ end
9
+
10
+ describe "/" do
11
+ it "should respond ok" do
12
+ get '/'
13
+ last_response.should be_ok
14
+ end
15
+ end
16
+
17
+
18
+ if defined? Barby
19
+ describe "QR Codes" do
20
+ before(:each) do
21
+ @url = Firefly::Url.create(:url => 'http://example.com/123', :code => 'alpha')
22
+ end
23
+
24
+ it "should return a 200 status" do
25
+ get '/alpha.png'
26
+ last_response.should be_ok
27
+ end
28
+
29
+ it "should return a PNG image" do
30
+ get '/alpha.png'
31
+ last_response.headers['Content-Type'].should eql('image/png')
32
+ end
33
+
34
+ it "should cache-control to 1 month" do
35
+ get '/alpha.png'
36
+ last_response.headers['Cache-Control'].should eql('public, max-age=2592000')
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "redirecting" do
42
+ it "should redirect to the original URL" do
43
+ fake = Firefly::Url.create(:url => 'http://example.com/123', :code => 'alpha')
44
+
45
+ get '/alpha'
46
+ follow_redirect!
47
+
48
+ last_request.url.should eql('http://example.com/123')
49
+ end
50
+
51
+ it "should increase the visits counter" do
52
+ fake = Firefly::Url.create(:url => 'http://example.com/123', :code => 'alpha')
53
+ Firefly::Url.should_receive(:first).and_return(fake)
54
+
55
+ lambda {
56
+ get '/alpha'
57
+ }.should change(fake, :clicks).by(1)
58
+ end
59
+
60
+ it "should redirect with a 301 Permanent redirect" do
61
+ fake = Firefly::Url.create(:url => 'http://example.com/123', :code => 'alpha')
62
+
63
+ get '/alpha'
64
+
65
+ last_response.status.should eql(301)
66
+ end
67
+
68
+ it "should throw a 404 when the code is unknown" do
69
+ get '/some_random_code_that_does_not_exist'
70
+
71
+ last_response.status.should eql(404)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,65 @@
1
+ # encoding: UTF-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
3
+
4
+ describe "Sharing" do
5
+ include Rack::Test::Methods
6
+
7
+ def app
8
+ self.class.class_variable_get(:@@app) # ruby 1.9.3 warning
9
+ end
10
+
11
+ before(:each) do
12
+ @params = {
13
+ :url => 'http://example.com/test',
14
+ :key => 'asdfasdf',
15
+ :target => 'facebook'
16
+ }
17
+ end
18
+
19
+ [:post, :get].each do |verb|
20
+ describe "facebook via #{verb.to_s.upcase}" do
21
+ it "should create a shortened URL" do
22
+ lambda {
23
+ self.send verb, '/api/share', @params
24
+ }.should change(Firefly::Url, :count).by(1)
25
+ end
26
+
27
+ it "should redirect to facebook with status" do
28
+ self.send verb, '/api/share', @params
29
+ last_response.should be_redirect
30
+ last_response['Location'].should match(/facebook.com/i)
31
+ end
32
+
33
+ it "should post the short url to facebook" do
34
+ self.send verb, '/api/share', @params
35
+ url = Firefly::Url.first(:url => @params[:url])
36
+
37
+ last_response['Location'].should include(URI.escape("http://test.host/#{url.code}"))
38
+ end
39
+
40
+ it "should not allow sharing of example.org URL" do
41
+ self.send verb, '/api/share', @params.merge(:url => 'http://example.org/test123')
42
+ last_response.status.should eql(401)
43
+ last_response.body.should match(/cannot share that URL/i)
44
+ end
45
+
46
+ it "should not create a short URL for example.org URL" do
47
+ lambda {
48
+ self.send verb, '/api/share', @params.merge(:url => 'http://example.org/test123')
49
+ }.should_not change(Firefly::Url, :count)
50
+ end
51
+
52
+ it "should not share to unknown target" do
53
+ self.send verb, '/api/share', @params.merge(:target => 'twitterbook')
54
+ last_response.status.should eql(401)
55
+ last_response.body.should match(/cannot share that URL/i)
56
+ end
57
+
58
+ it "should not create a short URL for unknown target" do
59
+ lambda {
60
+ self.send verb, '/api/share', @params.merge(:target => 'twitterbook')
61
+ }.should_not change(Firefly::Url, :count)
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,107 @@
1
+ # encoding: UTF-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
3
+
4
+ describe "Sharing" do
5
+ include Rack::Test::Methods
6
+
7
+ def app
8
+ self.class.class_variable_get(:@@app) # ruby 1.9.3 warning
9
+ end
10
+
11
+ before(:each) do
12
+ @params = {
13
+ :url => 'http://example.com/test',
14
+ :key => 'asdfasdf',
15
+ :target => 'hyves',
16
+ :title => 'Test post'
17
+ }
18
+ end
19
+
20
+ [:post, :get].each do |verb|
21
+ describe "hyves via #{verb.to_s.upcase}" do
22
+ it "should create a shortened URL" do
23
+ lambda {
24
+ self.send verb, '/api/share', @params
25
+ }.should change(Firefly::Url, :count).by(1)
26
+ end
27
+
28
+ it "should redirect to hyves with status" do
29
+ self.send verb, '/api/share', @params
30
+ last_response.should be_redirect
31
+ last_response['Location'].should match(/hyves.nl/i)
32
+ end
33
+
34
+ it "should post the title to hyves" do
35
+ self.send verb, '/api/share', @params
36
+ url = Firefly::Url.first(:url => @params[:url])
37
+ last_response['Location'].should include(URI.escape("#{@params[:title]}"))
38
+ end
39
+
40
+ it "should post the title and short url to hyves" do
41
+ self.send verb, '/api/share', @params
42
+ url = Firefly::Url.first(:url => @params[:url])
43
+ last_response['Location'].should include(URI.escape("http://test.host/#{url.code}"))
44
+ end
45
+
46
+ it "should not allow sharing of example.org URL" do
47
+ self.send verb, '/api/share', @params.merge(:url => 'http://example.org/test123')
48
+ last_response.status.should eql(401)
49
+ last_response.body.should match(/cannot share that URL/i)
50
+ end
51
+
52
+ it "should not create a short URL for example.org URL" do
53
+ lambda {
54
+ self.send verb, '/api/share', @params.merge(:url => 'http://example.org/test123')
55
+ }.should_not change(Firefly::Url, :count)
56
+ end
57
+
58
+ it "should not share to unknown target" do
59
+ self.send verb, '/api/share', @params.merge(:target => 'twitterbook')
60
+ last_response.status.should eql(401)
61
+ last_response.body.should match(/cannot share that URL/i)
62
+ end
63
+
64
+ it "should not create a short URL for unknown target" do
65
+ lambda {
66
+ self.send verb, '/api/share', @params.merge(:target => 'twitterbook')
67
+ }.should_not change(Firefly::Url, :count)
68
+ end
69
+
70
+ it "should strip the title to remove any unnecessary white space" do
71
+ title = " Test post "
72
+ self.send verb, '/api/share', @params.merge(:title => title)
73
+ url = Firefly::Url.first(:url => @params[:url])
74
+
75
+ last_response['Location'].should include(URI.escape("Test post"))
76
+ last_response['Location'].should_not include(URI.escape(title))
77
+ end
78
+
79
+ it "should strip the body to remove any unnecessary white space" do
80
+ title = " This is the test body "
81
+ self.send verb, '/api/share', @params.merge(:title => title)
82
+ url = Firefly::Url.first(:url => @params[:url])
83
+
84
+ last_response['Location'].should include(URI.escape("http://test.host/#{url.code}"))
85
+ last_response['Location'].should_not include(URI.escape(title))
86
+ end
87
+
88
+ it "should strip the title from url encoded entities correctly" do
89
+ title = "Test%20post"
90
+ self.send verb, '/api/share', @params.merge(:title => title)
91
+ url = Firefly::Url.first(:url => @params[:url])
92
+
93
+ last_response['Location'].should include(URI.escape("Test post"))
94
+ last_response['Location'].should_not include(URI.escape(title))
95
+ end
96
+
97
+ it "should escape UTF-8 correctly" do
98
+ title = "Chávez"
99
+ self.send verb, '/api/share', @params.merge(:title => title)
100
+ url = Firefly::Url.first(:url => @params[:url])
101
+
102
+ last_response['Location'].should include("Ch%C3%A1vez")
103
+ last_response['Location'].should_not include("Ch%E1vez")
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,104 @@
1
+ # encoding: UTF-8
2
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
3
+
4
+ describe "Sharing" do
5
+ include Rack::Test::Methods
6
+
7
+ def app
8
+ self.class.class_variable_get(:@@app) # ruby 1.9.3 warning
9
+ end
10
+
11
+ before(:each) do
12
+ @params = {
13
+ :url => 'http://example.com/test',
14
+ :key => 'asdfasdf',
15
+ :target => 'twitter',
16
+ :title => 'Test post'
17
+ }
18
+ end
19
+
20
+ [:post, :get].each do |verb|
21
+ describe "twitter via #{verb.to_s.upcase}" do
22
+ it "should create a shortened URL" do
23
+ lambda {
24
+ self.send verb, '/api/share', @params
25
+ }.should change(Firefly::Url, :count).by(1)
26
+ end
27
+
28
+ it "should redirect to twitter with status" do
29
+ self.send verb, '/api/share', @params
30
+ last_response.should be_redirect
31
+ last_response['Location'].should match(/twitter.com/i)
32
+ end
33
+
34
+ it "should post the title and short url to twitter" do
35
+ self.send verb, '/api/share', @params
36
+ url = Firefly::Url.first(:url => @params[:url])
37
+
38
+ last_response['Location'].should include(URI.escape("#{@params[:title]} http://test.host/#{url.code}"))
39
+ end
40
+
41
+ it "should not allow sharing of example.org URL" do
42
+ self.send verb, '/api/share', @params.merge(:url => 'http://example.org/test123')
43
+ last_response.status.should eql(401)
44
+ last_response.body.should match(/cannot share that URL/i)
45
+ end
46
+
47
+ it "should not create a short URL for example.org URL" do
48
+ lambda {
49
+ self.send verb, '/api/share', @params.merge(:url => 'http://example.org/test123')
50
+ }.should_not change(Firefly::Url, :count)
51
+ end
52
+
53
+ it "should not share to unknown target" do
54
+ self.send verb, '/api/share', @params.merge(:target => 'twitterbook')
55
+ last_response.status.should eql(401)
56
+ last_response.body.should match(/cannot share that URL/i)
57
+ end
58
+
59
+ it "should not create a short URL for unknown target" do
60
+ lambda {
61
+ self.send verb, '/api/share', @params.merge(:target => 'twitterbook')
62
+ }.should_not change(Firefly::Url, :count)
63
+ end
64
+
65
+ it "should shorten long titles to fit within the 140 character limit" do
66
+ title = "This is a very long title that will never fit in the current one hundred and forty character limit enforce by twitter. Or does it?"
67
+ self.send verb, '/api/share', @params.merge(:title => title)
68
+ url = Firefly::Url.first(:url => @params[:url])
69
+
70
+ short_url = "http://test.host/#{url.code}"
71
+ expected = title.slice(0...(140-1-short_url.length)) + ' ' + short_url
72
+
73
+ last_response['Location'].should include(URI.escape(expected))
74
+ end
75
+
76
+ it "should strip the title to remove any unnecessary white space" do
77
+ title = " Test post "
78
+ self.send verb, '/api/share', @params.merge(:title => title)
79
+ url = Firefly::Url.first(:url => @params[:url])
80
+
81
+ last_response['Location'].should include(URI.escape("Test post http://test.host/#{url.code}"))
82
+ last_response['Location'].should_not include(URI.escape(title))
83
+ end
84
+
85
+ it "should strip the title from url encoded entities correctly" do
86
+ title = "Test%20post"
87
+ self.send verb, '/api/share', @params.merge(:title => title)
88
+ url = Firefly::Url.first(:url => @params[:url])
89
+
90
+ last_response['Location'].should include(URI.escape("Test post http://test.host/#{url.code}"))
91
+ last_response['Location'].should_not include(URI.escape(title))
92
+ end
93
+
94
+ it "should escape UTF-8 correctly" do
95
+ title = "Chávez"
96
+ self.send verb, '/api/share', @params.merge(:title => title)
97
+ url = Firefly::Url.first(:url => @params[:url])
98
+
99
+ last_response['Location'].should include("Ch%C3%A1vez")
100
+ last_response['Location'].should_not include("Ch%E1vez")
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,124 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe "Url" do
4
+ before do
5
+ Firefly::CodeFactory.order = :sequential
6
+ end
7
+
8
+ describe "shortening" do
9
+ it "should generate a code after create" do
10
+ url = Firefly::Url.shorten("http://example.com/")
11
+ Firefly::Url.first(:url => "http://example.com/").code.should_not be_nil
12
+ end
13
+
14
+ it "should set a clicks count of 0 for newly shortened urls" do
15
+ url = Firefly::Url.shorten("http://example.com/")
16
+ Firefly::Url.first(:url => "http://example.com/").clicks.should eql(0)
17
+ end
18
+
19
+ it "should create a new Firefly::Url with a new long_url" do
20
+ lambda {
21
+ Firefly::Url.shorten("http://example.com/")
22
+ }.should change(Firefly::Url, :count).by(1)
23
+ end
24
+
25
+ it "should return an existing Firefly::Url if the long_url exists" do
26
+ Firefly::Url.shorten("http://example.com/")
27
+ lambda {
28
+ Firefly::Url.shorten("http://example.com/")
29
+ }.should_not change(Firefly::Url, :count)
30
+ end
31
+
32
+ it "should normalize urls correctly" do
33
+ # Note the trailing '/'
34
+ Firefly::Url.shorten("http://example.com/")
35
+ lambda {
36
+ Firefly::Url.shorten("http://example.com")
37
+ }.should_not change(Firefly::Url, :count)
38
+ end
39
+
40
+ it "should shortend urls containing spaces" do
41
+ lambda {
42
+ url = Firefly::Url.shorten("http://example.com/article with spaces.html")
43
+ }.should change(Firefly::Url, :count).by(1)
44
+ end
45
+
46
+ it "should escape urls with spaces" do
47
+ url = Firefly::Url.shorten("http://example.com/article with spaces.html")
48
+ url.url.should eql("http://example.com/article%20with%20spaces.html")
49
+ end
50
+
51
+ it "should shortend urls containing weird characters" do
52
+ lambda {
53
+ url = Firefly::Url.shorten("http://example.com/?a=\11\15")
54
+ }.should change(Firefly::Url, :count).by(1)
55
+ end
56
+
57
+ it "should escape urls with weird characters" do
58
+ url = Firefly::Url.shorten("http://example.com/?a=\11\15")
59
+ url.url.should eql("http://example.com/?a=%09%0D")
60
+ end
61
+
62
+ it "should not unescape invalid URL characters" do
63
+ url = Firefly::Url.shorten("http://example.com/?a=%09")
64
+ url.url.should eql("http://example.com/?a=%09")
65
+ end
66
+
67
+ it "should not escape already escaped URLs" do
68
+ url = Firefly::Url.shorten("http://en.wikipedia.org/wiki/Tarski%27s_circle-squaring_problem")
69
+ url.url.should eql("http://en.wikipedia.org/wiki/Tarski's_circle-squaring_problem")
70
+ end
71
+
72
+ it "should automatically forward code to prevent duplicates" do
73
+ url = Firefly::Url.shorten("http://example.com/")
74
+ the_code = url.code.next
75
+ Firefly::Url.create(:url => "http://example.com/blah", :code => the_code)
76
+
77
+ url_correct = Firefly::Url.shorten("http://example.com/testit")
78
+ url_correct.code.should_not eql(the_code)
79
+ url_correct.code.should eql(the_code.next)
80
+ end
81
+ end
82
+
83
+ describe "long url validation" do
84
+ [ "http://ariejan.net",
85
+ "https://ariejan.net",
86
+ "http://ariejan.net/page/1",
87
+ "http://ariejan.net/page/1?q=x&p=123",
88
+ "http://ariejan.net:8080/"
89
+ ].each do |url|
90
+ it "should accept #{url}" do
91
+ Firefly::Url.shorten(url).should_not be_nil
92
+ end
93
+ end
94
+
95
+ [ "ftp://ariejan.net",
96
+ "irc://freenode.org/rails",
97
+ "skype:adevroom",
98
+ "ariejan.net",
99
+ ].each do |url|
100
+ it "should not accept #{url}" do
101
+ lambda {
102
+ Firefly::Url.shorten(url).should be_nil
103
+ }.should raise_error(Firefly::InvalidUrlError)
104
+ end
105
+ end
106
+ end
107
+
108
+ describe "clicking" do
109
+ before(:each) do
110
+ Firefly::Url.create(
111
+ :url => 'http://example.com/123',
112
+ :code => 'alpha',
113
+ :clicks => 69
114
+ )
115
+ @url = Firefly::Url.first(:code => 'alpha')
116
+ end
117
+
118
+ it "should increase the click count" do
119
+ lambda {
120
+ @url.register_click!
121
+ }.should change(@url, :clicks).by(1)
122
+ end
123
+ end
124
+ end