tweetwine 0.2.12 → 0.3.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 (67) hide show
  1. data/CHANGELOG.rdoc +7 -0
  2. data/Gemfile +17 -0
  3. data/README.md +57 -47
  4. data/Rakefile +17 -26
  5. data/bin/tweetwine +11 -12
  6. data/contrib/tweetwine-completion.bash +2 -3
  7. data/example/application_behavior_example.rb +173 -0
  8. data/example/example_helper.rb +44 -28
  9. data/example/fixture/config.yaml +8 -0
  10. data/example/fixture/shorten_rubygems.html +5 -0
  11. data/example/fixture/shorten_rubylang.html +5 -0
  12. data/example/fixture/update_utf8.json +1 -0
  13. data/example/fixture/update_with_urls.json +1 -0
  14. data/example/fixture/{update.json → update_without_urls.json} +0 -0
  15. data/example/search_statuses_example.rb +49 -16
  16. data/example/show_followers_example.rb +7 -8
  17. data/example/show_friends_example.rb +7 -8
  18. data/example/show_home_example.rb +19 -16
  19. data/example/show_mentions_example.rb +8 -9
  20. data/example/show_user_example.rb +16 -13
  21. data/example/update_status_example.rb +143 -26
  22. data/example/use_http_proxy_example.rb +40 -20
  23. data/lib/tweetwine/basic_object.rb +19 -0
  24. data/lib/tweetwine/character_encoding.rb +59 -0
  25. data/lib/tweetwine/cli.rb +354 -230
  26. data/lib/tweetwine/config.rb +65 -0
  27. data/lib/tweetwine/http.rb +120 -0
  28. data/lib/tweetwine/oauth.rb +104 -0
  29. data/lib/tweetwine/obfuscate.rb +21 -0
  30. data/lib/tweetwine/option_parser.rb +31 -0
  31. data/lib/tweetwine/promise.rb +39 -0
  32. data/lib/tweetwine/twitter.rb +211 -0
  33. data/lib/tweetwine/{io.rb → ui.rb} +30 -21
  34. data/lib/tweetwine/url_shortener.rb +15 -9
  35. data/lib/tweetwine/util.rb +30 -15
  36. data/lib/tweetwine.rb +72 -12
  37. data/man/tweetwine.7 +43 -69
  38. data/man/tweetwine.7.ronn +57 -47
  39. data/test/character_encoding_test.rb +87 -0
  40. data/test/cli_test.rb +19 -6
  41. data/test/config_test.rb +244 -0
  42. data/test/fixture/oauth.rb +21 -0
  43. data/test/fixture/test_config.yaml +4 -4
  44. data/test/http_test.rb +199 -0
  45. data/test/oauth_test.rb +77 -0
  46. data/test/obfuscate_test.rb +16 -0
  47. data/test/option_parser_test.rb +60 -0
  48. data/test/promise_test.rb +56 -0
  49. data/test/test_helper.rb +76 -8
  50. data/test/twitter_test.rb +625 -0
  51. data/test/{io_test.rb → ui_test.rb} +92 -74
  52. data/test/url_shortener_test.rb +115 -135
  53. data/test/util_test.rb +136 -85
  54. data/tweetwine.gemspec +53 -0
  55. metadata +112 -56
  56. data/example/show_metadata_example.rb +0 -86
  57. data/lib/tweetwine/client.rb +0 -187
  58. data/lib/tweetwine/meta.rb +0 -5
  59. data/lib/tweetwine/options.rb +0 -24
  60. data/lib/tweetwine/retrying_http.rb +0 -99
  61. data/lib/tweetwine/startup_config.rb +0 -50
  62. data/man/tweetwine.1 +0 -109
  63. data/man/tweetwine.1.ronn +0 -69
  64. data/test/client_test.rb +0 -544
  65. data/test/options_test.rb +0 -45
  66. data/test/retrying_http_test.rb +0 -147
  67. data/test/startup_config_test.rb +0 -162
