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.
Files changed (67) hide show
  1. data/CHANGELOG.rdoc +7 -0
  2. data/Gemfile +17 -0
  3. data/README.md +57 -47
  4. data/Rakefile +17 -26
  5. data/bin/tweetwine +11 -12
  6. data/contrib/tweetwine-completion.bash +2 -3
  7. data/example/application_behavior_example.rb +173 -0
  8. data/example/example_helper.rb +44 -28
  9. data/example/fixture/config.yaml +8 -0
  10. data/example/fixture/shorten_rubygems.html +5 -0
  11. data/example/fixture/shorten_rubylang.html +5 -0
  12. data/example/fixture/update_utf8.json +1 -0
  13. data/example/fixture/update_with_urls.json +1 -0
  14. data/example/fixture/{update.json → update_without_urls.json} +0 -0
  15. data/example/search_statuses_example.rb +49 -16
  16. data/example/show_followers_example.rb +7 -8
  17. data/example/show_friends_example.rb +7 -8
  18. data/example/show_home_example.rb +19 -16
  19. data/example/show_mentions_example.rb +8 -9
  20. data/example/show_user_example.rb +16 -13
  21. data/example/update_status_example.rb +143 -26
  22. data/example/use_http_proxy_example.rb +40 -20
  23. data/lib/tweetwine/basic_object.rb +19 -0
  24. data/lib/tweetwine/character_encoding.rb +59 -0
  25. data/lib/tweetwine/cli.rb +354 -230
  26. data/lib/tweetwine/config.rb +65 -0
  27. data/lib/tweetwine/http.rb +120 -0
  28. data/lib/tweetwine/oauth.rb +104 -0
  29. data/lib/tweetwine/obfuscate.rb +21 -0
  30. data/lib/tweetwine/option_parser.rb +31 -0
  31. data/lib/tweetwine/promise.rb +39 -0
  32. data/lib/tweetwine/twitter.rb +211 -0
  33. data/lib/tweetwine/{io.rb → ui.rb} +30 -21
  34. data/lib/tweetwine/url_shortener.rb +15 -9
  35. data/lib/tweetwine/util.rb +30 -15
  36. data/lib/tweetwine.rb +72 -12
  37. data/man/tweetwine.7 +43 -69
  38. data/man/tweetwine.7.ronn +57 -47
  39. data/test/character_encoding_test.rb +87 -0
  40. data/test/cli_test.rb +19 -6
  41. data/test/config_test.rb +244 -0
  42. data/test/fixture/oauth.rb +21 -0
  43. data/test/fixture/test_config.yaml +4 -4
  44. data/test/http_test.rb +199 -0
  45. data/test/oauth_test.rb +77 -0
  46. data/test/obfuscate_test.rb +16 -0
  47. data/test/option_parser_test.rb +60 -0
  48. data/test/promise_test.rb +56 -0
  49. data/test/test_helper.rb +76 -8
  50. data/test/twitter_test.rb +625 -0
  51. data/test/{io_test.rb → ui_test.rb} +92 -74
  52. data/test/url_shortener_test.rb +115 -135
  53. data/test/util_test.rb +136 -85
  54. data/tweetwine.gemspec +53 -0
  55. metadata +112 -56
  56. data/example/show_metadata_example.rb +0 -86
  57. data/lib/tweetwine/client.rb +0 -187
  58. data/lib/tweetwine/meta.rb +0 -5
  59. data/lib/tweetwine/options.rb +0 -24
  60. data/lib/tweetwine/retrying_http.rb +0 -99
  61. data/lib/tweetwine/startup_config.rb +0 -50
  62. data/man/tweetwine.1 +0 -109
  63. data/man/tweetwine.1.ronn +0 -69
  64. data/test/client_test.rb +0 -544
  65. data/test/options_test.rb +0 -45
  66. data/test/retrying_http_test.rb +0 -147
  67. data/test/startup_config_test.rb +0 -162
@@ -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
@@ -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