tweetwine 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/.gitignore +6 -0
  2. data/CHANGELOG.rdoc +9 -0
  3. data/Gemfile +5 -13
  4. data/LICENSE.txt +1 -1
  5. data/README.md +3 -2
  6. data/Rakefile +8 -2
  7. data/lib/tweetwine/character_encoding.rb +1 -1
  8. data/lib/tweetwine/cli.rb +9 -3
  9. data/lib/tweetwine/config.rb +3 -3
  10. data/lib/tweetwine/exceptions.rb +54 -0
  11. data/lib/tweetwine/http.rb +1 -1
  12. data/lib/tweetwine/{util.rb → support.rb} +19 -12
  13. data/lib/tweetwine/tweet.rb +69 -0
  14. data/lib/tweetwine/twitter.rb +70 -72
  15. data/lib/tweetwine/ui.rb +36 -41
  16. data/lib/tweetwine/uri.rb +31 -0
  17. data/lib/tweetwine/version.rb +15 -0
  18. data/lib/tweetwine.rb +6 -64
  19. data/man/tweetwine.7 +4 -3
  20. data/man/tweetwine.7.ronn +3 -2
  21. data/release-script.txt +10 -0
  22. data/test/example/authorization_example.rb +40 -0
  23. data/test/example/example_helper.rb +1 -1
  24. data/test/example/global_options_example.rb +64 -0
  25. data/test/example/search_statuses_example.rb +36 -31
  26. data/test/example/show_followers_example.rb +1 -1
  27. data/test/example/show_friends_example.rb +1 -1
  28. data/test/example/show_home_example.rb +17 -29
  29. data/test/example/show_mentions_example.rb +2 -2
  30. data/test/example/show_user_example.rb +14 -12
  31. data/test/example/update_status_example.rb +9 -9
  32. data/test/example/use_http_proxy_example.rb +7 -6
  33. data/test/example/{application_behavior_example.rb → user_help_example.rb} +6 -39
  34. data/test/unit/config_test.rb +1 -1
  35. data/test/unit/http_test.rb +1 -21
  36. data/test/unit/oauth_test.rb +11 -11
  37. data/test/unit/{util_test.rb → support_test.rb} +37 -38
  38. data/test/unit/tweet_helper.rb +83 -0
  39. data/test/unit/tweet_test.rb +153 -0
  40. data/test/unit/twitter_test.rb +240 -248
  41. data/test/unit/ui_test.rb +174 -78
  42. data/test/unit/unit_helper.rb +18 -6
  43. data/test/unit/uri_test.rb +41 -0
  44. data/test/unit/url_shortener_test.rb +7 -7
  45. data/tweetwine.gemspec +12 -22
  46. metadata +52 -73
@@ -5,24 +5,32 @@ require "unit_helper"
5
5
  module Tweetwine::Test
6
6
 
7
7
  class ClientTest < UnitTestCase
8
+ setup do
9
+ @config = {
10
+ :num_tweets => 20,
11
+ :page => 1
12
+ }
13
+ stub_config @config
14
+ end
15
+
8
16
  context "for initialization" do
9
17
  should "use default number of statuses if not configured" do
10
18
  @twitter = Twitter.new
11
- assert_equal Twitter::DEFAULT_NUM_STATUSES, @twitter.num_statuses
19
+ assert_equal @config[:num_tweets], @twitter.num_tweets
12
20
  end
13
21
 
14
22
  should "use configured number of statuses if in allowed range" do
15
- @twitter = Twitter.new(:num_statuses => 12)
16
- assert_equal 12, @twitter.num_statuses
23
+ @twitter = Twitter.new(:num_tweets => 12)
24
+ assert_equal 12, @twitter.num_tweets
17
25
  end
18
26
 
19
27
  should "raise exception if configured number of status not in allowed range" do
20
- assert_raise(ArgumentError) { Twitter.new(:num_statuses => 0) }
28
+ assert_raise(CommandLineError) { Twitter.new(:num_tweets => 0) }
21
29
  end
22
30
 
23
31
  should "use default page number if not configured otherwise" do
24
32
  @twitter = Twitter.new
25
- assert_equal Twitter::DEFAULT_PAGE_NUM, @twitter.page
33
+ assert_equal @config[:page], @twitter.page
26
34
  end
27
35
 
28
36
  should "use configured page number if in allowed range" do
@@ -31,7 +39,7 @@ class ClientTest < UnitTestCase
31
39
  end
32
40
 
33
41
  should "raise exception if configured page number not in allowed range" do
34
- assert_raise(ArgumentError) { Twitter.new(:page => 0) }
42
+ assert_raise(CommandLineError) { Twitter.new(:page => 0) }
35
43
  end
36
44
  end
37
45
 
@@ -46,132 +54,139 @@ class ClientTest < UnitTestCase
46
54
  @http.stubs(:as_resource).with("https://api.twitter.com/1").returns(@rest_api)
47
55
  @http.stubs(:as_resource).with("http://search.twitter.com").returns(@search_api)
48
56
  @twitter = Twitter.new(:username => @username)
