tweetwine 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/CHANGELOG.rdoc +6 -0
  2. data/Rakefile +22 -23
  3. data/lib/tweetwine/cli.rb +167 -165
  4. data/lib/tweetwine/config.rb +3 -2
  5. data/lib/tweetwine/exceptions.rb +1 -0
  6. data/lib/tweetwine/version.rb +1 -1
  7. data/project.rb +16 -16
  8. data/test/fixture/{config_example.yaml → config_integration.yaml} +0 -0
  9. data/test/fixture/oauth.rb +11 -11
  10. data/test/{test_helper.rb → helper.rb} +16 -7
  11. data/test/{example/authorization_example.rb → integration/authorization_test.rb} +17 -17
  12. data/test/integration/global_options_test.rb +67 -0
  13. data/test/integration/helper.rb +70 -0
  14. data/test/integration/invalid_config_file_test.rb +28 -0
  15. data/test/integration/search_statuses_test.rb +81 -0
  16. data/test/integration/show_followers_test.rb +24 -0
  17. data/test/integration/show_friends_test.rb +24 -0
  18. data/test/integration/show_home_test.rb +47 -0
  19. data/test/integration/show_mentions_test.rb +24 -0
  20. data/test/integration/show_user_test.rb +48 -0
  21. data/test/integration/update_status_test.rb +199 -0
  22. data/test/integration/use_http_proxy_test.rb +71 -0
  23. data/test/{example/user_help_example.rb → integration/user_help_test.rb} +36 -36
  24. data/test/unit/character_encoding_test.rb +19 -15
  25. data/test/unit/cli_test.rb +9 -10
  26. data/test/unit/config_test.rb +73 -71
  27. data/test/unit/helper.rb +108 -0
  28. data/test/unit/http_test.rb +39 -39
  29. data/test/unit/oauth_test.rb +15 -16
  30. data/test/unit/obfuscate_test.rb +4 -4
  31. data/test/unit/option_parser_test.rb +12 -12
  32. data/test/unit/promise_test.rb +10 -10
  33. data/test/unit/support_test.rb +44 -45
  34. data/test/unit/tweet_helper.rb +1 -1
  35. data/test/unit/tweet_test.rb +42 -42
  36. data/test/unit/twitter_test.rb +300 -303
  37. data/test/unit/ui_test.rb +310 -312
  38. data/test/unit/uri_test.rb +7 -7
  39. data/test/unit/url_shortener_test.rb +77 -79
  40. data/tweetwine.gemspec +6 -15
  41. metadata +55 -145
  42. data/test/example/example_helper.rb +0 -58
  43. data/test/example/global_options_example.rb +0 -64
  44. data/test/example/search_statuses_example.rb +0 -76
  45. data/test/example/show_followers_example.rb +0 -24
  46. data/test/example/show_friends_example.rb +0 -24
  47. data/test/example/show_home_example.rb +0 -44
  48. data/test/example/show_mentions_example.rb +0 -24
  49. data/test/example/show_user_example.rb +0 -44
  50. data/test/example/update_status_example.rb +0 -183
  51. data/test/example/use_http_proxy_example.rb +0 -68
  52. data/test/unit/unit_helper.rb +0 -111
@@ -1,11 +1,11 @@
1
1
  # coding: utf-8
2
2
 
3
- require "unit_helper"
3
+ require 'unit/helper'
4
4
 
5
- module Tweetwine::Test
5
+ module Tweetwine::Test::Unit
6
6
 
