twitter 5.8.0 → 5.9.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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/README.md +10 -36
  4. data/lib/twitter/base.rb +20 -3
  5. data/lib/twitter/basic_user.rb +6 -4
  6. data/lib/twitter/client.rb +2 -1
  7. data/lib/twitter/configuration.rb +1 -1
  8. data/lib/twitter/cursor.rb +1 -1
  9. data/lib/twitter/entities.rb +10 -6
  10. data/lib/twitter/enumerable.rb +2 -2
  11. data/lib/twitter/error.rb +7 -0
  12. data/lib/twitter/geo_results.rb +1 -1
  13. data/lib/twitter/list.rb +3 -2
  14. data/lib/twitter/media/photo.rb +1 -1
  15. data/lib/twitter/place.rb +13 -15
  16. data/lib/twitter/profile.rb +1 -1
  17. data/lib/twitter/profile_banner.rb +1 -1
  18. data/lib/twitter/rest/client.rb +17 -2
  19. data/lib/twitter/rest/friends_and_followers.rb +1 -1
  20. data/lib/twitter/rest/lists.rb +4 -2
  21. data/lib/twitter/rest/spam_reporting.rb +1 -1
  22. data/lib/twitter/rest/tweets.rb +17 -17
  23. data/lib/twitter/rest/users.rb +77 -13
  24. data/lib/twitter/rest/utils.rb +10 -6
  25. data/lib/twitter/search_results.rb +1 -1
  26. data/lib/twitter/settings.rb +4 -3
  27. data/lib/twitter/source_user.rb +3 -2
  28. data/lib/twitter/streaming/client.rb +7 -2
  29. data/lib/twitter/streaming/connection.rb +9 -2
  30. data/lib/twitter/streaming/response.rb +3 -3
  31. data/lib/twitter/suggestion.rb +1 -1
  32. data/lib/twitter/target_user.rb +1 -1
  33. data/lib/twitter/trend.rb +2 -1
  34. data/lib/twitter/trend_results.rb +1 -1
  35. data/lib/twitter/tweet.rb +4 -4
  36. data/lib/twitter/user.rb +60 -19
  37. data/lib/twitter/utils.rb +12 -5
  38. data/lib/twitter/version.rb +1 -1
  39. data/spec/fixtures/following.json +1 -1
  40. data/spec/fixtures/sferik.json +1 -1
  41. data/spec/helper.rb +14 -5
  42. data/spec/twitter/base_spec.rb +16 -4
  43. data/spec/twitter/direct_message_spec.rb +12 -13
  44. data/spec/twitter/entity/uri_spec.rb +2 -2
  45. data/spec/twitter/error_spec.rb +2 -2
  46. data/spec/twitter/media/photo_spec.rb +4 -4
  47. data/spec/twitter/oembed_spec.rb +3 -3
  48. data/spec/twitter/place_spec.rb +1 -1
  49. data/spec/twitter/rest/client_spec.rb +54 -14
  50. data/spec/twitter/rest/friends_and_followers_spec.rb +76 -76
  51. data/spec/twitter/rest/lists_spec.rb +85 -64
  52. data/spec/twitter/rest/timelines_spec.rb +2 -2
  53. data/spec/twitter/rest/tweets_spec.rb +20 -16
  54. data/spec/twitter/rest/undocumented_spec.rb +17 -17
  55. data/spec/twitter/rest/users_spec.rb +101 -17
  56. data/spec/twitter/streaming/client_spec.rb +1 -1
  57. data/spec/twitter/streaming/connection_spec.rb +32 -0
  58. data/spec/twitter/streaming/response_spec.rb +21 -0
  59. data/spec/twitter/trend_spec.rb +1 -1
  60. data/spec/twitter/tweet_spec.rb +14 -23
  61. data/spec/twitter/user_spec.rb +120 -13
  62. data/twitter.gemspec +3 -3
  63. metadata +8 -4
@@ -21,7 +21,7 @@ module Twitter
21
21
  # @return [Twitter::TrendResults]
22
22
  def initialize(attrs = {})
23
23
  @attrs = attrs
24
- @collection = Array(@attrs[:trends]).collect do |trend|
24
+ @collection = @attrs.fetch(:trends, []).collect do |trend|
25
25
  Trend.new(trend)
26
26
  end
27
27
  end
@@ -6,10 +6,9 @@ module Twitter
6
6
  class Tweet < Twitter::Identity
7
7
  include Twitter::Creatable
8
8
  include Twitter::Entities
9
- attr_reader :favorite_count, :favorited, :filter_level,
10
- :in_reply_to_screen_name, :in_reply_to_attrs_id,
11
- :in_reply_to_status_id, :in_reply_to_user_id, :lang,
12
- :retweet_count, :retweeted, :source, :text, :truncated
9
+ attr_reader :favorite_count, :filter_level, :in_reply_to_screen_name,
10
+ :in_reply_to_attrs_id, :in_reply_to_status_id, :in_reply_to_user_id,
11
+ :lang, :retweet_count, :source, :text
13
12
  deprecate_alias :favorites_count, :favorite_count