49
- @rest_api_status_query_str = "count=#{Twitter::DEFAULT_NUM_STATUSES}&page=#{Twitter::DEFAULT_PAGE_NUM}"
50
- @search_api_query_str = "page=#{Twitter::DEFAULT_PAGE_NUM}&rpp=#{Twitter::DEFAULT_NUM_STATUSES}"
57
+ @rest_api_status_query_str = "count=#{@config[:num_tweets]}&page=#{@config[:page]}"
58
+ @search_api_query_str = "page=#{@config[:page]}&rpp=#{@config[:num_tweets]}"
59
+ end
60
+
61
+ should "skip showing an invalid tweet" do
62
+ invalid_from_user = nil
63
+ twitter_records, internal_records = create_rest_api_status_records(
64
+ {
65
+ :from_user => invalid_from_user,
66
+ :status => "wassup?"
67
+ },
68
+ {
69
+ :from_user => "lulzwoo",
70
+ :status => "nuttin'"
71
+ }
72
+ )
73
+ @oauth.expects(:request_signer)
74
+ @rest_api.expects(:[]).
75
+ with("statuses/home_timeline.json?#{@rest_api_status_query_str}").
76
+ returns(stub(:get => twitter_records.to_json))
77
+ @ui.expects(:warn).with("Invalid tweet. Skipping...")
78
+ @ui.expects(:show_tweets).with(internal_records[1..-1])
79
+ @twitter.home
51
80
  end
52
81
 
53
82
  should "fetch friends' statuses (home view)" do
54
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api(
83
+ twitter_records, internal_records = create_rest_api_status_records(
55
84
  {
56
85
  :from_user => "zanzibar",
57
- :status => "wassup?",
58
- :created_at => Time.at(1).to_s,
59
- :to_user => nil
86
+ :status => "wassup?"
60
87
  },
61
88
  {
62
89
  :from_user => "lulzwoo",
63
- :status => "nuttin'",
64
- :created_at => Time.at(1).to_s,
65
- :to_user => nil
66
- })
90
+ :status => "nuttin'"
91
+ }
92
+ )
67
93
  @oauth.expects(:request_signer)
68
94
  @rest_api.expects(:[]).
69
- with("statuses/home_timeline.json?#{@rest_api_status_query_str}").
70
- returns(stub(:get => twitter_records.to_json))
71
- @ui.expects(:show_record).with(internal_records[0])
72
- @ui.expects(:show_record).with(internal_records[1])
95
+ with("statuses/home_timeline.json?#{@rest_api_status_query_str}").
96
+ returns(stub(:get => twitter_records.to_json))
97
+ @ui.expects(:show_tweets).with(internal_records)
73
98
  @twitter.home
74
99
  end
75
100
 
76
101
  should "fetch mentions" do
77
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api(
102
+ twitter_records, internal_records = create_rest_api_status_records(
78
103
  {
79
104
  :from_user => "zanzibar",
80
105
  :status => "wassup, @#{@username}?",
81
- :created_at => Time.at(1).to_s,
82
106
  :to_user => @username
83
107
  },
84
108
  {
85
109
  :from_user => "lulzwoo",
86
110
  :status => "@#{@username}, doing nuttin'",
87
- :created_at => Time.at(1).to_s,
88
111
  :to_user => @username
89
- })
112
+ }
113
+ )
90
114
  @oauth.expects(:request_signer)
91
115
  @rest_api.expects(:[]).
92
- with("statuses/mentions.json?#{@rest_api_status_query_str}").
93
- returns(stub(:get => twitter_records.to_json))
94
- @ui.expects(:show_record).with(internal_records[0])
95
- @ui.expects(:show_record).with(internal_records[1])
116
+ with("statuses/mentions.json?#{@rest_api_status_query_str}").
117
+ returns(stub(:get => twitter_records.to_json))
118
+ @ui.expects(:show_tweets).with(internal_records)
96
119
  @twitter.mentions
97
120
  end
98
121
 
99
122
  should "fetch a specific user's statuses, when user is given as argument" do
100
123
  username = "spoonman"
101
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api({
102
- :from_user => username,
103
- :status => "wassup?",
104
- :created_at => Time.at(1).to_s,
105
- :to_user => nil
106
- })
124
+ twitter_records, internal_records = create_rest_api_status_records({
125
+ :from_user => username,
126
+ :status => "wassup?"
127
+ })
107
128
  @oauth.expects(:request_signer)
108
129
  @rest_api.expects(:[]).
109
- with("statuses/user_timeline.json?#{@rest_api_status_query_str}&screen_name=#{username}").
110
- returns(stub(:get => twitter_records.to_json))
111
- @ui.expects(:show_record).with(internal_records[0])
130
+ with("statuses/user_timeline.json?#{@rest_api_status_query_str}&screen_name=#{username}").
131
+ returns(stub(:get => twitter_records.to_json))
132
+ @ui.expects(:show_tweets).with(internal_records)
112
133
  @twitter.user(username)
113
134
  end
114
135
 
115
136
  should "fetch a specific user's statuses, with user being the authenticated user itself when given no argument" do
116
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api({
117
- :from_user => @username,
118
- :status => "wassup?",
119
- :created_at => Time.at(1).to_s,
120
- :to_user => nil
121
- })
137
+ twitter_records, internal_records = create_rest_api_status_records({
138
+ :from_user => @username,
139
+ :status => "wassup?"
140
+ })
122
141
  @oauth.expects(:request_signer)