@@ -2,64 +2,82 @@
2
2
 
3
3
  require "test_helper"
4
4
 
5
- module Tweetwine
5
+ module Tweetwine::Test
6
6
 
7
- class IOTest < TweetwineTestCase
8
- context "An IO instance" do
7
+ class UITest < UnitTestCase
8
+ context "a UI instance" do
9
9
  setup do
10
- @input = mock()
11
- @output = mock()
12
- @io = IO.new({ :input => @input, :output => @output })
10
+ @in = mock
11
+ @out = mock
12
+ @err = mock
13
+ @ui = UI.new({ :in => @in, :out => @out, :err => @err })
13
14
  end
14
15
 
15
16
  should "output prompt and return input as trimmed" do
16
- @output.expects(:print).with("The answer: ")
17
- @input.expects(:gets).returns(" 42 ")
18
- assert_equal "42", @io.prompt("The answer")
17
+ @out.expects(:print).with("The answer: ")
18
+ @in.expects(:gets).returns(" 42 ")
19
+ assert_equal "42", @ui.prompt("The answer")
19
20
  end
20
21
 
21
22
  should "output info message" do
22
- @output.expects(:puts).with("foo")
23
- @io.info("foo")
23
+ @out.expects(:puts).with("foo")
24
+ @ui.info("foo")
25
+ end
26
+
27
+ should "output info message in process style when given a block" do
28
+ inform = sequence('inform')
29
+ @out.expects(:print).with("processing...").in_sequence(inform)
30
+ @out.expects(:puts).with(" done.").in_sequence(inform)
31
+ @ui.info("processing...") { true }
32
+ end
33
+
34
+ should "output empty line as info message" do
35
+ @out.expects(:puts).with("\n")
36
+ @ui.info
24
37
  end
25
38
 
26
39
  should "output warning message" do
27
- @output.expects(:puts).with("Warning: monkey patching ahead")
28
- @io.warn("monkey patching ahead")
40
+ @out.expects(:puts).with("Warning: monkey patching ahead")
41
+ @ui.warn("monkey patching ahead")
42
+ end
43
+
44
+ should "output error message" do
45
+ @err.expects(:puts).with("ERROR: Invalid monkey patch")
46
+ @ui.error("Invalid monkey patch")
29
47
  end
30
48
 
31
49
  should "confirm action, with positive answer" do
32
- @output.expects(:print).with("Fire nukes? [yN] ")
33
- @input.expects(:gets).returns("y")
34
- assert_equal true, @io.confirm("Fire nukes?")
50
+ @out.expects(:print).with("Fire nukes? [yN] ")
51
+ @in.expects(:gets).returns("y")
52
+ assert_equal true, @ui.confirm("Fire nukes?")
35
53
  end
36
54
 
37
55
  should "confirm action, with negative answer" do
38
- @output.expects(:print).with("Fire nukes? [yN] ")
39
- @input.expects(:gets).returns("n")
40
- assert_equal false, @io.confirm("Fire nukes?")
56
+ @out.expects(:print).with("Fire nukes? [yN] ")
57
+ @in.expects(:gets).returns("n")
58
+ assert_equal false, @ui.confirm("Fire nukes?")
41
59
  end
42
60
 
43
61
  should "confirm action, with default answer" do
44
- @output.expects(:print).with("Fire nukes? [yN] ")
45
- @input.expects(:gets).returns("")
46
- assert_equal false, @io.confirm("Fire nukes?")
62
+ @out.expects(:print).with("Fire nukes? [yN] ")
63
+ @in.expects(:gets).returns("")
64
+ assert_equal false, @ui.confirm("Fire nukes?")
47
65
  end
48
66
 
49
67
  context "with colorization disabled" do
50
68
  setup do
51
- @io = IO.new({ :input => @input, :output => @output, :colors => false })
69
+ @ui = UI.new({:in => @in, :out => @out, :colors => false })
52
70
  end
53
71
 
