yt 0.25.13 → 0.32.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +305 -1
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +86 -5
  5. data/YOUTUBE_IT.md +3 -3
  6. data/lib/yt.rb +5 -2
  7. data/lib/yt/actions/list.rb +3 -3
  8. data/lib/yt/associations/has_authentication.rb +33 -1
  9. data/lib/yt/associations/has_reports.rb +13 -18
  10. data/lib/yt/collections/assets.rb +2 -2
  11. data/lib/yt/collections/authentications.rb +9 -2
  12. data/lib/yt/collections/base.rb +3 -3
  13. data/lib/yt/collections/bulk_report_jobs.rb +28 -0
  14. data/lib/yt/collections/bulk_reports.rb +24 -0
  15. data/lib/yt/collections/claims.rb +22 -1
  16. data/lib/yt/collections/comment_threads.rb +41 -0
  17. data/lib/yt/collections/content_owners.rb +1 -1
  18. data/lib/yt/collections/group_infos.rb +27 -0
  19. data/lib/yt/collections/group_items.rb +45 -0
  20. data/lib/yt/collections/reports.rb +75 -13
  21. data/lib/yt/collections/revocations.rb +30 -0
  22. data/lib/yt/collections/video_groups.rb +29 -0
  23. data/lib/yt/collections/videos.rb +34 -9
  24. data/lib/yt/constants/geography.rb +326 -0
  25. data/lib/yt/errors/forbidden.rb +1 -3
  26. data/lib/yt/errors/no_items.rb +1 -3
  27. data/lib/yt/errors/request_error.rb +10 -7
  28. data/lib/yt/errors/server_error.rb +1 -3
  29. data/lib/yt/errors/unauthorized.rb +3 -3
  30. data/lib/yt/models/account.rb +12 -0
  31. data/lib/yt/models/advertising_options_set.rb +4 -4
  32. data/lib/yt/models/bulk_report.rb +23 -0
  33. data/lib/yt/models/bulk_report_job.rb +23 -0
  34. data/lib/yt/models/channel.rb +21 -12
  35. data/lib/yt/models/claim.rb +13 -2
  36. data/lib/yt/models/comment.rb +37 -0
  37. data/lib/yt/models/comment_thread.rb +50 -0
  38. data/lib/yt/models/content_detail.rb +6 -0
  39. data/lib/yt/models/content_owner.rb +31 -1
  40. data/lib/yt/models/group_info.rb +16 -0
  41. data/lib/yt/models/group_item.rb +15 -0
  42. data/lib/yt/models/resource.rb +3 -10
  43. data/lib/yt/models/revocation.rb +12 -0
  44. data/lib/yt/models/right_owner.rb +0 -2
  45. data/lib/yt/models/snippet.rb +24 -3
  46. data/lib/yt/models/video.rb +42 -11
  47. data/lib/yt/models/video_group.rb +186 -0
  48. data/lib/yt/request.rb +5 -3
  49. data/lib/yt/version.rb +2 -2
  50. data/spec/collections/comment_threads_spec.rb +46 -0
  51. data/spec/collections/playlist_items_spec.rb +1 -1
  52. data/spec/collections/reports_spec.rb +2 -2
  53. data/spec/constants/geography_spec.rb +16 -0
  54. data/spec/models/annotation_spec.rb +1 -1
  55. data/spec/models/claim_spec.rb +15 -3
  56. data/spec/models/comment_spec.rb +40 -0
  57. data/spec/models/comment_thread_spec.rb +93 -0
  58. data/spec/models/content_detail_spec.rb +7 -0
  59. data/spec/models/reference_spec.rb +2 -2
  60. data/spec/models/request_spec.rb +21 -0
  61. data/spec/models/resource_spec.rb +0 -15
  62. data/spec/models/video_spec.rb +1 -1
  63. data/spec/requests/as_account/account_spec.rb +16 -4
  64. data/spec/requests/as_account/authentications_spec.rb +1 -13
  65. data/spec/requests/as_account/channel_spec.rb +15 -45
  66. data/spec/requests/as_account/playlist_item_spec.rb +3 -3
  67. data/spec/requests/as_account/playlist_spec.rb +5 -32
  68. data/spec/requests/as_account/video_spec.rb +2022 -21
  69. data/spec/requests/as_content_owner/account_spec.rb +4 -0
  70. data/spec/requests/as_content_owner/bulk_report_job_spec.rb +19 -0
  71. data/spec/requests/as_content_owner/channel_spec.rb +59 -270
  72. data/spec/requests/as_content_owner/content_owner_spec.rb +89 -1
  73. data/spec/requests/as_content_owner/playlist_spec.rb +0 -15
  74. data/spec/requests/as_content_owner/video_group_spec.rb +112 -0
  75. data/spec/requests/as_content_owner/video_spec.rb +72 -146
  76. data/spec/requests/as_server_app/channel_spec.rb +1 -21
  77. data/spec/requests/as_server_app/comment_spec.rb +22 -0
  78. data/spec/requests/as_server_app/comment_thread_spec.rb +27 -0
  79. data/spec/requests/as_server_app/comment_threads_spec.rb +41 -0
  80. data/spec/requests/as_server_app/playlist_item_spec.rb +2 -2
  81. data/spec/requests/as_server_app/playlist_spec.rb +1 -22
  82. data/spec/requests/as_server_app/video_spec.rb +21 -19
  83. data/spec/requests/as_server_app/videos_spec.rb +5 -5
  84. data/spec/requests/unauthenticated/video_spec.rb +1 -9
  85. data/spec/spec_helper.rb +1 -1
  86. data/yt.gemspec +2 -1
  87. metadata +51 -17
  88. data/lib/yt/collections/ids.rb +0 -27
  89. data/lib/yt/config.rb +0 -54
  90. data/lib/yt/models/configuration.rb +0 -70
  91. data/lib/yt/models/description.rb +0 -58
  92. data/lib/yt/models/url.rb +0 -91
  93. data/spec/models/configuration_spec.rb +0 -44
  94. data/spec/models/description_spec.rb +0 -94
  95. data/spec/models/url_spec.rb +0 -84
  96. data/spec/requests/as_account/resource_spec.rb +0 -18