123
142
  @rest_api.expects(:[]).
124
- with("statuses/user_timeline.json?#{@rest_api_status_query_str}&screen_name=#{@username}").
125
- returns(stub(:get => twitter_records.to_json))
126
- @ui.expects(:show_record).with(internal_records[0])
143
+ with("statuses/user_timeline.json?#{@rest_api_status_query_str}&screen_name=#{@username}").
144
+ returns(stub(:get => twitter_records.to_json))
145
+ @ui.expects(:show_tweets).with(internal_records)
127
146
  @twitter.user
128
147
  end
129
148
 
130
149
  context "when posting status updates" do
131
150
  should "post a status update via argument, when positive confirmation" do
132
151
  status = "wondering around"
133
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api({
134
- :from_user => @username,
135
- :status => status,
136
- :created_at => Time.at(1).to_s,
137
- :to_user => nil
138
- })
152
+ twitter_records, internal_records = create_rest_api_status_records({
153
+ :from_user => @username,
154
+ :status => status
155
+ })
139
156
  @oauth.expects(:request_signer)
140
157
  http_subresource = mock
141
158
  http_subresource.expects(:post).
142
- with({ :status => status }).
143
- returns(twitter_records[0].to_json)
159
+ with({ :status => status }).
160
+ returns(twitter_records[0].to_json)
144
161
  @rest_api.expects(:[]).
145
- with("statuses/update.json").
146
- returns(http_subresource)
162
+ with("statuses/update.json").
163
+ returns(http_subresource)
147
164
  @ui.expects(:confirm).with("Really send?").returns(true)
148
165
  @ui.expects(:show_status_preview).with(status)
149
166
  @ui.expects(:info).with("Sent status update.\n\n")
150
- @ui.expects(:show_record).with(internal_records[0])
167
+ @ui.expects(:show_tweets).with(internal_records)
151
168
  @twitter.update(status)
152
169
  end
153
170
 
154
171
  should "post a status update via prompt, when positive confirmation" do
155
172
  status = "wondering around"
156
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api({
157
- :from_user => @username,
158
- :status => status,
159
- :created_at => Time.at(1).to_s,
160
- :to_user => nil
161
- })
173
+ twitter_records, internal_records = create_rest_api_status_records({
174
+ :from_user => @username,
175
+ :status => status
176
+ })
162
177
  @oauth.expects(:request_signer)
163
178
  http_subresource = mock
164
179
  http_subresource.expects(:post).
165
- with({ :status => status }).
166
- returns(twitter_records[0].to_json)
180
+ with({ :status => status }).
181
+ returns(twitter_records[0].to_json)
167
182
  @rest_api.expects(:[]).
168
- with("statuses/update.json").
169
- returns(http_subresource)
183
+ with("statuses/update.json").
184
+ returns(http_subresource)
170
185
  @ui.expects(:prompt).with("Status update").returns(status)
171
186
  @ui.expects(:show_status_preview).with(status)
172
187
  @ui.expects(:confirm).with("Really send?").returns(true)
173
188
  @ui.expects(:info).with("Sent status update.\n\n")
174
- @ui.expects(:show_record).with(internal_records[0])
189
+ @ui.expects(:show_tweets).with(internal_records)
175
190
  @twitter.update
176
191
  end
177
192
 
@@ -181,7 +196,7 @@ class ClientTest < UnitTestCase
181
196
  @ui.expects(:show_status_preview).with(status)
182
197
  @ui.expects(:confirm).with("Really send?").returns(false)
183
198
  @ui.expects(:info).with("Cancelled.")
184
- @ui.expects(:show_record).never
199
+ @ui.expects(:show_tweets).never
185
200
  @twitter.update(status)
186
201
  end
187
202
 
@@ -192,7 +207,7 @@ class ClientTest < UnitTestCase
192
207
  @ui.expects(:show_status_preview).with(status)
193
208
  @ui.expects(:confirm).with("Really send?").returns(false)
194
209
  @ui.expects(:info).with("Cancelled.")
195
- @ui.expects(:show_record).never
210
+ @ui.expects(:show_tweets).never
196
211
  @twitter.update
197
212
  end
198
213
 
@@ -201,7 +216,7 @@ class ClientTest < UnitTestCase
201
216
  @ui.expects(:prompt).with("Status update").returns("")
202
217
  @ui.expects(:confirm).never
203
218
  @ui.expects(:info).with("Cancelled.")
204
- @ui.expects(:show_record).never
219
+ @ui.expects(:show_tweets).never
205
220
  @twitter.update("")
206
221
  end
207
222
 
@@ -210,80 +225,74 @@ class ClientTest < UnitTestCase
210
225
  @ui.expects(:prompt).with("Status update").returns("")
211
226
  @ui.expects(:confirm).never
212
227
  @ui.expects(:info).with("Cancelled.")
213
- @ui.expects(:show_record).never
228
+ @ui.expects(:show_tweets).never
214
229
  @twitter.update
215
230
  end
216
231
 
217
232
  should "remove excess whitespace around a status update" do
