tweetwine 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +6 -0
- data/Rakefile +22 -23
- data/lib/tweetwine/cli.rb +167 -165
- data/lib/tweetwine/config.rb +3 -2
- data/lib/tweetwine/exceptions.rb +1 -0
- data/lib/tweetwine/version.rb +1 -1
- data/project.rb +16 -16
- data/test/fixture/{config_example.yaml → config_integration.yaml} +0 -0
- data/test/fixture/oauth.rb +11 -11
- data/test/{test_helper.rb → helper.rb} +16 -7
- data/test/{example/authorization_example.rb → integration/authorization_test.rb} +17 -17
- data/test/integration/global_options_test.rb +67 -0
- data/test/integration/helper.rb +70 -0
- data/test/integration/invalid_config_file_test.rb +28 -0
- data/test/integration/search_statuses_test.rb +81 -0
- data/test/integration/show_followers_test.rb +24 -0
- data/test/integration/show_friends_test.rb +24 -0
- data/test/integration/show_home_test.rb +47 -0
- data/test/integration/show_mentions_test.rb +24 -0
- data/test/integration/show_user_test.rb +48 -0
- data/test/integration/update_status_test.rb +199 -0
- data/test/integration/use_http_proxy_test.rb +71 -0
- data/test/{example/user_help_example.rb → integration/user_help_test.rb} +36 -36
- data/test/unit/character_encoding_test.rb +19 -15
- data/test/unit/cli_test.rb +9 -10
- data/test/unit/config_test.rb +73 -71
- data/test/unit/helper.rb +108 -0
- data/test/unit/http_test.rb +39 -39
- data/test/unit/oauth_test.rb +15 -16
- data/test/unit/obfuscate_test.rb +4 -4
- data/test/unit/option_parser_test.rb +12 -12
- data/test/unit/promise_test.rb +10 -10
- data/test/unit/support_test.rb +44 -45
- data/test/unit/tweet_helper.rb +1 -1
- data/test/unit/tweet_test.rb +42 -42
- data/test/unit/twitter_test.rb +300 -303
- data/test/unit/ui_test.rb +310 -312
- data/test/unit/uri_test.rb +7 -7
- data/test/unit/url_shortener_test.rb +77 -79
- data/tweetwine.gemspec +6 -15
- metadata +55 -145
- data/test/example/example_helper.rb +0 -58
- data/test/example/global_options_example.rb +0 -64
- data/test/example/search_statuses_example.rb +0 -76
- data/test/example/show_followers_example.rb +0 -24
- data/test/example/show_friends_example.rb +0 -24
- data/test/example/show_home_example.rb +0 -44
- data/test/example/show_mentions_example.rb +0 -24
- data/test/example/show_user_example.rb +0 -44
- data/test/example/update_status_example.rb +0 -183
- data/test/example/use_http_proxy_example.rb +0 -68
- data/test/unit/unit_helper.rb +0 -111
data/test/unit/twitter_test.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'unit/helper'
|
4
4
|
|
5
|
-
module Tweetwine::Test
|
5
|
+
module Tweetwine::Test::Unit
|
6
6
|
|
7
|
-
class ClientTest <
|
8
|
-
|
7
|
+
class ClientTest < TestCase
|
8
|
+
before do
|
9
9
|
@config = {
|
10
10
|
:num_tweets => 20,
|
11
11
|
:page => 1
|
@@ -13,38 +13,38 @@ class ClientTest < UnitTestCase
|
|
13
13
|
stub_config @config
|
14
14
|
end
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
describe "for initialization" do
|
17
|
+
it "uses default number of statuses if not configured" do
|
18
18
|
@twitter = Twitter.new
|
19
19
|
assert_equal @config[:num_tweets], @twitter.num_tweets
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
it "uses configured number of statuses if in allowed range" do
|
23
23
|
@twitter = Twitter.new(:num_tweets => 12)
|
24
24
|
assert_equal 12, @twitter.num_tweets
|
25
25
|
end
|
26
26
|
|
27
|
-
|
28
|
-
|
27
|
+
it "raises exception if configured number of status not in allowed range" do
|
28
|
+
assert_raises(CommandLineError) { Twitter.new(:num_tweets => 0) }
|
29
29
|
end
|
30
30
|
|
31
|
-
|
31
|
+
it "uses default page number if not configured otherwise" do
|
32
32
|
@twitter = Twitter.new
|
33
33
|
assert_equal @config[:page], @twitter.page
|
34
34
|
end
|
35
35
|
|
36
|
-
|
36
|
+
it "uses configured page number if in allowed range" do
|
37
37
|
@twitter = Twitter.new(:page => 12)
|
38
38
|
assert_equal 12, @twitter.page
|
39
39
|
end
|
40
40
|
|
41
|
-
|
42
|
-
|
41
|
+
it "raises exception if configured page number not in allowed range" do
|
42
|
+
assert_raises(CommandLineError) { Twitter.new(:page => 0) }
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
|
47
|
-
|
46
|
+
describe "at runtime" do
|
47
|
+
before do
|
48
48
|
mock_http
|
49
49
|
mock_oauth
|
50
50
|
mock_ui
|
@@ -58,7 +58,7 @@ class ClientTest < UnitTestCase
|
|
58
58
|
@search_api_query_str = "page=#{@config[:page]}&rpp=#{@config[:num_tweets]}"
|
59
59
|
end
|
60
60
|
|
61
|
-
|
61
|
+
it "skips showing an invalid tweet" do
|
62
62
|
invalid_from_user = nil
|
63
63
|
twitter_records, internal_records = create_rest_api_status_records(
|
64
64
|
{
|
@@ -79,7 +79,7 @@ class ClientTest < UnitTestCase
|
|
79
79
|
@twitter.home
|
80
80
|
end
|
81
81
|
|
82
|
-
|
82
|
+
it "fetches friends' statuses (home view)" do
|
83
83
|
twitter_records, internal_records = create_rest_api_status_records(
|
84
84
|
{
|
85
85
|
:from_user => "zanzibar",
|
@@ -98,7 +98,7 @@ class ClientTest < UnitTestCase
|
|
98
98
|
@twitter.home
|
99
99
|
end
|
100
100
|
|
101
|
-
|
101
|
+
it "fetches mentions" do
|
102
102
|
twitter_records, internal_records = create_rest_api_status_records(
|
103
103
|
{
|
104
104
|
:from_user => "zanzibar",
|
@@ -119,7 +119,7 @@ class ClientTest < UnitTestCase
|
|
119
119
|
@twitter.mentions
|
120
120
|
end
|
121
121
|
|
122
|
-
|
122
|
+
it "fetches a specific user's statuses, when user is given as argument" do
|
123
123
|
username = "spoonman"
|
124
124
|
twitter_records, internal_records = create_rest_api_status_records({
|
125
125
|
:from_user => username,
|
@@ -133,7 +133,7 @@ class ClientTest < UnitTestCase
|
|
133
133
|
@twitter.user(username)
|
134
134
|
end
|
135
135
|
|
136
|
-
|
136
|
+
it "fetches a specific user's statuses, with user being the authenticated user itself when given no argument" do
|
137
137
|
twitter_records, internal_records = create_rest_api_status_records({
|
138
138
|
:from_user => @username,
|
139
139
|
:status => "wassup?"
|
@@ -146,30 +146,197 @@ class ClientTest < UnitTestCase
|
|
146
146
|
@twitter.user
|
147
147
|
end
|
148
148
|
|
149
|
-
|
150
|
-
|
151
|
-
|
149
|
+
it "posts a status update via argument, when positive confirmation" do
|
150
|
+
status = "wondering around"
|
151
|
+
twitter_records, internal_records = create_rest_api_status_records({
|
152
|
+
:from_user => @username,
|
153
|
+
:status => status
|
154
|
+
})
|
155
|
+
@oauth.expects(:request_signer)
|
156
|
+
http_subresource = mock
|
157
|
+
http_subresource.expects(:post).
|
158
|
+
with({ :status => status }).
|
159
|
+
returns(twitter_records[0].to_json)
|
160
|
+
@rest_api.expects(:[]).
|
161
|
+
with("statuses/update.json").
|
162
|
+
returns(http_subresource)
|
163
|
+
@ui.expects(:confirm).with("Really send?").returns(true)
|
164
|
+
@ui.expects(:show_status_preview).with(status)
|
165
|
+
@ui.expects(:info).with("Sent status update.\n\n")
|
166
|
+
@ui.expects(:show_tweets).with(internal_records)
|
167
|
+
@twitter.update(status)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "posts a status update via prompt, when positive confirmation" do
|
171
|
+
status = "wondering around"
|
172
|
+
twitter_records, internal_records = create_rest_api_status_records({
|
173
|
+
:from_user => @username,
|
174
|
+
:status => status
|
175
|
+
})
|
176
|
+
@oauth.expects(:request_signer)
|
177
|
+
http_subresource = mock
|
178
|
+
http_subresource.expects(:post).
|
179
|
+
with({ :status => status }).
|
180
|
+
returns(twitter_records[0].to_json)
|
181
|
+
@rest_api.expects(:[]).
|
182
|
+
with("statuses/update.json").
|
183
|
+
returns(http_subresource)
|
184
|
+
@ui.expects(:prompt).with("Status update").returns(status)
|
185
|
+
@ui.expects(:show_status_preview).with(status)
|
186
|
+
@ui.expects(:confirm).with("Really send?").returns(true)
|
187
|
+
@ui.expects(:info).with("Sent status update.\n\n")
|
188
|
+
@ui.expects(:show_tweets).with(internal_records)
|
189
|
+
@twitter.update
|
190
|
+
end
|
191
|
+
|
192
|
+
it "cancels a status update via argument, when negative confirmation" do
|
193
|
+
status = "wondering around"
|
194
|
+
@rest_api.expects(:[]).never
|
195
|
+
@ui.expects(:show_status_preview).with(status)
|
196
|
+
@ui.expects(:confirm).with("Really send?").returns(false)
|
197
|
+
@ui.expects(:info).with("Cancelled.")
|
198
|
+
@ui.expects(:show_tweets).never
|
199
|
+
@twitter.update(status)
|
200
|
+
end
|
201
|
+
|
202
|
+
it "cancels a status update via prompt, when negative confirmation" do
|
203
|
+
status = "wondering around"
|
204
|
+
@rest_api.expects(:[]).never
|
205
|
+
@ui.expects(:prompt).with("Status update").returns(status)
|
206
|
+
@ui.expects(:show_status_preview).with(status)
|
207
|
+
@ui.expects(:confirm).with("Really send?").returns(false)
|
208
|
+
@ui.expects(:info).with("Cancelled.")
|
209
|
+
@ui.expects(:show_tweets).never
|
210
|
+
@twitter.update
|
211
|
+
end
|
212
|
+
|
213
|
+
it "cancels a status update via argument, when empty status" do
|
214
|
+
@rest_api.expects(:[]).never
|
215
|
+
@ui.expects(:prompt).with("Status update").returns("")
|
216
|
+
@ui.expects(:confirm).never
|
217
|
+
@ui.expects(:info).with("Cancelled.")
|
218
|
+
@ui.expects(:show_tweets).never
|
219
|
+
@twitter.update("")
|
220
|
+
end
|
221
|
+
|
222
|
+
it "cancels a status update via prompt, when empty status" do
|
223
|
+
@rest_api.expects(:[]).never
|
224
|
+
@ui.expects(:prompt).with("Status update").returns("")
|
225
|
+
@ui.expects(:confirm).never
|
226
|
+
@ui.expects(:info).with("Cancelled.")
|
227
|
+
@ui.expects(:show_tweets).never
|
228
|
+
@twitter.update
|
229
|
+
end
|
230
|
+
|
231
|
+
it "removes excess whitespace around a status update" do
|
232
|
+
whitespaced_status = " oh, i was sloppy \t "
|
233
|
+
stripped_status = "oh, i was sloppy"
|
234
|
+
twitter_records, internal_records = create_rest_api_status_records({
|
235
|
+
:from_user => @username,
|
236
|
+
:status => stripped_status
|
237
|
+
})
|
238
|
+
@oauth.expects(:request_signer)
|
239
|
+
http_subresource = mock
|
240
|
+
http_subresource.expects(:post).
|
241
|
+
with({ :status => stripped_status }).
|
242
|
+
returns(twitter_records[0].to_json)
|
243
|
+
@rest_api.expects(:[]).
|
244
|
+
with("statuses/update.json").
|
245
|
+
returns(http_subresource)
|
246
|
+
@ui.expects(:show_status_preview).with(stripped_status)
|
247
|
+
@ui.expects(:confirm).with("Really send?").returns(true)
|
248
|
+
@ui.expects(:info).with("Sent status update.\n\n")
|
249
|
+
@ui.expects(:show_tweets).with(internal_records)
|
250
|
+
@twitter.update(whitespaced_status)
|
251
|
+
end
|
252
|
+
|
253
|
+
it "truncates a status update with too long argument and warn the user" do
|
254
|
+
truncated_status = "ab c" * 35 # 4 * 35 = 140
|
255
|
+
long_status = "#{truncated_status} dd"
|
256
|
+
twitter_records, internal_records = create_rest_api_status_records({
|
257
|
+
:from_user => @username,
|
258
|
+
:status => truncated_status
|
259
|
+
})
|
260
|
+
@oauth.expects(:request_signer)
|
261
|
+
http_subresource = mock
|
262
|
+
http_subresource.expects(:post).
|
263
|
+
with({ :status => truncated_status }).
|
264
|
+
returns(twitter_records[0].to_json)
|
265
|
+
@rest_api.expects(:[]).
|
266
|
+
with("statuses/update.json").
|
267
|
+
returns(http_subresource)
|
268
|
+
@ui.expects(:warn).with("Status will be truncated.")
|
269
|
+
@ui.expects(:show_status_preview).with(truncated_status)
|
270
|
+
@ui.expects(:confirm).with("Really send?").returns(true)
|
271
|
+
@ui.expects(:info).with("Sent status update.\n\n")
|
272
|
+
@ui.expects(:show_tweets).with(internal_records)
|
273
|
+
@twitter.update(long_status)
|
274
|
+
end
|
275
|
+
|
276
|
+
if defined? Encoding
|
277
|
+
it "encodes status in UTF-8 (String supports encoding)" do
|
278
|
+
status_utf8, status_latin1 = "résumé", "résumé".encode('ISO-8859-1')
|
152
279
|
twitter_records, internal_records = create_rest_api_status_records({
|
153
280
|
:from_user => @username,
|
154
|
-
:status =>
|
281
|
+
:status => status_utf8
|
155
282
|
})
|
156
283
|
@oauth.expects(:request_signer)
|
157
284
|
http_subresource = mock
|
158
285
|
http_subresource.expects(:post).
|
159
|
-
with({ :status =>
|
286
|
+
with({ :status => status_utf8 }).
|
160
287
|
returns(twitter_records[0].to_json)
|
161
288
|
@rest_api.expects(:[]).
|
162
289
|
with("statuses/update.json").
|
163
290
|
returns(http_subresource)
|
164
291
|
@ui.expects(:confirm).with("Really send?").returns(true)
|
165
|
-
@ui.expects(:show_status_preview).with(
|
292
|
+
@ui.expects(:show_status_preview).with(status_latin1)
|
166
293
|
@ui.expects(:info).with("Sent status update.\n\n")
|
167
294
|
@ui.expects(:show_tweets).with(internal_records)
|
168
|
-
@twitter.update(
|
295
|
+
@twitter.update(status_latin1)
|
296
|
+
end
|
297
|
+
else
|
298
|
+
it "encodes status in UTF-8 (String does not support encoding)" do
|
299
|
+
CharacterEncoding.forget_guess
|
300
|
+
tmp_kcode('NONE') do
|
301
|
+
tmp_env(:LANG => 'ISO-8859-1') do
|
302
|
+
status_utf8, status_latin1 = "r\xc3\xa9sum\xc3\xa9", "r\xe9sum\xe9"
|
303
|
+
twitter_records, internal_records = create_rest_api_status_records({
|
304
|
+
:from_user => @username,
|
305
|
+
:status => status_utf8
|
306
|
+
})
|
307
|
+
@oauth.expects(:request_signer)
|
308
|
+
http_subresource = mock
|
309
|
+
http_subresource.expects(:post).
|
310
|
+
with({ :status => status_utf8 }).
|
311
|
+
returns(twitter_records[0].to_json)
|
312
|
+
@rest_api.expects(:[]).
|
313
|
+
with("statuses/update.json").
|
314
|
+
returns(http_subresource)
|
315
|
+
@ui.expects(:confirm).with("Really send?").returns(true)
|
316
|
+
@ui.expects(:show_status_preview).with(status_latin1)
|
317
|
+
@ui.expects(:info).with("Sent status update.\n\n")
|
318
|
+
@ui.expects(:show_tweets).with(internal_records)
|
319
|
+
@twitter.update(status_latin1)
|
320
|
+
end
|
321
|
+
end
|
169
322
|
end
|
323
|
+
end
|
170
324
|
|
171
|
-
|
172
|
-
|
325
|
+
describe "with URL shortening" do
|
326
|
+
before do
|
327
|
+
mock_url_shortener
|
328
|
+
stub_config(
|
329
|
+
:shorten_urls => {
|
330
|
+
:service_url => "http://shorten.it/create",
|
331
|
+
:method => "post",
|
332
|
+
:url_param_name => "url",
|
333
|
+
:xpath_selector => "//input[@id='short_url']/@value"
|
334
|
+
})
|
335
|
+
end
|
336
|
+
|
337
|
+
it "does not shorten URLs if not configured" do
|
338
|
+
stub_config
|
339
|
+
status = "reading http://www.w3.org/TR/1999/REC-xpath-19991116"
|
173
340
|
twitter_records, internal_records = create_rest_api_status_records({
|
174
341
|
:from_user => @username,
|
175
342
|
:status => status
|
@@ -179,310 +346,142 @@ class ClientTest < UnitTestCase
|
|
179
346
|
http_subresource.expects(:post).
|
180
347
|
with({ :status => status }).
|
181
348
|
returns(twitter_records[0].to_json)
|
349
|
+
@url_shortener.expects(:shorten).never
|
182
350
|
@rest_api.expects(:[]).
|
183
351
|
with("statuses/update.json").
|
184
352
|
returns(http_subresource)
|
185
|
-
@ui.expects(:prompt).with("Status update").returns(status)
|
186
|
-
@ui.expects(:show_status_preview).with(status)
|
187
353
|
@ui.expects(:confirm).with("Really send?").returns(true)
|
354
|
+
@ui.expects(:show_status_preview).with(status)
|
188
355
|
@ui.expects(:info).with("Sent status update.\n\n")
|
189
356
|
@ui.expects(:show_tweets).with(internal_records)
|
190
|
-
@twitter.update
|
191
|
-
end
|
192
|
-
|
193
|
-
should "cancel a status update via argument, when negative confirmation" do
|
194
|
-
status = "wondering around"
|
195
|
-
@rest_api.expects(:[]).never
|
196
|
-
@ui.expects(:show_status_preview).with(status)
|
197
|
-
@ui.expects(:confirm).with("Really send?").returns(false)
|
198
|
-
@ui.expects(:info).with("Cancelled.")
|
199
|
-
@ui.expects(:show_tweets).never
|
200
357
|
@twitter.update(status)
|
201
358
|
end
|
202
359
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
@
|
218
|
-
|
219
|
-
|
220
|
-
@
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
@
|
225
|
-
@ui.expects(:
|
226
|
-
@
|
227
|
-
@ui.expects(:info).with("Cancelled.")
|
228
|
-
@ui.expects(:show_tweets).never
|
229
|
-
@twitter.update
|
360
|
+
it "shortens HTTP and HTTPS URLs" do
|
361
|
+
long_urls = ["http://www.google.fi/search?q=ruby+nokogiri&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a", "https://twitter.com/#!/messages"]
|
362
|
+
long_status = long_urls.join(" and ")
|
363
|
+
short_urls = ["http://shorten.it/2k7i8", "http://shorten.it/2k7mk"]
|
364
|
+
shortened_status = short_urls.join(" and ")
|
365
|
+
twitter_records, internal_records = create_rest_api_status_records({
|
366
|
+
:from_user => @username,
|
367
|
+
:status => shortened_status
|
368
|
+
})
|
369
|
+
@oauth.expects(:request_signer)
|
370
|
+
http_subresource = mock
|
371
|
+
http_subresource.expects(:post).
|
372
|
+
with({ :status => shortened_status }).
|
373
|
+
returns(twitter_records[0].to_json)
|
374
|
+
@rest_api.expects(:[]).
|
375
|
+
with("statuses/update.json").
|
376
|
+
returns(http_subresource)
|
377
|
+
@url_shortener.expects(:shorten).with(long_urls.first).returns(short_urls.first)
|
378
|
+
@url_shortener.expects(:shorten).with(long_urls.last).returns(short_urls.last)
|
379
|
+
@ui.expects(:show_status_preview).with(shortened_status)
|
380
|
+
@ui.expects(:confirm).with("Really send?").returns(true)
|
381
|
+
@ui.expects(:info).with("Sent status update.\n\n")
|
382
|
+
@ui.expects(:show_tweets).with(internal_records)
|
383
|
+
@twitter.update(long_status)
|
230
384
|
end
|
231
385
|
|
232
|
-
|
233
|
-
|
234
|
-
|
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, ""]
|
235
390
|
twitter_records, internal_records = create_rest_api_status_records({
|
236
391
|
:from_user => @username,
|
237
|
-
:status =>
|
392
|
+
:status => status
|
238
393
|
})
|
239
394
|
@oauth.expects(:request_signer)
|
240
395
|
http_subresource = mock
|
241
396
|
http_subresource.expects(:post).
|
242
|
-
with({ :status =>
|
397
|
+
with({ :status => status }).
|
243
398
|
returns(twitter_records[0].to_json)
|
244
399
|
@rest_api.expects(:[]).
|
245
400
|
with("statuses/update.json").
|
246
401
|
returns(http_subresource)
|
247
|
-
@
|
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)
|
248
405
|
@ui.expects(:confirm).with("Really send?").returns(true)
|
249
406
|
@ui.expects(:info).with("Sent status update.\n\n")
|
250
407
|
@ui.expects(:show_tweets).with(internal_records)
|
251
|
-
@twitter.update(
|
408
|
+
@twitter.update(status)
|
252
409
|
end
|
253
410
|
|
254
|
-
|
255
|
-
|
256
|
-
long_status = "
|
411
|
+
it "reuses a shortened URL for duplicate long URLs" do
|
412
|
+
long_urls = ["http://www.w3.org/TR/1999/REC-xpath-19991116"] * 2
|
413
|
+
long_status = long_urls.join(" and ")
|
414
|
+
short_url = "http://shorten.it/2k7mk"
|
415
|
+
short_status = ([short_url] * 2).join(" and ")
|
257
416
|
twitter_records, internal_records = create_rest_api_status_records({
|
258
417
|
:from_user => @username,
|
259
|
-
:status =>
|
418
|
+
:status => short_status
|
260
419
|
})
|
261
420
|
@oauth.expects(:request_signer)
|
262
421
|
http_subresource = mock
|
263
422
|
http_subresource.expects(:post).
|
264
|
-
with({ :status =>
|
423
|
+
with({ :status => short_status }).
|
265
424
|
returns(twitter_records[0].to_json)
|
266
425
|
@rest_api.expects(:[]).
|
267
426
|
with("statuses/update.json").
|
268
427
|
returns(http_subresource)
|
269
|
-
@
|
270
|
-
@ui.expects(:show_status_preview).with(
|
428
|
+
@url_shortener.expects(:shorten).with(long_urls.first).returns(short_url)
|
429
|
+
@ui.expects(:show_status_preview).with(short_status)
|
271
430
|
@ui.expects(:confirm).with("Really send?").returns(true)
|
272
431
|
@ui.expects(:info).with("Sent status update.\n\n")
|
273
432
|
@ui.expects(:show_tweets).with(internal_records)
|
274
433
|
@twitter.update(long_status)
|
275
434
|
end
|
276
435
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
436
|
+
describe "in erroneous situations" do
|
437
|
+
before do
|
438
|
+
@url = "http://www.w3.org/TR/1999/REC-xpath-19991116"
|
439
|
+
@status = "skimming through #{@url}"
|
440
|
+
@twitter_records, @internal_records = create_rest_api_status_records({
|
281
441
|
:from_user => @username,
|
282
|
-
:status =>
|
442
|
+
:status => @status
|
283
443
|
})
|
284
|
-
@oauth.expects(:request_signer)
|
285
|
-
http_subresource = mock
|
286
|
-
http_subresource.expects(:post).
|
287
|
-
with({ :status => status_utf8 }).
|
288
|
-
returns(twitter_records[0].to_json)
|
289
|
-
@rest_api.expects(:[]).
|
290
|
-
with("statuses/update.json").
|
291
|
-
returns(http_subresource)
|
292
|
-
@ui.expects(:confirm).with("Really send?").returns(true)
|
293
|
-
@ui.expects(:show_status_preview).with(status_latin1)
|
294
|
-
@ui.expects(:info).with("Sent status update.\n\n")
|
295
|
-
@ui.expects(:show_tweets).with(internal_records)
|
296
|
-
@twitter.update(status_latin1)
|
297
|
-
end
|
298
|
-
else
|
299
|
-
should "encode status in UTF-8 (String does not support encoding)" do
|
300
|
-
tmp_kcode('NONE') do
|
301
|
-
tmp_env(:LANG => 'ISO-8859-1') do
|
302
|
-
status_utf8, status_latin1 = "r\xc3\xa9sum\xc3\xa9", "r\xe9sum\xe9"
|
303
|
-
twitter_records, internal_records = create_rest_api_status_records({
|
304
|
-
:from_user => @username,
|
305
|
-
:status => status_utf8
|
306
|
-
})
|
307
|
-
@oauth.expects(:request_signer)
|
308
|
-
http_subresource = mock
|
309
|
-
http_subresource.expects(:post).
|
310
|
-
with({ :status => status_utf8 }).
|
311
|
-
returns(twitter_records[0].to_json)
|
312
|
-
@rest_api.expects(:[]).
|
313
|
-
with("statuses/update.json").
|
314
|
-
returns(http_subresource)
|
315
|
-
@ui.expects(:confirm).with("Really send?").returns(true)
|
316
|
-
@ui.expects(:show_status_preview).with(status_latin1)
|
317
|
-
@ui.expects(:info).with("Sent status update.\n\n")
|
318
|
-
@ui.expects(:show_tweets).with(internal_records)
|
319
|
-
@twitter.update(status_latin1)
|
320
|
-
end
|
321
|
-
end
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
|
-
context "with URL shortening" do
|
326
|
-
setup do
|
327
|
-
mock_url_shortener
|
328
|
-
stub_config(
|
329
|
-
:shorten_urls => {
|
330
|
-
:service_url => "http://shorten.it/create",
|
331
|
-
:method => "post",
|
332
|
-
:url_param_name => "url",
|
333
|
-
:xpath_selector => "//input[@id='short_url']/@value"
|
334
|
-
})
|
335
444
|
end
|
336
445
|
|
337
|
-
|
338
|
-
|
339
|
-
status = "reading http://www.w3.org/TR/1999/REC-xpath-19991116"
|
340
|
-
twitter_records, internal_records = create_rest_api_status_records({
|
341
|
-
:from_user => @username,
|
342
|
-
:status => status
|
343
|
-
})
|
344
|
-
@oauth.expects(:request_signer)
|
345
|
-
http_subresource = mock
|
346
|
-
http_subresource.expects(:post).
|
347
|
-
with({ :status => status }).
|
348
|
-
returns(twitter_records[0].to_json)
|
349
|
-
@url_shortener.expects(:shorten).never
|
350
|
-
@rest_api.expects(:[]).
|
351
|
-
with("statuses/update.json").
|
352
|
-
returns(http_subresource)
|
353
|
-
@ui.expects(:confirm).with("Really send?").returns(true)
|
354
|
-
@ui.expects(:show_status_preview).with(status)
|
355
|
-
@ui.expects(:info).with("Sent status update.\n\n")
|
356
|
-
@ui.expects(:show_tweets).with(internal_records)
|
357
|
-
@twitter.update(status)
|
358
|
-
end
|
359
|
-
|
360
|
-
should "shorten HTTP and HTTPS URLs" do
|
361
|
-
long_urls = ["http://www.google.fi/search?q=ruby+nokogiri&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a", "https://twitter.com/#!/messages"]
|
362
|
-
long_status = long_urls.join(" and ")
|
363
|
-
short_urls = ["http://shorten.it/2k7i8", "http://shorten.it/2k7mk"]
|
364
|
-
shortened_status = short_urls.join(" and ")
|
365
|
-
twitter_records, internal_records = create_rest_api_status_records({
|
366
|
-
:from_user => @username,
|
367
|
-
:status => shortened_status
|
368
|
-
})
|
369
|
-
@oauth.expects(:request_signer)
|
370
|
-
http_subresource = mock
|
371
|
-
http_subresource.expects(:post).
|
372
|
-
with({ :status => shortened_status }).
|
373
|
-
returns(twitter_records[0].to_json)
|
374
|
-
@rest_api.expects(:[]).
|
375
|
-
with("statuses/update.json").
|
376
|
-
returns(http_subresource)
|
377
|
-
@url_shortener.expects(:shorten).with(long_urls.first).returns(short_urls.first)
|
378
|
-
@url_shortener.expects(:shorten).with(long_urls.last).returns(short_urls.last)
|
379
|
-
@ui.expects(:show_status_preview).with(shortened_status)
|
380
|
-
@ui.expects(:confirm).with("Really send?").returns(true)
|
381
|
-
@ui.expects(:info).with("Sent status update.\n\n")
|
382
|
-
@ui.expects(:show_tweets).with(internal_records)
|
383
|
-
@twitter.update(long_status)
|
384
|
-
end
|
385
|
-
|
386
|
-
should "discard 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
|
-
})
|
446
|
+
it "skips shortening URLs if required libraries are not found" do
|
447
|
+
Tweetwine::CLI.stubs(:url_shortener).raises(LoadError, 'gem not found')
|
394
448
|
@oauth.expects(:request_signer)
|
395
449
|
http_subresource = mock
|
396
450
|
http_subresource.expects(:post).
|
397
|
-
with({ :status => status }).
|
398
|
-
returns(twitter_records[0].to_json)
|
451
|
+
with({ :status => @status }).
|
452
|
+
returns(@twitter_records[0].to_json)
|
399
453
|
@rest_api.expects(:[]).
|
400
454
|
with("statuses/update.json").
|
401
455
|
returns(http_subresource)
|
402
|
-
@
|
403
|
-
@
|
404
|
-
@ui.expects(:show_status_preview).with(status)
|
456
|
+
@ui.expects(:warn)
|
457
|
+
@ui.expects(:show_status_preview).with(@status)
|
405
458
|
@ui.expects(:confirm).with("Really send?").returns(true)
|
406
459
|
@ui.expects(:info).with("Sent status update.\n\n")
|
407
|
-
@ui.expects(:show_tweets).with(internal_records)
|
408
|
-
@twitter.update(status)
|
460
|
+
@ui.expects(:show_tweets).with(@internal_records)
|
461
|
+
@twitter.update(@status)
|
409
462
|
end
|
410
463
|
|
411
|
-
|
412
|
-
long_urls = ["http://www.w3.org/TR/1999/REC-xpath-19991116"] * 2
|
413
|
-
long_status = long_urls.join(" and ")
|
414
|
-
short_url = "http://shorten.it/2k7mk"
|
415
|
-
short_status = ([short_url] * 2).join(" and ")
|
416
|
-
twitter_records, internal_records = create_rest_api_status_records({
|
417
|
-
:from_user => @username,
|
418
|
-
:status => short_status
|
419
|
-
})
|
464
|
+
it "skips shortening URLs upon connection error to the URL shortening service" do
|
420
465
|
@oauth.expects(:request_signer)
|
421
466
|
http_subresource = mock
|
422
467
|
http_subresource.expects(:post).
|
423
|
-
with({ :status =>
|
424
|
-
returns(twitter_records[0].to_json)
|
468
|
+
with({ :status => @status }).
|
469
|
+
returns(@twitter_records[0].to_json)
|
425
470
|
@rest_api.expects(:[]).
|
426
471
|
with("statuses/update.json").
|
427
472
|
returns(http_subresource)
|
428
|
-
@url_shortener.expects(:shorten).with(
|
429
|
-
@ui.expects(:
|
473
|
+
@url_shortener.expects(:shorten).with(@url).raises(HttpError.new(404, "Not Found"))
|
474
|
+
@ui.expects(:warn)
|
475
|
+
@ui.expects(:show_status_preview).with(@status)
|
430
476
|
@ui.expects(:confirm).with("Really send?").returns(true)
|
431
477
|
@ui.expects(:info).with("Sent status update.\n\n")
|
432
|
-
@ui.expects(:show_tweets).with(internal_records)
|
433
|
-
@twitter.update(
|
434
|
-
end
|
435
|
-
|
436
|
-
context "in erroneous situations" do
|
437
|
-
setup do
|
438
|
-
@url = "http://www.w3.org/TR/1999/REC-xpath-19991116"
|
439
|
-
@status = "skimming through #{@url}"
|
440
|
-
@twitter_records, @internal_records = create_rest_api_status_records({
|
441
|
-
:from_user => @username,
|
442
|
-
:status => @status
|
443
|
-
})
|
444
|
-
end
|
445
|
-
|
446
|
-
should "skip shortening URLs if required libraries are not found" do
|
447
|
-
Tweetwine::CLI.stubs(:url_shortener).raises(LoadError, 'gem not found')
|
448
|
-
@oauth.expects(:request_signer)
|
449
|
-
http_subresource = mock
|
450
|
-
http_subresource.expects(:post).
|
451
|
-
with({ :status => @status }).
|
452
|
-
returns(@twitter_records[0].to_json)
|
453
|
-
@rest_api.expects(:[]).
|
454
|
-
with("statuses/update.json").
|
455
|
-
returns(http_subresource)
|
456
|
-
@ui.expects(:warn)
|
457
|
-
@ui.expects(:show_status_preview).with(@status)
|
458
|
-
@ui.expects(:confirm).with("Really send?").returns(true)
|
459
|
-
@ui.expects(:info).with("Sent status update.\n\n")
|
460
|
-
@ui.expects(:show_tweets).with(@internal_records)
|
461
|
-
@twitter.update(@status)
|
462
|
-
end
|
463
|
-
|
464
|
-
should "skip shortening URLs upon connection error to the URL shortening service" do
|
465
|
-
@oauth.expects(:request_signer)
|
466
|
-
http_subresource = mock
|
467
|
-
http_subresource.expects(:post).
|
468
|
-
with({ :status => @status }).
|
469
|
-
returns(@twitter_records[0].to_json)
|
470
|
-
@rest_api.expects(:[]).
|
471
|
-
with("statuses/update.json").
|
472
|
-
returns(http_subresource)
|
473
|
-
@url_shortener.expects(:shorten).with(@url).raises(HttpError.new(404, "Not Found"))
|
474
|
-
@ui.expects(:warn)
|
475
|
-
@ui.expects(:show_status_preview).with(@status)
|
476
|
-
@ui.expects(:confirm).with("Really send?").returns(true)
|
477
|
-
@ui.expects(:info).with("Sent status update.\n\n")
|
478
|
-
@ui.expects(:show_tweets).with(@internal_records)
|
479
|
-
@twitter.update(@status)
|
480
|
-
end
|
478
|
+
@ui.expects(:show_tweets).with(@internal_records)
|
479
|
+
@twitter.update(@status)
|
481
480
|
end
|
482
481
|
end
|
483
482
|
end
|
484
483
|
|
485
|
-
|
484
|
+
it "fetches friends" do
|
486
485
|
twitter_records, internal_records = create_rest_api_user_records(
|
487
486
|
{
|
488
487
|
:from_user => "zanzibar",
|
@@ -503,7 +502,7 @@ class ClientTest < UnitTestCase
|
|
503
502
|
@twitter.friends
|
504
503
|
end
|
505
504
|
|
506
|
-
|
505
|
+
it "fetches followers" do
|
507
506
|
twitter_records, internal_records = create_rest_api_user_records(
|
508
507
|
{
|
509
508
|
:from_user => "zanzibar",
|
@@ -522,63 +521,61 @@ class ClientTest < UnitTestCase
|
|
522
521
|
@twitter.followers
|
523
522
|
end
|
524
523
|
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
end
|
529
|
-
|
530
|
-
[
|
531
|
-
[nil, "no operator"],
|
532
|
-
[:and, "and operator"]
|
533
|
-
].each do |op, desc|
|
534
|
-
should "search tweets matching all the given words with #{desc}" do
|
535
|
-
twitter_response, internal_records = create_search_api_status_records(
|
536
|
-
{
|
537
|
-
:from_user => "zanzibar",
|
538
|
-
:status => "@foo, wassup? #greets",
|
539
|
-
:to_user => "foo"
|
540
|
-
},
|
541
|
-
{
|
542
|
-
:from_user => "spoonman",
|
543
|
-
:status => "@foo long time no see #greets",
|
544
|
-
:to_user => "foo"
|
545
|
-
}
|
546
|
-
)
|
547
|
-
@search_api.expects(:[]).
|
548
|
-
with("search.json?q=%23greets%20%40foo&#{@search_api_query_str}").
|
549
|
-
returns(stub(:get => twitter_response.to_json))
|
550
|
-
@ui.expects(:show_tweets).with(internal_records)
|
551
|
-
@twitter.search(["#greets", "@foo"], op)
|
552
|
-
end
|
553
|
-
end
|
524
|
+
it "raises exception if no search word is given for searching tweets" do
|
525
|
+
assert_raises(ArgumentError) { @twitter.search }
|
526
|
+
end
|
554
527
|
|
555
|
-
|
528
|
+
[
|
529
|
+
[nil, "no operator"],
|
530
|
+
[:and, "and operator"]
|
531
|
+
].each do |op, desc|
|
532
|
+
it "searches tweets matching all the given words with #{desc}" do
|
556
533
|
twitter_response, internal_records = create_search_api_status_records(
|
557
534
|
{
|
558
535
|
:from_user => "zanzibar",
|
559
|
-
:status => "
|
536
|
+
:status => "@foo, wassup? #greets",
|
560
537
|
:to_user => "foo"
|
561
538
|
},
|
562
539
|
{
|
563
540
|
:from_user => "spoonman",
|
564
|
-
:status => "
|
541
|
+
:status => "@foo long time no see #greets",
|
565
542
|
:to_user => "foo"
|
566
543
|
}
|
567
544
|
)
|
568
545
|
@search_api.expects(:[]).
|
569
|
-
with("search.json?q=%
|
546
|
+
with("search.json?q=%23greets%20%40foo&#{@search_api_query_str}").
|
570
547
|
returns(stub(:get => twitter_response.to_json))
|
571
548
|
@ui.expects(:show_tweets).with(internal_records)
|
572
|
-
@twitter.search(["#
|
549
|
+
@twitter.search(["#greets", "@foo"], op)
|
573
550
|
end
|
574
551
|
end
|
575
552
|
|
576
|
-
|
577
|
-
|
553
|
+
it "searches tweets matching any of the given words with or operator" do
|
554
|
+
twitter_response, internal_records = create_search_api_status_records(
|
555
|
+
{
|
556
|
+
:from_user => "zanzibar",
|
557
|
+
:status => "spinning around the floor #habits",
|
558
|
+
:to_user => "foo"
|
559
|
+
},
|
560
|
+
{
|
561
|
+
:from_user => "spoonman",
|
562
|
+
:status => "drinking coffee, again #neurotic",
|
563
|
+
:to_user => "foo"
|
564
|
+
}
|
565
|
+
)
|
566
|
+
@search_api.expects(:[]).
|
567
|
+
with("search.json?q=%23habits%20OR%20%23neurotic&#{@search_api_query_str}").
|
568
|
+
returns(stub(:get => twitter_response.to_json))
|
569
|
+
@ui.expects(:show_tweets).with(internal_records)
|
570
|
+
@twitter.search(["#habits", "#neurotic"], :or)
|
571
|
+
end
|
572
|
+
|
573
|
+
describe "when authorization fails with HTTP 401 response" do
|
574
|
+
before do
|
578
575
|
mock_config
|
579
576
|
end
|
580
577
|
|
581
|
-
|
578
|
+
it "authorizes with OAuth and save config" do
|
582
579
|
twitter_records, internal_records = create_rest_api_status_records({
|
583
580
|
:from_user => @username,
|
584
581
|
:status => "wassup?"
|