tweetwine 0.4.2 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/CHANGELOG.rdoc
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -24,7 +24,7 @@ Install Tweetwine with RubyGems:
|
|
24
24
|
|
25
25
|
$ gem install tweetwine
|
26
26
|
|
27
|
-
The program is tested with
|
27
|
+
The program is tested with MRI 1.8.7, 1.9.2, and 1.9.3.
|
28
28
|
|
29
29
|
The program requires [oauth](http://oauth.rubyforge.org/) gem to be installed.
|
30
30
|
In addition, the program needs a JSON parser library, such as
|
@@ -81,7 +81,7 @@ enabled via `shorten_urls` field in the configuration file; for example:
|
|
81
81
|
shorten_urls:
|
82
82
|
service_url: http://is.gd/create.php
|
83
83
|
method: post
|
84
|
-
url_param_name:
|
84
|
+
url_param_name: url
|
85
85
|
xpath_selector: //input[@id='short_url']/@value
|
86
86
|
disable: false # optional
|
87
87
|
|
data/Rakefile
CHANGED
@@ -80,6 +80,11 @@ namespace :test do
|
|
80
80
|
task :all => [:unit, :integration]
|
81
81
|
end
|
82
82
|
|
83
|
+
desc "Profile fetching home timeline"
|
84
|
+
task :profile do
|
85
|
+
sh %{bundle exec ruby -I lib -I test benchmark/home_bm.rb}
|
86
|
+
end
|
87
|
+
|
83
88
|
desc "Find code smells"
|
84
89
|
task :roodi do
|
85
90
|
sh %{roodi "**/*.rb"}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
require 'tweetwine'
|
5
|
+
require 'perftools'
|
6
|
+
require 'support/common_helpers'
|
7
|
+
require 'webmock'
|
8
|
+
|
9
|
+
WebMock.disable_net_connect!
|
10
|
+
|
11
|
+
module Driver
|
12
|
+
extend WebMock::API
|
13
|
+
extend Tweetwine::Test::CommonHelpers
|
14
|
+
|
15
|
+
def self.run
|
16
|
+
stub_http_request(:get, "https://api.twitter.com/1/statuses/home_timeline.json?count=20&page=1").to_return(:body => fixture_file('home.json'))
|
17
|
+
yield
|
18
|
+
ensure
|
19
|
+
WebMock.reset!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Driver.run do
|
24
|
+
output_path = "/tmp/tweetwine_home_bm"
|
25
|
+
|
26
|
+
PerfTools::CpuProfiler.start(output_path) do
|
27
|
+
1_000.times do
|
28
|
+
Tweetwine::CLI.start %w{home}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
system %{pprof.rb --gif #{output_path} > #{output_path}.gif}
|
33
|
+
|
34
|
+
puts "Profiling output: #{output_path}"
|
35
|
+
puts "Visualization: #{output_path}.gif"
|
36
|
+
end
|
data/lib/tweetwine/http.rb
CHANGED
@@ -17,7 +17,7 @@ module Tweetwine
|
|
17
17
|
if retries < max_retries
|
18
18
|
retries += 1
|
19
19
|
timeout = retry_base_wait_timeout**retries
|
20
|
-
CLI.ui.warn
|
20
|
+
CLI.ui.warn "Could not connect -- retrying in #{timeout} seconds"
|
21
21
|
sleep timeout
|
22
22
|
retry
|
23
23
|
else
|
data/lib/tweetwine/support.rb
CHANGED
@@ -36,15 +36,15 @@ module Tweetwine
|
|
36
36
|
else [(difference/86400.0).round, "day"]
|
37
37
|
end
|
38
38
|
|
39
|
-
[value, pluralize_unit(value, unit)]
|
39
|
+
[value, Helper.pluralize_unit(value, unit)]
|
40
40
|
end
|
41
41
|
|
42
42
|
def stringify_hash_keys(hash)
|
43
|
-
recursive_copy_hash(hash) { |key, value| [key.to_s, value] }
|
43
|
+
Helper.recursive_copy_hash(hash) { |key, value| [key.to_s, value] }
|
44
44
|
end
|
45
45
|
|
46
46
|
def symbolize_hash_keys(hash)
|
47
|
-
recursive_copy_hash(hash) { |key, value| [key.to_sym, value] }
|
47
|
+
Helper.recursive_copy_hash(hash) { |key, value| [key.to_sym, value] }
|
48
48
|
end
|
49
49
|
|
50
50
|
def parse_int_gt(value, default, min, name_for_error)
|
@@ -64,7 +64,7 @@ module Tweetwine
|
|
64
64
|
dup_str = str.dup
|
65
65
|
str_pos, dup_pos = 0, 0
|
66
66
|
while str_pos < str.size && (match_data = regexp.match(str[str_pos..-1]))
|
67
|
-
matching_group_indexes = indexes_of_filled_matches(match_data)
|
67
|
+
matching_group_indexes = Helper.indexes_of_filled_matches(match_data)
|
68
68
|
|
69
69
|
matching_group_indexes.each do |i|
|
70
70
|
replacement = (yield match_data[i]).to_s
|
@@ -93,30 +93,32 @@ module Tweetwine
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
96
|
+
module Helper
|
97
|
+
class << self
|
98
|
+
def recursive_copy_hash(hash, &pair_modifier)
|
99
|
+
hash.inject({}) do |result, pair|
|
100
|
+
value = pair.last
|
101
|
+
value = recursive_copy_hash(value, &pair_modifier) if value.is_a? Hash
|
102
|
+
key, value = pair_modifier.call(pair.first, value)
|
103
|
+
result[key] = value
|
104
|
+
result
|
105
|
+
end
|
106
|
+
end
|
107
107
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
108
|
+
def pluralize_unit(value, unit)
|
109
|
+
if %w{hour day}.include?(unit) && value > 1
|
110
|
+
unit = unit + 's'
|
111
|
+
end
|
112
|
+
unit
|
113
|
+
end
|
114
114
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
115
|
+
def indexes_of_filled_matches(match_data)
|
116
|
+
if match_data.size > 1
|
117
|
+
(1...match_data.size).to_a.reject { |i| match_data[i].nil? }
|
118
|
+
else
|
119
|
+
[0]
|
120
|
+
end
|
121
|
+
end
|
120
122
|
end
|
121
123
|
end
|
122
124
|
end
|
data/lib/tweetwine/twitter.rb
CHANGED
@@ -184,8 +184,8 @@ module Tweetwine
|
|
184
184
|
status.dup
|
185
185
|
end
|
186
186
|
status.strip!
|
187
|
-
shorten_urls_in
|
188
|
-
truncate_status
|
187
|
+
shorten_urls_in status if CLI.config[:shorten_urls] && !CLI.config[:shorten_urls][:disable]
|
188
|
+
truncate_status status if status.length > MAX_STATUS_LENGTH
|
189
189
|
status
|
190
190
|
end
|
191
191
|
|
@@ -193,9 +193,12 @@ module Tweetwine
|
|
193
193
|
url_pairs = Uri.
|
194
194
|
extract(status, %w{http https}).
|
195
195
|
uniq.
|
196
|
-
map { |
|
197
|
-
|
198
|
-
|
196
|
+
map { |url| [ url, CLI.url_shortener.shorten(url) ] }
|
197
|
+
failed, succeeded = *url_pairs.partition do |(full_url, short_url)|
|
198
|
+
Support.blank? short_url or full_url == short_url
|
199
|
+
end
|
200
|
+
failed.each { |(full_url, _)| CLI.ui.warn "No short URL for #{full_url}" }
|
201
|
+
succeeded.each { |(full_url, short_url)| status.gsub! full_url, short_url }
|
199
202
|
rescue HttpError, LoadError => e
|
200
203
|
CLI.ui.warn "#{e}\nSkipping URL shortening..."
|
201
204
|
end
|
data/lib/tweetwine/version.rb
CHANGED
data/lib/tweetwine.rb
CHANGED
data/man/tweetwine.7
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
.\" generated with Ronn/v0.7.3
|
2
2
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
3
3
|
.
|
4
|
-
.TH "TWEETWINE" "7" "
|
4
|
+
.TH "TWEETWINE" "7" "November 2011" "Tuomas Kareinen" "Tweetwine Manual"
|
5
5
|
.
|
6
6
|
.SH "DESCRIPTION"
|
7
7
|
Tweetwine shows the latest tweets from the command line quickly\.
|
@@ -40,7 +40,7 @@ $ gem install tweetwine
|
|
40
40
|
.IP "" 0
|
41
41
|
.
|
42
42
|
.P
|
43
|
-
The program is tested with
|
43
|
+
The program is tested with MRI 1\.8\.7, 1\.9\.2, and 1\.9\.3\.
|
44
44
|
.
|
45
45
|
.P
|
46
46
|
The program requires oauth \fIhttp://oauth\.rubyforge\.org/\fR gem to be installed\. In addition, the program needs a JSON parser library, such as json \fIhttp://json\.rubyforge\.org/\fR gem, on Ruby 1\.8\.
|
@@ -130,7 +130,7 @@ show_reverse: true
|
|
130
130
|
shorten_urls:
|
131
131
|
service_url: http://is\.gd/create\.php
|
132
132
|
method: post
|
133
|
-
url_param_name:
|
133
|
+
url_param_name: url
|
134
134
|
xpath_selector: //input[@id=\'short_url\']/@value
|
135
135
|
disable: false # optional
|
136
136
|
.
|
data/man/tweetwine.7.ronn
CHANGED
@@ -24,7 +24,7 @@ Install Tweetwine with RubyGems:
|
|
24
24
|
|
25
25
|
$ gem install tweetwine
|
26
26
|
|
27
|
-
The program is tested with
|
27
|
+
The program is tested with MRI 1.8.7, 1.9.2, and 1.9.3.
|
28
28
|
|
29
29
|
The program requires [oauth](http://oauth.rubyforge.org/) gem to be installed.
|
30
30
|
In addition, the program needs a JSON parser library, such as
|
@@ -81,7 +81,7 @@ enabled via `shorten_urls` field in the configuration file; for example:
|
|
81
81
|
shorten_urls:
|
82
82
|
service_url: http://is.gd/create.php
|
83
83
|
method: post
|
84
|
-
url_param_name:
|
84
|
+
url_param_name: url
|
85
85
|
xpath_selector: //input[@id='short_url']/@value
|
86
86
|
disable: false # optional
|
87
87
|
|
data/project.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
3
|
name = 'tweetwine'
|
4
|
+
# Add lib dir to $LOAD_PATH so that `require 'tweetwine/version'`
|
5
|
+
# (executed in tests) loads the version file only once on MRI 1.8.7.
|
4
6
|
$LOAD_PATH.unshift File.expand_path('lib', File.dirname(__FILE__))
|
5
7
|
require "#{name}/version"
|
6
8
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'support/integration_test_case'
|
4
4
|
require 'yaml'
|
5
5
|
|
6
6
|
module Tweetwine::Test::Integration
|
@@ -8,17 +8,14 @@ module Tweetwine::Test::Integration
|
|
8
8
|
class UpdateStatusTest < TestCase
|
9
9
|
RUBYGEMS_FIXTURE = fixture_file 'shorten_rubygems.html'
|
10
10
|
RUBYGEMS_FULL_URL = 'http://rubygems.org/'
|
11
|
-
RUBYGEMS_FULL_URL_ENC = 'http%3a%2f%2frubygems.org%2f'
|
12
11
|
RUBYGEMS_SHORT_URL = 'http://is.gd/gGazV'
|
13
|
-
RUBYGEMS_SHORT_URL_ENC = 'http%3a%2f%2fis.gd%2fgGazV'
|
14
12
|
RUBYLANG_FIXTURE = fixture_file 'shorten_rubylang.html'
|
15
13
|
RUBYLANG_FULL_URL = 'http://ruby-lang.org/'
|
16
|
-
RUBYLANG_FULL_URL_ENC = 'http%3a%2f%2fruby-lang.org%2f'
|
17
14
|
RUBYLANG_SHORT_URL = 'http://is.gd/gGaM3'
|
18
|
-
RUBYLANG_SHORT_URL_ENC = 'http%3a%2f%2fis.gd%2fgGaM3'
|
19
15
|
SHORTEN_CONFIG = read_shorten_config
|
20
16
|
SHORTEN_METHOD = SHORTEN_CONFIG[:method].to_sym
|
21
17
|
STATUS_WITH_FULL_URLS = "ruby links: #{RUBYGEMS_FULL_URL} #{RUBYLANG_FULL_URL}"
|
18
|
+
STATUS_WITH_MIXED_URLS = "ruby links: #{RUBYGEMS_SHORT_URL} #{RUBYLANG_FULL_URL}"
|
22
19
|
STATUS_WITH_SHORT_URLS = "ruby links: #{RUBYGEMS_SHORT_URL} #{RUBYLANG_SHORT_URL}"
|
23
20
|
STATUS_WITHOUT_URLS = "bored. going to sleep."
|
24
21
|
UPDATE_FIXTURE_WITH_URLS = fixture_file 'update_with_urls.json'
|
@@ -26,8 +23,9 @@ class UpdateStatusTest < TestCase
|
|
26
23
|
UPDATE_FIXTURE_UTF8 = fixture_file 'update_utf8.json'
|
27
24
|
UPDATE_URL = "https://api.twitter.com/1/statuses/update.json"
|
28
25
|
|
29
|
-
BODY_WITH_SHORT_URLS =
|
30
|
-
|
26
|
+
BODY_WITH_SHORT_URLS = { 'status' => STATUS_WITH_SHORT_URLS }
|
27
|
+
BODY_WITH_MIXED_URLS = { 'status' => STATUS_WITH_MIXED_URLS }
|
28
|
+
BODY_WITHOUT_URLS = { 'status' => STATUS_WITHOUT_URLS }
|
31
29
|
|
32
30
|
describe "update my status from command line with colorization disabled" do
|
33
31
|
before do
|
@@ -111,8 +109,7 @@ class UpdateStatusTest < TestCase
|
|
111
109
|
before do
|
112
110
|
@status_utf8 = "résumé"
|
113
111
|
@status_latin1 = @status_utf8.encode('ISO-8859-1')
|
114
|
-
|
115
|
-
stub_http_request(:post, UPDATE_URL).with(:body => url_encoded_body).to_return(:body => UPDATE_FIXTURE_UTF8)
|
112
|
+
stub_http_request(:post, UPDATE_URL).with(:body => { 'status' => @status_utf8 }).to_return(:body => UPDATE_FIXTURE_UTF8)
|
116
113
|
at_snapshot do
|
117
114
|
@output = start_cli %W{--no-colors update #{@status_latin1}}, %w{y}
|
118
115
|
end
|
@@ -131,8 +128,7 @@ class UpdateStatusTest < TestCase
|
|
131
128
|
before do
|
132
129
|
@status_latin1 = "r\xe9sum\xe9"
|
133
130
|
@status_utf8 = "r\xc3\xa9sum\xc3\xa9"
|
134
|
-
|
135
|
-
stub_http_request(:post, UPDATE_URL).with(:body => url_encoded_body).to_return(:body => UPDATE_FIXTURE_UTF8)
|
131
|
+
stub_http_request(:post, UPDATE_URL).with(:body => { 'status' => @status_utf8 }).to_return(:body => UPDATE_FIXTURE_UTF8)
|
136
132
|
tmp_kcode('NONE') do
|
137
133
|
tmp_env(:LANG => 'latin1') do
|
138
134
|
Tweetwine::CharacterEncoding.forget_guess
|
@@ -153,14 +149,7 @@ class UpdateStatusTest < TestCase
|
|
153
149
|
|
154
150
|
describe "shorten URLs in status update" do
|
155
151
|
before do
|
156
|
-
|
157
|
-
@shorten_rubylang_body = "#{SHORTEN_CONFIG[:url_param_name]}=#{RUBYLANG_FULL_URL_ENC}"
|
158
|
-
stub_http_request(SHORTEN_METHOD, SHORTEN_CONFIG[:service_url]).
|
159
|
-
with(:body => @shorten_rubygems_body).
|
160
|
-
to_return(:body => RUBYGEMS_FIXTURE)
|
161
|
-
stub_http_request(SHORTEN_METHOD, SHORTEN_CONFIG[:service_url]).
|
162
|
-
with(:body => @shorten_rubylang_body).
|
163
|
-
to_return(:body => RUBYLANG_FIXTURE)
|
152
|
+
stub_url_shortening(:rubygems => RUBYGEMS_FIXTURE, :rubylang => RUBYLANG_FIXTURE)
|
164
153
|
stub_http_request(:post, UPDATE_URL).
|
165
154
|
with(:body => BODY_WITH_SHORT_URLS).
|
166
155
|
to_return(:body => UPDATE_FIXTURE_WITH_URLS)
|
@@ -170,14 +159,31 @@ class UpdateStatusTest < TestCase
|
|
170
159
|
end
|
171
160
|
|
172
161
|
it "shortens the URLs in the status before sending it" do
|
173
|
-
assert_requested(SHORTEN_METHOD, SHORTEN_CONFIG[:service_url], :body => @
|
174
|
-
assert_requested(SHORTEN_METHOD, SHORTEN_CONFIG[:service_url], :body => @
|
162
|
+
assert_requested(SHORTEN_METHOD, SHORTEN_CONFIG[:service_url], :body => @request_bodies[:rubygems])
|
163
|
+
assert_requested(SHORTEN_METHOD, SHORTEN_CONFIG[:service_url], :body => @request_bodies[:rubylang])
|
175
164
|
@output[1].must_equal STATUS_WITH_SHORT_URLS
|
176
165
|
@output[5].must_equal "#{USER}, 9 hours ago:"
|
177
166
|
@output[6].must_equal STATUS_WITH_SHORT_URLS
|
178
167
|
end
|
179
168
|
end
|
180
169
|
|
170
|
+
describe "warn if URL shortening results in no shortened URL in status update" do
|
171
|
+
before do
|
172
|
+
stub_url_shortening(:rubygems => RUBYGEMS_FIXTURE, :rubylang => '')
|
173
|
+
stub_http_request(:post, UPDATE_URL).
|
174
|
+
with(:body => BODY_WITH_MIXED_URLS).
|
175
|
+
to_return(:body => UPDATE_FIXTURE_WITH_URLS)
|
176
|
+
at_snapshot do
|
177
|
+
@output = start_cli %W{--no-colors update #{STATUS_WITH_FULL_URLS}}, %w{y}
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
it "warns which URL was not shortened, falling back to using the original URL" do
|
182
|
+
@output[0].must_equal "Warning: No short URL for #{RUBYLANG_FULL_URL}"
|
183
|
+
@output[2].must_equal STATUS_WITH_MIXED_URLS
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
181
187
|
describe "disable URL shortening for status updates" do
|
182
188
|
before do
|
183
189
|
stub_http_request(:post, UPDATE_URL).
|
@@ -194,6 +200,21 @@ class UpdateStatusTest < TestCase
|
|
194
200
|
@output[6].must_equal STATUS_WITH_SHORT_URLS
|
195
201
|
end
|
196
202
|
end
|
203
|
+
|
204
|
+
private
|
205
|
+
|
206
|
+
def stub_url_shortening(response_bodies)
|
207
|
+
@request_bodies = {
|
208
|
+
:rubygems => { SHORTEN_CONFIG[:url_param_name] => RUBYGEMS_FULL_URL },
|
209
|
+
:rubylang => { SHORTEN_CONFIG[:url_param_name] => RUBYLANG_FULL_URL }
|
210
|
+
}
|
211
|
+
stub_http_request(SHORTEN_METHOD, SHORTEN_CONFIG[:service_url]).
|
212
|
+
with(:body => @request_bodies[:rubygems]).
|
213
|
+
to_return(:body => response_bodies[:rubygems])
|
214
|
+
stub_http_request(SHORTEN_METHOD, SHORTEN_CONFIG[:service_url]).
|
215
|
+
with(:body => @request_bodies[:rubylang]).
|
216
|
+
to_return(:body => response_bodies[:rubylang])
|
217
|
+
end
|
197
218
|
end
|
198
219
|
|
199
220
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'support/integration_test_case'
|
4
4
|
|
5
5
|
module Tweetwine::Test::Integration
|
6
6
|
|
@@ -22,7 +22,7 @@ class UseHttpProxyTest < TestCase
|
|
22
22
|
end
|
23
23
|
|
24
24
|
it "uses the proxy to fetch my home timeline" do
|
25
|
-
|
25
|
+
assert_use_proxy
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -33,7 +33,7 @@ class UseHttpProxyTest < TestCase
|
|
33
33
|
end
|
34
34
|
|
35
35
|
it "uses the proxy to fetch my home timeline" do
|
36
|
-
|
36
|
+
assert_use_proxy
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
@@ -50,16 +50,16 @@ class UseHttpProxyTest < TestCase
|
|
50
50
|
|
51
51
|
private
|
52
52
|
|
53
|
-
def
|
53
|
+
def assert_use_proxy
|
54
54
|
nh = net_http
|
55
|
-
nh.proxy_class
|
55
|
+
assert nh.proxy_class?
|
56
56
|
nh.instance_variable_get(:@proxy_address).must_equal PROXY_HOST
|
57
57
|
nh.instance_variable_get(:@proxy_port).must_equal PROXY_PORT
|
58
58
|
assert_requested(:get, HOME_URL)
|
59
59
|
end
|
60
60
|
|
61
61
|
def refute_use_proxy
|
62
|
-
net_http.proxy_class
|
62
|
+
refute net_http.proxy_class?
|
63
63
|
assert_requested(:get, HOME_URL)
|
64
64
|
end
|
65
65
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'support/integration_test_case'
|
4
4
|
|
5
5
|
module Tweetwine::Test::Integration
|
6
6
|
|
@@ -14,7 +14,7 @@ class UserHelpTest < TestCase
|
|
14
14
|
end
|
15
15
|
|
16
16
|
it "shows version and exists with success status" do
|
17
|
-
@output.must_match(/\d+\.\d+\.\d
|
17
|
+
@output.must_match(/\d+\.\d+\.\d+[\w\.]*$/)
|
18
18
|
@status.exitstatus.must_equal 0
|
19
19
|
end
|
20
20
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Tweetwine::Test
|
4
|
+
module Assertions
|
5
|
+
# Asserts whether an Enumeration-like object contains all the elements.
|
6
|
+
# Fails unless +actual+ contains the same elements as +expected+,
|
7
|
+
# ignoring the order of the elements.
|
8
|
+
def assert_contains_exactly(expected, actual, msg_diff_size = nil, msg_diff_elems = nil)
|
9
|
+
assert_equal(expected.size, actual.size, message(msg_diff_size) {
|
10
|
+
'Expected %s to be of same size as %s' % [actual.inspect, expected.inspect]
|
11
|
+
})
|
12
|
+
assert(Assertions.enumerable_minus_each_element(actual, expected).empty?, message(msg_diff_elems) {
|
13
|
+
'Expected %s to contain all the elements of %s' % [actual.inspect, expected.inspect]
|
14
|
+
})
|
15
|
+
end
|
16
|
+
|
17
|
+
# Fails unless +str+ is a full match to +regex+.
|
18
|
+
def assert_full_match(regex, str, msg = nil)
|
19
|
+
match_data = regex.match(str)
|
20
|
+
assert(str == match_data.to_s, message(msg) {
|
21
|
+
'Expected %s to be a full match to %s' % [str, regex.inspect]
|
22
|
+
})
|
23
|
+
end
|
24
|
+
|
25
|
+
# Fails if +str+ is a full match to +regex+.
|
26
|
+
def assert_no_full_match(regex, str, msg = nil)
|
27
|
+
match_data = regex.match(str)
|
28
|
+
assert(str != match_data.to_s, message(msg) {
|
29
|
+
'Expected %s not to be a full match to %s' % [str, regex.inspect]
|
30
|
+
})
|
31
|
+
end
|
32
|
+
|
33
|
+
# Fails unless +fun.call(*args)+ is equal to +expected+ and
|
34
|
+
# +fun.call(*args)+ is equal to +fun.call(*args.reverse)+.
|
35
|
+
def assert_commutative(expected, args, msg_not_expected = nil, msg_not_commutative = nil, &fun)
|
36
|
+
left_args = args
|
37
|
+
left_actual = fun.call(left_args)
|
38
|
+
assert_equal(expected, left_actual, message(msg_not_expected) {
|
39
|
+
'Expected %s, not %s' % [expected.inspect, left_actual.inspect]
|
40
|
+
})
|
41
|
+
right_args = args.reverse
|
42
|
+
right_actual = fun.call(*right_args)
|
43
|
+
assert_equal(left_actual, right_actual, message(msg_not_commutative) {
|
44
|
+
'Expected fun%s => %s to be commutative with fun%s => %s' %
|
45
|
+
[left_args.inspect, left_actual.inspect, right_args.inspect, right_actual.inspect]
|
46
|
+
})
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.enumerable_minus_each_element(enumerable, elements)
|
50
|
+
remaining = enumerable.dup.to_a
|
51
|
+
elements.each do |e|
|
52
|
+
index = remaining.index(e)
|
53
|
+
remaining.delete_at(index) if index
|
54
|
+
end
|
55
|
+
remaining
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|