218
233
  whitespaced_status = " oh, i was sloppy \t "
219
234
  stripped_status = "oh, i was sloppy"
220
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api({
221
- :from_user => @username,
222
- :status => stripped_status,
223
- :created_at => Time.at(1).to_s,
224
- :to_user => nil
225
- })
235
+ twitter_records, internal_records = create_rest_api_status_records({
236
+ :from_user => @username,
237
+ :status => stripped_status
238
+ })
226
239
  @oauth.expects(:request_signer)
227
240
  http_subresource = mock
228
241
  http_subresource.expects(:post).
229
- with({ :status => stripped_status }).
230
- returns(twitter_records[0].to_json)
242
+ with({ :status => stripped_status }).
243
+ returns(twitter_records[0].to_json)
231
244
  @rest_api.expects(:[]).
232
- with("statuses/update.json").
233
- returns(http_subresource)
245
+ with("statuses/update.json").
246
+ returns(http_subresource)
234
247
  @ui.expects(:show_status_preview).with(stripped_status)
235
248
  @ui.expects(:confirm).with("Really send?").returns(true)
236
249
  @ui.expects(:info).with("Sent status update.\n\n")
237
- @ui.expects(:show_record).with(internal_records[0])
250
+ @ui.expects(:show_tweets).with(internal_records)
238
251
  @twitter.update(whitespaced_status)
239
252
  end
240
253
 
241
254
  should "truncate a status update with too long argument and warn the user" do
242
255
  truncated_status = "ab c" * 35 # 4 * 35 = 140
243
256
  long_status = "#{truncated_status} dd"
244
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api({
245
- :from_user => @username,
246
- :status => truncated_status,
247
- :created_at => Time.at(1).to_s,
248
- :to_user => nil
249
- })
257
+ twitter_records, internal_records = create_rest_api_status_records({
258
+ :from_user => @username,
259
+ :status => truncated_status
260
+ })
250
261
  @oauth.expects(:request_signer)
251
262
  http_subresource = mock
252
263
  http_subresource.expects(:post).
253
- with({ :status => truncated_status }).
254
- returns(twitter_records[0].to_json)
264
+ with({ :status => truncated_status }).
265
+ returns(twitter_records[0].to_json)
255
266
  @rest_api.expects(:[]).
256
- with("statuses/update.json").
257
- returns(http_subresource)
267
+ with("statuses/update.json").
268
+ returns(http_subresource)
258
269
  @ui.expects(:warn).with("Status will be truncated.")
259
270
  @ui.expects(:show_status_preview).with(truncated_status)
260
271
  @ui.expects(:confirm).with("Really send?").returns(true)
261
272
  @ui.expects(:info).with("Sent status update.\n\n")
262
- @ui.expects(:show_record).with(internal_records[0])
273
+ @ui.expects(:show_tweets).with(internal_records)
263
274
  @twitter.update(long_status)
264
275
  end
265
276
 
266
277
  if defined? Encoding
267
278
  should "encode status in UTF-8 (String supports encoding)" do
268
279
  status_utf8, status_latin1 = "résumé", "résumé".encode('ISO-8859-1')
269
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api({
270
- :from_user => @username,
271
- :status => status_utf8,
272
- :created_at => Time.at(1).to_s,
273
- :to_user => nil
274
- })
280
+ twitter_records, internal_records = create_rest_api_status_records({
281
+ :from_user => @username,
282
+ :status => status_utf8
283
+ })
275
284
  @oauth.expects(:request_signer)
276
285
  http_subresource = mock
277
286
  http_subresource.expects(:post).
278
- with({ :status => status_utf8 }).
279
- returns(twitter_records[0].to_json)
287
+ with({ :status => status_utf8 }).
288
+ returns(twitter_records[0].to_json)
280
289
  @rest_api.expects(:[]).
281
- with("statuses/update.json").
282
- returns(http_subresource)
290
+ with("statuses/update.json").
291
+ returns(http_subresource)
283
292
  @ui.expects(:confirm).with("Really send?").returns(true)
284
293
  @ui.expects(:show_status_preview).with(status_latin1)
285
294
  @ui.expects(:info).with("Sent status update.\n\n")
286
- @ui.expects(:show_record).with(internal_records[0])
295
+ @ui.expects(:show_tweets).with(internal_records)
287
296
  @twitter.update(status_latin1)
288
297
  end
289
298
  else
@@ -291,24 +300,22 @@ class ClientTest < UnitTestCase
291
300
  tmp_kcode('NONE') do
292
301
  tmp_env(:LANG => 'ISO-8859-1') do
293
302
  status_utf8, status_latin1 = "r\xc3\xa9sum\xc3\xa9", "r\xe9sum\xe9"
294
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api({
295
- :from_user => @username,
296
- :status => status_utf8,
297
- :created_at => Time.at(1).to_s,
298
- :to_user => nil
299
- })
303
+ twitter_records, internal_records = create_rest_api_status_records({
304
+ :from_user => @username,
305
+ :status => status_utf8
306
+ })
300
307
  @oauth.expects(:request_signer)
301
308
  http_subresource = mock
302
309
  http_subresource.expects(:post).
