yt 0.25.13 → 0.32.2
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +305 -1
- data/MIT-LICENSE +1 -1
- data/README.md +86 -5
- data/YOUTUBE_IT.md +3 -3
- data/lib/yt.rb +5 -2
- data/lib/yt/actions/list.rb +3 -3
- data/lib/yt/associations/has_authentication.rb +33 -1
- data/lib/yt/associations/has_reports.rb +13 -18
- data/lib/yt/collections/assets.rb +2 -2
- data/lib/yt/collections/authentications.rb +9 -2
- data/lib/yt/collections/base.rb +3 -3
- data/lib/yt/collections/bulk_report_jobs.rb +28 -0
- data/lib/yt/collections/bulk_reports.rb +24 -0
- data/lib/yt/collections/claims.rb +22 -1
- data/lib/yt/collections/comment_threads.rb +41 -0
- data/lib/yt/collections/content_owners.rb +1 -1
- data/lib/yt/collections/group_infos.rb +27 -0
- data/lib/yt/collections/group_items.rb +45 -0
- data/lib/yt/collections/reports.rb +75 -13
- data/lib/yt/collections/revocations.rb +30 -0
- data/lib/yt/collections/video_groups.rb +29 -0
- data/lib/yt/collections/videos.rb +34 -9
- data/lib/yt/constants/geography.rb +326 -0
- data/lib/yt/errors/forbidden.rb +1 -3
- data/lib/yt/errors/no_items.rb +1 -3
- data/lib/yt/errors/request_error.rb +10 -7
- data/lib/yt/errors/server_error.rb +1 -3
- data/lib/yt/errors/unauthorized.rb +3 -3
- data/lib/yt/models/account.rb +12 -0
- data/lib/yt/models/advertising_options_set.rb +4 -4
- data/lib/yt/models/bulk_report.rb +23 -0
- data/lib/yt/models/bulk_report_job.rb +23 -0
- data/lib/yt/models/channel.rb +21 -12
- data/lib/yt/models/claim.rb +13 -2
- data/lib/yt/models/comment.rb +37 -0
- data/lib/yt/models/comment_thread.rb +50 -0
- data/lib/yt/models/content_detail.rb +6 -0
- data/lib/yt/models/content_owner.rb +31 -1
- data/lib/yt/models/group_info.rb +16 -0
- data/lib/yt/models/group_item.rb +15 -0
- data/lib/yt/models/resource.rb +3 -10
- data/lib/yt/models/revocation.rb +12 -0
- data/lib/yt/models/right_owner.rb +0 -2
- data/lib/yt/models/snippet.rb +24 -3
- data/lib/yt/models/video.rb +42 -11
- data/lib/yt/models/video_group.rb +186 -0
- data/lib/yt/request.rb +5 -3
- data/lib/yt/version.rb +2 -2
- data/spec/collections/comment_threads_spec.rb +46 -0
- data/spec/collections/playlist_items_spec.rb +1 -1
- data/spec/collections/reports_spec.rb +2 -2
- data/spec/constants/geography_spec.rb +16 -0
- data/spec/models/annotation_spec.rb +1 -1
- data/spec/models/claim_spec.rb +15 -3
- data/spec/models/comment_spec.rb +40 -0
- data/spec/models/comment_thread_spec.rb +93 -0
- data/spec/models/content_detail_spec.rb +7 -0
- data/spec/models/reference_spec.rb +2 -2
- data/spec/models/request_spec.rb +21 -0
- data/spec/models/resource_spec.rb +0 -15
- data/spec/models/video_spec.rb +1 -1
- data/spec/requests/as_account/account_spec.rb +16 -4
- data/spec/requests/as_account/authentications_spec.rb +1 -13
- data/spec/requests/as_account/channel_spec.rb +15 -45
- data/spec/requests/as_account/playlist_item_spec.rb +3 -3
- data/spec/requests/as_account/playlist_spec.rb +5 -32
- data/spec/requests/as_account/video_spec.rb +2022 -21
- data/spec/requests/as_content_owner/account_spec.rb +4 -0
- data/spec/requests/as_content_owner/bulk_report_job_spec.rb +19 -0
- data/spec/requests/as_content_owner/channel_spec.rb +59 -270
- data/spec/requests/as_content_owner/content_owner_spec.rb +89 -1
- data/spec/requests/as_content_owner/playlist_spec.rb +0 -15
- data/spec/requests/as_content_owner/video_group_spec.rb +112 -0
- data/spec/requests/as_content_owner/video_spec.rb +72 -146
- data/spec/requests/as_server_app/channel_spec.rb +1 -21
- data/spec/requests/as_server_app/comment_spec.rb +22 -0
- data/spec/requests/as_server_app/comment_thread_spec.rb +27 -0
- data/spec/requests/as_server_app/comment_threads_spec.rb +41 -0
- data/spec/requests/as_server_app/playlist_item_spec.rb +2 -2
- data/spec/requests/as_server_app/playlist_spec.rb +1 -22
- data/spec/requests/as_server_app/video_spec.rb +21 -19
- data/spec/requests/as_server_app/videos_spec.rb +5 -5
- data/spec/requests/unauthenticated/video_spec.rb +1 -9
- data/spec/spec_helper.rb +1 -1
- data/yt.gemspec +2 -1
- metadata +51 -17
- data/lib/yt/collections/ids.rb +0 -27
- data/lib/yt/config.rb +0 -54
- data/lib/yt/models/configuration.rb +0 -70
- data/lib/yt/models/description.rb +0 -58
- data/lib/yt/models/url.rb +0 -91
- data/spec/models/configuration_spec.rb +0 -44
- data/spec/models/description_spec.rb +0 -94
- data/spec/models/url_spec.rb +0 -84
- 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, :
|
|
17
|
-
:subscribers_gained, :subscribers_lost,
|
|
16
|
+
[:views, :comments, :likes, :dislikes, :shares,
|
|
17
|
+
:subscribers_gained, :subscribers_lost,
|
|
18
18
|
:videos_added_to_playlists, :videos_removed_from_playlists,
|
|
19
|
-
:
|
|
20
|
-
:average_view_percentage, :
|
|
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
|
-
:
|
|
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,
|
|
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
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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,
|
|
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, :
|
|
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, :
|
|
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,
|
|
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,
|
|
180
|
+
subscribers_lost: Integer,
|
|
217
181
|
videos_added_to_playlists: Integer, videos_removed_from_playlists: Integer,
|
|
218
|
-
|
|
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,
|
|
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 '
|
|
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
|
-
|
|
264
|
-
expect(
|
|
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 '
|
|
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
|
-
|
|
273
|
-
expect(
|
|
274
|
-
expect(
|
|
275
|
-
expect(
|
|
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
|
|
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 '
|
|
427
|
-
let(:
|
|
428
|
-
let(:
|
|
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
|
|
451
|
-
|
|
452
|
-
expect(
|
|
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 '
|
|
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
|
-
|
|
937
|
-
expect(
|
|
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 '
|
|
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
|
-
|
|
946
|
-
expect(
|
|
947
|
-
expect(
|
|
948
|
-
expect(
|
|
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
|