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,19 +2,52 @@
2
2
 
3
3
  require "example_helper"
4
4
 
5
- FakeWeb.register_uri(:get, "http://search.twitter.com/search.json?q=braid%20game&rpp=2&page=1", :body => fixture("search.json"))
6
-
7
- Feature "search statuses" do
5
+ Feature "search tweets" do
8
6
  in_order_to "search statuses"
9
- as_a "any user"
10
- i_want_to "see latest statuses that match the search"
7
+ as_a "authenticated user"
8
+ i_want_to "see tweets matching the search"
9
+
10
+ SEARCH_OR_URL = "http://search.twitter.com/search.json?q=braid%20game&rpp=2&page=1"
11
+ SEARCH_AND_URL = "http://search.twitter.com/search.json?q=braid%20OR%20game&rpp=2&page=1"
12
+ SEARCH_FIXTURE = fixture("search.json")
13
+
14
+ Scenario "search words" do
15
+ When "I start the application with command 'search' and search words" do
16
+ stub_http_request(:get, SEARCH_OR_URL).to_return(:body => SEARCH_FIXTURE)
17
+ @output = start_cli %w{-n 2 search braid game}
18
+ end
19
+
20
+ Then "the application shows tweets matching all the words" do
21
+ @output[0].should == "thatswhatshesaid, in reply to hatguy, 5 hours ago:"
22
+ @output[1].should == "@hatguy braid, perhaps the best indie game of 2009"
23
+ @output[2].should == ""
24
+ @output[3].should == "jillv, 11 hours ago:"
25
+ @output[4].should == "braid is even better than of the games i'm in, expect re4"
26
+ end
27
+ end
28
+
29
+ Scenario "search tweets matching all words" do
30
+ When "I start the application with command 'search', option '-a', and search words" do
31
+ stub_http_request(:get, SEARCH_OR_URL).to_return(:body => SEARCH_FIXTURE)
32
+ @output = start_cli %w{-n 2 search -a braid game}
33
+ end
34
+
35
+ Then "the application shows tweets matching all the words" do
36
+ @output[0].should == "thatswhatshesaid, in reply to hatguy, 5 hours ago:"
37
+ @output[1].should == "@hatguy braid, perhaps the best indie game of 2009"
38
+ @output[2].should == ""
39
+ @output[3].should == "jillv, 11 hours ago:"
40
+ @output[4].should == "braid is even better than of the games i'm in, expect re4"
41
+ end
42
+ end
11
43
 
12
- Scenario "see statuses that match the search" do
13
- When "application is launched 'search' command and search words as extra arguments" do
14
- @output = launch_cli(%W{-a anyuser:anypwd --no-colors -n 2 search braid game})
44
+ Scenario "search tweets matching any words" do
45
+ When "I start the application with command 'search', option '-o', and search words" do
46
+ stub_http_request(:get, SEARCH_AND_URL).to_return(:body => SEARCH_FIXTURE)
47
+ @output = start_cli %w{-n 2 search -o braid game}
15
48
  end
16
49
 
17
- Then "the latest statuses that match the search are shown" do
50
+ Then "the application shows tweets matching any of the words" do
18
51
  @output[0].should == "thatswhatshesaid, in reply to hatguy, 5 hours ago:"
19
52
  @output[1].should == "@hatguy braid, perhaps the best indie game of 2009"
20
53
  @output[2].should == ""
@@ -23,16 +56,16 @@ Feature "search statuses" do
23
56
  end
24
57
  end
25
58
 
26
- Scenario "attempt searching without specifying search word" do
27
- When "application is launched 'search' command without extra arguments" do
28
- @status = launch_app("-a anyuser:anypwd --no-colors -n 2 search") do |pid, stdin, stdout|
29
- @output = stdout.readlines
59
+ Scenario "search without words" do
60
+ When "I start the application with 'search' command without search words" do
61
+ @status = start_app %w{-n 2 search} do |_, _, _, stderr|
62
+ @output = stderr.gets
30
63
  end
31
64
  end
32
65
 