303
- with({ :status => status_utf8 }).
304
- returns(twitter_records[0].to_json)
310
+ with({ :status => status_utf8 }).
311
+ returns(twitter_records[0].to_json)
305
312
  @rest_api.expects(:[]).
306
- with("statuses/update.json").
307
- returns(http_subresource)
313
+ with("statuses/update.json").
314
+ returns(http_subresource)
308
315
  @ui.expects(:confirm).with("Really send?").returns(true)
309
316
  @ui.expects(:show_status_preview).with(status_latin1)
310
317
  @ui.expects(:info).with("Sent status update.\n\n")
311
- @ui.expects(:show_record).with(internal_records[0])
318
+ @ui.expects(:show_tweets).with(internal_records)
312
319
  @twitter.update(status_latin1)
313
320
  end
314
321
  end
@@ -330,25 +337,23 @@ class ClientTest < UnitTestCase
330
337
  should "not shorten URLs if not configured" do
331
338
  stub_config
332
339
  status = "reading http://www.w3.org/TR/1999/REC-xpath-19991116"
333
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api({
334
- :from_user => @username,
335
- :status => status,
336
- :created_at => Time.at(1).to_s,
337
- :to_user => nil
338
- })
340
+ twitter_records, internal_records = create_rest_api_status_records({
341
+ :from_user => @username,
342
+ :status => status
343
+ })
339
344
  @oauth.expects(:request_signer)
340
345
  http_subresource = mock
341
346
  http_subresource.expects(:post).
342
- with({ :status => status }).
343
- returns(twitter_records[0].to_json)
347
+ with({ :status => status }).
348
+ returns(twitter_records[0].to_json)
344
349
  @url_shortener.expects(:shorten).never
345
350
  @rest_api.expects(:[]).
346
- with("statuses/update.json").
347
- returns(http_subresource)
351
+ with("statuses/update.json").
352
+ returns(http_subresource)
348
353
  @ui.expects(:confirm).with("Really send?").returns(true)
349
354
  @ui.expects(:show_status_preview).with(status)
350
355
  @ui.expects(:info).with("Sent status update.\n\n")
351
- @ui.expects(:show_record).with(internal_records[0])
356
+ @ui.expects(:show_tweets).with(internal_records)
352
357
  @twitter.update(status)
353
358
  end
354
359
 
@@ -357,26 +362,24 @@ class ClientTest < UnitTestCase
357
362
  long_status = long_urls.join(" and ")
358
363
  short_urls = ["http://shorten.it/2k7i8", "http://shorten.it/2k7mk"]
359
364
  shortened_status = short_urls.join(" and ")
360
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api({
361
- :from_user => @username,
362
- :status => shortened_status,
363
- :created_at => Time.at(1).to_s,
364
- :to_user => nil
365
- })
365
+ twitter_records, internal_records = create_rest_api_status_records({
366
+ :from_user => @username,
367
+ :status => shortened_status
368
+ })
366
369
  @oauth.expects(:request_signer)
367
370
  http_subresource = mock
368
371
  http_subresource.expects(:post).
369
- with({ :status => shortened_status }).
370
- returns(twitter_records[0].to_json)
372
+ with({ :status => shortened_status }).
373
+ returns(twitter_records[0].to_json)
371
374
  @rest_api.expects(:[]).
372
- with("statuses/update.json").
373
- returns(http_subresource)
375
+ with("statuses/update.json").
376
+ returns(http_subresource)
374
377
  @url_shortener.expects(:shorten).with(long_urls.first).returns(short_urls.first)
375
378
  @url_shortener.expects(:shorten).with(long_urls.last).returns(short_urls.last)
376
379
  @ui.expects(:show_status_preview).with(shortened_status)
377
380
  @ui.expects(:confirm).with("Really send?").returns(true)
378
381
  @ui.expects(:info).with("Sent status update.\n\n")
379
- @ui.expects(:show_record).with(internal_records[0])
382
+ @ui.expects(:show_tweets).with(internal_records)
380
383
  @twitter.update(long_status)
381
384
  end
382
385
 
@@ -384,26 +387,24 @@ class ClientTest < UnitTestCase
384
387
  long_urls = ["http://www.google.fi/", "http://www.w3.org/TR/1999/REC-xpath-19991116"]
385
388
  status = long_urls.join(" and ")
386
389
  short_urls = [nil, ""]
387
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api({
388
- :from_user => @username,
389
- :status => status,
390
- :created_at => Time.at(1).to_s,
391
- :to_user => nil
392
- })
390
+ twitter_records, internal_records = create_rest_api_status_records({
391
+ :from_user => @username,
392
+ :status => status
393
+ })
393
394
  @oauth.expects(:request_signer)
394
395
  http_subresource = mock
395
396
  http_subresource.expects(:post).
396
- with({ :status => status }).
397
- returns(twitter_records[0].to_json)
397
+ with({ :status => status }).
398
+ returns(twitter_records[0].to_json)
398
399
  @rest_api.expects(:[]).
399
- with("statuses/update.json").
400
- returns(http_subresource)
400
+ with("statuses/update.json").
401
+ returns(http_subresource)
401
402
  @url_shortener.expects(:shorten).with(long_urls.first).returns(short_urls.first)