54
72
  should "output a record as user info when no status is given" do
55
73
  from_user = "fooman"
56
74
  record = { :from_user => from_user }
57
- @output.expects(:puts).with(<<-END
75
+ @out.expects(:puts).with(<<-END
58
76
  #{from_user}
59
77
 
60
78
  END
61
79
  )
62
- @io.show_record(record)
80
+ @ui.show_record(record)
63
81
  end
64
82
 
65
83
  should "output a record as status info when status is given, without in-reply info" do
@@ -72,13 +90,13 @@ class IOTest < TweetwineTestCase
72
90
  :to_user => nil
73
91
  }
74
92
  Util.expects(:humanize_time_diff).returns([2, "secs"])
75
- @output.expects(:puts).with(<<-END
93
+ @out.expects(:puts).with(<<-END
76
94
  #{from_user}, 2 secs ago:
77
95
  #{status}
78
96
 
79
97
  END
80
98
  )
81
- @io.show_record(record)
99
+ @ui.show_record(record)
82
100
  end
83
101
 
84
102
  should "output a record as status info when status is given, with in-reply info" do
@@ -92,13 +110,13 @@ class IOTest < TweetwineTestCase
92
110
  :to_user => to_user
93
111
  }
94
112
  Util.expects(:humanize_time_diff).returns([2, "secs"])
95
- @output.expects(:puts).with(<<-END
113
+ @out.expects(:puts).with(<<-END
96
114
  #{from_user}, in reply to #{to_user}, 2 secs ago:
97
115
  #{status}
98
116
 
99
117
  END
100
118
  )
101
- @io.show_record(record)
119
+ @ui.show_record(record)
102
120
  end
103
121
 
104
122
 
@@ -113,41 +131,41 @@ class IOTest < TweetwineTestCase
113
131
  :to_user => nil
114
132
  }
115
133
  Util.expects(:humanize_time_diff).returns([2, "secs"])