@@ -14,6 +14,71 @@ describe Yt::ContentOwner, :partner do
14
14
  end
15
15
  end
16
16
 
17
+ describe '.videos' do
18
+ let(:video) { $content_owner.videos.where(order: 'viewCount').first }
19
+
20
+ specify 'returns the videos in network with the content owner with their tags and category ID' do
21
+ expect(video).to be_a Yt::Video
22
+ expect(video.tags).not_to be_empty
23
+ expect(video.category_id).not_to be_nil
24
+ end
25
+
26
+ describe '.includes(:snippet)' do
27
+ let(:video) { $content_owner.videos.includes(:snippet).first }
28
+
29
+ specify 'eager-loads the *full* snippet of each video' do
30
+ expect(video.instance_variable_defined? :@snippet).to be true
31
+ expect(video.channel_title).to be
32
+ expect(video.snippet).to be_complete
33
+ end
34
+ end
35
+
36
+ describe '.includes(:statistics, :status)' do
37
+ let(:video) { $content_owner.videos.includes(:statistics, :status).first }
38
+
39
+ specify 'eager-loads the statistics and status of each video' do
40
+ expect(video.instance_variable_defined? :@statistics_set).to be true
41
+ expect(video.instance_variable_defined? :@status).to be true
42
+ end
43
+ end
44
+
45
+ describe '.includes(:content_details)' do
46
+ let(:video) { $content_owner.videos.includes(:content_details).first }
47
+
48
+ specify 'eager-loads the statistics of each video' do
49
+ expect(video.instance_variable_defined? :@content_detail).to be true
50
+ end
51
+ end
52
+
53
+ describe '.includes(:claim)' do
54
+ let(:videos) { $content_owner.videos.includes(:claim) }
55
+ let(:video_with_claim) { videos.find{|v| v.claim.present?} }
56
+
57
+ specify 'eager-loads the claim of each video and its asset' do
58
+ expect(video_with_claim.claim).to be_a Yt::Claim
59
+ expect(video_with_claim.claim.id).to be_a String
60
+ expect(video_with_claim.claim.video_id).to eq video_with_claim.id
61
+ expect(video_with_claim.claim.asset).to be_a Yt::Asset
62
+ expect(video_with_claim.claim.asset.id).to be_a String
63
+ end
64
+ end
65
+ end
66
+
67
+ describe '.video_groups' do
68
+ let(:video_group) { $content_owner.video_groups.first }
69
+
70
+ specify 'returns the first video-group created by the account' do
71
+ expect(video_group).to be_a Yt::VideoGroup
72
+ expect(video_group.title).to be_a String
73
+ expect(video_group.item_count).to be_an Integer
74
+ expect(video_group.published_at).to be_a Time
75
+ end
76
+
77
+ specify 'allows to run reports against each video-group' do
78
+ expect(video_group.views).to be
79
+ end
80
+ end
81
+
17
82
  describe 'claims' do