14
13
  deprecate_alias :favoriters_count, :favorite_count
15
14
  alias_method :in_reply_to_tweet_id, :in_reply_to_status_id
@@ -23,6 +22,7 @@ module Twitter
23
22
  alias_method :retweet?, :retweeted_status?
24
23
  alias_method :retweeted_tweet?, :retweeted_status?
25
24
  object_attr_reader :User, :user, :status
25
+ predicate_attr_reader :favorited, :retweeted, :truncated
26
26
 
27
27
  # @note May be > 140 characters.
28
28
  # @return [String]
@@ -10,36 +10,73 @@ module Twitter
10
10
  include Twitter::Creatable
11
11
  include Twitter::Profile
12
12
  include Memoizable
13
- attr_reader :connections, :contributors_enabled, :default_profile,
14
- :default_profile_image, :description, :favourites_count,
15
- :follow_request_sent, :followers_count, :friends_count,
16
- :geo_enabled, :is_translator, :lang, :listed_count, :location,
17
- :name, :notifications, :profile_background_color,
13
+ attr_reader :connections, :description, :favourites_count,
14
+ :followers_count, :friends_count, :lang, :listed_count,
15
+ :location, :name, :profile_background_color,
18
16
  :profile_background_image_url,
19
- :profile_background_image_url_https, :profile_background_tile,
20
- :profile_link_color, :profile_sidebar_border_color,
21
- :profile_sidebar_fill_color, :profile_text_color,
22
- :profile_use_background_image, :protected, :statuses_count,
23
- :time_zone, :utc_offset, :verified
17
+ :profile_background_image_url_https, :profile_link_color,
18
+ :profile_sidebar_border_color, :profile_sidebar_fill_color,
19
+ :profile_text_color, :statuses_count, :time_zone, :utc_offset
24
20
  alias_method :favorites_count, :favourites_count
25
21
  remove_method :favourites_count
26
22
  alias_method :profile_background_image_uri, :profile_background_image_url
27
23
  alias_method :profile_background_image_uri_https, :profile_background_image_url_https
28
- alias_method :translator?, :is_translator
29
24
  alias_method :tweets_count, :statuses_count
30
25
  object_attr_reader :Tweet, :status, :user
31
26
  alias_method :tweet, :status
32
27
  alias_method :tweet?, :status?
33
28
  alias_method :tweeted?, :status?
29
+ predicate_attr_reader :contributors_enabled, :default_profile,
30
+ :default_profile_image, :follow_request_sent,
31
+ :geo_enabled, :muting, :needs_phone_verification,
32
+ :notifications, :protected, :profile_background_tile,
33
+ :profile_use_background_image, :suspended, :verified
34
+ define_predicate_method :translator, :is_translator
35
+ define_predicate_method :translation_enabled, :is_translation_enabled
34
36
 
35
- # @return [Array<Twitter::Entity::URI>]
36
- def description_uris
37
- Array(@attrs[:entities][:description][:urls]).collect do |entity|
38
- Entity::URI.new(entity)
37
+ class << self
38
+ private
39
+
40
+ # Dynamically define a method for entity URIs
41
+ #
42
+ # @param key1 [Symbol]
43
+ # @param key2 [Symbol]
44
+ def define_entity_uris_methods(key1, key2)
45
+ array = key1.to_s.split('_')
46
+ index = array.index('uris')
47
+ array[index] = 'urls'
48
+ url_key = array.join('_').to_sym
49
+ define_entity_uris_method(key1, key2)
50
+ alias_method(url_key, key1)
51
+ define_entity_uris_predicate_method(key1)
52
+ alias_method(:"#{url_key}?", :"#{key1}?")
53
+ end
54
+
55
+ def define_entity_uris_method(key1, key2)
56
+ define_method(key1) do ||
57
+ @attrs.fetch(:entities, {}).fetch(key2, {}).fetch(:urls, []).collect do |url|
58
+ Entity::URI.new(url)
59
+ end
60
+ end
61
+ memoize(key1)
62
+ end
63
+
64
+ def define_entity_uris_predicate_method(key1)
65
+ define_method(:"#{key1}?") do ||
66
+ send(:"#{key1}").any?
67
+ end
68
+ memoize(:"#{key1}?")
39
69
  end
40
70
  end
41
- memoize :description_uris
42
- alias_method :description_urls, :description_uris
71
+
72
+ define_entity_uris_methods :description_uris, :description
73
+ define_entity_uris_methods :website_uris, :url
74
+
75
+ # @return [Boolean]
76
+ def entities?
77
+ !@attrs[:entities].nil? && @attrs[:entities].any? { |_, hash| hash[:urls].any? }
78
+ end
79
+ memoize :entities?
43
80
 
44
81
  # @return [String] The URL to the user.
