tweetwine 0.3.2 → 0.4.0

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