18
83
  let(:asset_id) { ENV['YT_TEST_PARTNER_ASSET_ID'] }
19
84
  let(:video_id) { ENV['YT_TEST_PARTNER_CLAIMABLE_VIDEO_ID'] }
@@ -227,6 +292,29 @@ describe Yt::ContentOwner, :partner do
227
292
  end
228
293
  end
229
294
 
295
+ describe '.assets' do
296
+ describe 'given the content owner has assets' do
297
+ let(:asset) { $content_owner.assets.first }
298
+
299
+ it 'returns valid asset' do
300
+ expect(asset.id).to be_a String
301
+ expect(asset.type).to be_a String
302
+ expect(asset.title).to be_a String
303
+ expect(asset.custom_id).to be_a String
304
+ end
305
+ end
306
+ end
307
+
308
+ describe '.bulk_report_jobs' do
309
+ describe 'given the content owner has bulk report jobs' do
310
+ let(:job) { $content_owner.bulk_report_jobs.first }
311
+
312
+ it 'returns valid job' do
313
+ expect(job.id).to be_a String
314
+ expect(job.report_type_id).to be_a String
315
+ end
316
+ end
317
+ end
230
318
  # @note: The following test works, but YouTube API endpoint to mark
231
319
  # an asset as 'invalid' (soft-delete) does not work, and apparently
232
320
  # there is no way to update the status of a asset.
@@ -238,4 +326,4 @@ describe Yt::ContentOwner, :partner do
238
326
  # after { @asset.delete } # This does not seem to work
239
327
  # it { expect(@asset).to be_a Yt::Asset }
240
328
  # end
241
- end
329
+ end
@@ -100,21 +100,6 @@ describe Yt::Playlist, :partner do
100
100
  end
101
101
  end
102
102
 
103
- describe "#{metric} can be retrieved for a specific day" do
104
- let(:metric) { metric }
105
- let(:result) { playlist.public_send "#{metric}_on", date }
106
-
107
- context 'in which the playlist had data' do
108
- let(:date) { ENV['YT_TEST_PARTNER_VIDEO_DATE'] }
109
- it { expect(result).to be_a type }
110
- end
111
-
112
- context 'in the future' do
113
- let(:date) { 5.days.from_now }
114
- it { expect(result).to be_nil }
115
- end
116
- end
117
-
118
103
  describe "#{metric} can be grouped by range" do
119
104
  let(:metric) { metric }
