tweetwine 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/CHANGELOG.rdoc +5 -0
- data/{release-script.txt → RELEASING.txt} +0 -0
- data/Rakefile +19 -19
- data/lib/tweetwine/http.rb +1 -3
- data/lib/tweetwine/ui.rb +2 -1
- data/lib/tweetwine/version.rb +1 -1
- data/project.rb +30 -0
- data/test/unit/config_test.rb +2 -5
- data/test/unit/http_test.rb +6 -5
- data/test/unit/promise_test.rb +2 -0
- data/test/unit/support_test.rb +71 -32
- data/test/unit/tweet_helper.rb +13 -1
- data/test/unit/tweet_test.rb +1 -1
- data/test/unit/ui_test.rb +109 -88
- data/test/unit/unit_helper.rb +37 -15
- data/test/unit/uri_test.rb +2 -2
- data/tweetwine.gemspec +12 -22
- metadata +77 -8
data/.gitignore
CHANGED
data/CHANGELOG.rdoc
CHANGED
File without changes
|
data/Rakefile
CHANGED
@@ -1,51 +1,51 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
require '
|
3
|
+
require File.expand_path('project', File.dirname(__FILE__))
|
4
4
|
|
5
|
-
|
6
|
-
name = 'tweetwine'
|
7
|
-
require "#{name}/version"
|
8
|
-
version = Tweetwine.version
|
5
|
+
require 'rake/clean'
|
9
6
|
|
10
7
|
namespace :gem do
|
11
|
-
CLOBBER.include "#{name}-*.gem"
|
8
|
+
CLOBBER.include "#{Project.name}-*.gem"
|
12
9
|
|
13
|
-
|
14
|
-
|
10
|
+
current_gem = "#{Project.name}-#{Project.version}.gem"
|
11
|
+
|
12
|
+
file current_gem do |f|
|
13
|
+
sh %{gem build #{Project.name}.gemspec}
|
15
14
|
end
|
16
15
|
|
17
16
|
desc "Package the software as a gem"
|
18
|
-
task :build => [:"man:build", :"test:all",
|
17
|
+
task :build => [:"man:build", :"test:all", current_gem]
|
19
18
|
|
20
19
|
desc "Install the software as a gem"
|
21
20
|
task :install => :build do
|
22
|
-
sh %{gem install #{
|
21
|
+
sh %{gem install #{current_gem}}
|
23
22
|
end
|
24
23
|
|
25
24
|
desc "Uninstall the gem"
|
26
25
|
task :uninstall => :clean do
|
27
|
-
sh %{gem uninstall #{name}}
|
26
|
+
sh %{gem uninstall #{Project.name}}
|
28
27
|
end
|
29
28
|
end
|
30
29
|
|
31
30
|
namespace :man do
|
32
|
-
CLOBBER.include "man/#{name}.?", "man/#{name}.?.html"
|
31
|
+
CLOBBER.include "#{Project.dirs.man}/#{Project.name}.?", "#{Project.dirs.man}/#{Project.name}.?.html"
|
33
32
|
|
34
33
|
desc "Build the manual"
|
35
34
|
task :build do
|
36
|
-
sh
|
35
|
+
sh %{ronn -br5 --manual='#{Project.name.capitalize} Manual' --organization='#{Project.authors.first}' #{Project.dirs.man}/*.ronn}
|
37
36
|
end
|
38
37
|
|
39
38
|
desc "Show the manual section 7"
|
40
39
|
task :show => :build do
|
41
|
-
sh
|
40
|
+
sh %{man #{Project.dirs.man}/#{Project.name}.7}
|
42
41
|
end
|
43
42
|
end
|
44
43
|
|
45
|
-
CLOBBER.include
|
44
|
+
CLOBBER.include Project.dirs.rdoc
|
45
|
+
|
46
46
|
desc "Generate RDoc"
|
47
47
|
task :rdoc do
|
48
|
-
sh %{rdoc --encoding=UTF-8 --line-numbers --title='#{
|
48
|
+
sh %{rdoc --encoding=UTF-8 --line-numbers --title='#{Project.title}' --output=#{Project.dirs.rdoc} *.rdoc LICENSE.txt lib}
|
49
49
|
end
|
50
50
|
|
51
51
|
namespace :test do
|
@@ -53,7 +53,7 @@ namespace :test do
|
|
53
53
|
base_dir = options[:base_dir]
|
54
54
|
file_glob = options[:file_glob]
|
55
55
|
test_desc = options[:desc] || "Run #{type} tests"
|
56
|
-
includes = ['lib',
|
56
|
+
includes = ['lib', Project.dirs.test, base_dir].map { |dir| "-I #{dir}" }.join(' ')
|
57
57
|
warn_opt = options[:warn] ? '-w' : ''
|
58
58
|
|
59
59
|
desc test_desc
|
@@ -68,11 +68,11 @@ namespace :test do
|
|
68
68
|
end
|
69
69
|
|
70
70
|
create_test_task :unit,
|
71
|
-
:base_dir =>
|
71
|
+
:base_dir => "#{Project.dirs.test}/unit",
|
72
72
|
:file_glob => '**/*_test.rb',
|
73
73
|
:warn => true
|
74
74
|
create_test_task :example,
|
75
|
-
:base_dir =>
|
75
|
+
:base_dir => "#{Project.dirs.test}/example",
|
76
76
|
:file_glob => '**/*_example.rb',
|
77
77
|
:desc => 'Run integration/example tests',
|
78
78
|
:warn => false
|
data/lib/tweetwine/http.rb
CHANGED
@@ -80,12 +80,10 @@ module Tweetwine
|
|
80
80
|
response = yield connection, uri
|
81
81
|
raise HttpError.new(response.code, response.message) unless response.is_a? Net::HTTPSuccess
|
82
82
|
response.body
|
83
|
-
rescue Errno::ECONNABORTED, Errno::ECONNRESET => e
|
83
|
+
rescue Errno::ECONNABORTED, Errno::ECONNRESET, SocketError => e
|
84
84
|
raise ConnectionError, e
|
85
85
|
rescue Timeout::Error => e
|
86
86
|
raise TimeoutError, e
|
87
|
-
rescue Net::HTTPError => e
|
88
|
-
raise HttpError, e
|
89
87
|
end
|
90
88
|
|
91
89
|
def https_scheme?(uri)
|
data/lib/tweetwine/ui.rb
CHANGED
@@ -10,6 +10,7 @@ module Tweetwine
|
|
10
10
|
}.freeze
|
11
11
|
HASHTAG_REGEX = /#[\w-]+/
|
12
12
|
USERNAME_REGEX = /^(@\w+)|\s+(@\w+)/
|
13
|
+
URI_SCHEMES_TO_COLORIZE = %w{http https}
|
13
14
|
|
14
15
|
def initialize(options = {})
|
15
16
|
@in = options[:in] || $stdin
|
@@ -96,7 +97,7 @@ module Tweetwine
|
|
96
97
|
if @colors
|
97
98
|
status = colorize_matching(:yellow, status, USERNAME_REGEX)
|
98
99
|
status = colorize_matching(:magenta, status, HASHTAG_REGEX)
|
99
|
-
status = colorize_matching(:cyan, status, Uri.extract(status,
|
100
|
+
status = colorize_matching(:cyan, status, Uri.extract(status, URI_SCHEMES_TO_COLORIZE).uniq)
|
100
101
|
end
|
101
102
|
status
|
102
103
|
end
|
data/lib/tweetwine/version.rb
CHANGED
data/project.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
name = 'tweetwine'
|
6
|
+
$LOAD_PATH.unshift File.expand_path('lib', File.dirname(__FILE__))
|
7
|
+
require "#{name}/version"
|
8
|
+
|
9
|
+
Project = OpenStruct.new({
|
10
|
+
:name => name,
|
11
|
+
:version => Tweetwine.version.dup,
|
12
|
+
:summary => Tweetwine.summary,
|
13
|
+
:description => '',
|
14
|
+
:email => 'tkareine@gmail.com',
|
15
|
+
:homepage => 'https://github.com/tkareine/tweetwine',
|
16
|
+
:authors => ['Tuomas Kareinen'],
|
17
|
+
:dirs => OpenStruct.new({
|
18
|
+
:man => 'man',
|
19
|
+
:rdoc => 'rdoc',
|
20
|
+
:test => 'test'
|
21
|
+
}).freeze
|
22
|
+
})
|
23
|
+
|
24
|
+
Project.description = <<-END
|
25
|
+
A simple but tasty Twitter agent for command line use, designed for quickly
|
26
|
+
showing the latest tweets.
|
27
|
+
END
|
28
|
+
Project.title = "#{Project.name} #{Project.version}"
|
29
|
+
|
30
|
+
Project.freeze
|
data/test/unit/config_test.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
require "
|
3
|
+
require "unit_helper"
|
4
4
|
|
5
5
|
require "fileutils"
|
6
6
|
require "tempfile"
|
@@ -190,10 +190,7 @@ class ConfigTest < UnitTestCase
|
|
190
190
|
end
|
191
191
|
|
192
192
|
should "ignore nonexisting config file for initial read" do
|
193
|
-
assert_contains_exactly
|
194
|
-
# On Ruby 1.8, Symbol does not have #<=> operator for comparison.
|
195
|
-
a.to_s <=> b.to_s
|
196
|
-
end
|
193
|
+
assert_contains_exactly @default_config.keys, @config.keys
|
197
194
|
end
|
198
195
|
|
199
196
|
should "save config to the file, implicitly without config file, env lookouts, and excludes set itself" do
|
data/test/unit/http_test.rb
CHANGED
@@ -79,17 +79,18 @@ class HttpTest < UnitTestCase
|
|
79
79
|
end
|
80
80
|
|
81
81
|
[
|
82
|
-
[Errno::ECONNABORTED, 'abort'],
|
83
|
-
[Errno::ECONNRESET, 'reset']
|
84
|
-
|
85
|
-
|
82
|
+
[Errno::ECONNABORTED, 'connection abort'],
|
83
|
+
[Errno::ECONNRESET, 'connection reset'],
|
84
|
+
[SocketError, 'socket error']
|
85
|
+
].each do |(error, desc)|
|
86
|
+
should "retry connection upon #{desc} to #{method} request" do
|
86
87
|
stub_request(method, LATEST_ARTICLES_URL).to_raise(error).then.to_return(:body => RESPONSE_BODY)
|
87
88
|
@ui.expects(:warn).with("Could not connect -- retrying in 4 seconds")
|
88
89
|
@client.send(method, LATEST_ARTICLES_URL)
|
89
90
|
assert_equal(RESPONSE_BODY, @client.send(method, LATEST_ARTICLES_URL))
|
90
91
|
end
|
91
92
|
|
92
|
-
should "retry connection a maximum of certain number of times upon
|
93
|
+
should "retry connection a maximum of certain number of times upon #{desc} to #{method} request" do
|
93
94
|
stub_request(method, LATEST_ARTICLES_URL).to_raise(error)
|
94
95
|
io_calls = sequence("IO")
|
95
96
|
Http::Client::MAX_RETRIES.times { @ui.expects(:warn).in_sequence(io_calls) }
|
data/test/unit/promise_test.rb
CHANGED
data/test/unit/support_test.rb
CHANGED
@@ -16,28 +16,28 @@ class SupportTest < UnitTestCase
|
|
16
16
|
["foo", false, "nonempty string"],
|
17
17
|
[[], true, "empty array"],
|
18
18
|
[%w{a b}, false, "nonempty array"]
|
19
|
-
].each do |(subject, emptiness,
|
20
|
-
should "return #{emptiness} for blank? with #{
|
19
|
+
].each do |(subject, emptiness, desc)|
|
20
|
+
should "return #{emptiness} for blank? with #{desc}" do
|
21
21
|
assert_equal emptiness, blank?(subject)
|
22
22
|
end
|
23
23
|
|
24
|
-
should "return #{!emptiness} for present? with #{
|
24
|
+
should "return #{!emptiness} for present? with #{desc}" do
|
25
25
|
assert_equal !emptiness, present?(subject)
|
26
26
|
end
|
27
27
|
|
28
|
-
should "return non-empty subject for presence, when subject is #{
|
28
|
+
should "return non-empty subject for presence, when subject is #{desc}" do
|
29
29
|
actual = presence(subject)
|
30
30
|
expected = present?(subject) ? subject : nil
|
31
31
|
assert_same expected, actual
|
32
32
|
end
|
33
33
|
|
34
|
-
should "return value of block for presence, when subject is #{
|
34
|
+
should "return value of block for presence, when subject is #{desc}" do
|
35
35
|
actual = presence(subject) { |s| s.size }
|
36
36
|
expected = present?(subject) ? subject.size : nil
|
37
37
|
assert_same expected, actual
|
38
38
|
end
|
39
39
|
|
40
|
-
should "allow presence to be used with || operator, when subject is #{
|
40
|
+
should "allow presence to be used with || operator, when subject is #{desc}" do
|
41
41
|
alternative = "hey"
|
42
42
|
actual = presence(subject) || alternative
|
43
43
|
expected = present?(subject) ? subject : alternative
|
@@ -47,31 +47,66 @@ class SupportTest < UnitTestCase
|
|
47
47
|
end
|
48
48
|
|
49
49
|
context "for humanizing time differences" do
|
50
|
+
should "accept string and time arguments" do
|
51
|
+
start = '2009-01-01 01:01:00'
|
52
|
+
stop = Time.parse '2009-01-01 01:03:00'
|
53
|
+
assert_commutative([2, 'min'], [start, stop]) do |a, b|
|
54
|
+
humanize_time_diff(a, b)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
50
58
|
should "use second granularity for time differences smaller than a minute" do
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
59
|
+
[
|
60
|
+
[0, '2009-01-01 01:00:00', '2009-01-01 01:00:00'],
|
61
|
+
[1, '2009-01-01 00:00:59', '2009-01-01 00:01:00'],
|
62
|
+
[1, '2009-01-01 01:00:00', '2009-01-01 01:00:01'],
|
63
|
+
[59, '2009-01-01 01:00:00', '2009-01-01 01:00:59']
|
64
|
+
].each do |(diff, start, stop)|
|
65
|
+
assert_commutative([diff, 'sec'], [start, stop]) do |a, b|
|
66
|
+
humanize_time_diff(a, b)
|
67
|
+
end
|
68
|
+
end
|
55
69
|
end
|
56
70
|
|
57
71
|
should "use minute granularity for time differences greater than a minute but smaller than an hour" do
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
72
|
+
[
|
73
|
+
[1, '2009-01-01 01:00:00', '2009-01-01 01:01:00'],
|
74
|
+
[2, '2009-01-01 01:01:00', '2009-01-01 01:03:29'],
|
75
|
+
[3, '2009-01-01 01:01:00', '2009-01-01 01:03:30'],
|
76
|
+
[59, '2009-01-01 01:00:00', '2009-01-01 01:59:00'],
|
77
|
+
[59, '2009-01-01 01:00:30', '2009-01-01 01:59:00'],
|
78
|
+
[57, '2009-01-01 01:01:00', '2009-01-01 01:58:00']
|
79
|
+
].each do |(diff, start, stop)|
|
80
|
+
assert_commutative([diff, 'min'], [start, stop]) do |a, b|
|
81
|
+
humanize_time_diff(a, b)
|
82
|
+
end
|
83
|
+
end
|
64
84
|
end
|
65
85
|
|
66
86
|
should "use hour granularity for time differences greater than an hour but smaller than a day" do
|
67
|
-
|
68
|
-
|
69
|
-
|
87
|
+
[
|
88
|
+
[1, 'hour', '2009-01-01 01:00', '2009-01-01 02:00'],
|
89
|
+
[2, 'hours', '2009-01-01 01:00', '2009-01-01 03:00'],
|
90
|
+
[2, 'hours', '2009-01-01 01:00', '2009-01-01 03:29'],
|
91
|
+
[3, 'hours', '2009-01-01 01:00', '2009-01-01 03:30']
|
92
|
+
].each do |(diff, unit, start, stop)|
|
93
|
+
assert_commutative([diff, unit], [start, stop]) do |a, b|
|
94
|
+
humanize_time_diff(a, b)
|
95
|
+
end
|
96
|
+
end
|
70
97
|
end
|
71
98
|
|
72
99
|
should "use day granularity for time differences greater than a day" do
|
73
|
-
|
74
|
-
|
100
|
+
[
|
101
|
+
[1, 'day', '2009-01-01 01:00', '2009-01-02 01:00'],
|
102
|
+
[2, 'days', '2009-01-01 01:00', '2009-01-03 01:00'],
|
103
|
+
[2, 'days', '2009-01-01 01:00', '2009-01-03 12:59'],
|
104
|
+
[3, 'days', '2009-01-01 01:00', '2009-01-03 13:00']
|
105
|
+
].each do |(diff, unit, start, stop)|
|
106
|
+
assert_commutative([diff, unit], [start, stop]) do |a, b|
|
107
|
+
humanize_time_diff(a, b)
|
108
|
+
end
|
109
|
+
end
|
75
110
|
end
|
76
111
|
end
|
77
112
|
|
@@ -194,7 +229,7 @@ class SupportTest < UnitTestCase
|
|
194
229
|
%w{- dash},
|
195
230
|
%w{_ underscore},
|
196
231
|
%w{+ plus}
|
197
|
-
].each do |char, desc|
|
232
|
+
].each do |(char, desc)|
|
198
233
|
should "not affect already unescaped characters, case #{desc}" do
|
199
234
|
assert_equal char, unescape_html(char)
|
200
235
|
end
|
@@ -206,7 +241,7 @@ class SupportTest < UnitTestCase
|
|
206
241
|
%w{& &},
|
207
242
|
%w{" "},
|
208
243
|
%W{ \ }
|
209
|
-
].each do |input, expected|
|
244
|
+
].each do |(input, expected)|
|
210
245
|
should "unescape HTML-escaped characters, case '#{input}'" do
|
211
246
|
assert_equal expected, unescape_html(input)
|
212
247
|
end
|
@@ -228,12 +263,12 @@ class SupportTest < UnitTestCase
|
|
228
263
|
end
|
229
264
|
|
230
265
|
should "support both a non-array and a single element array path for finding the value" do
|
231
|
-
assert_equal
|
232
|
-
assert_equal
|
266
|
+
assert_equal @outer_hash[:simple], find_hash_path(@outer_hash, :simple)
|
267
|
+
assert_equal @outer_hash[:simple], find_hash_path(@outer_hash, [:simple])
|
233
268
|
end
|
234
269
|
|
235
270
|
should "find a nested value with an array path" do
|
236
|
-
assert_equal
|
271
|
+
assert_equal @inner_hash[:salmon], find_hash_path(@outer_hash, [:inner, :salmon])
|
237
272
|
end
|
238
273
|
|
239
274
|
should "return the default value of the hash if the value cannot be found" do
|
@@ -243,15 +278,19 @@ class SupportTest < UnitTestCase
|
|
243
278
|
end
|
244
279
|
|
245
280
|
should "return the default value of the hash if invalid path value" do
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
281
|
+
[
|
282
|
+
nil,
|
283
|
+
[:no_such, nil],
|
284
|
+
[:simple, nil],
|
285
|
+
[:inner, nil],
|
286
|
+
[:inner, :salmon, nil]
|
287
|
+
].each do |path|
|
288
|
+
assert_equal @outer_hash.default, find_hash_path(@outer_hash, path)
|
289
|
+
end
|
251
290
|
end
|
252
291
|
|
253
292
|
should "return nil if nil hash value" do
|
254
|
-
assert_equal nil, find_hash_path(nil,
|
293
|
+
assert_equal nil, find_hash_path(nil, [:salmon])
|
255
294
|
end
|
256
295
|
end
|
257
296
|
end
|
data/test/unit/tweet_helper.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
+
require 'timecop'
|
4
|
+
|
3
5
|
module Tweetwine::Test
|
4
6
|
module TweetHelper
|
5
7
|
FIELD_PATHS = {
|
@@ -10,11 +12,13 @@ module Tweetwine::Test
|
|
10
12
|
:status => %w{status text}
|
11
13
|
}.freeze
|
12
14
|
|
15
|
+
DEFAULT_TIMESTAMP = Time.utc(2011, 'feb', 17, 22, 28, 0)
|
16
|
+
|
13
17
|
DEFAULT_FIELD_VALUES = {
|
14
18
|
:from_user => 'fred',
|
15
19
|
:to_user => nil,
|
16
20
|
:retweet => nil,
|
17
|
-
:created_at =>
|
21
|
+
:created_at => DEFAULT_TIMESTAMP.iso8601,
|
18
22
|
:status => nil
|
19
23
|
}.freeze
|
20
24
|
|
@@ -38,6 +42,14 @@ module Tweetwine::Test
|
|
38
42
|
Tweetwine::Tweet.new(create_record(fields), FIELD_PATHS)
|
39
43
|
end
|
40
44
|
|
45
|
+
def at_default_time(&block)
|
46
|
+
Timecop.freeze(TweetHelper::DEFAULT_TIMESTAMP, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_timestamp(minus_seconds)
|
50
|
+
(TweetHelper::DEFAULT_TIMESTAMP - minus_seconds).iso8601
|
51
|
+
end
|
52
|
+
|
41
53
|
private
|
42
54
|
|
43
55
|
def find_hash_of_field_path(hash, path)
|
data/test/unit/tweet_test.rb
CHANGED
data/test/unit/ui_test.rb
CHANGED
@@ -86,18 +86,19 @@ class UITest < UnitTestCase
|
|
86
86
|
should "output regular tweet" do
|
87
87
|
from_user = "fooman"
|
88
88
|
status = "Hi, @barman! Lulz woo! #hellos"
|
89
|
+
time = 2
|
89
90
|
tweet = create_tweet(
|
90
91
|
:from_user => from_user,
|
91
|
-
:status => status
|
92
|
+
:status => status,
|
93
|
+
:created_at => create_timestamp(time)
|
92
94
|
)
|
93
|
-
Support.expects(:humanize_time_diff).returns([2, "secs"])
|
94
95
|
@out.expects(:puts).with(<<-END
|
95
|
-
#{from_user},
|
96
|
+
#{from_user}, #{time} sec ago:
|
96
97
|
#{status}
|
97
98
|
|
98
99
|
END
|
99
100
|
)
|
100
|
-
|
101
|
+
show_tweet_at_default_time(tweet)
|
101
102
|
end
|
102
103
|
|
103
104
|
should "output replying tweet" do
|
@@ -109,14 +110,13 @@ class UITest < UnitTestCase
|
|
109
110
|
:status => status,
|
110
111
|
:to_user => to_user
|
111
112
|
)
|
112
|
-
Support.expects(:humanize_time_diff).returns([2, "secs"])
|
113
113
|
@out.expects(:puts).with(<<-END
|
114
|
-
#{from_user}, in reply to #{to_user},
|
114
|
+
#{from_user}, in reply to #{to_user}, 0 sec ago:
|
115
115
|
#{status}
|
116
116
|
|
117
117
|
END
|
118
118
|
)
|
119
|
-
|
119
|
+
show_tweet_at_default_time(tweet)
|
120
120
|
end
|
121
121
|
|
122
122
|
should "output regular retweet" do
|
@@ -128,14 +128,13 @@ class UITest < UnitTestCase
|
|
128
128
|
:status => status,
|
129
129
|
:rt_user => rt_user
|
130
130
|
)
|
131
|
-
Support.expects(:humanize_time_diff).returns([2, "secs"])
|
132
131
|
@out.expects(:puts).with(<<-END
|
133
|
-
#{rt_user} RT #{from_user},
|
132
|
+
#{rt_user} RT #{from_user}, 0 sec ago:
|
134
133
|
#{status}
|
135
134
|
|
136
135
|
END
|
137
136
|
)
|
138
|
-
|
137
|
+
show_tweet_at_default_time(tweet)
|
139
138
|
end
|
140
139
|
|
141
140
|
should "output replying retweet" do
|
@@ -149,14 +148,13 @@ class UITest < UnitTestCase
|
|
149
148
|
:status => status,
|
150
149
|
:rt_user => rt_user
|
151
150
|
)
|
152
|
-
Support.expects(:humanize_time_diff).returns([2, "secs"])
|
153
151
|
@out.expects(:puts).with(<<-END
|
154
|
-
#{rt_user} RT #{from_user}, in reply to #{to_user},
|
152
|
+
#{rt_user} RT #{from_user}, in reply to #{to_user}, 0 sec ago:
|
155
153
|
#{status}
|
156
154
|
|
157
155
|
END
|
158
156
|
)
|
159
|
-
|
157
|
+
show_tweet_at_default_time(tweet)
|
160
158
|
end
|
161
159
|
|
162
160
|
should "unescape HTML in a status" do
|
@@ -167,14 +165,13 @@ class UITest < UnitTestCase
|
|
167
165
|
:from_user => from_user,
|
168
166
|
:status => escaped_status
|
169
167
|
)
|
170
|
-
Support.expects(:humanize_time_diff).returns([2, "secs"])
|
171
168
|
@out.expects(:puts).with(<<-END
|
172
|
-
#{from_user},
|
169
|
+
#{from_user}, 0 sec ago:
|
173
170
|
#{unescaped_status}
|
174
171
|
|
175
172
|
END
|
176
173
|
)
|
177
|
-
|
174
|
+
show_tweet_at_default_time(tweet)
|
178
175
|
end
|
179
176
|
|
180
177
|
should "output a preview of a status" do
|
@@ -212,14 +209,13 @@ class UITest < UnitTestCase
|
|
212
209
|
:from_user => from_user,
|
213
210
|
:status => status
|
214
211
|
)
|
215
|
-
Support.expects(:humanize_time_diff).returns([2, "secs"])
|
216
212
|
@out.expects(:puts).with(<<-END
|
217
|
-
\e[32m#{from_user}\e[0m,
|
213
|
+
\e[32m#{from_user}\e[0m, 0 sec ago:
|
218
214
|
#{status}
|
219
215
|
|
220
216
|
END
|
221
217
|
)
|
222
|
-
|
218
|
+
show_tweet_at_default_time(tweet)
|
223
219
|
end
|
224
220
|
|
225
221
|
should "output replying tweet" do
|
@@ -230,14 +226,13 @@ class UITest < UnitTestCase
|
|
230
226
|
:status => "@#{to_user}! How are you doing?",
|
231
227
|
:to_user => to_user
|
232
228
|
)
|
233
|
-
Support.expects(:humanize_time_diff).returns([2, "secs"])
|
234
229
|
@out.expects(:puts).with(<<-END
|
235
|
-
\e[32m#{from_user}\e[0m, in reply to \e[32m#{to_user}\e[0m,
|
230
|
+
\e[32m#{from_user}\e[0m, in reply to \e[32m#{to_user}\e[0m, 0 sec ago:
|
236
231
|
\e[33m@#{to_user}\e[0m! How are you doing?
|
237
232
|
|
238
233
|
END
|
239
234
|
)
|
240
|
-
|
235
|
+
show_tweet_at_default_time(tweet)
|
241
236
|
end
|
242
237
|
|
243
238
|
should "output regular retweet" do
|
@@ -249,14 +244,13 @@ class UITest < UnitTestCase
|
|
249
244
|
:status => status,
|
250
245
|
:rt_user => rt_user
|
251
246
|
)
|
252
|
-
Support.expects(:humanize_time_diff).returns([2, "secs"])
|
253
247
|
@out.expects(:puts).with(<<-END
|
254
|
-
\e[32m#{rt_user}\e[0m RT \e[32m#{from_user}\e[0m,
|
248
|
+
\e[32m#{rt_user}\e[0m RT \e[32m#{from_user}\e[0m, 0 sec ago:
|
255
249
|
#{status}
|
256
250
|
|
257
251
|
END
|
258
252
|
)
|
259
|
-
|
253
|
+
show_tweet_at_default_time(tweet)
|
260
254
|
end
|
261
255
|
|
262
256
|
should "output replying retweet" do
|
@@ -269,14 +263,13 @@ class UITest < UnitTestCase
|
|
269
263
|
:status => "@#{to_user}, reply worth retweeting",
|
270
264
|
:rt_user => rt_user
|
271
265
|
)
|
272
|
-
Support.expects(:humanize_time_diff).returns([2, "secs"])
|
273
266
|
@out.expects(:puts).with(<<-END
|
274
|
-
\e[32m#{rt_user}\e[0m RT \e[32m#{from_user}\e[0m, in reply to \e[32m#{to_user}\e[0m,
|
267
|
+
\e[32m#{rt_user}\e[0m RT \e[32m#{from_user}\e[0m, in reply to \e[32m#{to_user}\e[0m, 0 sec ago:
|
275
268
|
\e[33m@#{to_user}\e[0m, reply worth retweeting
|
276
269
|
|
277
270
|
END
|
278
271
|
)
|
279
|
-
|
272
|
+
show_tweet_at_default_time(tweet)
|
280
273
|
end
|
281
274
|
|
282
275
|
should "output a preview of a status" do
|
@@ -297,14 +290,13 @@ class UITest < UnitTestCase
|
|
297
290
|
:from_user => from_user,
|
298
291
|
:status => "Lulz, so happy! #{hashtags[0]} #{hashtags[1]}"
|
299
292
|
)
|
300
|
-
Support.expects(:humanize_time_diff).returns([2, "secs"])
|
301
293
|
@out.expects(:puts).with(<<-END
|
302
|
-
\e[32m#{from_user}\e[0m,
|
294
|
+
\e[32m#{from_user}\e[0m, 0 sec ago:
|
303
295
|
Lulz, so happy! \e[35m#{hashtags[0]}\e[0m \e[35m#{hashtags[1]}\e[0m
|
304
296
|
|
305
297
|
END
|
306
298
|
)
|
307
|
-
|
299
|
+
show_tweet_at_default_time(tweet)
|
308
300
|
end
|
309
301
|
|
310
302
|
%w{http://is.gd/1qLk3 http://is.gd/1qLk3?id=foo}.each do |url|
|
@@ -314,14 +306,13 @@ Lulz, so happy! \e[35m#{hashtags[0]}\e[0m \e[35m#{hashtags[1]}\e[0m
|
|
314
306
|
:from_user => from_user,
|
315
307
|
:status => "New Rails³ - #{url}"
|
316
308
|
)
|
317
|
-
Support.expects(:humanize_time_diff).returns([2, "secs"])
|
318
309
|
@out.expects(:puts).with(<<-END
|
319
|
-
\e[32m#{from_user}\e[0m,
|
310
|
+
\e[32m#{from_user}\e[0m, 0 sec ago:
|
320
311
|
New Rails³ - \e[36m#{url}\e[0m
|
321
312
|
|
322
313
|
END
|
323
314
|
)
|
324
|
-
|
315
|
+
show_tweet_at_default_time(tweet)
|
325
316
|
end
|
326
317
|
end
|
327
318
|
|
@@ -335,14 +326,13 @@ New Rails³ - \e[36m#{url}\e[0m
|
|
335
326
|
:from_user => from_user,
|
336
327
|
:status => "Links: #{first_url} and #{second_url} np"
|
337
328
|
)
|
338
|
-
Support.expects(:humanize_time_diff).returns([2, "secs"])
|
339
329
|
@out.expects(:puts).with(<<-END
|
340
|
-
\e[32m#{from_user}\e[0m,
|
330
|
+
\e[32m#{from_user}\e[0m, 0 sec ago:
|
341
331
|
Links: \e[36m#{first_url}\e[0m and \e[36m#{second_url}\e[0m np
|
342
332
|
|
343
333
|
END
|
344
334
|
)
|
345
|
-
|
335
|
+
show_tweet_at_default_time(tweet)
|
346
336
|
end
|
347
337
|
end
|
348
338
|
|
@@ -353,14 +343,13 @@ Links: \e[36m#{first_url}\e[0m and \e[36m#{second_url}\e[0m np
|
|
353
343
|
:from_user => from_user,
|
354
344
|
:status => "I salute you #{users[0]}, #{users[1]}, and #{users[2]}!"
|
355
345
|
)
|
356
|
-
Support.expects(:humanize_time_diff).returns([2, "secs"])
|
357
346
|
@out.expects(:puts).with(<<-END
|
358
|
-
\e[32m#{from_user}\e[0m,
|
347
|
+
\e[32m#{from_user}\e[0m, 0 sec ago:
|
359
348
|
I salute you \e[33m#{users[0]}\e[0m, \e[33m#{users[1]}\e[0m, and \e[33m#{users[2]}\e[0m!
|
360
349
|
|
361
350
|
END
|
362
351
|
)
|
363
|
-
|
352
|
+
show_tweet_at_default_time(tweet)
|
364
353
|
end
|
365
354
|
|
366
355
|
should "not highlight email addresses as usernames in a status" do
|
@@ -371,86 +360,118 @@ I salute you \e[33m#{users[0]}\e[0m, \e[33m#{users[1]}\e[0m, and \e[33m#{users[2
|
|
371
360
|
:from_user => from_user,
|
372
361
|
:status => "Hi, #{users[0]}! You should notify #{users[1]}, #{email}"
|
373
362
|
)
|
374
|
-
Support.expects(:humanize_time_diff).returns([2, "secs"])
|
375
363
|
@out.expects(:puts).with(<<-END
|
376
|
-
\e[32m#{from_user}\e[0m,
|
364
|
+
\e[32m#{from_user}\e[0m, 0 sec ago:
|
377
365
|
Hi, \e[33m#{users[0]}\e[0m! You should notify \e[33m#{users[1]}\e[0m, #{email}
|
378
366
|
|
379
367
|
END
|
380
368
|
)
|
381
|
-
|
369
|
+
show_tweet_at_default_time(tweet)
|
382
370
|
end
|
383
371
|
end
|
384
372
|
|
385
373
|
context "for outputting a collection of tweets" do
|
386
374
|
setup do
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
375
|
+
users_and_times = [
|
376
|
+
['first', 11],
|
377
|
+
['second', 12],
|
378
|
+
['third', 13]
|
379
|
+
]
|
380
|
+
statuses = users_and_times.map { |(user, _)| "Hi, I'm #{user}." }
|
381
|
+
users_and_statuses = users_and_times.zip(statuses)
|
382
|
+
@outputs = Hash[users_and_statuses.map { |(user, time), status|
|
383
|
+
output = <<-END
|
384
|
+
#{user}, #{time} sec ago:
|
392
385
|
#{status}
|
393
386
|
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
:
|
387
|
+
END
|
388
|
+
[user.to_sym, output]
|
389
|
+
}]
|
390
|
+
@tweets = users_and_statuses.map { |(user, time), status| create_tweet(
|
391
|
+
:from_user => user,
|
392
|
+
:status => status,
|
393
|
+
:created_at => create_timestamp(time)
|
399
394
|
)}
|
400
|
-
Support.expects(:humanize_time_diff).twice.returns([2, "secs"])
|
401
395
|
end
|
402
396
|
|
403
|
-
should "output tweets in
|
404
|
-
ui = UI.new({ :out => @out, :show_reverse => false })
|
405
|
-
|
406
|
-
|
407
|
-
|
397
|
+
should "output tweets in normal order" do
|
398
|
+
@ui = UI.new({ :out => @out, :show_reverse => false })
|
399
|
+
[:first, :second, :third].each do |user|
|
400
|
+
@out.expects(:puts).with(@outputs[user])
|
401
|
+
end
|
402
|
+
show_tweets_at_default_time(@tweets)
|
408
403
|
end
|
409
404
|
|
410
|
-
should "output tweets in
|
411
|
-
ui = UI.new({ :out => @out, :show_reverse => true })
|
412
|
-
|
413
|
-
|
414
|
-
|
405
|
+
should "output tweets in reverse order" do
|
406
|
+
@ui = UI.new({ :out => @out, :show_reverse => true })
|
407
|
+
[:third, :second, :first].each do |user|
|
408
|
+
@out.expects(:puts).with(@outputs[user])
|
409
|
+
end
|
410
|
+
show_tweets_at_default_time(@tweets)
|
415
411
|
end
|
416
412
|
end
|
417
413
|
end
|
418
414
|
|
419
415
|
context "username regex" do
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
416
|
+
[
|
417
|
+
['@nick', 'normal'],
|
418
|
+
['@nick_man', 'underscore separated'],
|
419
|
+
[' @nick', 'beginning with space']
|
420
|
+
].each do |(nick, desc)|
|
421
|
+
should "match proper username reference, case #{desc}" do
|
422
|
+
assert_full_match UI::USERNAME_REGEX, nick
|
423
|
+
end
|
425
424
|
end
|
426
425
|
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
426
|
+
[
|
427
|
+
['@', 'just prefix'],
|
428
|
+
['nick', 'just body'],
|
429
|
+
['-@nick', 'beginning with dash'],
|
430
|
+
['@nick-man', 'dash separated'],
|
431
|
+
['@nick ', 'ending with space'],
|
432
|
+
[' @nick ', 'surrounded with space'],
|
433
|
+
['man @nick', 'space separated'],
|
434
|
+
['man@nick', 'prefix in between']
|
435
|
+
].each do |(no_nick, desc)|
|
436
|
+
should "not match an inproper username reference, case #{desc}" do
|
437
|
+
assert_no_full_match UI::USERNAME_REGEX, no_nick
|
438
|
+
end
|
436
439
|
end
|
437
440
|
end
|
438
441
|
|
439
442
|
context "hashtag regex" do
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
443
|
+
[
|
444
|
+
['#mayhem', 'normal'],
|
445
|
+
['#friday_mayhem', 'underscore separated'],
|
446
|
+
['#friday-mayhem', 'dash separated']
|
447
|
+
].each do |(hashtag, desc)|
|
448
|
+
should "match a proper hashtag reference, case #{desc}" do
|
449
|
+
assert_full_match UI::HASHTAG_REGEX, hashtag
|
450
|
+
end
|
444
451
|
end
|
445
452
|
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
453
|
+
[
|
454
|
+
['#', 'just prefix'],
|
455
|
+
['mayhem', 'just body'],
|
456
|
+
[' #mayhem', 'beginning with space'],
|
457
|
+
['#mayhem ', 'ending with space'],
|
458
|
+
[' #mayhem ', 'surrounded with space']
|
459
|
+
].each do |(no_hashtag, desc)|
|
460
|
+
should "not match an inproper hashtag reference, case #{desc}" do
|
461
|
+
assert_no_full_match UI::HASHTAG_REGEX, no_hashtag
|
462
|
+
end
|
452
463
|
end
|
453
464
|
end
|
465
|
+
|
466
|
+
private
|
467
|
+
|
468
|
+
def show_tweet_at_default_time(tweet)
|
469
|
+
at_default_time { @ui.show_tweet(tweet) }
|
470
|
+
end
|
471
|
+
|
472
|
+
def show_tweets_at_default_time(tweets)
|
473
|
+
at_default_time { @ui.show_tweets(tweets) }
|
474
|
+
end
|
454
475
|
end
|
455
476
|
|
456
477
|
end
|
data/test/unit/unit_helper.rb
CHANGED
@@ -9,42 +9,64 @@ Mocha::Configuration.prevent(:stubbing_non_existent_method)
|
|
9
9
|
|
10
10
|
module Tweetwine::Test
|
11
11
|
module Assertions
|
12
|
-
# Asserts whether an Enumeration
|
12
|
+
# Asserts whether an Enumeration-like object contains all the elements.
|
13
13
|
# Fails unless +actual+ contains the same elements as +expected+, ignoring
|
14
14
|
# the order of the elements.
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
actual = block_given? ? actual.sort(&sorter) : actual.sort
|
22
|
-
assert_equal(expected, actual, get_message(msg) {
|
23
|
-
'after sorting, collection %s is not equal to %s' % [expected.inspect, actual.inspect]
|
15
|
+
def assert_contains_exactly(expected, actual, msg_diff_size = nil, msg_diff_elems = nil)
|
16
|
+
assert_equal(expected.size, actual.size, message(msg_diff_size) {
|
17
|
+
'Expected %s to be of same size as %s' % [actual.inspect, expected.inspect]
|
18
|
+
})
|
19
|
+
assert(enumerable_minus_each_element(actual, expected).empty?, message(msg_diff_elems) {
|
20
|
+
'Expected %s to contain all the elements of %s' % [actual.inspect, expected.inspect]
|
24
21
|
})
|
25
22
|
end
|
26
23
|
|
27
24
|
# Fails unless +str+ is a full match to +regex+.
|
28
25
|
def assert_full_match(regex, str, msg = nil)
|
29
26
|
match_data = regex.match(str)
|
30
|
-
assert(str == match_data.to_s,
|
31
|
-
'%s
|
27
|
+
assert(str == match_data.to_s, message(msg) {
|
28
|
+
'Expected %s to be a full match to %s' % [str, regex.inspect]
|
32
29
|
})
|
33
30
|
end
|
34
31
|
|
35
32
|
# Fails if +str+ is a full match to +regex+.
|
36
33
|
def assert_no_full_match(regex, str, msg = nil)
|
37
34
|
match_data = regex.match(str)
|
38
|
-
assert(str != match_data.to_s,
|
39
|
-
'%s
|
35
|
+
assert(str != match_data.to_s, message(msg) {
|
36
|
+
'Expected %s not to be a full match to %s' % [str, regex.inspect]
|
37
|
+
})
|
38
|
+
end
|
39
|
+
|
40
|
+
# Fails unless +fun.call(*args)+ is equal to +expected+ and
|
41
|
+
# +fun.call(*args)+ is equal to +fun.call(*args.reverse)+.
|
42
|
+
def assert_commutative(expected, args, msg_not_expected = nil, msg_not_commutative = nil, &fun)
|
43
|
+
left_args = args
|
44
|
+
left_actual = fun.call(left_args)
|
45
|
+
assert_equal(expected, left_actual, message(msg_not_expected) {
|
46
|
+
'Expected %s, not %s' % [expected.inspect, left_actual.inspect]
|
47
|
+
})
|
48
|
+
right_args = args.reverse
|
49
|
+
right_actual = fun.call(*right_args)
|
50
|
+
assert_equal(left_actual, right_actual, message(msg_not_commutative) {
|
51
|
+
'Expected fun%s => %s to be commutative with fun%s => %s' %
|
52
|
+
[left_args.inspect, left_actual.inspect, right_args.inspect, right_actual.inspect]
|
40
53
|
})
|
41
54
|
end
|
42
55
|
|
43
56
|
private
|
44
57
|
|
45
|
-
def
|
58
|
+
def message(given, &default)
|
46
59
|
given.nil? ? default.call : given
|
47
60
|
end
|
61
|
+
|
62
|
+
def enumerable_minus_each_element(enumerable, elements)
|
63
|
+
remaining = enumerable.dup.to_a
|
64
|
+
elements.each do |e|
|
65
|
+
index = remaining.index(e)
|
66
|
+
remaining.delete_at(index) if index
|
67
|
+
end
|
68
|
+
remaining
|
69
|
+
end
|
48
70
|
end
|
49
71
|
|
50
72
|
module Doubles
|
data/test/unit/uri_test.rb
CHANGED
@@ -13,7 +13,7 @@ class UriTest < UnitTestCase
|
|
13
13
|
%w{. period},
|
14
14
|
%w{- dash},
|
15
15
|
%w{_ underscore},
|
16
|
-
].each do |char, desc|
|
16
|
+
].each do |(char, desc)|
|
17
17
|
should "not encode safe characters, case #{desc}" do
|
18
18
|
assert_equal char, Uri.percent_encode(char)
|
19
19
|
end
|
@@ -29,7 +29,7 @@ class UriTest < UnitTestCase
|
|
29
29
|
%w{/ %2F slash},
|
30
30
|
%w{: %3A colon},
|
31
31
|
%w{, %2C comma}
|
32
|
-
].each do |char, expected, desc|
|
32
|
+
].each do |(char, expected, desc)|
|
33
33
|
should "encode unsafe characters that URI.encode leaves by default unencoded, case #{desc}" do
|
34
34
|
assert_equal char, Uri.parser.escape(char)
|
35
35
|
assert_equal expected, Uri.percent_encode(char)
|
data/tweetwine.gemspec
CHANGED
@@ -1,27 +1,18 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
|
4
|
-
name = 'tweetwine'
|
5
|
-
require "#{name}/version"
|
6
|
-
version = Tweetwine.version
|
3
|
+
require File.expand_path('project', File.dirname(__FILE__))
|
7
4
|
|
8
5
|
Gem::Specification.new do |s|
|
9
|
-
s.name
|
10
|
-
s.version
|
11
|
-
|
12
|
-
s.
|
13
|
-
s.
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
s.
|
19
|
-
s.homepage = 'https://github.com/tkareine/tweetwine'
|
20
|
-
|
21
|
-
s.authors = ['Tuomas Kareinen']
|
22
|
-
|
23
|
-
s.files = `git ls-files`.split("\n") + Dir['man/**/*.[1-9]']
|
24
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
6
|
+
s.name = Project.name
|
7
|
+
s.version = Project.version
|
8
|
+
s.summary = Project.summary
|
9
|
+
s.description = Project.description
|
10
|
+
s.email = Project.email
|
11
|
+
s.homepage = Project.homepage
|
12
|
+
s.authors = Project.authors
|
13
|
+
|
14
|
+
s.files = `git ls-files`.split("\n") + Dir["#{Project.dirs.man}/**/*.[1-9]"]
|
15
|
+
s.test_files = `git ls-files -- #{Project.dirs.test}/*`.split("\n")
|
25
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
26
17
|
|
27
18
|
s.add_dependency 'oauth', '~> 0.4.4'
|
@@ -45,6 +36,5 @@ default. For Ruby 1.8, you can install 'json' gem, for example.
|
|
45
36
|
|
46
37
|
s.has_rdoc = true
|
47
38
|
s.extra_rdoc_files = Dir['*.rdoc', 'LICENSE.txt']
|
48
|
-
s.rdoc_options << '--title'
|
49
|
-
<< '--exclude' << 'test'
|
39
|
+
s.rdoc_options << '--title' << Project.title << '--exclude' << Project.dirs.test
|
50
40
|
end
|
metadata
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tweetwine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 13
|
4
5
|
prerelease:
|
5
|
-
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 4
|
9
|
+
- 1
|
10
|
+
version: 0.4.1
|
6
11
|
platform: ruby
|
7
12
|
authors:
|
8
13
|
- Tuomas Kareinen
|
@@ -10,7 +15,7 @@ autorequire:
|
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
17
|
|
13
|
-
date: 2011-
|
18
|
+
date: 2011-03-23 00:00:00 +02:00
|
14
19
|
default_executable:
|
15
20
|
dependencies:
|
16
21
|
- !ruby/object:Gem::Dependency
|
@@ -21,6 +26,11 @@ dependencies:
|
|
21
26
|
requirements:
|
22
27
|
- - ~>
|
23
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 7
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
- 4
|
33
|
+
- 4
|
24
34
|
version: 0.4.4
|
25
35
|
type: :runtime
|
26
36
|
version_requirements: *id001
|
@@ -32,6 +42,11 @@ dependencies:
|
|
32
42
|
requirements:
|
33
43
|
- - ~>
|
34
44
|
- !ruby/object:Gem::Version
|
45
|
+
hash: 31
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
- 1
|
49
|
+
- 2
|
35
50
|
version: 0.1.2
|
36
51
|
type: :development
|
37
52
|
version_requirements: *id002
|
@@ -43,6 +58,11 @@ dependencies:
|
|
43
58
|
requirements:
|
44
59
|
- - ~>
|
45
60
|
- !ruby/object:Gem::Version
|
61
|
+
hash: 1
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
- 6
|
65
|
+
- 3
|
46
66
|
version: 0.6.3
|
47
67
|
type: :development
|
48
68
|
version_requirements: *id003
|
@@ -54,6 +74,11 @@ dependencies:
|
|
54
74
|
requirements:
|
55
75
|
- - ~>
|
56
76
|
- !ruby/object:Gem::Version
|
77
|
+
hash: 23
|
78
|
+
segments:
|
79
|
+
- 0
|
80
|
+
- 2
|
81
|
+
- 0
|
57
82
|
version: 0.2.0
|
58
83
|
type: :development
|
59
84
|
version_requirements: *id004
|
@@ -65,6 +90,11 @@ dependencies:
|
|
65
90
|
requirements:
|
66
91
|
- - ~>
|
67
92
|
- !ruby/object:Gem::Version
|
93
|
+
hash: 15
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
- 5
|
97
|
+
- 2
|
68
98
|
version: 0.5.2
|
69
99
|
type: :development
|
70
100
|
version_requirements: *id005
|
@@ -76,6 +106,11 @@ dependencies:
|
|
76
106
|
requirements:
|
77
107
|
- - ~>
|
78
108
|
- !ruby/object:Gem::Version
|
109
|
+
hash: 35
|
110
|
+
segments:
|
111
|
+
- 0
|
112
|
+
- 9
|
113
|
+
- 12
|
79
114
|
version: 0.9.12
|
80
115
|
type: :development
|
81
116
|
version_requirements: *id006
|
@@ -87,6 +122,11 @@ dependencies:
|
|
87
122
|
requirements:
|
88
123
|
- - ~>
|
89
124
|
- !ruby/object:Gem::Version
|
125
|
+
hash: 21
|
126
|
+
segments:
|
127
|
+
- 1
|
128
|
+
- 0
|
129
|
+
- 1
|
90
130
|
version: 1.0.1
|
91
131
|
type: :development
|
92
132
|
version_requirements: *id007
|
@@ -98,6 +138,11 @@ dependencies:
|
|
98
138
|
requirements:
|
99
139
|
- - ~>
|
100
140
|
- !ruby/object:Gem::Version
|
141
|
+
hash: 49
|
142
|
+
segments:
|
143
|
+
- 0
|
144
|
+
- 8
|
145
|
+
- 7
|
101
146
|
version: 0.8.7
|
102
147
|
type: :development
|
103
148
|
version_requirements: *id008
|
@@ -109,6 +154,11 @@ dependencies:
|
|
109
154
|
requirements:
|
110
155
|
- - ~>
|
111
156
|
- !ruby/object:Gem::Version
|
157
|
+
hash: 5
|
158
|
+
segments:
|
159
|
+
- 0
|
160
|
+
- 7
|
161
|
+
- 3
|
112
162
|
version: 0.7.3
|
113
163
|
type: :development
|
114
164
|
version_requirements: *id009
|
@@ -120,6 +170,11 @@ dependencies:
|
|
120
170
|
requirements:
|
121
171
|
- - ~>
|
122
172
|
- !ruby/object:Gem::Version
|
173
|
+
hash: 25
|
174
|
+
segments:
|
175
|
+
- 0
|
176
|
+
- 3
|
177
|
+
- 5
|
123
178
|
version: 0.3.5
|
124
179
|
type: :development
|
125
180
|
version_requirements: *id010
|
@@ -131,6 +186,11 @@ dependencies:
|
|
131
186
|
requirements:
|
132
187
|
- - ~>
|
133
188
|
- !ruby/object:Gem::Version
|
189
|
+
hash: 11
|
190
|
+
segments:
|
191
|
+
- 1
|
192
|
+
- 6
|
193
|
+
- 2
|
134
194
|
version: 1.6.2
|
135
195
|
type: :development
|
136
196
|
version_requirements: *id011
|
@@ -152,6 +212,7 @@ files:
|
|
152
212
|
- Gemfile
|
153
213
|
- LICENSE.txt
|
154
214
|
- README.md
|
215
|
+
- RELEASING.txt
|
155
216
|
- Rakefile
|
156
217
|
- bin/tweetwine
|
157
218
|
- contrib/tweetwine-completion.bash
|
@@ -174,7 +235,7 @@ files:
|
|
174
235
|
- lib/tweetwine/url_shortener.rb
|
175
236
|
- lib/tweetwine/version.rb
|
176
237
|
- man/tweetwine.7.ronn
|
177
|
-
-
|
238
|
+
- project.rb
|
178
239
|
- test/example/authorization_example.rb
|
179
240
|
- test/example/example_helper.rb
|
180
241
|
- test/example/global_options_example.rb
|
@@ -223,12 +284,14 @@ has_rdoc: true
|
|
223
284
|
homepage: https://github.com/tkareine/tweetwine
|
224
285
|
licenses: []
|
225
286
|
|
226
|
-
post_install_message:
|
227
|
-
|
228
|
-
|
287
|
+
post_install_message: |+
|
288
|
+
|
289
|
+
Tweetwine requires a JSON parser library. Ruby 1.9 comes bundled with one by
|
290
|
+
default. For Ruby 1.8, you can install 'json' gem, for example.
|
291
|
+
|
229
292
|
rdoc_options:
|
230
293
|
- --title
|
231
|
-
- tweetwine 0.4.
|
294
|
+
- tweetwine 0.4.1
|
232
295
|
- --exclude
|
233
296
|
- test
|
234
297
|
require_paths:
|
@@ -238,17 +301,23 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
238
301
|
requirements:
|
239
302
|
- - ">="
|
240
303
|
- !ruby/object:Gem::Version
|
304
|
+
hash: 3
|
305
|
+
segments:
|
306
|
+
- 0
|
241
307
|
version: "0"
|
242
308
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
243
309
|
none: false
|
244
310
|
requirements:
|
245
311
|
- - ">="
|
246
312
|
- !ruby/object:Gem::Version
|
313
|
+
hash: 3
|
314
|
+
segments:
|
315
|
+
- 0
|
247
316
|
version: "0"
|
248
317
|
requirements: []
|
249
318
|
|
250
319
|
rubyforge_project:
|
251
|
-
rubygems_version: 1.
|
320
|
+
rubygems_version: 1.6.2
|
252
321
|
signing_key:
|
253
322
|
specification_version: 3
|
254
323
|
summary: Tweetwine shows the latest tweets from the command line quickly.
|