tweetwine 0.4.1 → 0.4.2

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 (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?"