120
105
 
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+ require 'yt/models/video_group'
3
+ require 'yt/models/group_item'
4
+
5
+ describe Yt::VideoGroup, :partner do
6
+ subject(:video_group) { Yt::VideoGroup.new id: id, auth: $content_owner }
7
+
8
+ context 'given a channel-group', :partner do
9
+ context 'managed by the authenticated Content Owner' do
10
+ let(:id) { ENV['YT_TEST_PARTNER_CHANNEL_GROUP_ID'] }
11
+
12
+ specify '.videos loads each video of each channel' do
13
+ video = video_group.videos.first
14
+ expect(video.instance_variable_defined? :@snippet).to be true
15
+ expect(video.instance_variable_defined? :@status).to be true
16
+ expect(video.instance_variable_defined? :@statistics_set).to be true
17
+ end
18
+
19
+ specify '.channels loads each channel' do
20
+ channel = video_group.channels.first
21
+ expect(channel.instance_variable_defined? :@snippet).to be true
22
+ end
23
+ end
24
+ end
25
+
26
+ context 'given a video-group', :partner do
27
+ context 'managed by the authenticated Content Owner' do
28
+ let(:id) { ENV['YT_TEST_PARTNER_VIDEO_GROUP_ID'] }
29
+
30
+ specify 'the title can be retrieved' do
31
+ expect(video_group.title).to be_a(String)
32
+ expect(video_group.title).not_to be_empty
33
+ end
34
+
35
+ specify 'the number of videos in the group can be retrieved' do
36
+ expect(video_group.item_count).to be_an(Integer)
37
+ expect(video_group.item_count).not_to be_zero
38
+ end
39
+
40
+ specify '.group_items retrieves the group items' do
41
+ expect(video_group.group_items.count).to be_an(Integer)
42
+ expect(video_group.group_items.map{|g| g}).to all(be_a Yt::GroupItem)
43
+ end
44
+
45
+ specify '.group_items.includes(:video) eager-loads each video' do
46
+ item = video_group.group_items.includes(:video).first
47
+ expect(item.video.instance_variable_defined? :@snippet).to be true
48
+ expect(item.video.instance_variable_defined? :@status).to be true
49
+ expect(item.video.instance_variable_defined? :@statistics_set).to be true
50
+ end
51
+
52
+ specify '.videos loads each video' do
53
+ video = video_group.videos.first
54
+ expect(video.instance_variable_defined? :@snippet).to be true
55
+ expect(video.instance_variable_defined? :@status).to be true
56
+ expect(video.instance_variable_defined? :@statistics_set).to be true
57
+ end
58
+
59
+ specify '.channels loads each channel' do
60
+ channel = video_group.channels.first
61
+ expect(channel.instance_variable_defined? :@snippet).to be true
62
+ end
63
+
64
+ describe 'multiple reports can be retrieved at once' do
65
+ metrics = {views: Integer,
66
+ estimated_minutes_watched: Integer, comments: Integer, likes: Integer,
67
+ dislikes: Integer, shares: Integer, subscribers_gained: Integer,
68
+ subscribers_lost: Integer,
69
+ videos_added_to_playlists: Integer, videos_removed_from_playlists: Integer,
70
+ average_view_duration: Integer,
71
+ card_impressions: Integer, card_clicks: Integer,
72
+ card_click_rate: Float, card_teaser_impressions: Integer,
73
+ card_teaser_clicks: Integer, card_teaser_click_rate: Float,
74
+ average_view_percentage: Float, annotation_clicks: Integer,
75
+ annotation_click_through_rate: Float,
76
+ annotation_close_rate: Float, estimated_revenue: Float, ad_impressions: Integer,
77
+ monetized_playbacks: Integer}
78
+
79
+ specify 'by day, and are chronologically sorted' do
80
+ range = {since: 5.days.ago.to_date, until: 3.days.ago.to_date}
81
+ result = video_group.reports range.merge(only: metrics, by: :day)
82
+ metrics.each do |metric, type|
83
+ expect(result[metric].keys).to all(be_a Date)
84
+ expect(result[metric].values).to all(be_a type)
85
+ expect(result[metric].keys.sort).to eq result[metric].keys
86
+ end
87
+ end
88
+
89
+ # NOTE: all the other filters also apply, not tested for brevity
90
+ end
91
+
92
+ describe 'viewer_percentage can be grouped by age group' do
93
+ let(:range) { {since: 1.year.ago.to_date, until: 1.week.ago.to_date} }
94
+ let(:keys) { range.values }
95
+
96
+ specify 'with the :by option set to :age_group' do
97
+ viewer_percentage = video_group.viewer_percentage range.merge by: :age_group
98
+ expect(viewer_percentage.keys - %w(65- 35-44 45-54 13-17 25-34 55-64 18-24)).to be_empty
99
+ expect(viewer_percentage.values).to all(be_instance_of Float)
100
+ end
101
+ end
102
+ end
103
+
104
+ context 'not managed by the authenticated Content Owner' do
105
+ let(:id) { 'ABExJp9gAAA' }
106
+
107
+ specify 'views cannot be retrieved' do
108
+ expect{video_group.views}.to raise_error Yt::Error
109
+ end
110
+ end
111
+ end
112
+ end
@@ -13,13 +13,15 @@ describe Yt::Video, :partner do
13
13
  it { expect{video.advertising_options_set}.not_to raise_error }