45
82
  def uri
@@ -50,12 +87,16 @@ module Twitter
50
87
 
51
88
  # @return [String] The URL to the user's website.
52
89
  def website
53
- Addressable::URI.parse(@attrs[:url]) unless @attrs[:url].nil?
90
+ if website_urls?
91
+ website_urls.first.expanded_url
92
+ elsif @attrs[:url]
93
+ Addressable::URI.parse(@attrs[:url])
94
+ end
54
95
  end
55
96
  memoize :website
56
97
 
57
98
  def website?
58
- !!@attrs[:url]
99
+ !!(website_uris? || @attrs[:url])
59
100
  end
60
101
  memoize :website?
61
102
  end
@@ -8,9 +8,13 @@ module Twitter
8
8
 
9
9
  module ClassMethods
10
10
  def deprecate_alias(new_name, old_name)
11
- define_method(new_name) do |*args, &block|
11
+ define_method(new_name) do |*args|
12
12
  warn "#{Kernel.caller.first}: [DEPRECATION] ##{new_name} is deprecated. Use ##{old_name} instead."
13
- send(old_name, *args, &block)
13
+ if block_given?
14
+ send(old_name, *args, &Proc.new)
15
+ else
16
+ send(old_name, *args)
17
+ end
14
18
  end
15
19
  end
16
20
  end
@@ -20,9 +24,12 @@ module Twitter
20
24
  #
21
25
  # @param enumerable [Enumerable]
22
26
  # @return [Array, Enumerator]
23
- def flat_pmap(enumerable, &block)
24
- return to_enum(:flat_pmap, enumerable) unless block_given?
25
- pmap(enumerable, &block).flatten(1)
27
+ def flat_pmap(enumerable)
28
+ if block_given?
29
+ pmap(enumerable, &Proc.new).flatten(1)
30
+ else
31
+ to_enum(:flat_pmap, enumerable)
32
+ end
26
33
  end
27
34
  module_function :flat_pmap
28
35
 
@@ -1,7 +1,7 @@
1
1
  module Twitter
2
2
  class Version
3
3
  MAJOR = 5
4
- MINOR = 8
4
+ MINOR = 9
5
5
  PATCH = 0
6
6
  PRE = nil
7
7
 