116
- @output.expects(:puts).with(<<-END
134
+ @out.expects(:puts).with(<<-END
117
135
  #{from_user}, 2 secs ago:
118
136
  #{unescaped_status}
119
137
 
120
138
  END
121
139
  )
122
- @io.show_record(record)
140
+ @ui.show_record(record)
123
141
  end
124
142
 
125
143
  should "output a preview of a status" do
126
144
  status = "@nick, check http://bit.ly/18rU_Vx"
127
- @output.expects(:puts).with(<<-END
145
+ @out.expects(:puts).with(<<-END
128
146
 
129
147
  #{status}
130
148
 
131
149
  END
132
150
  )
133
- @io.show_status_preview(status)
151
+ @ui.show_status_preview(status)
134
152
  end
135
153
  end
136
154
 
137
155
  context "with colorization enabled" do
138
156
  setup do
139
- @io = IO.new({ :input => @input, :output => @output, :colors => true })
157
+ @ui = UI.new({:in => @in, :out => @out, :colors => true})
140
158
  end
141
159
 
142
160
  should "output a record as user info when no status is given" do
143
161
  from_user = "fooman"
144
162
  record = { :from_user => from_user }
145
- @output.expects(:puts).with(<<-END
163
+ @out.expects(:puts).with(<<-END
146
164
  \e[32m#{from_user}\e[0m
147
165
 
148
166
  END
149
167
  )
150
- @io.show_record(record)
168
+ @ui.show_record(record)
151
169
  end
152
170
 
153
171
  should "output a record as status info when status is given, without in-reply info" do
@@ -160,13 +178,13 @@ class IOTest < TweetwineTestCase
160
178
  :to_user => nil
161
179
  }
162
180
  Util.expects(:humanize_time_diff).returns([2, "secs"])
163
- @output.expects(:puts).with(<<-END
181
+ @out.expects(:puts).with(<<-END
164
182
  \e[32m#{from_user}\e[0m, 2 secs ago:
165
183
  #{status}
166
184
 
167
185
  END
168
186
  )
169
- @io.show_record(record)
187
+ @ui.show_record(record)
170
188
  end
171
189
 
172
190
  should "output a record as status info when status is given, with in-reply info" do
@@ -179,24 +197,24 @@ class IOTest < TweetwineTestCase
179
197
  :to_user => to_user
180
198
  }
181
199
  Util.expects(:humanize_time_diff).returns([2, "secs"])
182
- @output.expects(:puts).with(<<-END
200
+ @out.expects(:puts).with(<<-END
183
201
  \e[32m#{from_user}\e[0m, in reply to \e[32m#{to_user}\e[0m, 2 secs ago:
184
202
  \e[33m@#{to_user}\e[0m! How are you doing?
185
203
 
186
204
  END
187
205
  )
188
- @io.show_record(record)
206
+ @ui.show_record(record)
189
207
  end
190
208
 
191
209
  should "output a preview of a status" do
192
210
  status = "@nick, check http://bit.ly/18rU_Vx"
193
- @output.expects(:puts).with(<<-END
211
+ @out.expects(:puts).with(<<-END
194
212
 
195
213
  \e[33m@nick\e[0m, check \e[36mhttp://bit.ly/18rU_Vx\e[0m
196
214
 
197
215
  END
198
216
  )
199
- @io.show_status_preview(status)
217
+ @ui.show_status_preview(status)
200
218
  end
201
219
 
202
220
  should "highlight hashtags in a status" do
@@ -209,13 +227,13 @@ class IOTest < TweetwineTestCase
209
227
  :to_user => nil
210
228
  }
211
229
  Util.expects(:humanize_time_diff).returns([2, "secs"])
212
- @output.expects(:puts).with(<<-END
230
+ @out.expects(:puts).with(<<-END
213
231
  \e[32m#{from_user}\e[0m, 2 secs ago:
214
232
  Lulz, so happy! \e[35m#{hashtags[0]}\e[0m \e[35m#{hashtags[1]}\e[0m
215
233
 
216
234
  END
217
235
  )
218
- @io.show_record(record)
236
+ @ui.show_record(record)
219
237
  end
220
238
 
221
239
  %w{http://is.gd/1qLk3 http://is.gd/1qLk3?id=foo}.each do |url|
@@ -228,13 +246,13 @@ Lulz, so happy! \e[35m#{hashtags[0]}\e[0m \e[35m#{hashtags[1]}\e[0m
228
246
  :to_user => nil
229
247
  }
230
248
  Util.expects(:humanize_time_diff).returns([2, "secs"])
231
- @output.expects(:puts).with(<<-END
249
+ @out.expects(:puts).with(<<-END
232
250
  \e[32m#{from_user}\e[0m, 2 secs ago:
233
251
  New Rails³ - \e[36m#{url}\e[0m
234
252
 
235
253
  END
236
254
  )
237
- @io.show_record(record)
255
+ @ui.show_record(record)
238
256
  end
239
257
  end
240
258
 
@@ -251,13 +269,13 @@ New Rails³ - \e[36m#{url}\e[0m
251
269
  :to_user => nil
252
270
  }
253
271
  Util.expects(:humanize_time_diff).returns([2, "secs"])
254
- @output.expects(:puts).with(<<-END
272
+ @out.expects(:puts).with(<<-END
255
273
  \e[32m#{from_user}\e[0m, 2 secs ago:
256
274
  Links: \e[36m#{first_url}\e[0m and \e[36m#{second_url}\e[0m np
257
275
 
258
276
  END
259
277
  )
260
- @io.show_record(record)
278
+ @ui.show_record(record)
261
279
  end
262
280
  end
263
281
 
@@ -271,13 +289,13 @@ Links: \e[36m#{first_url}\e[0m and \e[36m#{second_url}\e[0m np
271
289
  :to_user => nil
272
290
  }
273
291
  Util.expects(:humanize_time_diff).returns([2, "secs"])
274
- @output.expects(:puts).with(<<-END
292
+ @out.expects(:puts).with(<<-END
275
293
  \e[32m#{from_user}\e[0m, 2 secs ago:
276
294
  I salute you \e[33m#{users[0]}\e[0m, \e[33m#{users[1]}\e[0m, and \e[33m#{users[2]}\e[0m!
277
295
 
278
296
  END
279
297
  )
280
- @io.show_record(record)
298
+ @ui.show_record(record)
281
299
  end
282
300
 
283
301
  should "not highlight email addresses as usernames in a status" do
@@ -291,50 +309,50 @@ I salute you \e[33m#{users[0]}\e[0m, \e[33m#{users[1]}\e[0m, and \e[33m#{users[2
291
309
  :to_user => nil
292
310
  }
293
311
  Util.expects(:humanize_time_diff).returns([2, "secs"])
294
- @output.expects(:puts).with(<<-END
312
+ @out.expects(:puts).with(<<-END
295
313
  \e[32m#{from_user}\e[0m, 2 secs ago:
296
314
  Hi, \e[33m#{users[0]}\e[0m! You should notify \e[33m#{users[1]}\e[0m, #{email}
297
315
 
298
316
  END
299
317
  )
300
- @io.show_record(record)
318
+ @ui.show_record(record)
301
319
  end
302
320
  end
303
321
  end
304
322
 
305
- context "Username regex" do
323
+ context "username regex" do
306
324
  should "match a proper username reference" do
307
- assert_full_match IO::USERNAME_REGEX, "@nick"
308
- assert_full_match IO::USERNAME_REGEX, "@nick_man"
309
- assert_full_match IO::USERNAME_REGEX, "@nick"
310
- assert_full_match IO::USERNAME_REGEX, " @nick"
325
+ assert_full_match UI::USERNAME_REGEX, "@nick"
326
+ assert_full_match UI::USERNAME_REGEX, "@nick_man"
327
+ assert_full_match UI::USERNAME_REGEX, "@nick"
328
+ assert_full_match UI::USERNAME_REGEX, " @nick"
311
329
  end
312
330
 
313
331
  should "not match an inproper username reference" do
314
- assert_no_full_match IO::USERNAME_REGEX, "@"
315
- assert_no_full_match IO::USERNAME_REGEX, "nick"
316
- assert_no_full_match IO::USERNAME_REGEX, "-@nick"
317
- assert_no_full_match IO::USERNAME_REGEX, "@nick-man"
318
- assert_no_full_match IO::USERNAME_REGEX, "@nick "
319
- assert_no_full_match IO::USERNAME_REGEX, " @nick "
320
- assert_no_full_match IO::USERNAME_REGEX, "man @nick"
321
- assert_no_full_match IO::USERNAME_REGEX, "man@nick"
332
+ assert_no_full_match UI::USERNAME_REGEX, "@"
333
+ assert_no_full_match UI::USERNAME_REGEX, "nick"
334
+ assert_no_full_match UI::USERNAME_REGEX, "-@nick"
335
+ assert_no_full_match UI::USERNAME_REGEX, "@nick-man"
336
+ assert_no_full_match UI::USERNAME_REGEX, "@nick "
337
+ assert_no_full_match UI::USERNAME_REGEX, " @nick "
338
+ assert_no_full_match UI::USERNAME_REGEX, "man @nick"
339
+ assert_no_full_match UI::USERNAME_REGEX, "man@nick"
322
340
  end
323
341
  end
324
342
 
325
- context "Hashtag regex" do
343
+ context "hashtag regex" do
326
344
  should "match a proper hashtag reference" do
327
- assert_full_match IO::HASHTAG_REGEX, "#mayhem"
328
- assert_full_match IO::HASHTAG_REGEX, "#friday_mayhem"
329
- assert_full_match IO::HASHTAG_REGEX, "#friday-mayhem"
345
+ assert_full_match UI::HASHTAG_REGEX, "#mayhem"
346
+ assert_full_match UI::HASHTAG_REGEX, "#friday_mayhem"
347
+ assert_full_match UI::HASHTAG_REGEX, "#friday-mayhem"
330
348
  end
331
349
 
332
350
  should "not match an inproper hashtag reference" do
333
- assert_no_full_match IO::USERNAME_REGEX, "#"
334
- assert_no_full_match IO::USERNAME_REGEX, "mayhem"
335
- assert_no_full_match IO::USERNAME_REGEX, " #mayhem"
336
- assert_no_full_match IO::USERNAME_REGEX, "#mayhem "
337
- assert_no_full_match IO::USERNAME_REGEX, " #mayhem "
351
+ assert_no_full_match UI::USERNAME_REGEX, "#"
352
+ assert_no_full_match UI::USERNAME_REGEX, "mayhem"
353
+ assert_no_full_match UI::USERNAME_REGEX, " #mayhem"
354
+ assert_no_full_match UI::USERNAME_REGEX, "#mayhem "
355
+ assert_no_full_match UI::USERNAME_REGEX, " #mayhem "
338
356
  end
339
357
  end
340
358
  end
@@ -2,159 +2,139 @@
2
2
 
3
3
  require "test_helper"
4
4
 
5
- module Tweetwine
5
+ module Tweetwine::Test
6
6
 
7
- class UrlShortenerTest < TweetwineTestCase
8
- context "An UrlShortener instance" do
9
- setup do
10
- @http_client = mock()
7
+ class UrlShortenerTest < UnitTestCase
8
+ setup do
9
+ mock_http
10
+ end
11
+
12
+ context "for initialization" do
13
+ should "raise exception if service should be disabled" do
14
+ assert_raise(RuntimeError) do
15
+ UrlShortener.new(
16
+ :disable => true,
17
+ :service_url => "http://shorten.it/create",
18
+ :url_param_name => "url",
19
+ :xpath_selector => "//input[@id='short_url']/@value")
20
+ end
11
21
  end
12
22
 
13
- context "upon initialization" do
14
- should "raise exception if service URL is not given" do
15
- assert_raise(ArgumentError) do
16
- UrlShortener.new(
17
- @http_client,
18
- {
19
- :service_url => nil,
20
- :url_param_name => "url",
21
- :xpath_selector => "//input[@id='short_url']/@value"
22
- }
23
- )
24
- end
23
+ should "raise exception if service URL is not given" do
24
+ assert_raise(RequiredOptionError) do
25
+ UrlShortener.new(
26
+ :service_url => nil,
27
+ :url_param_name => "url",
28
+ :xpath_selector => "//input[@id='short_url']/@value")
25
29
  end
30
+ end
26
31
 
27
- should "raise exception if URL parameter name is not given" do
28
- assert_raise(ArgumentError) do
29
- UrlShortener.new(
30
- @http_client,
31
- {
32
- :service_url => "http://shorten.it/create",
33
- :url_param_name => nil,
34
- :xpath_selector => "//input[@id='short_url']/@value"
35
- }
36
- )
37
- end
32
+ should "raise exception if URL parameter name is not given" do
33
+ assert_raise(RequiredOptionError) do
34
+ UrlShortener.new(
35
+ :service_url => "http://shorten.it/create",
36
+ :url_param_name => nil,
37
+ :xpath_selector => "//input[@id='short_url']/@value")
38
38
  end
39
+ end
39
40
 
40
- should "raise exception if XPath selector is not given" do
41
- assert_raise(ArgumentError) do
42
- UrlShortener.new(
43
- @http_client,
44
- {
45
- :service_url => "http://shorten.it/create",
46
- :url_param_name => "url",
47
- :xpath_selector => nil
48
- }
49
- )
50
- end
41
+ should "raise exception if XPath selector is not given" do
42
+ assert_raise(RequiredOptionError) do
43
+ UrlShortener.new(
44
+ :service_url => "http://shorten.it/create",
45
+ :url_param_name => "url",
46
+ :xpath_selector => nil)
51
47
  end
48
+ end
52
49
 
53
- should "fallback to use GET method if not given explicitly" do
54
- url_shortener = UrlShortener.new(
55
- @http_client,
56
- {
57
- :service_url => "http://shorten.it/create",
58
- :url_param_name => "url",
59
- :xpath_selector => "//input[@id='short_url']/@value"
60
- }
61
- )
62
- assert_equal(:get, url_shortener.instance_variable_get(:@method))
50
+ should "fallback to use GET method if method is not given explicitly" do
51
+ url_shortener = UrlShortener.new(
52
+ :service_url => "http://shorten.it/create",
53
+ :url_param_name => "url",
54
+ :xpath_selector => "//input[@id='short_url']/@value")
55
+ @http.expects(:get)
56
+ url_shortener.shorten("http://www.ruby-doc.org/core/")
57
+ end
58
+
59
+ should "raise exception if given HTTP request method is unsupported" do
60
+ assert_raise(CommandLineError) do
61
+ UrlShortener.new(
62
+ :method => "put",
63
+ :service_url => "http://shorten.it/create",
64
+ :url_param_name => "url",
65
+ :xpath_selector => "//input[@id='short_url']/@value")
63
66
  end
64
67
  end
68
+ end
65
69
 
66
- context "at runtime" do
67
- context "configured for HTTP GET" do
68
- should "use parameters as URL query parameters, with just the URL parameter" do
69
- url_shortener = UrlShortener.new(
70
- @http_client,
71
- {
72
- :method => "get",
73
- :service_url => "http://shorten.it/create",
74
- :url_param_name => "url",
75
- :xpath_selector => "//input[@id='short_url']/@value"
76
- }
77
- )
78
- @http_client.expects(:get) \
79
- .with("http://shorten.it/create?url=http://www.ruby-doc.org/core/")
80
- url_shortener.shorten("http://www.ruby-doc.org/core/")
81
- end
70
+ context "at runtime" do
71
+ context "configured for HTTP GET" do
72
+ should "use parameters as URL query parameters, with just the URL parameter" do
73
+ url_shortener = UrlShortener.new(
74
+ :method => "get",
75
+ :service_url => "http://shorten.it/create",
76
+ :url_param_name => "url",
77
+ :xpath_selector => "//input[@id='short_url']/@value")
78
+ @http.expects(:get).
79
+ with("http://shorten.it/create?url=http://www.ruby-doc.org/core/")
80
+ url_shortener.shorten("http://www.ruby-doc.org/core/")
81
+ end
82
82
 
83
- should "use parameters as URL query parameters, with additional extra parameters" do
84
- url_shortener = UrlShortener.new(
85
- @http_client,
86
- {
87
- :method => "get",
88
- :service_url => "http://shorten.it/create",
89
- :url_param_name => "url",
90
- :extra_params => {
91
- :token => "xyz"
92
- },
93
- :xpath_selector => "//input[@id='short_url']/@value"
94
- }
95
- )
96
- @http_client.expects(:get) \
97
- .with("http://shorten.it/create?token=xyz&url=http://www.ruby-doc.org/core/")
98
- url_shortener.shorten("http://www.ruby-doc.org/core/")
99
- end
83
+ should "use parameters as URL query parameters, with additional extra parameters" do
84
+ url_shortener = UrlShortener.new(
85
+ :method => "get",
86
+ :service_url => "http://shorten.it/create",
87
+ :url_param_name => "url",
88
+ :extra_params => {
89
+ :token => "xyz"
90
+ },
91
+ :xpath_selector => "//input[@id='short_url']/@value")
92
+ @http.expects(:get).
93
+ with("http://shorten.it/create?token=xyz&url=http://www.ruby-doc.org/core/")
94
+ url_shortener.shorten("http://www.ruby-doc.org/core/")
100
95
  end
96
+ end
101
97
 
102
- context "configured for HTTP POST" do
103
- should "use parameters as payload, with just the URL parameter" do
104
- url_shortener = UrlShortener.new(
105
- @http_client,
106
- {
107
- :method => "post",
108
- :service_url => "http://shorten.it/create",
109
- :url_param_name => "url",
110
- :xpath_selector => "//input[@id='short_url']/@value"
111
- }
112
- )
113
- @http_client.expects(:post) \
114
- .with("http://shorten.it/create", {:url => "http://www.ruby-doc.org/core/"})
115
- url_shortener.shorten("http://www.ruby-doc.org/core/")
116
- end
98
+ context "configured for HTTP POST" do
99
+ should "use parameters as payload, with just the URL parameter" do
100
+ url_shortener = UrlShortener.new(
101
+ :method => "post",
102
+ :service_url => "http://shorten.it/create",
103
+ :url_param_name => "url",
104
+ :xpath_selector => "//input[@id='short_url']/@value")
105
+ @http.expects(:post).
106
+ with("http://shorten.it/create", {:url => "http://www.ruby-doc.org/core/"})
107
+ url_shortener.shorten("http://www.ruby-doc.org/core/")
108
+ end
117
109
 
118
- should "use parameters as payload, with additional extra parameters" do
119
- url_shortener = UrlShortener.new(
120
- @http_client,
121
- {
122
- :method => "post",
123
- :service_url => "http://shorten.it/create",
124
- :url_param_name => "url",
125
- :extra_params => {
126
- :token => "xyz"
127
- },
128
- :xpath_selector => "//input[@id='short_url']/@value"
129
- }
130
- )
131
- @http_client.expects(:post) \
132
- .with("http://shorten.it/create", {
133
- :token => "xyz",
134
- :url => "http://www.ruby-doc.org/core/"
135
- })
136
- url_shortener.shorten("http://www.ruby-doc.org/core/")
137
- end
110
+ should "use parameters as payload, with additional extra parameters" do
111
+ url_shortener = UrlShortener.new(
112
+ :method => "post",
113
+ :service_url => "http://shorten.it/create",
114
+ :url_param_name => "url",
115
+ :extra_params => {
116
+ :token => "xyz"
117
+ },
118
+ :xpath_selector => "//input[@id='short_url']/@value")
119
+ @http.expects(:post).
120
+ with("http://shorten.it/create",
121
+ :token => "xyz",
122
+ :url => "http://www.ruby-doc.org/core/")
123
+ url_shortener.shorten("http://www.ruby-doc.org/core/")
138
124
  end
125
+ end
139
126
 
140
- context "in erroenous situations" do
141
- should "raise HttpError upon connection error" do
142
- url_shortener = UrlShortener.new(
143
- @http_client,
144
- {
145
- :method => "post",
146
- :service_url => "http://shorten.it/create",
147
- :url_param_name => "url",
148
- :xpath_selector => "//input[@id='short_url']/@value"
149
- }
150
- )
151
- @http_client.expects(:post) \
152
- .with("http://shorten.it/create", {
153
- :url => "http://www.ruby-doc.org/core/"
154
- }) \
155
- .raises(HttpError, "connection error")
156
- assert_raise(HttpError) { url_shortener.shorten("http://www.ruby-doc.org/core/") }
157
- end
127
+ context "in erroenous network situations" do
128
+ should "pass exceptions through" do
129
+ url_shortener = UrlShortener.new(
130
+ :method => "post",
131
+ :service_url => "http://shorten.it/create",
132
+ :url_param_name => "url",
133
+ :xpath_selector => "//input[@id='short_url']/@value")
134
+ @http.expects(:post).
135
+ with("http://shorten.it/create", :url => "http://www.ruby-doc.org/core/").
136
+ raises(HttpError.new(404, "Not Found"))
137
+ assert_raise(HttpError) { url_shortener.shorten("http://www.ruby-doc.org/core/") }
158
138
  end
159
139
  end
160
140
  end