14
14
  end
15
15
 
16
- [:views, :uniques, :comments, :likes, :dislikes, :shares,
17
- :subscribers_gained, :subscribers_lost, :favorites_added,
16
+ [:views, :comments, :likes, :dislikes, :shares,
17
+ :subscribers_gained, :subscribers_lost,
18
18
  :videos_added_to_playlists, :videos_removed_from_playlists,
19
- :favorites_removed, :estimated_minutes_watched, :average_view_duration,
20
- :average_view_percentage, :impressions, :monetized_playbacks,
19
+ :estimated_minutes_watched, :average_view_duration,
20
+ :average_view_percentage, :ad_impressions, :monetized_playbacks,
21
21
  :annotation_clicks, :annotation_click_through_rate, :playback_based_cpm,
22
- :annotation_close_rate, :earnings].each do |metric|
22
+ :card_impressions, :card_clicks, :card_click_rate,
23
+ :card_teaser_impressions, :card_teaser_clicks, :card_teaser_click_rate,
24
+ :annotation_close_rate, :estimated_revenue].each do |metric|
23
25
  describe "#{metric} can be retrieved for a range of days" do
24
26
  let(:date_in) { ENV['YT_TEST_PARTNER_VIDEO_DATE'] }
25
27
  let(:date_out) { Date.parse(ENV['YT_TEST_PARTNER_VIDEO_DATE']) + 5 }
@@ -88,60 +90,18 @@ describe Yt::Video, :partner do
88
90
  end
89
91
  end
90
92
 
91
- {views: Integer, comments: Integer, dislikes: Integer,
92
- estimated_minutes_watched: Integer, average_view_duration: Integer,
93
- average_view_percentage: Float, impressions: Integer,
94
- subscribers_lost: Integer, subscribers_gained: Integer, likes: Integer,
95
- monetized_playbacks: Integer, earnings: Float}.each do |metric, type|
96
- describe "#{metric} can be retrieved for a specific day" do
97
- let(:metric) { metric }
98
- let(:result) { video.public_send "#{metric}_on", date }
99
-
100
- context 'in which the video had data' do
101
- let(:date) { ENV['YT_TEST_PARTNER_VIDEO_DATE'] }
102
- it { expect(result).to be_a type }
103
- end
104
-
105
- context 'in the future' do
106
- let(:date) { 5.days.from_now }
107
- it { expect(result).to be_nil }
108
- end
109
- end
110
- end
111
-
112
93
  {views: Integer, comments: Integer, likes: Integer, dislikes: Integer,
113
94
  shares: Integer, subscribers_gained: Integer, subscribers_lost: Integer,
114
- favorites_added: Integer,
115
95
  videos_added_to_playlists: Integer, videos_removed_from_playlists: Integer,
116
96
  estimated_minutes_watched: Integer, average_view_duration: Integer,
117
- average_view_percentage: Float, impressions: Integer,
97
+ average_view_percentage: Float, ad_impressions: Integer,
118
98
  monetized_playbacks: Integer, annotation_clicks: Integer,
119
99
  annotation_click_through_rate: Float, annotation_close_rate: Float,
120
- earnings: Float}.each do |metric, type|
121
- describe "#{metric} can be grouped by range" do
122
- let(:metric) { metric }
123
-
124
- context 'without a :by option (default)' do
125
- let(:result) { video.public_send metric }
126
- specify do
127
- expect(result.size).to be 1
128
- expect(result[:total]).to be_a type
129
- end
130
- end
131
-
132
- context 'with the :by option set to :range' do
133
- let(:result) { video.public_send metric, by: :range }
134
- specify do
135
- expect(result.size).to be 1
136
- expect(result[:total]).to be_a type
137
- end
138
- end
139
- end
140
- end
141
-
142
- {favorites_removed: Integer}.each do |metric, type|
100
+ card_impressions: Integer, card_clicks: Integer,
101
+ card_click_rate: Float, card_teaser_impressions: Integer,
102
+ card_teaser_clicks: Integer, card_teaser_click_rate: Float,
103
+ estimated_revenue: Float}.each do |metric, type|
143
104
  describe "#{metric} can be grouped by range" do