402
403
  @url_shortener.expects(:shorten).with(long_urls.last).returns(short_urls.last)
403
404
  @ui.expects(:show_status_preview).with(status)
404
405
  @ui.expects(:confirm).with("Really send?").returns(true)
405
406
  @ui.expects(:info).with("Sent status update.\n\n")
406
- @ui.expects(:show_record).with(internal_records[0])
407
+ @ui.expects(:show_tweets).with(internal_records)
407
408
  @twitter.update(status)
408
409
  end
409
410
 
@@ -412,25 +413,23 @@ class ClientTest < UnitTestCase
412
413
  long_status = long_urls.join(" and ")
413
414
  short_url = "http://shorten.it/2k7mk"
414
415
  short_status = ([short_url] * 2).join(" and ")
415
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api({
416
- :from_user => @username,
417
- :status => short_status,
418
- :created_at => Time.at(1).to_s,
419
- :to_user => nil
420
- })
416
+ twitter_records, internal_records = create_rest_api_status_records({
417
+ :from_user => @username,
418
+ :status => short_status
419
+ })
421
420
  @oauth.expects(:request_signer)
422
421
  http_subresource = mock
423
422
  http_subresource.expects(:post).
424
- with({ :status => short_status }).
425
- returns(twitter_records[0].to_json)
423
+ with({ :status => short_status }).
424
+ returns(twitter_records[0].to_json)
426
425
  @rest_api.expects(:[]).
427
- with("statuses/update.json").
428
- returns(http_subresource)
426
+ with("statuses/update.json").
427
+ returns(http_subresource)
429
428
  @url_shortener.expects(:shorten).with(long_urls.first).returns(short_url)
430
429
  @ui.expects(:show_status_preview).with(short_status)
431
430
  @ui.expects(:confirm).with("Really send?").returns(true)
432
431
  @ui.expects(:info).with("Sent status update.\n\n")
433
- @ui.expects(:show_record).with(internal_records[0])
432
+ @ui.expects(:show_tweets).with(internal_records)
434
433
  @twitter.update(long_status)
435
434
  end
436
435
 
@@ -438,12 +437,10 @@ class ClientTest < UnitTestCase
438
437
  setup do
439
438
  @url = "http://www.w3.org/TR/1999/REC-xpath-19991116"
440
439
  @status = "skimming through #{@url}"
441
- @twitter_records, @internal_records = create_test_twitter_status_records_from_rest_api({
442
- :from_user => @username,
443
- :status => @status,
444
- :created_at => Time.at(1).to_s,
445
- :to_user => nil
446
- })
440
+ @twitter_records, @internal_records = create_rest_api_status_records({
441
+ :from_user => @username,
442
+ :status => @status
443
+ })
447
444
  end
448
445
 
449
446
  should "skip shortening URLs if required libraries are not found" do
@@ -451,16 +448,16 @@ class ClientTest < UnitTestCase
451
448
  @oauth.expects(:request_signer)
452
449
  http_subresource = mock
453
450
  http_subresource.expects(:post).
454
- with({ :status => @status }).
455
- returns(@twitter_records[0].to_json)
451
+ with({ :status => @status }).
452
+ returns(@twitter_records[0].to_json)
456
453
  @rest_api.expects(:[]).
457
- with("statuses/update.json").
458
- returns(http_subresource)
454
+ with("statuses/update.json").
455
+ returns(http_subresource)
459
456
  @ui.expects(:warn)
460
457
  @ui.expects(:show_status_preview).with(@status)
461
458
  @ui.expects(:confirm).with("Really send?").returns(true)
462
459
  @ui.expects(:info).with("Sent status update.\n\n")
463
- @ui.expects(:show_record).with(@internal_records[0])
460
+ @ui.expects(:show_tweets).with(@internal_records)
464
461
  @twitter.update(@status)
465
462
  end
466
463
 
@@ -468,17 +465,17 @@ class ClientTest < UnitTestCase
468
465
  @oauth.expects(:request_signer)
469
466
  http_subresource = mock
470
467
  http_subresource.expects(:post).
471
- with({ :status => @status }).
472
- returns(@twitter_records[0].to_json)
468
+ with({ :status => @status }).
469
+ returns(@twitter_records[0].to_json)
473
470
  @rest_api.expects(:[]).
474
- with("statuses/update.json").
475
- returns(http_subresource)
471
+ with("statuses/update.json").
472
+ returns(http_subresource)
476
473
  @url_shortener.expects(:shorten).with(@url).raises(HttpError.new(404, "Not Found"))
477
474
  @ui.expects(:warn)
478
475
  @ui.expects(:show_status_preview).with(@status)
479
476
  @ui.expects(:confirm).with("Really send?").returns(true)
480
477
  @ui.expects(:info).with("Sent status update.\n\n")
481
- @ui.expects(:show_record).with(@internal_records[0])
478
+ @ui.expects(:show_tweets).with(@internal_records)
482
479
  @twitter.update(@status)
483
480
  end
484
481
  end
@@ -486,48 +483,42 @@ class ClientTest < UnitTestCase
486
483
  end
487
484
 
488
485
  should "fetch friends" do