33
- Then "the latest statuses that match the search are shown" do
34
- @output[0].should == "Error: No search word\n"
35
- @status.exitstatus.should == CLI::EXIT_ERROR
66
+ Then "the application shows error message and exists with error status" do
67
+ @output.should == "ERROR: No search words.\n"
68
+ @status.exitstatus.should == CommandLineError.status_code
36
69
  end
37
70
  end
38
71
  end
@@ -2,19 +2,18 @@
2
2
 
3
3
  require "example_helper"
4
4
 
5
- FakeWeb.register_uri(:get, "https://#{TEST_AUTH}@twitter.com/statuses/followers/#{TEST_USER}.json", :body => fixture("users.json"))
6
-
7
- Feature "show followers and their latest statuses" do
5
+ Feature "show followers" do
8
6
  in_order_to "to see who follows me"
9
7
  as_a "authenticated user"
10
- i_want_to "see my followers and their latest statuses, if any"
8
+ i_want_to "see my followers"
11
9
 
12
- Scenario "see followers and their latest statuses" do
13
- When "application is launched 'followers' command" do
14
- @output = launch_cli(%W{-a #{TEST_AUTH} --no-colors followers})
10
+ Scenario "show followers" do
11
+ When "I start the application with 'followers' command" do
12
+ stub_http_request(:get, "https://api.twitter.com/1/statuses/followers.json?count=20&page=1").to_return(:body => fixture("users.json"))
13
+ @output = start_cli %w{followers}
15
14
  end
16
15
 
17
- Then "my followers and their latest statuses are shown" do
16
+ Then "the application shows followers and their latest tweets (if any)" do
18
17
  @output[0].should == "jillv, 12 hours ago:"
19
18
  @output[1].should == "choosing next target"
20
19
  @output[2].should == ""
@@ -2,19 +2,18 @@
2
2
 
3
3
  require "example_helper"
4
4
 
5
- FakeWeb.register_uri(:get, "https://#{TEST_AUTH}@twitter.com/statuses/friends/#{TEST_USER}.json", :body => fixture("users.json"))
6
-
7
- Feature "show friends and their latest statuses" do
5
+ Feature "show friends" do
8
6
  in_order_to "to see who I follow"
9
7
  as_a "authenticated user"
10
- i_want_to "see my friends and their latest statuses, if any"
8
+ i_want_to "see my friends"
11
9
 
12
- Scenario "see friends and their latest statuses" do
13
- When "application is launched 'friends' command" do
14
- @output = launch_cli(%W{-a #{TEST_AUTH} --no-colors friends})
10
+ Scenario "show friends" do
11
+ When "I start the application with 'followers' command" do
12
+ stub_http_request(:get, "https://api.twitter.com/1/statuses/friends.json?count=20&page=1").to_return(:body => fixture("users.json"))
13
+ @output = start_cli %w{friends}
15
14
  end
16
15
 
17
- Then "my friends and their latest statuses are shown" do
16
+ Then "the application shows friends and their latest tweets (if any)" do
18
17
  @output[0].should == "jillv, 12 hours ago:"
19
18
  @output[1].should == "choosing next target"
20
19
  @output[2].should == ""
@@ -2,19 +2,22 @@
2
2
 
3
3
  require "example_helper"
4
4
 
5
- FakeWeb.register_uri(:get, "https://#{TEST_AUTH}@twitter.com/statuses/home_timeline.json?count=20&page=1", :body => fixture("home.json"))
6
-
7
- Feature "show the latest statuses in the home timeline for the user" do
8
- in_order_to "stay up-to-date"
5
+ Feature "show tweets from home timeline" do
6
+ in_order_to "stay up-to-date of other people's doings"
9
7
  as_a "authenticated user"
10
- i_want_to "see the latest statuses in the home view"
8
+ i_want_to "see my home timeline"
9
+
10
+ def setup
11
+ super
12
+ stub_http_request(:get, "https://api.twitter.com/1/statuses/home_timeline.json?count=20&page=1").to_return(:body => fixture("home.json"))
13
+ end
11
14
 
12
- Scenario "see home with colorization disabled" do
13
- When "application is launched with no command" do
14
- @output = launch_cli(%W{-a #{TEST_AUTH} --no-colors})
15
+ Scenario "with colorization disabled" do
16
+ When "I start the application with no command" do
17
+ @output = start_cli %w{--no-colors}
15
18
  end
16
19
 
17
- Then "the latest statuses in the home view are shown" do
20
+ Then "the application shows tweets from home timeline without colors" do
18
21
  @output[0].should == "pelit, 11 days ago:"
19
22
  @output[1].should == "F1-kausi alkaa marraskuussa http://bit.ly/1qQwjQ"
20
23
  @output[2].should == ""
@@ -23,12 +26,12 @@ Feature "show the latest statuses in the home timeline for the user" do
23
26
  end
24
27
  end
25
28
 
26
- Scenario "see home with colorization enabled" do
27
- When "application is launched with no command" do
28
- @output = launch_cli(%W{-a #{TEST_AUTH} --colors})
29
+ Scenario "with colorization enabled" do
30
+ When "I start the application with no command" do
31
+ @output = start_cli %w{--colors}
29
32
  end
30
33
 
31
- Then "the latest statuses in the home view are shown" do
34
+ Then "the application shows tweets from home timeline with colors" do
32
35
  @output[0].should == "\e[32mpelit\e[0m, 11 days ago:"
33
36
  @output[1].should == "F1-kausi alkaa marraskuussa \e[36mhttp://bit.ly/1qQwjQ\e[0m"
34
37
  @output[2].should == ""
@@ -38,11 +41,11 @@ Feature "show the latest statuses in the home timeline for the user" do
38
41
  end
39
42
 
40
43
  Scenario "the command for showing the home view is the default command" do
41
- When "application is launched with 'home' command" do
42
- @output = launch_cli(%W{-a #{TEST_AUTH} --no-colors home})
44
+ When "I start the application with 'home' command" do
45
+ @output = start_cli %w{--no-colors home}
43
46
  end
44
47
 
45
- Then "the latest statuses in the home view are shown" do
48
+ Then "the application shows tweets from home timeline" do
46
49
  @output[0].should == "pelit, 11 days ago:"
47
50
  @output[1].should == "F1-kausi alkaa marraskuussa http://bit.ly/1qQwjQ"
48
51
  @output[2].should == ""
@@ -2,19 +2,18 @@
2
2
 
3
3
  require "example_helper"
4
4
 
5
- FakeWeb.register_uri(:get, "https://#{TEST_AUTH}@twitter.com/statuses/mentions.json?count=20&page=1", :body => fixture("mentions.json"))
6
-
7
- Feature "show the latest statuses mentioning the user" do
8
- in_order_to "know if someone has mention me"
5
+ Feature "show tweets mentioning the user" do
6
+ in_order_to "know if someone has mentioned me"
9
7
  as_a "authenticated user"
10
- i_want_to "see the latest statuses that mention me"
8
+ i_want_to "see the tweets mentioning me"
11
9
 
12
- Scenario "see the latest statuses that mention me" do
13
- When "application is launched with 'mentions' command" do
14
- @output = launch_cli(%W{-a #{TEST_AUTH} --no-colors mentions})
10
+ Scenario "show tweets mentioning me" do
11
+ When "I start the application with 'mentions' command" do
12
+ stub_http_request(:get, "https://api.twitter.com/1/statuses/mentions.json?count=20&page=1").to_return(:body => fixture("mentions.json"))
13
+ @output = start_cli %w{mentions}
15
14
  end
16
15
 
17
- Then "the latest statuses that mention me are shown" do
16
+ Then "the application shows tweets mentioning me" do
18
17
  @output[0].should == "jillv, in reply to fooman, 3 days ago:"
19
18
  @output[1].should == "@fooman, did you see their eyes glow yellow after sunset?"
20
19
  @output[2].should == ""
@@ -2,19 +2,21 @@
2
2
 
3
3
  require "example_helper"
4
4
 
5
- FakeWeb.register_uri(:get, "https://#{TEST_AUTH}@twitter.com/statuses/user_timeline/#{TEST_USER}.json?count=20&page=1", :body => fixture("user.json"))
6
-
7
- Feature "show a specific user's latest statuses" do
8
- in_order_to "to see what is going on with a specific user"
5
+ Feature "show user's tweets" do
6
+ in_order_to "to see what's going on with a specific user"
9
7
  as_a "authenticated user"
10
- i_want_to "see the latest statuses of a specific user"
8
+ i_want_to "see that user's tweets"
9
+
10
+ USER_URL = "https://api.twitter.com/1/statuses/user_timeline.json?count=20&page=1&screen_name=%s"
11
+ USER_FIXTURE = fixture("user.json")
11
12
 
12
- Scenario "see my latest statuses" do
13
- When "application is launched 'user' command and without extra arguments" do
14
- @output = launch_cli(%W{-a #{TEST_AUTH} --no-colors user})
13
+ Scenario "show my tweets" do
14
+ When "I start the application with 'user' command without extra arguments" do
15
+ stub_http_request(:get, USER_URL % USER).to_return(:body => USER_FIXTURE)
16
+ @output = start_cli %w{user}
15
17
  end
16
18
 
17
- Then "my the latest statuses are shown" do
19
+ Then "the application shows my tweets" do
18
20
  @output[0].should == "jillv, in reply to chris, 9 hours ago:"
19
21
  @output[1].should == "@chris wait me until the garden"
20
22
  @output[2].should == ""
@@ -23,12 +25,13 @@ Feature "show a specific user's latest statuses" do
23
25
  end
24
26
  end
25
27
 
26
- Scenario "see the latest statuses of another user" do
27
- When "application is launched 'user' command and the user as an extra argument" do
28
- @output = launch_cli(%W{-a #{TEST_AUTH} --no-colors user #{TEST_USER}})
28
+ Scenario "show another user's tweets" do
29
+ When "I start the application with 'user' command with the user as argument" do
30
+ stub_http_request(:get, USER_URL % 'jillv').to_return(:body => USER_FIXTURE)
31
+ @output = start_cli %w{user jillv}
29
32
  end
30
33
 
31
- Then "the latest statuses of the user are shown" do
34
+ Then "the application shows the user's tweets" do
32
35
  @output[0].should == "jillv, in reply to chris, 9 hours ago:"
33
36
  @output[1].should == "@chris wait me until the garden"
34
37
  @output[2].should == ""
@@ -1,67 +1,184 @@
1
1
  # coding: utf-8
2
2
 
3
3
  require "example_helper"
4
+ require "yaml"
4
5
 
5
- FakeWeb.register_uri(:post, "https://#{TEST_AUTH}@twitter.com/statuses/update.json", :body => fixture("update.json"))
6
-
7
- Feature "update my status" do
6
+ Feature "update my status (send new tweet)" do
8
7
  in_order_to "tell something about me to the world"
9
8
  as_a "authenticated user"
10
9
  i_want_to "update my status"
11
10
 
12
- STATUS = "bored. going to sleep."
11
+ RUBYGEMS_FIXTURE = fixture('shorten_rubygems.html')
12
+ RUBYGEMS_FULL_URL = 'http://rubygems.org/'
13
+ RUBYGEMS_FULL_URL_ENC = 'http%3a%2f%2frubygems.org%2f'
14
+ RUBYGEMS_SHORT_URL = 'http://is.gd/gGazV'
15
+ RUBYGEMS_SHORT_URL_ENC = 'http%3a%2f%2fis.gd%2fgGazV'
16
+ RUBYLANG_FIXTURE = fixture('shorten_rubylang.html')
17
+ RUBYLANG_FULL_URL = 'http://ruby-lang.org/'
18
+ RUBYLANG_FULL_URL_ENC = 'http%3a%2f%2fruby-lang.org%2f'
19
+ RUBYLANG_SHORT_URL = 'http://is.gd/gGaM3'
20
+ RUBYLANG_SHORT_URL_ENC = 'http%3a%2f%2fis.gd%2fgGaM3'
21
+ SHORTEN_CONFIG = read_shorten_config
22
+ SHORTEN_METHOD = SHORTEN_CONFIG[:method].to_sym
23
+ STATUS_WITH_FULL_URLS = "ruby links: #{RUBYGEMS_FULL_URL} #{RUBYLANG_FULL_URL}"
24
+ STATUS_WITH_SHORT_URLS = "ruby links: #{RUBYGEMS_SHORT_URL} #{RUBYLANG_SHORT_URL}"
25
+ STATUS_WITHOUT_URLS = "bored. going to sleep."
26
+ UPDATE_FIXTURE_WITH_URLS = fixture("update_with_urls.json")
27
+ UPDATE_FIXTURE_WITHOUT_URLS = fixture("update_without_urls.json")
28
+ UPDATE_FIXTURE_UTF8 = fixture("update_utf8.json")
29
+ UPDATE_URL = "https://api.twitter.com/1/statuses/update.json"
30
+
31
+ BODY_WITH_SHORT_URLS = "status=ruby%20links%3a%20#{RUBYGEMS_SHORT_URL_ENC}%20#{RUBYLANG_SHORT_URL_ENC}"
32
+ BODY_WITHOUT_URLS = "status=bored.%20going%20to%20sleep."
13
33
 
14
34
  Scenario "update my status from command line with colorization disabled" do
15
- When "application is launched 'update' command" do
16
- @output = launch_cli(%W{-a #{TEST_AUTH} --no-colors update '#{STATUS}'}, "y")
35
+ When "I start the application with 'update' command with --no-colors option, give status in single command line argument, and confirm" do
36
+ stub_http_request(:post, UPDATE_URL).with(:body => BODY_WITHOUT_URLS).to_return(:body => UPDATE_FIXTURE_WITHOUT_URLS)
37
+ @output = start_cli %W{--no-colors update #{STATUS_WITHOUT_URLS}}, %w{y}
17
38
  end
18
39
 
19
- Then "the status sent is shown" do
20
- @output[5].should == "#{TEST_USER}, 9 hours ago:"
21
- @output[6].should == "#{STATUS}"
40
+ Then "the application sends and shows the status" do
41
+ @output[5].should == "#{USER}, 9 hours ago:"
42
+ @output[6].should == STATUS_WITHOUT_URLS
22
43
  end
23
44
  end
24
45
 
25
46
  Scenario "update my status from command line with colorization enabled" do
26
- When "application is launched 'update' command" do
27
- @output = launch_cli(%W{-a #{TEST_AUTH} --colors update '#{STATUS}'}, "y")
47
+ When "I start the application with 'update' command with --colors option, give status in single command line argument, and confirm" do
48
+ stub_http_request(:post, UPDATE_URL).with(:body => BODY_WITHOUT_URLS).to_return(:body => UPDATE_FIXTURE_WITHOUT_URLS)
49
+ @output = start_cli %W{--colors update #{STATUS_WITHOUT_URLS}}, %w{y}
50
+ end
51
+
52
+ Then "the application sends and shows the status" do
53
+ @output[5].should == "\e[32m#{USER}\e[0m, 9 hours ago:"
54
+ @output[6].should == STATUS_WITHOUT_URLS
55
+ end
56
+ end
57
+
58
+ Scenario "update my status from command line when message is spread over multiple arguments" do
59
+ When "I start the application with 'update' command, give status in multiple command line arguments, and confirm" do
60
+ stub_http_request(:post, UPDATE_URL).with(:body => BODY_WITHOUT_URLS).to_return(:body => UPDATE_FIXTURE_WITHOUT_URLS)
61
+ @output = start_cli(%w{--no-colors update} + STATUS_WITHOUT_URLS.split, %w{y})
28
62
  end
29
63
 
30
- Then "the status sent is shown" do
31
- @output[5].should == "\e[32m#{TEST_USER}\e[0m, 9 hours ago:"
32
- @output[6].should == "#{STATUS}"
64
+ Then "the application sends and shows the status" do
65
+ @output[5].should == "#{USER}, 9 hours ago:"
66
+ @output[6].should == STATUS_WITHOUT_URLS
33
67
  end
34
68
  end
35
69
 
36
- Scenario "cancel a status from command line" do
37
- When "application is launched 'update' command" do
38
- @output = launch_cli(%W{-a #{TEST_AUTH} --colors update '#{STATUS}'}, "n")
70
+ Scenario "cancel status update from command line" do
71
+ When "I start the application with 'update' command, and cancel" do
72
+ @output = start_cli %W{--no-colors update #{STATUS_WITHOUT_URLS}}, %w{n}
39
73
  end
40
74
 
41
- Then "a cancellation message is shown" do
75
+ Then "the application shows a cancellation message" do
42
76
  @output[3].should =~ /Cancelled./
43
77
  end
44
78
  end
45
79
 
46
80
  Scenario "update my status from STDIN" do
47
- When "application is launched 'update' command" do
48
- @output = launch_cli(%W{-a #{TEST_AUTH} --no-colors update}, STATUS, "y")
81
+ When "I start the application with 'update' command, give status from STDIN, and confirm" do
82
+ stub_http_request(:post, UPDATE_URL).with(:body => BODY_WITHOUT_URLS).to_return(:body => UPDATE_FIXTURE_WITHOUT_URLS)
83
+ @output = start_cli %w{update}, [STATUS_WITHOUT_URLS, 'y']
49
84
  end
50
85
 
51
- Then "the status sent is shown" do
86
+ Then "the application sends and shows the status" do
52
87
  @output[0].should == "Status update: "
53
- @output[5].should == "#{TEST_USER}, 9 hours ago:"
54
- @output[6].should == "#{STATUS}"
88
+ @output[5].should == "#{USER}, 9 hours ago:"
89
+ @output[6].should == STATUS_WITHOUT_URLS
55
90
  end
56
91
  end
57
92
 
58
93
  Scenario "cancel a status update from STDIN" do
59
- When "application is launched 'update' command" do
60
- @output = launch_cli(%W{-a #{TEST_AUTH} --no-colors update}, STATUS, "n")
94
+ When "I start the application with 'update' command, give status from STDIN, and cancel" do
95
+ @output = start_cli %w{update}, [STATUS_WITHOUT_URLS, 'n']
61
96
  end
62
97
 
63
- Then "a cancellation message is shown" do
98
+ Then "the application shows a cancellation message" do
64
99
  @output[3].should =~ /Cancelled./
65
100
  end
66
101
  end
102
+
103
+ if "".respond_to?(:encode)
104
+ Scenario "encode status in UTF-8 (String supports encoding)" do
105
+ When "I start the application with 'update' command, input latin1 encoded status, and confirm" do
106
+ @status_utf8 = "résumé"
107
+ @status_latin1 = @status_utf8.encode('ISO-8859-1')
108
+ url_encoded_body = "status=r%c3%a9sum%c3%a9"
109
+ stub_http_request(:post, UPDATE_URL).with(:body => url_encoded_body).to_return(:body => UPDATE_FIXTURE_UTF8)
110
+ @output = start_cli %W{--no-colors update #{@status_latin1}}, %w{y}
111
+ end
112
+
113
+ Then "the application sends and shows the status" do
114
+ # NOTE: Should be in latin-1, but StringIO converts it to UTF-8. At
115
+ # least on tty Ruby 1.9.2 outputs it in latin-1.
116
+ #@output[1].should == @status_latin1 # preview
117
+ @output[5].should == "#{USER}, 9 hours ago:"
118
+ @output[6].should == @status_utf8
119
+ end
120
+ end
121
+ else
122
+ Scenario "encode status in UTF-8 (String does not support encoding)" do
123
+ When "I have latin1 in LANG envar, start the application with 'update' command, input status, and confirm" do
124
+ @status_latin1 = "r\xe9sum\xe9"
125
+ @status_utf8 = "r\xc3\xa9sum\xc3\xa9"
126
+ url_encoded_body = "status=r%c3%a9sum%c3%a9"
127
+ stub_http_request(:post, UPDATE_URL).with(:body => url_encoded_body).to_return(:body => UPDATE_FIXTURE_UTF8)
128
+ tmp_kcode('NONE') do
129
+ tmp_env(:LANG => 'latin1') do
130
+ Tweetwine::CharacterEncoding.forget_guess
131
+ @output = start_cli %W{--no-colors update #{@status_latin1}}, %w{y}
132
+ end
133
+ end
134
+ end
135
+
136
+ Then "the application sends and shows the status" do
137
+ @output[1].should == @status_latin1 # preview
138
+ @output[5].should == "#{USER}, 9 hours ago:"
139
+ # TODO: we should convert status back to latin-1
140
+ @output[6].should == @status_utf8
141
+ end
142
+ end
143
+ end
144
+
145
+ Scenario "shorten URLs in status update" do
146
+ When "I have configured URL shortening, start the application with 'update' command, input status containing URLs, and confirm" do
147
+ @shorten_rubygems_body = "#{SHORTEN_CONFIG[:url_param_name]}=#{RUBYGEMS_FULL_URL_ENC}"
148
+ @shorten_rubylang_body = "#{SHORTEN_CONFIG[:url_param_name]}=#{RUBYLANG_FULL_URL_ENC}"
149
+ stub_http_request(SHORTEN_METHOD, SHORTEN_CONFIG[:service_url]).
150
+ with(:body => @shorten_rubygems_body).
151
+ to_return(:body => RUBYGEMS_FIXTURE)
152
+ stub_http_request(SHORTEN_METHOD, SHORTEN_CONFIG[:service_url]).
153
+ with(:body => @shorten_rubylang_body).
154
+ to_return(:body => RUBYLANG_FIXTURE)
155
+ stub_http_request(:post, UPDATE_URL).
156
+ with(:body => BODY_WITH_SHORT_URLS).
157
+ to_return(:body => UPDATE_FIXTURE_WITH_URLS)
158
+ @output = start_cli %W{--no-colors update #{STATUS_WITH_FULL_URLS}}, %w{y}
159
+ end
160
+
161
+ Then "the application shortens the URLs in the status before sending it" do
162
+ assert_requested(SHORTEN_METHOD, SHORTEN_CONFIG[:service_url], :body => @shorten_rubygems_body)
163
+ assert_requested(SHORTEN_METHOD, SHORTEN_CONFIG[:service_url], :body => @shorten_rubylang_body)
164
+ @output[1].should == STATUS_WITH_SHORT_URLS
165
+ @output[5].should == "#{USER}, 9 hours ago:"
166
+ @output[6].should == STATUS_WITH_SHORT_URLS
167
+ end
168
+ end
169
+
170
+ Scenario "disable URL shortening for status updates" do
171
+ When "I have configured URL shortening, start the application with 'update' command with --no-url-shorten option, input status containing URLs, and confirm" do
172
+ stub_http_request(:post, UPDATE_URL).
173
+ with(:body => BODY_WITH_SHORT_URLS).
174
+ to_return(:body => UPDATE_FIXTURE_WITH_URLS)
175
+ @output = start_cli %W{--no-colors --no-url-shorten update #{STATUS_WITH_SHORT_URLS}}, %w{y}
176
+ end
177
+
178
+ Then "the application passes URLs as is in the status" do
179
+ @output[1].should == STATUS_WITH_SHORT_URLS
180
+ @output[5].should == "#{USER}, 9 hours ago:"
181
+ @output[6].should == STATUS_WITH_SHORT_URLS
182
+ end
183
+ end
67
184
  end
@@ -2,46 +2,66 @@
2
2
 
3
3
  require "example_helper"
4
4
 
5
- FakeWeb.register_uri(:get, "https://#{TEST_AUTH}@twitter.com/statuses/home_timeline.json?count=20&page=1", :body => fixture("home.json"))
6
-
7
- Feature "using HTTP proxy setting" do
5
+ Feature "using HTTP proxy" do
8
6
  in_order_to "tweet behind an HTTP proxy"
9
7
  as_a "authenticated user"
10
8
  i_want_to "tweet as before"
11
9
 
12
- Scenario "Proxy is enabled via environment variable" do
13
- When "application is launched" do
14
- ENV['http_proxy'] = TEST_PROXY_URL
15
- @output = launch_cli(%W{-a #{TEST_AUTH} --no-colors})
10
+ def setup
11
+ super
12
+ stub_http_request(:get, "https://api.twitter.com/1/statuses/home_timeline.json?count=20&page=1").to_return(:body => fixture("home.json"))
13
+ end
14
+
15
+ Scenario "enable proxy via environment variable" do
16
+ When "I have proxy in envar, and start the application with 'home' command" do
17
+ ENV['http_proxy'] = PROXY_URL
18
+ @output = start_cli %w{home}
16
19
  end
17
20
 
18
- Then "the latest statuses in the home view are shown via proxy" do
19
- RestClient.proxy.should == TEST_PROXY_URL
21
+ Then "the application uses the proxy to fetch my home timeline" do
22
+ should_use_proxy
20
23
  @output[0].should == "pelit, 11 days ago:"
21
24
  end
22
25
  end
23
26
 
24
- Scenario "Proxy is enabled via command line option" do
25
- When "application is launched with --http-proxy" do
27
+ Scenario "enable proxy via command line option" do
28
+ When "I start the application with --http-proxy option and 'home' command" do
26
29
  ENV['http_proxy'] = nil
27
- @output = launch_cli(%W{-a #{TEST_AUTH} --no-colors --http-proxy #{TEST_PROXY_URL}})
30
+ @output = start_cli %W{--http-proxy #{PROXY_URL} home}
28
31
  end
29
32
 
30
- Then "the latest statuses in the home view are shown via proxy" do
31
- RestClient.proxy.should == TEST_PROXY_URL
33
+ Then "the application uses the proxy to fetch my home timeline" do
34
+ should_use_proxy
32
35
  @output[0].should == "pelit, 11 days ago:"
33
36
  end
34
37
  end
35
38
 
36
- Scenario "Proxy is disabled via command line option" do
37
- When "application is launched with --no-http-proxy" do
38
- ENV['http_proxy'] = TEST_PROXY_URL
39
- @output = launch_cli(%W{-a #{TEST_AUTH} --no-colors --no-http-proxy})
39
+ Scenario "disable proxy via command line option" do
40
+ When "I have proxy in envar, and start the application with --no-http-proxy option and 'home' command" do
41
+ ENV['http_proxy'] = PROXY_URL
42
+ @output = start_cli %w{--no-http-proxy home}
40
43
  end
41
44
 
42
- Then "the latest statuses in the home view are shown via proxy" do
43
- RestClient.proxy.should == nil
45
+ Then "the application does not use the proxy to fetch my home timeline" do
46
+ should_not_use_proxy
44
47
  @output[0].should == "pelit, 11 days ago:"
45
48
  end
46
49
  end
50
+
51
+ private
52
+
53
+ def should_use_proxy
54
+ nh = net_http
55
+ nh.proxy_class?.should == true
56
+ nh.instance_variable_get(:@proxy_address).should == PROXY_HOST
57
+ nh.instance_variable_get(:@proxy_port).should == PROXY_PORT
58
+ end
59
+
60
+ def should_not_use_proxy
61
+ net_http.proxy_class?.should == false
62
+ end
63
+
64
+ def net_http
65
+ CLI.http.instance_variable_get(:@http)
66
+ end
47
67
  end
@@ -0,0 +1,19 @@
1
+ # coding: utf-8
2
+
3
+ unless defined?(BasicObject)
4
+ module Tweetwine
5
+ # Adapted from
6
+ # <http://sequel.heroku.com/2010/03/31/sequelbasicobject-and-ruby-18/>.
7
+ class BasicObject
8
+ KEEP_METHODS = %w{__id__ __send__ instance_eval == equal? initialize}
9
+
10
+ def self.remove_methods!
11
+ ((private_instance_methods + instance_methods) - KEEP_METHODS).each do |m|
12
+ undef_method m
13
+ end
14
+ end
15
+
16
+ remove_methods!
17
+ end
18
+ end
19
+ end