7
- class ClientTest < UnitTestCase
8
- setup do
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
- context "for initialization" do
17
- should "use default number of statuses if not configured" do
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
- should "use configured number of statuses if in allowed range" do
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
- should "raise exception if configured number of status not in allowed range" do
28
- assert_raise(CommandLineError) { Twitter.new(:num_tweets => 0) }
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
- should "use default page number if not configured otherwise" do
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
- should "use configured page number if in allowed range" do
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
- should "raise exception if configured page number not in allowed range" do
42
- assert_raise(CommandLineError) { Twitter.new(:page => 0) }
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
- context "at runtime" do
47
- setup do
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
- should "skip showing an invalid tweet" do
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
- should "fetch friends' statuses (home view)" do
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
- should "fetch mentions" do
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
- should "fetch a specific user's statuses, when user is given as argument" do
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
- should "fetch a specific user's statuses, with user being the authenticated user itself when given no argument" do
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
- context "when posting status updates" do
150
- should "post a status update via argument, when positive confirmation" do
151
- status = "wondering around"
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 => 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 => 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(status)
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(status)
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
- should "post a status update via prompt, when positive confirmation" do
172
- status = "wondering around"
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
- should "cancel a status update via prompt, when negative confirmation" do
204
- status = "wondering around"
205
- @rest_api.expects(:[]).never
206
- @ui.expects(:prompt).with("Status update").returns(status)
207
- @ui.expects(:show_status_preview).with(status)
208
- @ui.expects(:confirm).with("Really send?").returns(false)
209
- @ui.expects(:info).with("Cancelled.")
210
- @ui.expects(:show_tweets).never
211
- @twitter.update
212
- end
213
-
214
- should "cancel a status update via argument, when empty status" do
215
- @rest_api.expects(:[]).never
216
- @ui.expects(:prompt).with("Status update").returns("")
217
- @ui.expects(:confirm).never
218
- @ui.expects(:info).with("Cancelled.")
219
- @ui.expects(:show_tweets).never
220
- @twitter.update("")
221
- end
222
-
223
- should "cancel a status update via prompt, when empty status" do
224
- @rest_api.expects(:[]).never
225
- @ui.expects(:prompt).with("Status update").returns("")
226
- @ui.expects(:confirm).never
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
- should "remove excess whitespace around a status update" do
233
- whitespaced_status = " oh, i was sloppy \t "
234
- stripped_status = "oh, i was sloppy"
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 => stripped_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 => stripped_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
- @ui.expects(:show_status_preview).with(stripped_status)
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(whitespaced_status)
408
+ @twitter.update(status)
252
409
  end
253
410
 
254
- should "truncate a status update with too long argument and warn the user" do
255
- truncated_status = "ab c" * 35 # 4 * 35 = 140
256
- long_status = "#{truncated_status} dd"
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 => truncated_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 => truncated_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
- @ui.expects(:warn).with("Status will be truncated.")
270
- @ui.expects(:show_status_preview).with(truncated_status)
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
- if defined? Encoding
278
- should "encode status in UTF-8 (String supports encoding)" do
279
- status_utf8, status_latin1 = "résumé", "résumé".encode('ISO-8859-1')
280
- twitter_records, internal_records = create_rest_api_status_records({
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 => status_utf8
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
- should "not shorten URLs if not configured" do
338
- stub_config
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
- @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)
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
- should "reuse 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 ")
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 => short_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(long_urls.first).returns(short_url)
429
- @ui.expects(:show_status_preview).with(short_status)
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(long_status)
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
- should "fetch friends" do
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
- should "fetch followers" do
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
- context "when searching tweets" do
526
- should "raise exception if no search word is given" do
527
- assert_raise(ArgumentError) { @twitter.search }
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
- should "search tweets matching any of the given words with or operator" do
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 => "spinning around the floor #habits",
536
+ :status => "@foo, wassup? #greets",
560
537
  :to_user => "foo"
561
538
  },
562
539
  {
563
540
  :from_user => "spoonman",
564
- :status => "drinking coffee, again #neurotic",
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=%23habits%20OR%20%23neurotic&#{@search_api_query_str}").
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(["#habits", "#neurotic"], :or)
549
+ @twitter.search(["#greets", "@foo"], op)
573
550
  end
574
551
  end
575
552
 
576
- context "when authorization fails with HTTP 401 response" do
577
- setup do
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
- should "authorize with OAuth and save config" do
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?"