489
- twitter_records, internal_records = create_test_twitter_user_records_from_rest_api(
486
+ twitter_records, internal_records = create_rest_api_user_records(
490
487
  {
491
488
  :from_user => "zanzibar",
492
489
  :status => "wassup, @foo?",
493
- :created_at => Time.at(1).to_s,
494
490
  :to_user => "foo"
495
491
  },
496
492
  {
497
493
  :from_user => "lulzwoo",
498
494
  :status => "@foo, doing nuttin'",
499
- :created_at => Time.at(1).to_s,
500
495
  :to_user => "foo"
501
- })
496
+ }
497
+ )
502
498
  @oauth.expects(:request_signer)
503
499
  @rest_api.expects(:[]).
504
- with("statuses/friends.json?#{@rest_api_status_query_str}").
505
- returns(stub(:get => twitter_records.to_json))
506
- @ui.expects(:show_record).with(internal_records[0])
507
- @ui.expects(:show_record).with(internal_records[1])
500
+ with("statuses/friends.json?#{@rest_api_status_query_str}").
501
+ returns(stub(:get => twitter_records.to_json))
502
+ @ui.expects(:show_tweets).with(internal_records)
508
503
  @twitter.friends
509
504
  end
510
505
 
511
506
  should "fetch followers" do
512
- twitter_records, internal_records = create_test_twitter_user_records_from_rest_api(
507
+ twitter_records, internal_records = create_rest_api_user_records(
513
508
  {
514
509
  :from_user => "zanzibar",
515
510
  :status => "wassup, @foo?",
516
- :created_at => Time.at(1).to_s,
517
511
  :to_user => "foo"
518
512
  },
519
513
  {
520
- :from_user => "lulzwoo",
521
- :status => nil,
522
- :created_at => nil,
523
- :to_user => nil
524
- })
514
+ :from_user => "lulzwoo"
515
+ }
516
+ )
525
517
  @oauth.expects(:request_signer)
526
518
  @rest_api.expects(:[]).
527
- with("statuses/followers.json?#{@rest_api_status_query_str}").
528
- returns(stub(:get => twitter_records.to_json))
529
- @ui.expects(:show_record).with(internal_records[0])
530
- @ui.expects(:show_record).with(internal_records[1])
519
+ with("statuses/followers.json?#{@rest_api_status_query_str}").
520
+ returns(stub(:get => twitter_records.to_json))
521
+ @ui.expects(:show_tweets).with(internal_records)
531
522
  @twitter.followers
532
523
  end
533
524
 
@@ -541,47 +532,43 @@ class ClientTest < UnitTestCase
541
532
  [:and, "and operator"]
542
533
  ].each do |op, desc|
543
534
  should "search tweets matching all the given words with #{desc}" do
544
- twitter_response, internal_records = create_test_twitter_records_from_search_api(
535
+ twitter_response, internal_records = create_search_api_status_records(
545
536
  {
546
537
  :from_user => "zanzibar",
547
538
  :status => "@foo, wassup? #greets",
548
- :created_at => Time.at(1).to_s,
549
539
  :to_user => "foo"
550
540
  },
551
541
  {
552
542
  :from_user => "spoonman",
553
543
  :status => "@foo long time no see #greets",
554
- :created_at => Time.at(1).to_s,
555
544
  :to_user => "foo"
556
- })
545
+ }
546
+ )
557
547
  @search_api.expects(:[]).
558
- with("search.json?q=%23greets%20%40foo&#{@search_api_query_str}").
559
- returns(stub(:get => twitter_response.to_json))
560
- @ui.expects(:show_record).with(internal_records[0])
561
- @ui.expects(:show_record).with(internal_records[1])
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)
562
551
  @twitter.search(["#greets", "@foo"], op)
563
552
  end
564
553
  end
565
554
 
566
555
  should "search tweets matching any of the given words with or operator" do
567
- twitter_response, internal_records = create_test_twitter_records_from_search_api(
556
+ twitter_response, internal_records = create_search_api_status_records(
568
557
  {
569
558
  :from_user => "zanzibar",
570
559
  :status => "spinning around the floor #habits",
571
- :created_at => Time.at(1).to_s,
572
560
  :to_user => "foo"
573
561
  },
574
562
  {
575
563
  :from_user => "spoonman",
576
564
  :status => "drinking coffee, again #neurotic",
577
- :created_at => Time.at(1).to_s,
578
565
  :to_user => "foo"
579
- })
566
+ }
567
+ )
580
568
  @search_api.expects(:[]).
581
- with("search.json?q=%23habits%20OR%20%23neurotic&#{@search_api_query_str}").
582
- returns(stub(:get => twitter_response.to_json))
583
- @ui.expects(:show_record).with(internal_records[0])
584
- @ui.expects(:show_record).with(internal_records[1])
569
+ with("search.json?q=%23habits%20OR%20%23neurotic&#{@search_api_query_str}").
570
+ returns(stub(:get => twitter_response.to_json))
571
+ @ui.expects(:show_tweets).with(internal_records)
585
572
  @twitter.search(["#habits", "#neurotic"], :or)
586
573
  end
587
574
  end
@@ -592,29 +579,27 @@ class ClientTest < UnitTestCase
592
579
  end