144
- let(:id) { 'NeMlqbX2Ifg' }
145
105
  let(:metric) { metric }
146
106
 
147
107
  context 'without a :by option (default)' do
@@ -163,12 +123,14 @@ describe Yt::Video, :partner do
163
123
  end
164
124
 
165
125
  [:views, :comments, :likes, :dislikes, :shares,
166
- :subscribers_gained, :subscribers_lost, :favorites_added,
126
+ :subscribers_gained, :subscribers_lost,
167
127
  :videos_added_to_playlists, :videos_removed_from_playlists,
168
128
  :estimated_minutes_watched, :average_view_duration,
169
- :average_view_percentage, :impressions, :monetized_playbacks,
129
+ :average_view_percentage, :ad_impressions, :monetized_playbacks,
130
+ :card_impressions, :card_clicks, :card_click_rate,
131
+ :card_teaser_impressions, :card_teaser_clicks, :card_teaser_click_rate,
170
132
  :annotation_clicks, :annotation_click_through_rate,
171
- :annotation_close_rate, :earnings].each do |metric|
133
+ :annotation_close_rate, :estimated_revenue].each do |metric|
172
134
  describe "#{metric} can be retrieved for a single country" do
173
135
  let(:result) { video.public_send metric, options }
174
136
 
@@ -189,6 +151,8 @@ describe Yt::Video, :partner do
189
151
  end
190
152
 
191
153
  [:views, :annotation_clicks, :annotation_click_through_rate,
154
+ :card_impressions, :card_clicks, :card_click_rate,
155
+ :card_teaser_impressions, :card_teaser_clicks, :card_teaser_click_rate,
192
156
  :annotation_close_rate].each do |metric|
193
157
  describe "#{metric} can be retrieved for a single country" do
194
158
  let(:result) { video.public_send metric, options }
@@ -210,15 +174,18 @@ describe Yt::Video, :partner do
210
174
  end
211
175
 
212
176
  describe 'multiple reports can be retrieved at once' do
