tweetwine 0.4.2 → 0.4.3
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/CHANGELOG.rdoc +5 -0
- data/Gemfile +1 -1
- data/README.md +2 -2
- data/Rakefile +5 -0
- data/benchmark/home_bm.rb +36 -0
- data/lib/tweetwine/character_encoding.rb +1 -1
- data/lib/tweetwine/http.rb +1 -1
- data/lib/tweetwine/support.rb +28 -26
- data/lib/tweetwine/twitter.rb +8 -5
- data/lib/tweetwine/version.rb +1 -1
- data/lib/tweetwine.rb +0 -2
- data/man/tweetwine.7 +3 -3
- data/man/tweetwine.7.ronn +2 -2
- data/project.rb +2 -0
- data/test/fixture/config_integration.yaml +1 -1
- data/test/integration/authorization_test.rb +1 -1
- data/test/integration/global_options_test.rb +1 -1
- data/test/integration/invalid_config_file_test.rb +1 -1
- data/test/integration/search_statuses_test.rb +1 -1
- data/test/integration/show_followers_test.rb +1 -1
- data/test/integration/show_friends_test.rb +1 -1
- data/test/integration/show_home_test.rb +1 -1
- data/test/integration/show_mentions_test.rb +1 -1
- data/test/integration/show_user_test.rb +1 -1
- data/test/integration/update_status_test.rb +42 -21
- data/test/integration/use_http_proxy_test.rb +6 -6
- data/test/integration/user_help_test.rb +2 -2
- data/test/support/assertions.rb +58 -0
- data/test/support/common.rb +10 -0
- data/test/support/common_helpers.rb +43 -0
- data/test/support/doubles.rb +35 -0
- data/test/{integration/helper.rb → support/integration_test_case.rb} +12 -7
- data/test/support/mocha_integration.rb +16 -0
- data/test/support/tweets.rb +95 -0
- data/test/support/unit_test_case.rb +28 -0
- data/test/support/webmock_integration.rb +16 -0
- data/test/unit/character_encoding_test.rb +1 -1
- data/test/unit/cli_test.rb +4 -4
- data/test/unit/config_test.rb +1 -1
- data/test/unit/http_test.rb +1 -1
- data/test/unit/oauth_test.rb +1 -1
- data/test/unit/obfuscate_test.rb +1 -1
- data/test/unit/option_parser_test.rb +1 -1
- data/test/unit/promise_test.rb +1 -1
- data/test/unit/support_test.rb +1 -1
- data/test/unit/tweet_test.rb +3 -3
- data/test/unit/twitter_test.rb +29 -27
- data/test/unit/ui_test.rb +3 -3
- data/test/unit/uri_test.rb +1 -1
- data/test/unit/url_shortener_test.rb +1 -1
- data/tweetwine.gemspec +5 -4
- metadata +122 -97
- data/test/helper.rb +0 -60
- data/test/unit/helper.rb +0 -108
- data/test/unit/tweet_helper.rb +0 -95
@@ -0,0 +1,43 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Tweetwine::Test
|
4
|
+
module CommonHelpers
|
5
|
+
FIXTURE_DIR = File.join File.dirname(__FILE__), '..', 'fixture'
|
6
|
+
|
7
|
+
def file_mode(file)
|
8
|
+
File.stat(file).mode & 0777
|
9
|
+
end
|
10
|
+
|
11
|
+
def fixture_path(filename)
|
12
|
+
File.join FIXTURE_DIR, filename
|
13
|
+
end
|
14
|
+
|
15
|
+
def fixture_file(filename)
|
16
|
+
File.open(fixture_path(filename)) do |f|
|
17
|
+
f.readlines.join("\n")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def tmp_env(vars = {})
|
22
|
+
originals = {}
|
23
|
+
vars.each_pair do |key, value|
|
24
|
+
key = key.to_s
|
25
|
+
originals[key] = ENV[key]
|
26
|
+
ENV[key] = value
|
27
|
+
end
|
28
|
+
yield
|
29
|
+
ensure
|
30
|
+
originals.each_pair do |key, value|
|
31
|
+
ENV[key] = value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def tmp_kcode(val)
|
36
|
+
original = $KCODE
|
37
|
+
$KCODE = val
|
38
|
+
yield
|
39
|
+
ensure
|
40
|
+
$KCODE = original
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Tweetwine::Test
|
4
|
+
module Doubles
|
5
|
+
def mock_config
|
6
|
+
@config = mock('Config')
|
7
|
+
Tweetwine::CLI.stubs(:config).returns(@config)
|
8
|
+
end
|
9
|
+
|
10
|
+
def mock_http
|
11
|
+
@http = mock('Http')
|
12
|
+
Tweetwine::CLI.stubs(:http).returns(@http)
|
13
|
+
end
|
14
|
+
|
15
|
+
def mock_oauth
|
16
|
+
@oauth = mock('OAuth')
|
17
|
+
Tweetwine::CLI.stubs(:oauth).returns(@oauth)
|
18
|
+
end
|
19
|
+
|
20
|
+
def mock_ui
|
21
|
+
@ui = mock('UI')
|
22
|
+
Tweetwine::CLI.stubs(:ui).returns(@ui)
|
23
|
+
end
|
24
|
+
|
25
|
+
def mock_url_shortener
|
26
|
+
@url_shortener = mock('UrlShortener')
|
27
|
+
Tweetwine::CLI.stubs(:url_shortener).returns(@url_shortener)
|
28
|
+
end
|
29
|
+
|
30
|
+
def stub_config(options = {})
|
31
|
+
@config = options
|
32
|
+
Tweetwine::CLI.stubs(:config).returns(@config)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -7,15 +7,16 @@
|
|
7
7
|
tempfile
|
8
8
|
time
|
9
9
|
timecop
|
10
|
+
support/common
|
11
|
+
support/common_helpers
|
12
|
+
support/webmock_integration
|
10
13
|
}.each { |lib| require lib }
|
11
14
|
|
12
|
-
require 'helper'
|
13
|
-
|
14
15
|
module Tweetwine::Test
|
15
16
|
module Integration
|
16
|
-
module
|
17
|
-
include
|
18
|
-
extend
|
17
|
+
module Helpers
|
18
|
+
include CommonHelpers
|
19
|
+
extend CommonHelpers
|
19
20
|
|
20
21
|
SNAPSHOT_CREATED_AT = Time.parse "2009-10-14 01:56:15 +0300"
|
21
22
|
|
@@ -62,9 +63,13 @@ module Tweetwine::Test
|
|
62
63
|
|
63
64
|
class TestCase < MiniTest::Spec
|
64
65
|
include WebMockIntegration
|
66
|
+
|
67
|
+
include Helpers
|
68
|
+
extend Helpers
|
69
|
+
|
70
|
+
# Shorten writing tests a bit by making our main namespace available in
|
71
|
+
# the test case.
|
65
72
|
include Tweetwine
|
66
|
-
include Helper
|
67
|
-
extend Helper
|
68
73
|
end
|
69
74
|
end
|
70
75
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'mocha_standalone'
|
4
|
+
|
5
|
+
module Tweetwine::Test
|
6
|
+
module MochaIntegration
|
7
|
+
include Mocha::API
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
mocha_teardown
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Mocha::Configuration.prevent :stubbing_non_existent_method
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'timecop'
|
4
|
+
|
5
|
+
module Tweetwine::Test
|
6
|
+
module Tweets
|
7
|
+
FIELD_PATHS = {
|
8
|
+
:from_user => %w{screen_name},
|
9
|
+
:to_user => %w{status in_reply_to_screen_name},
|
10
|
+
:retweet => %w{retweeted_status},
|
11
|
+
:created_at => %w{status created_at},
|
12
|
+
:status => %w{status text}
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
DEFAULT_TIMESTAMP = Time.utc(2011, 'feb', 17, 22, 28, 0)
|
16
|
+
|
17
|
+
DEFAULT_FIELD_VALUES = {
|
18
|
+
:from_user => 'fred',
|
19
|
+
:to_user => nil,
|
20
|
+
:retweet => nil,
|
21
|
+
:created_at => DEFAULT_TIMESTAMP.iso8601,
|
22
|
+
:status => nil
|
23
|
+
}.freeze
|
24
|
+
|
25
|
+
RECORD_SKELETON = {
|
26
|
+
'screen_name' => nil,
|
27
|
+
'retweeted_status' => nil,
|
28
|
+
'status' => {
|
29
|
+
'in_reply_to_screen_name' => nil,
|
30
|
+
'created_at' => nil,
|
31
|
+
'text' => nil
|
32
|
+
}.freeze
|
33
|
+
}.freeze
|
34
|
+
|
35
|
+
def create_record(fields = {})
|
36
|
+
record = Tweets.create_nonrt_record(Tweets.nonrt_fields(fields))
|
37
|
+
Tweets.modify_to_rt_record(record, fields[:rt_user]) if fields[:rt_user]
|
38
|
+
record
|
39
|
+
end
|
40
|
+
|
41
|
+
def create_tweet(fields = {})
|
42
|
+
Tweetwine::Tweet.new(create_record(fields), FIELD_PATHS)
|
43
|
+
end
|
44
|
+
|
45
|
+
def at_default_time(&block)
|
46
|
+
Timecop.freeze(DEFAULT_TIMESTAMP, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
def create_timestamp(minus_seconds)
|
50
|
+
(DEFAULT_TIMESTAMP - minus_seconds).iso8601
|
51
|
+
end
|
52
|
+
|
53
|
+
class << self
|
54
|
+
def nonrt_fields(fields)
|
55
|
+
DEFAULT_FIELD_VALUES.merge(fields.reject { |(k, v)| k == :rt_user })
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_nonrt_record(fields)
|
59
|
+
FIELD_PATHS.inject(deep_copy(RECORD_SKELETON)) do |result, (path_name, path_actual)|
|
60
|
+
hash, field = find_hash_of_field_path(result, path_actual)
|
61
|
+
hash[field] = fields[path_name]
|
62
|
+
result
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def modify_to_rt_record(record, rt_user)
|
67
|
+
rt_hash, rt_field = find_hash_of_field_path(record, FIELD_PATHS[:retweet])
|
68
|
+
fr_hash, fr_field = find_hash_of_field_path(record, FIELD_PATHS[:from_user])
|
69
|
+
st_hash, st_field = find_hash_of_field_path(record, FIELD_PATHS[:status])
|
70
|
+
rt_hash[rt_field] = {
|
71
|
+
fr_field => fr_hash[fr_field].dup,
|
72
|
+
'status' => st_hash.dup
|
73
|
+
}
|
74
|
+
fr_hash[fr_field] = rt_user
|
75
|
+
st_hash[st_field] = 'retweeted status text. you should not see me.'
|
76
|
+
cr_hash, cr_field = find_hash_of_field_path(record, FIELD_PATHS[:created_at])
|
77
|
+
cr_hash[cr_field] = 'old created timestamp. you should not see me.'
|
78
|
+
end
|
79
|
+
|
80
|
+
def find_hash_of_field_path(hash, path)
|
81
|
+
path = [path] unless path.is_a? Array
|
82
|
+
if path.size > 1
|
83
|
+
hash_path, field = path[0..-2], path.last
|
84
|
+
[Tweetwine::Support.find_hash_path(hash, hash_path), field]
|
85
|
+
else
|
86
|
+
[hash, path.first]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def deep_copy(obj)
|
91
|
+
Marshal.load(Marshal.dump(obj))
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
%w{
|
4
|
+
support/common
|
5
|
+
support/common_helpers
|
6
|
+
support/assertions
|
7
|
+
support/doubles
|
8
|
+
support/mocha_integration
|
9
|
+
support/webmock_integration
|
10
|
+
}.each { |lib| require lib }
|
11
|
+
|
12
|
+
module Tweetwine::Test
|
13
|
+
module Unit
|
14
|
+
class TestCase < MiniTest::Spec
|
15
|
+
include MochaIntegration
|
16
|
+
include WebMockIntegration
|
17
|
+
|
18
|
+
include Assertions
|
19
|
+
include Doubles
|
20
|
+
include CommonHelpers
|
21
|
+
extend CommonHelpers
|
22
|
+
|
23
|
+
# Shorten writing tests a bit by making our main namespace available in
|
24
|
+
# the test case.
|
25
|
+
include Tweetwine
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/test/unit/cli_test.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'support/unit_test_case'
|
4
4
|
require 'stringio'
|
5
5
|
|
6
6
|
module Tweetwine::Test::Unit
|
@@ -9,13 +9,13 @@ module Tweetwine::Test::Unit
|
|
9
9
|
class CLITest < TestCase
|
10
10
|
describe "for initialization" do
|
11
11
|
it "disallows using #new to create a new instance" do
|
12
|
-
assert_raises(NoMethodError) { CLI.new }
|
12
|
+
assert_raises(NoMethodError) { Tweetwine::CLI.new }
|
13
13
|
end
|
14
14
|
|
15
15
|
it "allows defining same option multiple times, last value winning" do
|
16
16
|
winning_option_value = 'second'
|
17
17
|
start_cli %W{-f first -f #{winning_option_value} -v}
|
18
|
-
assert_equal winning_option_value, CLI.config[:config_file]
|
18
|
+
assert_equal winning_option_value, Tweetwine::CLI.config[:config_file]
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -23,7 +23,7 @@ class CLITest < TestCase
|
|
23
23
|
|
24
24
|
def start_cli(args)
|
25
25
|
output = StringIO.new
|
26
|
-
CLI.start(args, { :out => output })
|
26
|
+
Tweetwine::CLI.start(args, { :out => output })
|
27
27
|
output.string.split("\n")
|
28
28
|
end
|
29
29
|
end
|
data/test/unit/config_test.rb
CHANGED
data/test/unit/http_test.rb
CHANGED
data/test/unit/oauth_test.rb
CHANGED
data/test/unit/obfuscate_test.rb
CHANGED
data/test/unit/promise_test.rb
CHANGED
data/test/unit/support_test.rb
CHANGED
data/test/unit/tweet_test.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
require '
|
4
|
-
require '
|
3
|
+
require 'support/unit_test_case'
|
4
|
+
require 'support/tweets'
|
5
5
|
|
6
6
|
module Tweetwine::Test::Unit
|
7
7
|
|
8
8
|
class TweetTest < TestCase
|
9
|
-
include
|
9
|
+
include Test::Tweets
|
10
10
|
|
11
11
|
describe "for initialization" do
|
12
12
|
it "raises exception if from user field is not found" do
|
data/test/unit/twitter_test.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'support/unit_test_case'
|
4
4
|
|
5
5
|
module Tweetwine::Test::Unit
|
6
6
|
|
7
|
-
class
|
7
|
+
class TwitterTest < TestCase
|
8
8
|
before do
|
9
9
|
@config = {
|
10
10
|
:num_tweets => 20,
|
@@ -383,31 +383,6 @@ class ClientTest < TestCase
|
|
383
383
|
@twitter.update(long_status)
|
384
384
|
end
|
385
385
|
|
386
|
-
it "discards obviously invalid shortened URLs, using originals instead" do
|
387
|
-
long_urls = ["http://www.google.fi/", "http://www.w3.org/TR/1999/REC-xpath-19991116"]
|
388
|
-
status = long_urls.join(" and ")
|
389
|
-
short_urls = [nil, ""]
|
390
|
-
twitter_records, internal_records = create_rest_api_status_records({
|
391
|
-
:from_user => @username,
|
392
|
-
:status => status
|
393
|
-
})
|
394
|
-
@oauth.expects(:request_signer)
|
395
|
-
http_subresource = mock
|
396
|
-
http_subresource.expects(:post).
|
397
|
-
with({ :status => status }).
|
398
|
-
returns(twitter_records[0].to_json)
|
399
|
-
@rest_api.expects(:[]).
|
400
|
-
with("statuses/update.json").
|
401
|
-
returns(http_subresource)
|
402
|
-
@url_shortener.expects(:shorten).with(long_urls.first).returns(short_urls.first)
|
403
|
-
@url_shortener.expects(:shorten).with(long_urls.last).returns(short_urls.last)
|
404
|
-
@ui.expects(:show_status_preview).with(status)
|
405
|
-
@ui.expects(:confirm).with("Really send?").returns(true)
|
406
|
-
@ui.expects(:info).with("Sent status update.\n\n")
|
407
|
-
@ui.expects(:show_tweets).with(internal_records)
|
408
|
-
@twitter.update(status)
|
409
|
-
end
|
410
|
-
|
411
386
|
it "reuses a shortened URL for duplicate long URLs" do
|
412
387
|
long_urls = ["http://www.w3.org/TR/1999/REC-xpath-19991116"] * 2
|
413
388
|
long_status = long_urls.join(" and ")
|
@@ -443,6 +418,33 @@ class ClientTest < TestCase
|
|
443
418
|
})
|
444
419
|
end
|
445
420
|
|
421
|
+
it "warns if URLs returned from shortening service are not shortened, using originals instead" do
|
422
|
+
long_urls = ["http://www.google.fi/", "http://www.w3.org/TR/1999/REC-xpath-19991116"]
|
423
|
+
status = long_urls.join(" and ")
|
424
|
+
short_urls = [long_urls.first, ""]
|
425
|
+
twitter_records, internal_records = create_rest_api_status_records({
|
426
|
+
:from_user => @username,
|
427
|
+
:status => status
|
428
|
+
})
|
429
|
+
@oauth.expects(:request_signer)
|
430
|
+
http_subresource = mock
|
431
|
+
http_subresource.expects(:post).
|
432
|
+
with({ :status => status }).
|
433
|
+
returns(twitter_records[0].to_json)
|
434
|
+
@rest_api.expects(:[]).
|
435
|
+
with("statuses/update.json").
|
436
|
+
returns(http_subresource)
|
437
|
+
@url_shortener.expects(:shorten).with(long_urls.first).returns(short_urls.first)
|
438
|
+
@url_shortener.expects(:shorten).with(long_urls.last).returns(short_urls.last)
|
439
|
+
@ui.expects(:warn).with("No short URL for #{long_urls.first}")
|
440
|
+
@ui.expects(:warn).with("No short URL for #{long_urls.last}")
|
441
|
+
@ui.expects(:show_status_preview).with(status)
|
442
|
+
@ui.expects(:confirm).with("Really send?").returns(true)
|
443
|
+
@ui.expects(:info).with("Sent status update.\n\n")
|
444
|
+
@ui.expects(:show_tweets).with(internal_records)
|
445
|
+
@twitter.update(status)
|
446
|
+
end
|
447
|
+
|
446
448
|
it "skips shortening URLs if required libraries are not found" do
|
447
449
|
Tweetwine::CLI.stubs(:url_shortener).raises(LoadError, 'gem not found')
|
448
450
|
@oauth.expects(:request_signer)
|
data/test/unit/ui_test.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
require '
|
4
|
-
require '
|
3
|
+
require 'support/unit_test_case'
|
4
|
+
require 'support/tweets'
|
5
5
|
|
6
6
|
module Tweetwine::Test::Unit
|
7
7
|
|
8
8
|
class UITest < TestCase
|
9
|
-
include
|
9
|
+
include Test::Tweets
|
10
10
|
|
11
11
|
before do
|
12
12
|
@in = mock
|
data/test/unit/uri_test.rb
CHANGED
data/tweetwine.gemspec
CHANGED
@@ -10,14 +10,15 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
11
11
|
|
12
12
|
s.add_dependency 'oauth', '~> 0.4.4'
|
13
|
-
s.add_development_dependency 'gem-man', '~> 0.
|
14
|
-
s.add_development_dependency 'minitest', '~> 2.
|
13
|
+
s.add_development_dependency 'gem-man', '~> 0.3.0'
|
14
|
+
s.add_development_dependency 'minitest', '~> 2.4.0'
|
15
15
|
s.add_development_dependency 'mocha', '~> 0.9.12'
|
16
16
|
s.add_development_dependency 'open4', '~> 1.0.1'
|
17
|
-
s.add_development_dependency '
|
17
|
+
s.add_development_dependency 'perftools.rb', '~> 0.5.6'
|
18
|
+
s.add_development_dependency 'rake', '>= 0.8.7'
|
18
19
|
s.add_development_dependency 'ronn', '~> 0.7.3'
|
19
20
|
s.add_development_dependency 'timecop', '~> 0.3.5'
|
20
|
-
s.add_development_dependency 'webmock', '~> 1.
|
21
|
+
s.add_development_dependency 'webmock', '~> 1.7.7'
|
21
22
|
|
22
23
|
s.post_install_message = <<-END
|
23
24
|
|