593
580
 
594
581
  should "authorize with OAuth and save config" do
595
- twitter_records, internal_records = create_test_twitter_status_records_from_rest_api({
596
- :from_user => @username,
597
- :status => "wassup?",
598
- :created_at => Time.at(1).to_s,
599
- :to_user => nil
600
- })
582
+ twitter_records, internal_records = create_rest_api_status_records({
583
+ :from_user => @username,
584
+ :status => "wassup?"
585
+ })
601
586
  access_token = 'access token'
602
587
  user_has_authorized = states('User has authorized?').starts_as(false)
603
588
  @oauth.expects(:request_signer).twice
604
589
  @oauth.expects(:authorize).
605
- yields(access_token).
606
- then(user_has_authorized.is(true))
590
+ yields(access_token).
591
+ then(user_has_authorized.is(true))
607
592
  http_subresource = mock
608
593
  http_subresource.expects(:get).
609
- raises(HttpError.new(401, 'Unauthorized')).
610
- when(user_has_authorized.is(false))
594
+ raises(HttpError.new(401, 'Unauthorized')).
595
+ when(user_has_authorized.is(false))
611
596
  http_subresource.expects(:get).
612
- returns(twitter_records.to_json).
613
- when(user_has_authorized.is(true))
597
+ returns(twitter_records.to_json).
598
+ when(user_has_authorized.is(true))
614
599
  @rest_api.expects(:[]).returns(http_subresource)
615
600
  @config.expects(:[]=).with(:oauth_access, access_token)
616
601
  @config.expects(:save)
617
- @ui.expects(:show_record).with(internal_records[0])
602
+ @ui.expects(:show_tweets).with(internal_records)
618
603
  @twitter.home
619
604
  end
620
605
  end
@@ -622,49 +607,56 @@ class ClientTest < UnitTestCase
622
607
 
623
608
  private
624
609
 
625
- def create_test_twitter_status_records_from_rest_api(*internal_records)
626
- twitter_records = internal_records.map do |internal_record|
610
+ def create_rest_api_status_records(*records)
611
+ create_twitter_and_internal_records(records, Twitter::REST_API_STATUS_PATHS) do |record|
627
612
  {
628
- "user" => { "screen_name" => internal_record[:from_user] },
629
- "created_at" => internal_record[:created_at],
630
- "text" => internal_record[:status],
631
- "in_reply_to_screen_name" => internal_record[:to_user]
613
+ "user" => { "screen_name" => record[:from_user] },
614
+ "created_at" => create_timestamp,
615
+ "text" => record[:status],
616
+ "in_reply_to_screen_name" => record[:to_user]
632
617
  }
633
618
  end
634
- [twitter_records, internal_records]
635
619
  end
636
620
 
637
- def create_test_twitter_user_records_from_rest_api(*internal_records)
638
- twitter_records = internal_records.map do |internal_record|
639
- twitter_record = { "screen_name" => internal_record[:from_user] }
640
- if internal_record[:status]
621
+ def create_rest_api_user_records(*records)
622
+ create_twitter_and_internal_records(records, Twitter::REST_API_USER_PATHS) do |record|
623
+ twitter_record = { "screen_name" => record[:from_user] }
624
+ if record[:status]
641
625
  twitter_record.merge!({
642
626
  "status" => {
643
- "created_at" => internal_record[:created_at],
644
- "text" => internal_record[:status],
645
- "in_reply_to_screen_name" => internal_record[:to_user],
627
+ "created_at" => create_timestamp,
628
+ "text" => record[:status],
629
+ "in_reply_to_screen_name" => record[:to_user],
646
630
  }
647
631
  })
648
632
  end
649
633
  twitter_record
650
634
  end
651
- [twitter_records, internal_records]
652
635
  end
653
636
 
654
- def create_test_twitter_records_from_search_api(*internal_records)
655
- twitter_search_records = internal_records.map do |internal_record|
637
+ def create_search_api_status_records(*records)
638
+ twitter_records, internal_records = create_twitter_and_internal_records(
639
+ records, Twitter::SEARCH_API_STATUS_PATHS) do |record|
656
640
  {
657
- "from_user" => internal_record[:from_user],
658
- "created_at" => internal_record[:created_at],
659
- "text" => internal_record[:status],
660
- "to_user" => internal_record[:to_user]
641
+ "from_user" => record[:from_user],
642
+ "created_at" => create_timestamp,
643
+ "text" => record[:status],
644
+ "to_user" => record[:to_user]
661
645
  }
662
646
  end
663
- twitter_records = {
664
- "results" => twitter_search_records
665
- }
647
+ twitter_records = { 'results' => twitter_records }
648
+ [twitter_records, internal_records]
649
+ end
650
+
651
+ def create_twitter_and_internal_records(records, paths, &twitter_record_maker)
652
+ twitter_records = records.map(&twitter_record_maker)
653
+ internal_records = twitter_records.map { |rec| Tweet.new(rec, paths) rescue nil }
666
654
  [twitter_records, internal_records]
667
655
  end
656
+
657
+ def create_timestamp
658
+ Time.at(1).to_s
659
+ end
668
660
  end
669
661
 
670
662
  end