213
- metrics = {views: Integer, uniques: Integer,
177
+ metrics = {views: Integer,
214
178
  estimated_minutes_watched: Integer, comments: Integer, likes: Integer,
215
179
  dislikes: Integer, shares: Integer, subscribers_gained: Integer,
216
- subscribers_lost: Integer, favorites_added: Integer,
180
+ subscribers_lost: Integer,
217
181
  videos_added_to_playlists: Integer, videos_removed_from_playlists: Integer,
218
- favorites_removed: Integer, average_view_duration: Integer,
182
+ average_view_duration: Integer,
219
183
  average_view_percentage: Float, annotation_clicks: Integer,
184
+ card_impressions: Integer, card_clicks: Integer,
185
+ card_click_rate: Float, card_teaser_impressions: Integer,
186
+ card_teaser_clicks: Integer, card_teaser_click_rate: Float,
220
187
  annotation_click_through_rate: Float,
221
- annotation_close_rate: Float, earnings: Float, impressions: Integer,
188
+ annotation_close_rate: Float, estimated_revenue: Float, ad_impressions: Integer,
222
189
  monetized_playbacks: Integer}
223
190
 
224
191
  specify 'by day' do
@@ -255,24 +222,24 @@ describe Yt::Video, :partner do
255
222
  end
256
223
  end
257
224
 
258
- describe 'earnings can be grouped by day' do
225
+ describe 'estimated_revenue can be grouped by day' do
259
226
  let(:range) { {since: 4.days.ago.to_date, until: 3.days.ago.to_date} }
260
227
  let(:keys) { range.values }
261
228
 
262
229
  specify 'with the :by option set to :day' do
263
- earnings = video.earnings range.merge by: :day
264
- expect(earnings.keys).to eq range.values
230
+ estimated_revenue = video.estimated_revenue range.merge by: :day
231
+ expect(estimated_revenue.keys).to eq range.values
265
232
  end
266
233
  end
267
234
 
268
- describe 'earnings can be grouped by country' do
235
+ describe 'estimated_revenue can be grouped by country' do
269
236
  let(:range) { {since: 4.days.ago, until: 3.days.ago} }
270
237
 
271
238
  specify 'with the :by option set to :country' do
272
- earnings = video.earnings range.merge by: :country
273
- expect(earnings.keys).to all(be_a String)
274
- expect(earnings.keys.map(&:length).uniq).to eq [2]
275
- expect(earnings.values).to all(be_a Float)
239
+ estimated_revenue = video.estimated_revenue range.merge by: :country
240
+ expect(estimated_revenue.keys).to all(be_a String)
241
+ expect(estimated_revenue.keys.map(&:length).uniq).to eq [2]
242
+ expect(estimated_revenue.values).to all(be_a Float)
276
243
  end
277
244
  end
278
245
 
@@ -383,10 +350,31 @@ describe Yt::Video, :partner do
383
350
 
384
351
  describe 'views can be grouped by device type' do
385
352
  let(:range) { {since: ENV['YT_TEST_PARTNER_VIDEO_DATE']} }
353
+ let(:keys) { Yt::Collections::Reports::DEVICE_TYPES.keys }
386
354
 
387
355
  specify 'with the :by option set to :device_type' do
388
356
  views = video.views range.merge by: :device_type
389
- expect(views.keys).to all(be_instance_of Symbol)
357
+ expect(views.keys - keys).to be_empty
358
+ expect(views.values).to all(be_an Integer)
359
+ end
360
+ end
361
+
362
+ describe 'views can be grouped by operating system' do
363
+ let(:keys) { Yt::Collections::Reports::OPERATING_SYSTEMS.keys }
364
+
365
+ specify 'with the :by option set to :operating_system' do
366
+ views = video.views by: :operating_system
367
+ expect(views.keys - keys).to be_empty
368
+ expect(views.values).to all(be_an Integer)
369
+ end
370
+ end
371
+
372
+ describe 'views can be grouped by YouTube product' do
373
+ let(:keys) { Yt::Collections::Reports::YOUTUBE_PRODUCTS.keys }
374
+
375
+ specify 'with the :by option set to :youtube_product' do
376
+ views = video.views by: :youtube_product
377
+ expect(views.keys - keys).to be_empty
390
378
  expect(views.values).to all(be_an Integer)
391
379
  end
392
380
  end
@@ -423,33 +411,14 @@ describe Yt::Video, :partner do
423
411
  end
424
412
  end
425
413
 
426
- describe 'uniques can be retrieved for a single US state' do
427
- let(:state_code) { 'NY' }
428
- let(:result) { video.uniques since: date, by: by, in: location }
429
- let(:date) { 4.days.ago }
430
-
431
- context 'and grouped by day' do
432
- let(:by) { :day }
433
-
434
- context 'with the :in option set to {state: state code}' do
435
- let(:location) { {state: state_code} }
436
- it { expect(result.keys.min).to eq date.to_date }
437
- end
438
-
439
- context 'with the :in option set to {country: "US", state: state code}' do
440
- let(:location) { {country: 'US', state: state_code} }
441
- it { expect(result.keys.min).to eq date.to_date }
442
- end
443
- end
444
- end
445
-
446
- describe 'uniques can be grouped by day' do
447
- let(:range) { {since: 4.days.ago.to_date, until: 3.days.ago.to_date} }
448
- let(:keys) { range.values }
414
+ describe 'views can be grouped by subscribed statuses' do
415
+ let(:range) { {since: ENV['YT_TEST_PARTNER_VIDEO_DATE']} }
416
+ let(:keys) { Yt::Collections::Reports::SUBSCRIBED_STATUSES.keys }
449
417
 
450
- specify 'with the :by option set to :day' do
451
- uniques = video.uniques range.merge by: :day
452
- expect(uniques.keys).to eq range.values
418
+ specify 'with the :by option set to subscribed statuses' do
419
+ views = video.views range.merge by: :subscribed_status
420
+ expect(views.keys - keys).to be_empty
421
+ expect(views.values).to all(be_an Integer)
453
422
  end
454
423
  end
455
424
 
@@ -621,49 +590,6 @@ describe Yt::Video, :partner do
621
590
  end
622
591
  end
623
592
 
624
- describe 'added favorites can be grouped by day' do
625
- let(:range) { {since: 4.days.ago.to_date, until: 3.days.ago.to_date} }
626
- let(:keys) { range.values }
627
-
628
- specify 'with the :by option set to :day' do
629
- favorites_added = video.favorites_added range.merge by: :day
630
- expect(favorites_added.keys).to eq range.values
631
- end
632
- end
633
-
634
- describe 'added favorites can be grouped by country' do
635
- let(:range) { {since: ENV['YT_TEST_PARTNER_VIDEO_DATE']} }
636
-
637
- specify 'with the :by option set to :country' do
638
- favorites_added = video.favorites_added range.merge by: :country
639
- expect(favorites_added.keys).to all(be_a String)
640
- expect(favorites_added.keys.map(&:length).uniq).to eq [2]
641
- expect(favorites_added.values).to all(be_an Integer)
642
- end
643
- end
644
-
645
- describe 'removed favorites can be grouped by day' do
646
- let(:range) { {since: 4.days.ago.to_date, until: 3.days.ago.to_date} }
647
- let(:keys) { range.values }
648
-
649
- specify 'with the :by option set to :day' do
650
- favorites_removed = video.favorites_removed range.merge by: :day
651
- expect(favorites_removed.keys).to eq range.values
652
- end
653
- end
654
-
655
- # TODO: Remove "removed favorites" since it’s deprecated!
656
- # describe 'removed favorites can be grouped by country' do
657
- # let(:range) { {since: ENV['YT_TEST_PARTNER_VIDEO_DATE']} }
658
- #
659
- # specify 'with the :by option set to :country' do
660
- # favorites_removed = video.favorites_removed range.merge by: :country
661
- # expect(favorites_removed.keys).to all(be_a String)
662
- # expect(favorites_removed.keys.map(&:length).uniq).to eq [2]
663
- # expect(favorites_removed.values).to all(be_an Integer)
664
- # end
665
- # end
666
-
667
593
  describe 'estimated minutes watched can be retrieved for a single US state' do
668
594
  let(:state_code) { 'NY' }
669
595
  let(:minutes) { video.estimated_minutes_watched since: date, by: by, in: location }
@@ -928,24 +854,24 @@ describe Yt::Video, :partner do
928
854
  end
929
855
  end
930
856
 
931
- describe 'impressions can be grouped by day' do
857
+ describe 'ad_impressions can be grouped by day' do
932
858
  let(:range) { {since: 4.days.ago.to_date, until: 3.days.ago.to_date} }
933
859
  let(:keys) { range.values }
934
860
 
935
861
  specify 'with the :by option set to :day' do
936
- impressions = video.impressions range.merge by: :day
937
- expect(impressions.keys).to eq range.values
862
+ ad_impressions = video.ad_impressions range.merge by: :day
863
+ expect(ad_impressions.keys).to eq range.values
938
864
  end
939
865
  end
940
866
 
941
- describe 'impressions can be grouped by country' do
867
+ describe 'ad_impressions can be grouped by country' do
942
868
  let(:range) { {since: ENV['YT_TEST_PARTNER_VIDEO_DATE']} }
943
869
 
944
870
  specify 'with the :by option set to :country' do
945
- impressions = video.impressions range.merge by: :country
946
- expect(impressions.keys).to all(be_a String)
947
- expect(impressions.keys.map(&:length).uniq).to eq [2]
948
- expect(impressions.values).to all(be_an Integer)
871
+ ad_impressions = video.ad_impressions range.merge by: :country
872
+ expect(ad_impressions.keys).to all(be_a String)
873
+ expect(ad_impressions.keys.map(&:length).uniq).to eq [2]
874
+ expect(ad_impressions.values).to all(be_an Integer)
949
875
  end
950
876
  end
951
877
 
@@ -1282,4 +1208,4 @@ describe Yt::Video, :partner do
1282
1208
  end
1283
1209
  end
1284
1210
  end
1285
- end
1211
+ end