tmin_test 0.0.1
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/.DS_Store +0 -0
- data/.document +5 -0
- data/.gitignore +49 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +69 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +53 -0
- data/config.ru.example +20 -0
- data/firefly.sqlite3 +0 -0
- data/lib/tmin/base62.rb +27 -0
- data/lib/tmin/code_factory.rb +24 -0
- data/lib/tmin/config.rb +28 -0
- data/lib/tmin/server.rb +369 -0
- data/lib/tmin/url.rb +56 -0
- data/lib/tmin/version.rb +4 -0
- data/lib/tmin.rb +41 -0
- data/public/.DS_Store +0 -0
- data/public/favicon.ico +0 -0
- data/public/images/ec_background.gif +0 -0
- data/public/images/twitter.png +0 -0
- data/public/jquery-1.4.2.min.js +154 -0
- data/public/reset.css +48 -0
- data/public/style.css +94 -0
- data/spec/firefly/api_spec.rb +166 -0
- data/spec/firefly/base62_spec.rb +21 -0
- data/spec/firefly/code_factory_spec.rb +12 -0
- data/spec/firefly/server_spec.rb +74 -0
- data/spec/firefly/sharing_facebook_spec.rb +65 -0
- data/spec/firefly/sharing_hyves_spec.rb +107 -0
- data/spec/firefly/sharing_twitter_spec.rb +104 -0
- data/spec/firefly/url_spec.rb +121 -0
- data/spec/fixtures/urls.yml +11 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +55 -0
- data/test/helper.rb +18 -0
- data/test/test_tmin.rb +7 -0
- data/tmin_test.gemspec +35 -0
- data/views/admin.haml +92 -0
- data/views/ec.haml +35 -0
- data/views/error.haml +11 -0
- data/views/index.haml +1 -0
- data/views/info.haml +26 -0
- data/views/layout.haml +28 -0
- data/views/redirect.haml +51 -0
- metadata +242 -0
@@ -0,0 +1,166 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe "API" do
|
4
|
+
include Rack::Test::Methods
|
5
|
+
|
6
|
+
def app
|
7
|
+
@@app
|
8
|
+
end
|
9
|
+
|
10
|
+
[:post, :get].each do |verb|
|
11
|
+
describe "adding a URL by #{verb.to_s.upcase}" do
|
12
|
+
it "should be okay adding a new URL" do
|
13
|
+
self.send verb, '/api/add', :url => 'http://example.org/', :api_key => 'test'
|
14
|
+
last_response.should be_ok
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return the shortened URL" do
|
18
|
+
self.send verb, '/api/add', :url => 'http://example.org/', :api_key => 'test'
|
19
|
+
url = Firefly::Url.first(:url => "http://example.org/")
|
20
|
+
|
21
|
+
last_response.body.should eql("http://test.host/#{url.code}")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should generate a short code if `short` is blank" do
|
25
|
+
self.send verb, '/api/add', :url => "http://example.org", :short => "", :api_key => 'test'
|
26
|
+
url = Firefly::Url.first(:url => "http://example.org/")
|
27
|
+
|
28
|
+
last_response.should be_ok
|
29
|
+
last_response.body.should eql("http://test.host/#{url.code}")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should permit including a requested short code" do
|
33
|
+
self.send verb, '/api/add', :url => "http://example.org", :short => 'orz', :api_key => 'test'
|
34
|
+
|
35
|
+
last_response.should be_ok
|
36
|
+
last_response.body.should eql("http://test.host/orz")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should not allow the same short code twice" do
|
40
|
+
self.send verb, '/api/add', :url => "http://example.org", :short => 'orz', :api_key => 'test'
|
41
|
+
last_response.should be_ok
|
42
|
+
self.send verb, '/api/add', :url => "http://example.com", :short => 'orz', :api_key => 'test'
|
43
|
+
last_response.should_not be_ok
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should not allow short codes of size < 3" do
|
47
|
+
self.send verb, '/api/add', :url => "http://example.org", :short => 'or', :api_key => 'test'
|
48
|
+
last_response.should_not be_ok
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should not allow short codes of size > 64" do
|
52
|
+
self.send verb, '/api/add', :url => "http://example.org", :short => 'x' * 65, :api_key => 'test'
|
53
|
+
last_response.should_not be_ok
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should show an error when shortening an invalid URL" do
|
57
|
+
self.send verb, '/api/add', :url => 'ftp://example.org', :api_key => 'test'
|
58
|
+
last_response.body.should match("The URL you posted is invalid")
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should show an error when shortening an invalid URL in visual mode" do
|
62
|
+
self.send verb, '/api/add', :url => 'ftp://example.org', :api_key => 'test', :visual => "1"
|
63
|
+
last_response.body.should match("The URL you posted is invalid")
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should redirect to the highlighted URL when visual is enabled" do
|
67
|
+
self.send verb, '/api/add', :url => 'http://example.org/', :api_key => 'test', :visual => "1"
|
68
|
+
follow_redirect!
|
69
|
+
|
70
|
+
last_request.path.should eql("/")
|
71
|
+
last_request.should be_get
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should store the API key in the session with visual enabled" do
|
75
|
+
self.send verb, '/api/add', :url => 'http://example.org/', :api_key => 'test', :visual => "1"
|
76
|
+
follow_redirect!
|
77
|
+
|
78
|
+
last_response.body.should_not match(/API Key/)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should highlight the shortened URL" do
|
82
|
+
self.send verb, '/api/add', :url => 'http://example.org/', :api_key => 'test', :visual => "1"
|
83
|
+
url = Firefly::Url.first(:url => "http://example.org/")
|
84
|
+
follow_redirect!
|
85
|
+
|
86
|
+
last_request.query_string.should match(/highlight=#{url.code}/)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should return a 401 on a wrong API key" do
|
90
|
+
self.send verb, '/api/add', :url => 'http://example.org', :api_key => 'false'
|
91
|
+
last_response.status.should eql(401)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should not return a shortened URL on 401" do
|
95
|
+
self.send verb, '/api/add', :url => 'http://example.org', :api_key => 'false'
|
96
|
+
last_response.body.should match(/Permission denied: Invalid API key/)
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should create a new Firefly::Url" do
|
100
|
+
lambda {
|
101
|
+
self.send verb, '/api/add', :url => 'http://example.org/', :api_key => 'test'
|
102
|
+
}.should change(Firefly::Url, :count).by(1)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should not create the same Firefly::Url twice" do
|
106
|
+
self.send verb, '/api/add', :url => 'http://example.org', :api_key => 'test'
|
107
|
+
|
108
|
+
lambda {
|
109
|
+
self.send verb, '/api/add', :url => 'http://example.org', :api_key => 'test'
|
110
|
+
}.should_not change(Firefly::Url, :count).by(1)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "getting information" do
|
116
|
+
before(:each) do
|
117
|
+
@created_at = Time.now
|
118
|
+
@url = Firefly::Url.create(:url => 'http://example.com/123', :code => 'alpha', :clicks => 69, :created_at => @created_at)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should work" do
|
122
|
+
get '/api/info/alpha', :api_key => "test"
|
123
|
+
last_response.should be_ok
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should show the click count" do
|
127
|
+
get '/api/info/alpha', :api_key => "test"
|
128
|
+
last_response.body.should match(/69/)
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should show the short URL" do
|
132
|
+
get '/api/info/alpha', :api_key => "test"
|
133
|
+
last_response.body.should match(/alpha/)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should show the shortened at time" do
|
137
|
+
get '/api/info/alpha', :api_key => "test"
|
138
|
+
last_response.body.should match(/#{@created_at.strftime("%Y-%m-%d %H:%M")}/)
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should show the full URL" do
|
142
|
+
get '/api/info/alpha', :api_key => "test"
|
143
|
+
last_response.body.should match(/http:\/\/example.com\/123/)
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should validate API permissions" do
|
147
|
+
get '/api/info/alpha', :api_key => false
|
148
|
+
last_response.status.should be(401)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
describe "api key" do
|
153
|
+
def app
|
154
|
+
Firefly::Server.new do
|
155
|
+
set :hostname, "test.host"
|
156
|
+
set :api_key, "test#!"
|
157
|
+
set :database, "sqlite3://firefly_test_alt.sqlite3"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
it "should be okay adding a new URL" do
|
162
|
+
self.send :get, '/api/add', :url => 'http://example.org/api_key_test', :api_key => 'test#!'
|
163
|
+
last_response.should be_ok
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -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,12 @@
|
|
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 code_count" do
|
7
|
+
current_count = Firefly::CodeFactory.first.count
|
8
|
+
expected_code = Firefly::Base62.encode(current_count + 1)
|
9
|
+
Firefly::CodeFactory.next_code!.should eql(expected_code)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
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
|
+
@@app
|
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
|
+
@@app
|
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
|
+
@@app
|
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
|
+
@@app
|
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,121 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe "Url" do
|
4
|
+
|
5
|
+
describe "shortening" do
|
6
|
+
it "should generate a code after create" do
|
7
|
+
url = Firefly::Url.shorten("http://example.com/")
|
8
|
+
Firefly::Url.first(:url => "http://example.com/").code.should_not be_nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should set a clicks count of 0 for newly shortened urls" do
|
12
|
+
url = Firefly::Url.shorten("http://example.com/")
|
13
|
+
Firefly::Url.first(:url => "http://example.com/").clicks.should eql(0)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should create a new Firefly::Url with a new long_url" do
|
17
|
+
lambda {
|
18
|
+
Firefly::Url.shorten("http://example.com/")
|
19
|
+
}.should change(Firefly::Url, :count).by(1)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should return an existing Firefly::Url if the long_url exists" do
|
23
|
+
Firefly::Url.shorten("http://example.com/")
|
24
|
+
lambda {
|
25
|
+
Firefly::Url.shorten("http://example.com/")
|
26
|
+
}.should_not change(Firefly::Url, :count)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should normalize urls correctly" do
|
30
|
+
# Note the trailing '/'
|
31
|
+
Firefly::Url.shorten("http://example.com/")
|
32
|
+
lambda {
|
33
|
+
Firefly::Url.shorten("http://example.com")
|
34
|
+
}.should_not change(Firefly::Url, :count)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should shortend urls containing spaces" do
|
38
|
+
lambda {
|
39
|
+
url = Firefly::Url.shorten("http://example.com/article with spaces.html")
|
40
|
+
}.should change(Firefly::Url, :count).by(1)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should escape urls with spaces" do
|
44
|
+
url = Firefly::Url.shorten("http://example.com/article with spaces.html")
|
45
|
+
url.url.should eql("http://example.com/article%20with%20spaces.html")
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should shortend urls containing weird characters" do
|
49
|
+
lambda {
|
50
|
+
url = Firefly::Url.shorten("http://example.com/?a=\11\15")
|
51
|
+
}.should change(Firefly::Url, :count).by(1)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should escape urls with weird characters" do
|
55
|
+
url = Firefly::Url.shorten("http://example.com/?a=\11\15")
|
56
|
+
url.url.should eql("http://example.com/?a=%09%0D")
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should not unescape invalid URL characters" do
|
60
|
+
url = Firefly::Url.shorten("http://example.com/?a=%09")
|
61
|
+
url.url.should eql("http://example.com/?a=%09")
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should not escape already escaped URLs" do
|
65
|
+
url = Firefly::Url.shorten("http://en.wikipedia.org/wiki/Tarski%27s_circle-squaring_problem")
|
66
|
+
url.url.should eql("http://en.wikipedia.org/wiki/Tarski's_circle-squaring_problem")
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should automatically forward code to prevent duplicates" do
|
70
|
+
url = Firefly::Url.shorten("http://example.com/")
|
71
|
+
the_code = url.code.next
|
72
|
+
Firefly::Url.create(:url => "http://example.com/blah", :code => the_code)
|
73
|
+
|
74
|
+
url_correct = Firefly::Url.shorten("http://example.com/testit")
|
75
|
+
url_correct.code.should_not eql(the_code)
|
76
|
+
url_correct.code.should eql(the_code.next)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "long url validation" do
|
81
|
+
[ "http://ariejan.net",
|
82
|
+
"https://ariejan.net",
|
83
|
+
"http://ariejan.net/page/1",
|
84
|
+
"http://ariejan.net/page/1?q=x&p=123",
|
85
|
+
"http://ariejan.net:8080/"
|
86
|
+
].each do |url|
|
87
|
+
it "should accept #{url}" do
|
88
|
+
Firefly::Url.shorten(url).should_not be_nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
[ "ftp://ariejan.net",
|
93
|
+
"irc://freenode.org/rails",
|
94
|
+
"skype:adevroom",
|
95
|
+
"ariejan.net",
|
96
|
+
].each do |url|
|
97
|
+
it "should not accept #{url}" do
|
98
|
+
lambda {
|
99
|
+
Firefly::Url.shorten(url).should be_nil
|
100
|
+
}.should raise_error(Firefly::InvalidUrlError)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "clicking" do
|
106
|
+
before(:each) do
|
107
|
+
Firefly::Url.create(
|
108
|
+
:url => 'http://example.com/123',
|
109
|
+
:code => 'alpha',
|
110
|
+
:clicks => 69
|
111
|
+
)
|
112
|
+
@url = Firefly::Url.first(:code => 'alpha')
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should increase the click count" do
|
116
|
+
lambda {
|
117
|
+
@url.register_click!
|
118
|
+
}.should change(@url, :clicks).by(1)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|