@@ -1 +1 @@
1
- {"relationship":{"target":{"followed_by":true,"id_str":"14100886","following":false,"screen_name":"pengwynn","id":14100886},"source":{"marked_spam":false,"notifications_enabled":false,"followed_by":false,"want_retweets":true,"id_str":"7505382","blocking":false,"all_replies":false,"following":true,"screen_name":"sferik","id":7505382}}}
1
+ {"relationship":{"target":{"followed_by":true,"id_str":"14100886","following":false,"screen_name":"pengwynn","id":14100886},"source":{"marked_spam":false,"notifications_enabled":false,"muting":false,"followed_by":false,"want_retweets":true,"id_str":"7505382","blocking":false,"all_replies":false,"following":true,"screen_name":"sferik","id":7505382}}}
@@ -1 +1 @@
1
- {"id":7505382,"id_str":"7505382","name":"Erik Michaels-Ober","screen_name":"sferik","location":"San Francisco","description":"An ingredient in your recipe.","url":"https:\/\/github.com\/sferik","entities":{"url":{"urls":[{"url":"https:\/\/github.com\/sferik","expanded_url":null,"indices":[0,25]}]},"description":{"urls":[]}},"protected":false,"followers_count":2449,"friends_count":203,"listed_count":130,"created_at":"Mon Jul 16 12:59:01 +0000 2007","favourites_count":4306,"utc_offset":-28800,"time_zone":"Pacific Time (US & Canada)","geo_enabled":true,"verified":false,"statuses_count":8554,"lang":"en","status":{"created_at":"Tue Oct 02 23:21:06 +0000 2012","id":253273430739283969,"id_str":"253273430739283969","text":"@dakami RAM drives are the new SSDs","source":"\u003ca href=\"http:\/\/itunes.apple.com\/us\/app\/twitter\/id409789998?mt=12\" rel=\"nofollow\"\u003eTwitter for Mac\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":253272860473298944,"in_reply_to_status_id_str":"253272860473298944","in_reply_to_user_id":8917142,"in_reply_to_user_id_str":"8917142","in_reply_to_screen_name":"dakami","geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":0,"entities":{"hashtags":[],"urls":[],"user_mentions":[{"screen_name":"dakami","name":"Dan Kaminsky","id":8917142,"id_str":"8917142","indices":[0,7]}]},"favorited":false,"retweeted":false},"contributors_enabled":false,"is_translator":false,"profile_background_color":"000000","profile_background_image_url":"http:\/\/a0.twimg.com\/profile_background_images\/665875854\/bb0b3653dcf0644e344823e0a2eb3382.png","profile_background_image_url_https":"https:\/\/si0.twimg.com\/profile_background_images\/665875854\/bb0b3653dcf0644e344823e0a2eb3382.png","profile_background_tile":false,"profile_image_url":"http:\/\/a0.twimg.com\/profile_images\/1759857427\/image1326743606_normal.png","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/1759857427\/image1326743606_normal.png","profile_banner_url":"https:\/\/si0.twimg.com\/profile_banners\/7505382\/1348266581","profile_link_color":"0084B4","profile_sidebar_border_color":"000000","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false}
1
+ {"id":7505382,"id_str":"7505382","name":"Erik Michaels-Ober","screen_name":"sferik","location":"","description":"May contain forward-looking statements.","url":"https:\/\/t.co\/L2xIBazMPf","entities":{"url":{"urls":[{"url":"https:\/\/t.co\/L2xIBazMPf","expanded_url":"https:\/\/github.com\/sferik","display_url":"github.com\/sferik","indices":[0,23]}]},"description":{"urls":[]}},"protected":false,"followers_count":4051,"friends_count":361,"listed_count":238,"created_at":"Mon Jul 16 12:59:01 +0000 2007","favourites_count":8976,"utc_offset":3600,"time_zone":"Berlin","geo_enabled":true,"verified":false,"statuses_count":13844,"lang":"en","status":{"created_at":"Wed Mar 19 00:50:35 +0000 2014","id":446086297866993665,"id_str":"446086297866993665","text":"RT @AntonWSJ: Okean Elzy, #Ukraine's biggest rock band, performed in Berlin tonight amid many \"Glory to Ukraine!\" chants http:\/\/t.co\/dkIF8X\u2026","source":"\u003ca href=\"http:\/\/itunes.apple.com\/us\/app\/twitter\/id409789998?mt=12\" rel=\"nofollow\"\u003eTwitter for Mac\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"geo":null,"coordinates":null,"place":null,"contributors":null,"retweeted_status":{"created_at":"Tue Mar 18 23:56:08 +0000 2014","id":446072592227909632,"id_str":"446072592227909632","text":"Okean Elzy, #Ukraine's biggest rock band, performed in Berlin tonight amid many \"Glory to Ukraine!\" chants http:\/\/t.co\/dkIF8XvFyw","source":"\u003ca href=\"http:\/\/www.apple.com\" rel=\"nofollow\"\u003eiOS\u003c\/a\u003e","truncated":false,"in_reply_to_status_id":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id":null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name":null,"geo":null,"coordinates":null,"place":null,"contributors":null,"retweet_count":4,"favorite_count":2,"entities":{"hashtags":[{"text":"Ukraine","indices":[12,20]}],"symbols":[],"urls":[],"user_mentions":[],"media":[{"id":446072592047538176,"id_str":"446072592047538176","indices":[107,129],"media_url":"http:\/\/pbs.twimg.com\/media\/BjDEqLkIAAAIpE4.jpg","media_url_https":"https:\/\/pbs.twimg.com\/media\/BjDEqLkIAAAIpE4.jpg","url":"http:\/\/t.co\/dkIF8XvFyw","display_url":"pic.twitter.com\/dkIF8XvFyw","expanded_url":"http:\/\/twitter.com\/AntonWSJ\/status\/446072592227909632\/photo\/1","type":"photo","sizes":{"medium":{"w":600,"h":450,"resize":"fit"},"large":{"w":1024,"h":768,"resize":"fit"},"thumb":{"w":150,"h":150,"resize":"crop"},"small":{"w":340,"h":255,"resize":"fit"}}}]},"favorited":true,"retweeted":true,"possibly_sensitive":false,"lang":"en"},"retweet_count":4,"favorite_count":0,"entities":{"hashtags":[{"text":"Ukraine","indices":[26,34]}],"symbols":[],"urls":[],"user_mentions":[{"screen_name":"AntonWSJ","name":"Anton Troianovski","id":76773876,"id_str":"76773876","indices":[3,12]}],"media":[{"id":446072592047538176,"id_str":"446072592047538176","indices":[139,140],"media_url":"http:\/\/pbs.twimg.com\/media\/BjDEqLkIAAAIpE4.jpg","media_url_https":"https:\/\/pbs.twimg.com\/media\/BjDEqLkIAAAIpE4.jpg","url":"http:\/\/t.co\/dkIF8XvFyw","display_url":"pic.twitter.com\/dkIF8XvFyw","expanded_url":"http:\/\/twitter.com\/AntonWSJ\/status\/446072592227909632\/photo\/1","type":"photo","sizes":{"medium":{"w":600,"h":450,"resize":"fit"},"large":{"w":1024,"h":768,"resize":"fit"},"thumb":{"w":150,"h":150,"resize":"crop"},"small":{"w":340,"h":255,"resize":"fit"}}}]},"favorited":true,"retweeted":true,"possibly_sensitive":false,"lang":"en"},"contributors_enabled":false,"is_translator":false,"is_translation_enabled":false,"profile_background_color":"000000","profile_background_image_url":"http:\/\/pbs.twimg.com\/profile_background_images\/677717672\/bb0b3653dcf0644e344823e0a2eb3382.png","profile_background_image_url_https":"https:\/\/pbs.twimg.com\/profile_background_images\/677717672\/bb0b3653dcf0644e344823e0a2eb3382.png","profile_background_tile":false,"profile_image_url":"http:\/\/pbs.twimg.com\/profile_images\/378800000757402331\/d8dfba561e2e94112a737f17e7d138ca_normal.jpeg","profile_image_url_https":"https:\/\/pbs.twimg.com\/profile_images\/378800000757402331\/d8dfba561e2e94112a737f17e7d138ca_normal.jpeg","profile_banner_url":"https:\/\/pbs.twimg.com\/profile_banners\/7505382\/1385736840","profile_link_color":"0084B4","profile_sidebar_border_color":"000000","profile_sidebar_fill_color":"DDEEF6","profile_text_color":"333333","profile_use_background_image":true,"default_profile":false,"default_profile_image":false,"following":false,"follow_request_sent":false,"notifications":false,"suspended":false,"needs_phone_verification":false}
@@ -1,14 +1,11 @@
1
1
  require 'simplecov'
2
2
  require 'coveralls'
3
3
 
4
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
- SimpleCov::Formatter::HTMLFormatter,
6
- Coveralls::SimpleCov::Formatter
7
- ]
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter]
8
5
 
9
6
  SimpleCov.start do
10
7
  add_filter '/spec/'
11
- minimum_coverage(99.39)
8
+ minimum_coverage(99.15)
12
9
  end
13
10
 
14
11
  require 'twitter'
@@ -65,3 +62,15 @@ end
65
62
  def fixture(file)
66
63
  File.new(fixture_path + '/' + file)
67
64
  end
65
+
66
+ def capture_warning
67
+ begin
68
+ old_stderr = $stderr
69
+ $stderr = StringIO.new
70
+ yield
71
+ result = $stderr.string
72
+ ensure
73
+ $stderr = old_stderr
74
+ end
75
+ result
76
+ end
@@ -7,14 +7,26 @@ describe Twitter::Base do
7
7
 
8
8
  describe '#[]' do
9
9
  it 'calls methods using [] with symbol' do
10
- expect(@base[:object_id]).to be_an Integer
10
+ capture_warning do
11
+ expect(@base[:object_id]).to be_an Integer
12
+ end
11
13
  end
12
14
  it 'calls methods using [] with string' do
13
- expect(@base['object_id']).to be_an Integer
15
+ capture_warning do
16
+ expect(@base['object_id']).to be_an Integer
17
+ end
14
18
  end
15
19
  it 'returns nil for missing method' do
16
- expect(@base[:foo]).to be_nil
17
- expect(@base['foo']).to be_nil
20
+ capture_warning do
21
+ expect(@base[:foo]).to be_nil
22
+ expect(@base['foo']).to be_nil
23
+ end
24
+ end
25
+ it 'outputs a warning' do
26
+ warning = capture_warning do
27
+ @base[:object_id]
28
+ end
29
+ expect(warning).to match(/\[DEPRECATION\] #\[:object_id\] is deprecated. Use #object_id to fetch the value./)
18
30
  end
19
31
  end
20
32
 
@@ -53,27 +53,26 @@ describe Twitter::DirectMessage do
53
53
  end
54
54
 
55
55
  describe '#entities?' do
56
- it 'returns false if there are no entities set' do
57
- tweet = Twitter::DirectMessage.new(:id => 1_825_786_345)
58
- expect(tweet.entities?).to be false
59
- end
60
-
61
- it 'returns false if there are blank lists of entities set' do
62
- tweet = Twitter::DirectMessage.new(:id => 1_825_786_345, :entities => {:urls => []})
63
- expect(tweet.entities?).to be false
64
- end
65
56
  it 'returns true if there are entities set' do
66
57
  urls_array = [
67
58
  {
68
- :url => 'http://example.com/t.co',
59
+ :url => 'https://t.co/L2xIBazMPf',
69
60
  :expanded_url => 'http://example.com/expanded',
70
- :display_url => 'example.com/expandedâ¦',
61
+ :display_url => 'example.com/expanded',
71
62
  :indices => [10, 33],
72
63
  }
73
64
  ]
74
65
  tweet = Twitter::DirectMessage.new(:id => 1_825_786_345, :entities => {:urls => urls_array})
75
66
  expect(tweet.entities?).to be true
76
67
  end
68
+ it 'returns false if there are blank lists of entities set' do
69
+ tweet = Twitter::DirectMessage.new(:id => 1_825_786_345, :entities => {:urls => []})
70
+ expect(tweet.entities?).to be false
71
+ end
72
+ it 'returns false if there are no entities set' do
73
+ tweet = Twitter::DirectMessage.new(:id => 1_825_786_345)
74
+ expect(tweet.entities?).to be false
75
+ end
77
76
  end
78
77
 
79
78
  describe '#recipient' do
@@ -187,7 +186,7 @@ describe Twitter::DirectMessage do
187
186
  it 'returns an array of Entity::URIs when entities are set' do
188
187
  urls_array = [
189
188
  {
190
- :url => 'http://example.com/t.co',
189
+ :url => 'https://t.co/L2xIBazMPf',
191
190
  :expanded_url => 'http://example.com/expanded',
192
191
  :display_url => 'example.com/expanded…',
193
192
  :indices => [10, 33],
@@ -211,7 +210,7 @@ describe Twitter::DirectMessage do
211
210
  it 'can handle strange urls' do
212
211
  urls_array = [
213
212
  {
214
- :url => 'http://with_underscore.example.com/t.co',
213
+ :url => 'https://t.co/L2xIBazMPf',
215
214
  :expanded_url => 'http://with_underscore.example.com/expanded',
216
215
  :display_url => 'with_underscore.example.com/expanded…',
217
216
  :indices => [10, 33],
@@ -29,7 +29,7 @@ describe Twitter::Entity::URI do
29
29
  describe '#expanded_uri' do
30
30
  it 'returns a URI when the expanded_url is set' do
31
31
  uri = Twitter::Entity::URI.new(:expanded_url => 'https://github.com/sferik')
32
- expect(uri.expanded_uri).to be_a Addressable::URI
32
+ expect(uri.expanded_uri).to be_an Addressable::URI
33
33
  expect(uri.expanded_uri.to_s).to eq('https://github.com/sferik')
34
34
  end
35
35
  it 'returns nil when the expanded_url is not set' do
@@ -52,7 +52,7 @@ describe Twitter::Entity::URI do
52
52
  describe '#uri' do
53
53
  it 'returns a URI when the url is set' do
54
54
  uri = Twitter::Entity::URI.new(:url => 'https://github.com/sferik')
55
- expect(uri.uri).to be_a Addressable::URI
55
+ expect(uri.uri).to be_an Addressable::URI
56
56
  expect(uri.uri.to_s).to eq('https://github.com/sferik')
57
57
  end
58
58
  it 'returns nil when the url is not set' do
@@ -31,7 +31,7 @@ describe Twitter::Error do
31
31
  context "when JSON body contains #{key.inspect}" do
32
32
  before do
33
33
  body = "{\"#{key}\":\"Internal Server Error\"}" unless body.nil?
34
- stub_get('/1.1/statuses/user_timeline.json').with(:query => {:screen_name => 'sferik'}).to_return(:status => 500, :body => body)
34
+ stub_get('/1.1/statuses/user_timeline.json').with(:query => {:screen_name => 'sferik'}).to_return(:status => 500, :body => body, :headers => {:content_type => 'application/json; charset=utf-8'})
35
35
  end
36
36
  it 'raises an exception with the proper message' do
37
37
  expect { @client.user_timeline('sferik') }.to raise_error(Twitter::Error::InternalServerError)
@@ -42,7 +42,7 @@ describe Twitter::Error do
42
42
  Twitter::Error.errors.each do |status, exception|
43
43
  context "when HTTP status is #{status}" do
44
44
  before do
45
- stub_get('/1.1/statuses/user_timeline.json').with(:query => {:screen_name => 'sferik'}).to_return(:status => status, :body => '{}')
45
+ stub_get('/1.1/statuses/user_timeline.json').with(:query => {:screen_name => 'sferik'}).to_return(:status => status, :body => '{}', :headers => {:content_type => 'application/json; charset=utf-8'})
46
46
  end
47
47
  it "raises #{exception}" do
48
48
  expect { @client.user_timeline('sferik') }.to raise_error(exception)
@@ -59,7 +59,7 @@ describe Twitter::Media::Photo do
59
59
  describe '#expanded_uri' do
60
60
  it 'returns a URI when the expanded_url is set' do
61
61
  photo = Twitter::Media::Photo.new(:id => 1, :expanded_url => 'http://pbs.twimg.com/media/BQD6MPOCEAAbCH0.png')
62
- expect(photo.expanded_uri).to be_a Addressable::URI
62
+ expect(photo.expanded_uri).to be_an Addressable::URI
63
63
  expect(photo.expanded_uri.to_s).to eq('http://pbs.twimg.com/media/BQD6MPOCEAAbCH0.png')
64
64
  end
65
65
  it 'returns nil when the expanded_url is not set' do
@@ -82,7 +82,7 @@ describe Twitter::Media::Photo do
82
82
  describe '#media_uri' do
83
83
  it 'returns a URI when the media_url is set' do
84
84
  photo = Twitter::Media::Photo.new(:id => 1, :media_url => 'http://pbs.twimg.com/media/BQD6MPOCEAAbCH0.png')
85
- expect(photo.media_uri).to be_a Addressable::URI
85
+ expect(photo.media_uri).to be_an Addressable::URI
86
86
  expect(photo.media_uri.to_s).to eq('http://pbs.twimg.com/media/BQD6MPOCEAAbCH0.png')
87
87
  end
88
88
  it 'returns nil when the media_url is not set' do
@@ -105,7 +105,7 @@ describe Twitter::Media::Photo do
105
105
  describe '#media_uri_https' do
106
106
  it 'returns a URI when the media_url_https is set' do
107
107
  photo = Twitter::Media::Photo.new(:id => 1, :media_url_https => 'http://pbs.twimg.com/media/BQD6MPOCEAAbCH0.png')
108
- expect(photo.media_uri_https).to be_a Addressable::URI
108
+ expect(photo.media_uri_https).to be_an Addressable::URI
109
109
  expect(photo.media_uri_https.to_s).to eq('http://pbs.twimg.com/media/BQD6MPOCEAAbCH0.png')
110
110
  end
111
111
  it 'returns nil when the media_url_https is not set' do
@@ -128,7 +128,7 @@ describe Twitter::Media::Photo do
128
128
  describe '#uri' do
129
129
  it 'returns a URI when the url is set' do
130
130
  photo = Twitter::Media::Photo.new(:id => 1, :url => 'http://pbs.twimg.com/media/BQD6MPOCEAAbCH0.png')
131
- expect(photo.uri).to be_a Addressable::URI
131
+ expect(photo.uri).to be_an Addressable::URI
132
132
  expect(photo.uri.to_s).to eq('http://pbs.twimg.com/media/BQD6MPOCEAAbCH0.png')
133
133
  end
134
134
  it 'returns nil when the url is not set' do
@@ -5,7 +5,7 @@ describe Twitter::OEmbed do
5
5
  describe '#author_uri' do
6
6
  it 'returns a URI when the author_url is set' do
7
7
  oembed = Twitter::OEmbed.new(:author_url => 'https://twitter.com/sferik')
8
- expect(oembed.author_uri).to be_a Addressable::URI
8
+ expect(oembed.author_uri).to be_an Addressable::URI
9
9
  expect(oembed.author_uri.to_s).to eq('https://twitter.com/sferik')
10
10
  end
11
11
  it 'returns nil when the author_uri is not set' do
@@ -87,7 +87,7 @@ describe Twitter::OEmbed do
87
87
  describe '#provider_uri' do
88
88
  it 'returns a URI when the provider_url is set' do
89
89
  oembed = Twitter::OEmbed.new(:provider_url => 'http://twitter.com')
90
- expect(oembed.provider_uri).to be_a Addressable::URI
90
+ expect(oembed.provider_uri).to be_an Addressable::URI
91
91
  expect(oembed.provider_uri.to_s).to eq('http://twitter.com')
92
92
  end
93
93
  it 'returns nil when the provider_uri is not set' do
@@ -136,7 +136,7 @@ describe Twitter::OEmbed do
136
136
  describe '#uri' do
137
137
  it 'returns a URI when the url is set' do
138
138
  oembed = Twitter::OEmbed.new(:url => 'https://twitter.com/twitterapi/status/133640144317198338')
139
- expect(oembed.uri).to be_a Addressable::URI
139
+ expect(oembed.uri).to be_an Addressable::URI
140
140
  expect(oembed.uri.to_s).to eq('https://twitter.com/twitterapi/status/133640144317198338')
141
141
  end
142
142
  it 'returns nil when the url is not set' do
@@ -137,7 +137,7 @@ describe Twitter::Place do
137
137
  describe '#uri' do
138
138
  it 'returns a URI when the url is set' do
139
139
  place = Twitter::Place.new(:woeid => '247f43d441defc03', :url => 'https://api.twitter.com/1.1/geo/id/247f43d441defc03.json')
140
- expect(place.uri).to be_a Addressable::URI
140
+ expect(place.uri).to be_an Addressable::URI
141
141
  expect(place.uri.to_s).to eq('https://api.twitter.com/1.1/geo/id/247f43d441defc03.json')
142
142
  end
143
143
  it 'returns nil when the url is not set' do
@@ -65,6 +65,52 @@ describe Twitter::REST::Client do
65
65
  end
66
66
  end
67
67
 
68
+ describe '#connection_options=' do
69
+ it 'sets connection options' do
70
+ capture_warning do
71
+ @client.connection_options = 'connection options'
72
+ end
73
+ expect(@client.connection_options).to eq('connection options')
74
+ end
75
+ it 'outputs a warning' do
76
+ warning = capture_warning do
77
+ @client.connection_options = nil
78
+ end
79
+ expect(warning).to match(/\[DEPRECATION\] Twitter::REST::Client#connection_options= is deprecated and will be removed in version 6\.0\.0\.$/)
80
+ end
81
+ end
82
+
83
+ describe '#connection_options' do
84
+ it 'returns the connection options hash with proxy and user_agent' do
85
+ client = Twitter::REST::Client.new do |config|
86
+ config.consumer_key = 'CK'
87
+ config.consumer_secret = 'CS'
88
+ config.access_token = 'AT'
89
+ config.access_token_secret = 'ATS'
90
+ config.proxy = 'http://localhost:99'
91
+ config.user_agent = 'My Twitter Ruby Gem'
92
+ end
93
+
94
+ expect(client.connection_options[:proxy]).to eql('http://localhost:99')
95
+ expect(client.connection_options[:headers][:user_agent]).to eql('My Twitter Ruby Gem')
96
+ end
97
+ end
98
+
99
+ describe '#middleware=' do
100
+ it 'sets middleware' do
101
+ capture_warning do
102
+ @client.middleware = 'middleware'
103
+ end
104
+ expect(@client.middleware).to eq 'middleware'
105
+ end
106
+ it 'outputs a warning' do
107
+ warning = capture_warning do
108
+ @client.middleware = nil
109
+ end
110
+ expect(warning).to match(/\[DEPRECATION\] Twitter::REST::Client#middleware= is deprecated and will be removed in version 6\.0\.0\.$/)
111
+ end
112
+ end
113
+
68
114
  describe '#credentials?' do
69
115
  it 'returns true if all credentials are present' do
70
116
  client = Twitter::REST::Client.new(:consumer_key => 'CK', :consumer_secret => 'CS', :access_token => 'AT', :access_token_secret => 'AS')
@@ -128,29 +174,23 @@ describe Twitter::REST::Client do
128
174
  end
129
175
  it 'submits the correct auth header when no media is present' do
130
176
  # We use static values for nounce and timestamp to get a stable signature
131
- secret = {:consumer_key => 'CK', :consumer_secret => 'CS',
132
- :token => 'OT', :token_secret => 'OS',
133
- :nonce => 'b6ebe4c2a11af493f8a2290fe1296965', :timestamp => '1370968658'}
134
- header = {'Authorization' => /oauth_signature="FbthwmgGq02iQw%2FuXGEWaL6V6eM%3D"/}
177
+ secret = {:consumer_key => 'CK', :consumer_secret => 'CS', :token => 'OT', :token_secret => 'OS', :nonce => 'b6ebe4c2a11af493f8a2290fe1296965', :timestamp => '1370968658'}
178
+ headers = {:authorization => /oauth_signature="FbthwmgGq02iQw%2FuXGEWaL6V6eM%3D"/, :content_type => 'application/json; charset=utf-8'}
135
179
 
136
180
  allow(@client).to receive(:credentials).and_return(secret)
137
- stub_post('/1.1/statuses/update.json').with(:body => {:status => 'Just a test'}).to_return(:body => fixture('status.json'), :headers => {:content_type => 'application/json; charset=utf-8'})
181
+ stub_post('/1.1/statuses/update.json').with(:body => {:status => 'Just a test'}).to_return(:body => fixture('status.json'), :headers => headers)
138
182
  @client.update('Just a test')
139
- expect(a_post('/1.1/statuses/update.json').
140
- with(:headers => header)).to have_been_made
183
+ expect(a_post('/1.1/statuses/update.json').with(:headers => {:authorization => headers[:authorization]})).to have_been_made
141
184
  end
142
185
  it 'submits the correct auth header when media is present' do
143
186
  # We use static values for nounce and timestamp to get a stable signature
144
- secret = {:consumer_key => 'CK', :consumer_secret => 'CS',
145
- :token => 'OT', :token_secret => 'OS',
146
- :nonce => 'e08201ad0dab4897c99445056feefd95', :timestamp => '1370967652'}
147
- header = {'Authorization' => /oauth_signature="9ziouUPwZT9IWWRbJL8r0BerKYA%3D"/}
187
+ secret = {:consumer_key => 'CK', :consumer_secret => 'CS', :token => 'OT', :token_secret => 'OS', :nonce => 'e08201ad0dab4897c99445056feefd95', :timestamp => '1370967652'}
188
+ headers = {:authorization => /oauth_signature="9ziouUPwZT9IWWRbJL8r0BerKYA%3D"/, :content_type => 'application/json; charset=utf-8'}
148
189
 
149
190
  allow(@client).to receive(:credentials).and_return(secret)
150
- stub_post('/1.1/statuses/update_with_media.json').to_return(:body => fixture('status.json'), :headers => header)
191
+ stub_post('/1.1/statuses/update_with_media.json').to_return(:body => fixture('status.json'), :headers => headers)
151
192
  @client.update_with_media('Just a test', fixture('pbjt.gif'))
152
- expect(a_post('/1.1/statuses/update_with_media.json').
153
- with(:headers => header)).to have_been_made
193
+ expect(a_post('/1.1/statuses/update_with_media.json').with(:headers => {:authorization => headers[:authorization]})).to have_been_made
154
194
  end
155
195
  end
156
196