tweetwine 0.2.12 → 0.3.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.
- data/CHANGELOG.rdoc +7 -0
- data/Gemfile +17 -0
- data/README.md +57 -47
- data/Rakefile +17 -26
- data/bin/tweetwine +11 -12
- data/contrib/tweetwine-completion.bash +2 -3
- data/example/application_behavior_example.rb +173 -0
- data/example/example_helper.rb +44 -28
- data/example/fixture/config.yaml +8 -0
- data/example/fixture/shorten_rubygems.html +5 -0
- data/example/fixture/shorten_rubylang.html +5 -0
- data/example/fixture/update_utf8.json +1 -0
- data/example/fixture/update_with_urls.json +1 -0
- data/example/fixture/{update.json → update_without_urls.json} +0 -0
- data/example/search_statuses_example.rb +49 -16
- data/example/show_followers_example.rb +7 -8
- data/example/show_friends_example.rb +7 -8
- data/example/show_home_example.rb +19 -16
- data/example/show_mentions_example.rb +8 -9
- data/example/show_user_example.rb +16 -13
- data/example/update_status_example.rb +143 -26
- data/example/use_http_proxy_example.rb +40 -20
- data/lib/tweetwine/basic_object.rb +19 -0
- data/lib/tweetwine/character_encoding.rb +59 -0
- data/lib/tweetwine/cli.rb +354 -230
- data/lib/tweetwine/config.rb +65 -0
- data/lib/tweetwine/http.rb +120 -0
- data/lib/tweetwine/oauth.rb +104 -0
- data/lib/tweetwine/obfuscate.rb +21 -0
- data/lib/tweetwine/option_parser.rb +31 -0
- data/lib/tweetwine/promise.rb +39 -0
- data/lib/tweetwine/twitter.rb +211 -0
- data/lib/tweetwine/{io.rb → ui.rb} +30 -21
- data/lib/tweetwine/url_shortener.rb +15 -9
- data/lib/tweetwine/util.rb +30 -15
- data/lib/tweetwine.rb +72 -12
- data/man/tweetwine.7 +43 -69
- data/man/tweetwine.7.ronn +57 -47
- data/test/character_encoding_test.rb +87 -0
- data/test/cli_test.rb +19 -6
- data/test/config_test.rb +244 -0
- data/test/fixture/oauth.rb +21 -0
- data/test/fixture/test_config.yaml +4 -4
- data/test/http_test.rb +199 -0
- data/test/oauth_test.rb +77 -0
- data/test/obfuscate_test.rb +16 -0
- data/test/option_parser_test.rb +60 -0
- data/test/promise_test.rb +56 -0
- data/test/test_helper.rb +76 -8
- data/test/twitter_test.rb +625 -0
- data/test/{io_test.rb → ui_test.rb} +92 -74
- data/test/url_shortener_test.rb +115 -135
- data/test/util_test.rb +136 -85
- data/tweetwine.gemspec +53 -0
- metadata +112 -56
- data/example/show_metadata_example.rb +0 -86
- data/lib/tweetwine/client.rb +0 -187
- data/lib/tweetwine/meta.rb +0 -5
- data/lib/tweetwine/options.rb +0 -24
- data/lib/tweetwine/retrying_http.rb +0 -99
- data/lib/tweetwine/startup_config.rb +0 -50
- data/man/tweetwine.1 +0 -109
- data/man/tweetwine.1.ronn +0 -69
- data/test/client_test.rb +0 -544
- data/test/options_test.rb +0 -45
- data/test/retrying_http_test.rb +0 -147
- data/test/startup_config_test.rb +0 -162
data/test/retrying_http_test.rb
DELETED
@@ -1,147 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require "test_helper"
|
4
|
-
require "rest_client"
|
5
|
-
|
6
|
-
class Object
|
7
|
-
def sleep(timeout); end # speed up tests
|
8
|
-
end
|
9
|
-
|
10
|
-
module Tweetwine
|
11
|
-
|
12
|
-
class RetryingHttpModuleTest < TweetwineTestCase
|
13
|
-
context "When using HTTP proxy" do
|
14
|
-
setup do
|
15
|
-
RetryingHttp.proxy = "http://proxy.net:8080"
|
16
|
-
end
|
17
|
-
|
18
|
-
should "pass HTTP proxy configuration to RestClient" do
|
19
|
-
assert_equal "http://proxy.net:8080", RestClient.proxy
|
20
|
-
end
|
21
|
-
|
22
|
-
teardown do
|
23
|
-
RetryingHttp.proxy = nil
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class RetryingHttpClientTest < TweetwineTestCase
|
29
|
-
context "A Client instance" do
|
30
|
-
setup do
|
31
|
-
@io = mock()
|
32
|
-
@client = RetryingHttp::Client.new(@io)
|
33
|
-
end
|
34
|
-
|
35
|
-
should "wrap RestClient.get" do
|
36
|
-
RestClient.expects(:get).with("https://site.org")
|
37
|
-
@client.get("https://site.org")
|
38
|
-
end
|
39
|
-
|
40
|
-
should "wrap RestClient.post" do
|
41
|
-
RestClient.expects(:post).with("https://site.org", { :key => "value" })
|
42
|
-
@client.post("https://site.org", { :key => "value" })
|
43
|
-
end
|
44
|
-
|
45
|
-
should "raise HttpError for an invalid request" do
|
46
|
-
RestClient.expects(:get).with("https://charlie:42@authorization.org").raises(RestClient::Unauthorized)
|
47
|
-
assert_raise(HttpError) { @client.get("https://charlie:42@authorization.org") }
|
48
|
-
end
|
49
|
-
|
50
|
-
should "raise HttpError when connection cannot be established" do
|
51
|
-
RestClient.expects(:get).with("https://unreachable.org").raises(Errno::ECONNABORTED)
|
52
|
-
assert_raise(HttpError) { @client.get("https://unreachable.org") }
|
53
|
-
end
|
54
|
-
|
55
|
-
should "raise HttpError when host cannot be resolved" do
|
56
|
-
RestClient.expects(:get).with("https://unresolved.org").raises(SocketError)
|
57
|
-
assert_raise(HttpError) { @client.get("https://unresolved.org") }
|
58
|
-
end
|
59
|
-
|
60
|
-
[Errno::ECONNRESET, RestClient::RequestTimeout].each do |error_class|
|
61
|
-
should "retry connection upon connection reset, case #{error_class}" do
|
62
|
-
retrying_calls = sequence("Retrying Client calls")
|
63
|
-
RestClient.expects(:get).with("https://moderate.traffic.org").in_sequence(retrying_calls).raises(error_class)
|
64
|
-
RestClient.expects(:get).with("https://moderate.traffic.org").in_sequence(retrying_calls)
|
65
|
-
@io.expects(:warn).with("Could not connect -- retrying in 4 seconds")
|
66
|
-
@client.get("https://moderate.traffic.org")
|
67
|
-
end
|
68
|
-
|
69
|
-
should "retry connection a maximum of certain number of times, case #{error_class}" do
|
70
|
-
retrying_calls = sequence("Retrying Client calls")
|
71
|
-
io_calls = sequence("IO")
|
72
|
-
(RetryingHttp::Client::MAX_RETRIES + 1).times do
|
73
|
-
RestClient.expects(:get).with("https://unresponsive.org").in_sequence(retrying_calls).raises(error_class)
|
74
|
-
end
|
75
|
-
RetryingHttp::Client::MAX_RETRIES.times do
|
76
|
-
@io.expects(:warn).in_sequence(io_calls)
|
77
|
-
end
|
78
|
-
assert_raise(HttpError) { @client.get("https://unresponsive.org") }
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
should "return a resource with IO inherited from the client" do
|
83
|
-
resource = @client.as_resource("http://foo.bar")
|
84
|
-
assert_equal(@io, resource.io)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
class RetryingHttpResourceTest < TweetwineTestCase
|
90
|
-
context "A Resource instance" do
|
91
|
-
setup do
|
92
|
-
@io = mock()
|
93
|
-
@wrapped = mock()
|
94
|
-
@resource = RetryingHttp::Resource.new(@wrapped)
|
95
|
-
@resource.io = @io
|
96
|
-
end
|
97
|
-
|
98
|
-
should "allow wrapping RestClient::Resource#get" do
|
99
|
-
@wrapped.expects(:get).with("https://site.org")
|
100
|
-
@resource.get("https://site.org")
|
101
|
-
end
|
102
|
-
|
103
|
-
should "allow wrapping RestClient::Resource#post" do
|
104
|
-
@wrapped.expects(:post).with("https://site.org", { :key => "value" })
|
105
|
-
@resource.post("https://site.org", { :key => "value" })
|
106
|
-
end
|
107
|
-
|
108
|
-
should "raise HttpError for an invalid request" do
|
109
|
-
@wrapped.expects(:get).raises(RestClient::Unauthorized)
|
110
|
-
assert_raise(HttpError) { @resource.get }
|
111
|
-
end
|
112
|
-
|
113
|
-
should "raise HttpError when connection cannot be established" do
|
114
|
-
@wrapped.expects(:get).raises(Errno::ECONNABORTED)
|
115
|
-
assert_raise(HttpError) { @resource.get }
|
116
|
-
end
|
117
|
-
|
118
|
-
should "raise HttpError when host cannot be resolved" do
|
119
|
-
@wrapped.expects(:get).raises(SocketError)
|
120
|
-
assert_raise(HttpError) { @resource.get }
|
121
|
-
end
|
122
|
-
|
123
|
-
[Errno::ECONNRESET, RestClient::RequestTimeout].each do |error_class|
|
124
|
-
should "retry connection upon connection reset, case #{error_class}" do
|
125
|
-
retrying_calls = sequence("Retrying Resource calls")
|
126
|
-
@wrapped.expects(:get).in_sequence(retrying_calls).raises(error_class)
|
127
|
-
@wrapped.expects(:get).in_sequence(retrying_calls)
|
128
|
-
@io.expects(:warn).with("Could not connect -- retrying in 4 seconds")
|
129
|
-
@resource.get
|
130
|
-
end
|
131
|
-
|
132
|
-
should "retry connection a maximum of certain number of times, case #{error_class}" do
|
133
|
-
retrying_calls = sequence("Retrying Resource calls")
|
134
|
-
io_calls = sequence("IO")
|
135
|
-
(RetryingHttp::Resource::MAX_RETRIES + 1).times do
|
136
|
-
@wrapped.expects(:get).in_sequence(retrying_calls).raises(error_class)
|
137
|
-
end
|
138
|
-
RetryingHttp::Resource::MAX_RETRIES.times do
|
139
|
-
@io.expects(:warn).in_sequence(io_calls)
|
140
|
-
end
|
141
|
-
assert_raise(HttpError) { @resource.get }
|
142
|
-
end
|
143
|
-
end
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
end
|
data/test/startup_config_test.rb
DELETED
@@ -1,162 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require "test_helper"
|
4
|
-
|
5
|
-
module Tweetwine
|
6
|
-
|
7
|
-
class StartupConfigTest < TweetwineTestCase
|
8
|
-
TEST_CONFIG_FILE = Helper.fixture_file("test_config.yaml")
|
9
|
-
|
10
|
-
context "A StartupConfig instance" do
|
11
|
-
context "upon initialization" do
|
12
|
-
should "require at least one supported command" do
|
13
|
-
assert_raise(ArgumentError) { StartupConfig.new([]) }
|
14
|
-
assert_nothing_raised { StartupConfig.new([:cmd], :cmd) }
|
15
|
-
end
|
16
|
-
|
17
|
-
should "require the default command to be a supported command" do
|
18
|
-
assert_raise(ArgumentError) { StartupConfig.new([:cmd_a], :cmd_b) }
|
19
|
-
assert_nothing_raised { StartupConfig.new([:cmd_a], :cmd_a) }
|
20
|
-
end
|
21
|
-
|
22
|
-
should "allow passing default options" do
|
23
|
-
opts = {:opt => "foo"}
|
24
|
-
config = StartupConfig.new([:cmd_a], :cmd_a, opts)
|
25
|
-
assert_equal opts, config.options
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
context "at runtime" do
|
30
|
-
setup do
|
31
|
-
@config = StartupConfig.new(
|
32
|
-
[:default_action, :another_action],
|
33
|
-
:default_action,
|
34
|
-
{:defopt => 42})
|
35
|
-
end
|
36
|
-
|
37
|
-
should "use the default command when given no command as a cmdline argument" do
|
38
|
-
@config.parse
|
39
|
-
assert_equal :default_action, @config.command
|
40
|
-
end
|
41
|
-
|
42
|
-
should "pass supported commands" do
|
43
|
-
@config.parse(%w{default_action}) { |args| {} }
|
44
|
-
assert_equal :default_action, @config.command
|
45
|
-
|
46
|
-
@config.parse(%w{another_action}) { |args| {} }
|
47
|
-
assert_equal :another_action, @config.command
|
48
|
-
end
|
49
|
-
|
50
|
-
should "raise ArgumentError if given command is not supported" do
|
51
|
-
assert_raise(ArgumentError) do
|
52
|
-
@config.parse(%w{unknown_action}) { |args| {} }
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
context "when given cmdline args and no config file and no environment variables" do
|
57
|
-
setup do
|
58
|
-
@cmd_args = %w{--opt bar --another_opt baz another_action left overs}
|
59
|
-
@config.parse(@cmd_args) do |args|
|
60
|
-
args.slice!(0..3)
|
61
|
-
{:defopt => 56, :nopt => "baz"}
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
should "have the parsed option defined" do
|
66
|
-
assert_equal "baz", @config.options[:nopt]
|
67
|
-
end
|
68
|
-
|
69
|
-
should "override the default value for the option given as a cmdline arg" do
|
70
|
-
assert_equal 56, @config.options[:defopt]
|
71
|
-
end
|
72
|
-
|
73
|
-
should "parse cmdline args before the command" do
|
74
|
-
assert_equal({:defopt => 56, :nopt => "baz"}, @config.options)
|
75
|
-
end
|
76
|
-
|
77
|
-
should "identify the next argument after cmdline args as the command" do
|
78
|
-
assert_equal :another_action, @config.command
|
79
|
-
end
|
80
|
-
|
81
|
-
should "leave remaining args to be consumed by the command" do
|
82
|
-
assert_equal %w{left overs}, @cmd_args
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
context "when given a config file and no cmdline args and no environment variables" do
|
87
|
-
setup do
|
88
|
-
@config.parse([], TEST_CONFIG_FILE)
|
89
|
-
end
|
90
|
-
|
91
|
-
should "have the parsed option defined" do
|
92
|
-
assert_equal false, @config.options[:colors]
|
93
|
-
end
|
94
|
-
|
95
|
-
should "override the default value for the option given from the config file" do
|
96
|
-
assert_equal 78, @config.options[:defopt]
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
context "when given an environment variable and no cmdline args no config file" do
|
101
|
-
setup do
|
102
|
-
ENV['colors'] = "baba"
|
103
|
-
ENV['defopt'] = "zaza"
|
104
|
-
ENV['blank'] = ""
|
105
|
-
@config.parse([], nil, [:colors, :defopt])
|
106
|
-
end
|
107
|
-
|
108
|
-
should "have the parsed option defined" do
|
109
|
-
assert_equal "baba", @config.options[:colors]
|
110
|
-
end
|
111
|
-
|
112
|
-
should "override default value for the option given as an environment variable" do
|
113
|
-
assert_equal "zaza", @config.options[:defopt]
|
114
|
-
end
|
115
|
-
|
116
|
-
should "not pass blank environment variable" do
|
117
|
-
assert_equal nil, @config.options[:blank]
|
118
|
-
end
|
119
|
-
|
120
|
-
teardown do
|
121
|
-
ENV['colors'] = ENV['defopt'] = ENV['blank'] = nil
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
context "when given an option as a cmdline option and in a config file and as an environment variable" do
|
126
|
-
setup do
|
127
|
-
@config.parse(%w{--colors}, TEST_CONFIG_FILE, [:colors, :defopt]) do |args|
|
128
|
-
args.clear
|
129
|
-
{:defopt => 56, :colors => true}
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
should "the command line option should override all other option sources" do
|
134
|
-
assert_equal true, @config.options[:colors]
|
135
|
-
assert_equal 56, @config.options[:defopt]
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
context "when given an option from a config file and as an environment variable" do
|
140
|
-
setup do
|
141
|
-
ENV['colors'] = "baba"
|
142
|
-
ENV['defopt'] = "zaza"
|
143
|
-
@config.parse(%w{}, TEST_CONFIG_FILE, [:colors, :defopt]) do |args|
|
144
|
-
args.clear
|
145
|
-
{}
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
should "the config file option should override environment variable" do
|
150
|
-
assert_equal false, @config.options[:colors]
|
151
|
-
assert_equal 78, @config.options[:defopt]
|
152
|
-
end
|
153
|
-
|
154
|
-
teardown do
|
155
|
-
ENV['colors'] = ENV['defopt'] = nil
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
end
|