yt 0.23.0 → 0.23.1
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 +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +1 -1
- data/lib/yt/associations/has_reports.rb +66 -18
- data/lib/yt/collections/reports.rb +32 -20
- data/lib/yt/models/channel.rb +2 -0
- data/lib/yt/models/playlist.rb +2 -0
- data/lib/yt/models/video.rb +2 -0
- data/lib/yt/version.rb +1 -1
- data/spec/collections/reports_spec.rb +3 -3
- data/spec/requests/as_content_owner/channel_spec.rb +66 -20
- data/spec/requests/as_content_owner/playlist_spec.rb +58 -14
- data/spec/requests/as_content_owner/video_spec.rb +93 -42
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 004e3876d58c7c369d0e2a215d41234ad37f7b57
|
4
|
+
data.tar.gz: c4cc02ed5cf02d23858e7de931d5bc1bea63c932
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 691d6757cb7112eb8993d6c81b98cc44bd15a31a50e73c1294761563ba15117adde788c04d89003f23eb23f24bead8ca0aa5d4d0b7856da4287969c5836ab9fd
|
7
|
+
data.tar.gz: 3f488e8e0c4bbffe17c9b78177f61a4ee7ed535ba483217d7f71980bcd11f9939ddf52588a5f2dd0e244fae15023af9449b8539de930c7ed2bba43f15d8953c7
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,11 @@ For more information about changelogs, check
|
|
6
6
|
[Keep a Changelog](http://keepachangelog.com) and
|
7
7
|
[Vandamme](http://tech-angels.github.io/vandamme).
|
8
8
|
|
9
|
+
## 0.23.1 - 2015-05-19
|
10
|
+
|
11
|
+
* [FEATURE] New `by: :month` option for reports.
|
12
|
+
* [FEATURE] New `.reports` method to fetch multiple metrics at once.
|
13
|
+
|
9
14
|
## 0.23.0 - 2015-05-18
|
10
15
|
|
11
16
|
**How to upgrade**
|
data/README.md
CHANGED
@@ -41,7 +41,7 @@ To install on your system, run
|
|
41
41
|
|
42
42
|
To use inside a bundled Ruby project, add this line to the Gemfile:
|
43
43
|
|
44
|
-
gem 'yt', '~> 0.23.
|
44
|
+
gem 'yt', '~> 0.23.1'
|
45
45
|
|
46
46
|
Since the gem follows [Semantic Versioning](http://semver.org),
|
47
47
|
indicating the full version in your Gemfile (~> *major*.*minor*.*patch*)
|
@@ -3,6 +3,23 @@ module Yt
|
|
3
3
|
# @private
|
4
4
|
# Provides methods to access the analytics reports of a resource.
|
5
5
|
module HasReports
|
6
|
+
# @!macro [new] reports
|
7
|
+
# Returns the reports for the given metrics grouped by the given dimension.
|
8
|
+
# @!method reports(options = {})
|
9
|
+
# @param [Hash] options the metrics, time-range and dimensions for the reports.
|
10
|
+
# @option options [Array<Symbol>] :only The metrics to generate reports
|
11
|
+
# for.
|
12
|
+
# @option options [Symbol] :by (:day) The dimension to collect metrics
|
13
|
+
# by. Accepted values are: +:day+, +:month+.
|
14
|
+
# @option options [#to_date] :since The first day of the time-range.
|
15
|
+
# Also aliased as +:from+.
|
16
|
+
# @option options [#to_date] :until The last day of the time-range.
|
17
|
+
# Also aliased as +:to+.
|
18
|
+
# @return [Hash<Symbol, Hash>] the reports for each metric specified.
|
19
|
+
# @example Get the views and estimated minutes watched by day for last week:
|
20
|
+
# resource.reports only: [:views, :estimated_minutes_watched] since: 1.week.ago, by: :day
|
21
|
+
# # => {views: {Wed, 8 May 2014 => 12, Thu, 9 May 2014 => 34, …}, estimated_minutes_watched: {Wed, 8 May 2014 => 9.0, Thu, 9 May 2014 => 6.0, …}}
|
22
|
+
|
6
23
|
# @!macro [new] report
|
7
24
|
# Returns the $1 grouped by the given dimension.
|
8
25
|
# @!method $1(options = {})
|
@@ -18,6 +35,11 @@ module Yt
|
|
18
35
|
# @example Get the $1 for each day of last week:
|
19
36
|
# resource.$1 since: 2.weeks.ago, until: 1.week.ago, by: :day
|
20
37
|
# # => {Wed, 8 May 2014 => 12.0, Thu, 9 May 2014 => 34.0, …}
|
38
|
+
# @return [Hash<Range<Date, Date>, $2>] if grouped by month, the $1
|
39
|
+
# for each month in the time-range.
|
40
|
+
# @example Get the $1 for this and last month:
|
41
|
+
# resource.$1 since: 1.month.ago, by: :month
|
42
|
+
# # => {Wed, 01 Apr 2014..Thu, 30 Apr 2014 => 12.0, Fri, 01 May 2014..Sun, 31 May 2014 => 34.0, …}
|
21
43
|
# @macro report
|
22
44
|
|
23
45
|
# @!macro [new] report_with_range
|
@@ -48,19 +70,19 @@ module Yt
|
|
48
70
|
|
49
71
|
# @!macro [new] report_by_day
|
50
72
|
# @option options [Symbol] :by (:day) The dimension to collect $1 by.
|
51
|
-
# Accepted values are: +:day+.
|
73
|
+
# Accepted values are: +:day+, +:month+.
|
52
74
|
# @macro report_with_day
|
53
75
|
|
54
76
|
# @!macro [new] report_by_day_and_country
|
55
77
|
# @option options [Symbol] :by (:day) The dimension to collect $1 by.
|
56
|
-
# Accepted values are: +:day+, :+range+.
|
78
|
+
# Accepted values are: +:day+, +:month+, :+range+.
|
57
79
|
# @macro report_with_day
|
58
80
|
# @macro report_with_range
|
59
81
|
# @macro report_with_country
|
60
82
|
|
61
83
|
# @!macro [new] report_by_day_and_state
|
62
84
|
# @option options [Symbol] :by (:day) The dimension to collect $1 by.
|
63
|
-
# Accepted values are: +:day+, :+range+.
|
85
|
+
# Accepted values are: +:day+, +:month+, :+range+.
|
64
86
|
# @macro report_with_day
|
65
87
|
# @macro report_with_range
|
66
88
|
# @macro report_with_country_and_state
|
@@ -96,7 +118,7 @@ module Yt
|
|
96
118
|
|
97
119
|
# @!macro [new] report_by_video_dimensions
|
98
120
|
# @option options [Symbol] :by (:day) The dimension to collect $1 by.
|
99
|
-
# Accepted values are: +:day+, +:range+, +:traffic_source+,
|
121
|
+
# Accepted values are: +:day+, +:month+, +:range+, +:traffic_source+,
|
100
122
|
# +:search_term+, +:playback_location+, +:related_video+,
|
101
123
|
# +:embedded_player_location+.
|
102
124
|
# @return [Hash<Symbol, $2>] if grouped by embedded player location,
|
@@ -122,7 +144,7 @@ module Yt
|
|
122
144
|
|
123
145
|
# @!macro [new] report_by_channel_dimensions
|
124
146
|
# @option options [Symbol] :by (:day) The dimension to collect $1 by.
|
125
|
-
# Accepted values are: +:day+, +:range+, +:traffic_source+,
|
147
|
+
# Accepted values are: +:day+, +:month+, +:range+, +:traffic_source+,
|
126
148
|
# +:search_term+, +:playback_location+, +:related_video+, +:video+,
|
127
149
|
# +:playlist+, +:embedded_player_location+.
|
128
150
|
# @return [Hash<Symbol, $2>] if grouped by embedded player location,
|
@@ -135,7 +157,7 @@ module Yt
|
|
135
157
|
|
136
158
|
# @!macro [new] report_by_playlist_dimensions
|
137
159
|
# @option options [Symbol] :by (:day) The dimension to collect $1 by.
|
138
|
-
# Accepted values are: +:day+, +:range+, +:traffic_source+,
|
160
|
+
# Accepted values are: +:day+, +:month+, +:range+, +:traffic_source+,
|
139
161
|
# +:playback_location+, +:related_video+, +:video+,
|
140
162
|
# +:playlist+.
|
141
163
|
# @macro report_with_channel_dimensions
|
@@ -179,8 +201,9 @@ module Yt
|
|
179
201
|
|
180
202
|
define_metric_on_method metric
|
181
203
|
define_metric_method metric
|
182
|
-
|
183
|
-
|
204
|
+
define_reports_method metric, type
|
205
|
+
define_range_metric_method metric
|
206
|
+
define_all_metric_method metric, type
|
184
207
|
end
|
185
208
|
|
186
209
|
private
|
@@ -191,20 +214,45 @@ module Yt
|
|
191
214
|
end
|
192
215
|
end
|
193
216
|
|
217
|
+
def define_reports_method(metric, type)
|
218
|
+
(@metrics ||= {})[metric] = type
|
219
|
+
define_method :reports do |options = {}|
|
220
|
+
from = options[:since] || options[:from] || (options[:by].in?([:day, :month]) ? 5.days.ago : '2005-02-01')
|
221
|
+
to = options[:until] || options[:to] || Date.today
|
222
|
+
location = options[:in]
|
223
|
+
country = location.is_a?(Hash) ? location[:country] : location
|
224
|
+
state = location[:state] if location.is_a?(Hash)
|
225
|
+
dimension = options[:by] || (metric == :viewer_percentage ? :gender_age_group : :range)
|
226
|
+
if dimension == :month
|
227
|
+
from = from.to_date.beginning_of_month
|
228
|
+
to = to.to_date.beginning_of_month
|
229
|
+
end
|
230
|
+
date_range = Range.new *[from, to].map(&:to_date)
|
231
|
+
|
232
|
+
only = options.fetch :only, []
|
233
|
+
reports = Collections::Reports.of(self).tap do |reports|
|
234
|
+
reports.metrics = self.class.instance_variable_get(:@metrics).select{|k, v| k.in? only}
|
235
|
+
end
|
236
|
+
reports.within date_range, country, state, dimension
|
237
|
+
end unless defined?(reports)
|
238
|
+
end
|
239
|
+
|
194
240
|
def define_metric_method(metric)
|
195
241
|
define_method metric do |options = {}|
|
196
|
-
from = options[:since] || options[:from] || (options[:by]
|
242
|
+
from = options[:since] || options[:from] || (options[:by].in?([:day, :month]) ? 5.days.ago : '2005-02-01')
|
197
243
|
to = options[:until] || options[:to] || Date.today
|
198
244
|
location = options[:in]
|
199
245
|
country = location.is_a?(Hash) ? location[:country] : location
|
200
246
|
state = location[:state] if location.is_a?(Hash)
|
201
|
-
|
202
|
-
range = Range.new *[from, to].map(&:to_date)
|
203
247
|
dimension = options[:by] || (metric == :viewer_percentage ? :gender_age_group : :range)
|
248
|
+
if dimension == :month
|
249
|
+
from = from.to_date.beginning_of_month
|
250
|
+
to = to.to_date.beginning_of_month
|
251
|
+
end
|
252
|
+
range = Range.new *[from, to].map(&:to_date)
|
204
253
|
|
205
254
|
ivar = instance_variable_get "@#{metric}_#{dimension}_#{country}_#{state}"
|
206
255
|
instance_variable_set "@#{metric}_#{dimension}_#{country}_#{state}", ivar || {}
|
207
|
-
|
208
256
|
case dimension
|
209
257
|
when :day
|
210
258
|
Hash[*range.flat_map do |date|
|
@@ -216,23 +264,23 @@ module Yt
|
|
216
264
|
end
|
217
265
|
end
|
218
266
|
|
219
|
-
def define_range_metric_method(metric
|
267
|
+
def define_range_metric_method(metric)
|
220
268
|
define_method "range_#{metric}" do |date_range, dimension, country, state|
|
221
269
|
ivar = instance_variable_get "@range_#{metric}_#{dimension}_#{country}_#{state}"
|
222
270
|
instance_variable_set "@range_#{metric}_#{dimension}_#{country}_#{state}", ivar || {}
|
223
|
-
instance_variable_get("@range_#{metric}_#{dimension}_#{country}_#{state}")[date_range] ||= send("all_#{metric}").within date_range, country, state, dimension
|
271
|
+
instance_variable_get("@range_#{metric}_#{dimension}_#{country}_#{state}")[date_range] ||= send("all_#{metric}").within date_range, country, state, dimension
|
224
272
|
end
|
225
273
|
private "range_#{metric}"
|
226
274
|
end
|
227
275
|
|
228
|
-
def define_all_metric_method(metric)
|
276
|
+
def define_all_metric_method(metric, type)
|
229
277
|
define_method "all_#{metric}" do
|
230
278
|
# @note Asking for the "earnings" metric of a day in which a channel
|
231
279
|
# made 0 USD returns the wrong "nil". But adding to the request the
|
232
280
|
# "estimatedMinutesWatched" metric returns the correct value 0.
|
233
|
-
|
234
|
-
|
235
|
-
Collections::Reports.of(self).tap{|reports| reports.
|
281
|
+
metrics = {metric => type}
|
282
|
+
metrics[:estimated_minutes_watched] = Integer if metric == :earnings
|
283
|
+
Collections::Reports.of(self).tap{|reports| reports.metrics = metrics}
|
236
284
|
end
|
237
285
|
private "all_#{metric}"
|
238
286
|
end
|
@@ -4,21 +4,22 @@ module Yt
|
|
4
4
|
module Collections
|
5
5
|
# @private
|
6
6
|
class Reports < Base
|
7
|
-
DIMENSIONS = Hash.new({name: 'day', parse: ->(day, *values) {
|
8
|
-
hash[:
|
9
|
-
hash[:
|
10
|
-
hash[:
|
11
|
-
hash[:
|
12
|
-
hash[:
|
13
|
-
hash[:
|
14
|
-
hash[:
|
15
|
-
hash[:
|
16
|
-
hash[:
|
17
|
-
hash[:
|
18
|
-
hash[:
|
7
|
+
DIMENSIONS = Hash.new({name: 'day', parse: ->(day, *values) { @metrics.keys.zip(values.map{|v| {Date.iso8601(day) => v}}).to_h} }).tap do |hash|
|
8
|
+
hash[:month] = {name: 'month', parse: ->(month, *values) { @metrics.keys.zip(values.map{|v| {Range.new(Date.strptime(month, '%Y-%m').beginning_of_month, Date.strptime(month, '%Y-%m').end_of_month) => v} }).to_h} }
|
9
|
+
hash[:range] = {parse: ->(*values) { @metrics.keys.zip(values.map{|v| {total: v}}).to_h } }
|
10
|
+
hash[:traffic_source] = {name: 'insightTrafficSourceType', parse: ->(source, *values) { @metrics.keys.zip(values.map{|v| {TRAFFIC_SOURCES.key(source) => v}}).to_h} }
|
11
|
+
hash[:playback_location] = {name: 'insightPlaybackLocationType', parse: ->(location, *values) { @metrics.keys.zip(values.map{|v| {PLAYBACK_LOCATIONS.key(location) => v}}).to_h} }
|
12
|
+
hash[:embedded_player_location] = {name: 'insightPlaybackLocationDetail', parse: ->(url, *values) {@metrics.keys.zip(values.map{|v| {url => v}}).to_h} }
|
13
|
+
hash[:related_video] = {name: 'insightTrafficSourceDetail', parse: ->(video_id, *values) { @metrics.keys.zip(values.map{|v| {Yt::Video.new(id: video_id, auth: @auth) => v}}).to_h} }
|
14
|
+
hash[:search_term] = {name: 'insightTrafficSourceDetail', parse: ->(search_term, *values) {@metrics.keys.zip(values.map{|v| {search_term => v}}).to_h} }
|
15
|
+
hash[:video] = {name: 'video', parse: ->(video_id, *values) { @metrics.keys.zip(values.map{|v| {Yt::Video.new(id: video_id, auth: @auth) => v}}).to_h} }
|
16
|
+
hash[:playlist] = {name: 'playlist', parse: ->(playlist_id, *values) { @metrics.keys.zip(values.map{|v| {Yt::Playlist.new(id: playlist_id, auth: @auth) => v}}).to_h} }
|
17
|
+
hash[:device_type] = {name: 'deviceType', parse: ->(type, *values) {@metrics.keys.zip(values.map{|v| {type.downcase.to_sym => v}}).to_h} }
|
18
|
+
hash[:country] = {name: 'country', parse: ->(country_code, *values) { @metrics.keys.zip(values.map{|v| {country_code => v}}).to_h} }
|
19
|
+
hash[:state] = {name: 'province', parse: ->(country_and_state_code, *values) { @metrics.keys.zip(values.map{|v| {country_and_state_code[3..-1] => v}}).to_h} }
|
19
20
|
hash[:gender_age_group] = {name: 'gender,ageGroup', parse: ->(gender, *values) { [gender.downcase.to_sym, *values] }}
|
20
|
-
hash[:gender] = {name: 'gender', parse: ->(gender,
|
21
|
-
hash[:age_group] = {name: 'ageGroup', parse: ->(age_group,
|
21
|
+
hash[:gender] = {name: 'gender', parse: ->(gender, *values) {@metrics.keys.zip(values.map{|v| {gender.downcase.to_sym => v}}).to_h} }
|
22
|
+
hash[:age_group] = {name: 'ageGroup', parse: ->(age_group, *values) {@metrics.keys.zip(values.map{|v| {age_group[3..-1] => v}}).to_h} }
|
22
23
|
end
|
23
24
|
|
24
25
|
# @see https://developers.google.com/youtube/analytics/v1/dimsmets/dims#Traffic_Source_Dimensions
|
@@ -49,9 +50,9 @@ module Yt
|
|
49
50
|
mobile: 'MOBILE' # only present for data < September 10, 2013
|
50
51
|
}
|
51
52
|
|
52
|
-
attr_writer :
|
53
|
+
attr_writer :metrics
|
53
54
|
|
54
|
-
def within(days_range, country, state, dimension,
|
55
|
+
def within(days_range, country, state, dimension, try_again = true)
|
55
56
|
@days_range = days_range
|
56
57
|
@dimension = dimension
|
57
58
|
@country = country
|
@@ -61,7 +62,18 @@ module Yt
|
|
61
62
|
each{|gender, age_group, value| hash[gender][age_group[3..-1]] = value}
|
62
63
|
end
|
63
64
|
else
|
64
|
-
|
65
|
+
hash = flat_map do |hashes|
|
66
|
+
hashes.map do |metric, values|
|
67
|
+
[metric, values.transform_values{|v| type_cast(v, @metrics[metric])}]
|
68
|
+
end.to_h
|
69
|
+
end
|
70
|
+
hash = hash.inject(@metrics.transform_values{|v| {}}) do |result, hash|
|
71
|
+
result.deep_merge hash
|
72
|
+
end
|
73
|
+
if dimension == :month
|
74
|
+
hash = hash.transform_values{|h| h.sort_by{|range, v| range.first}.to_h}
|
75
|
+
end
|
76
|
+
(@metrics.one? || @metrics.keys == [:earnings, :estimated_minutes_watched]) ? hash[@metrics.keys.first] : hash
|
65
77
|
end
|
66
78
|
# NOTE: Once in a while, YouTube responds with 400 Error and the message
|
67
79
|
# "Invalid query. Query did not conform to the expectations."; in this
|
@@ -70,7 +82,7 @@ module Yt
|
|
70
82
|
# same query is a workaround that works and can hardly cause any damage.
|
71
83
|
# Similarly, once in while YouTube responds with a random 503 error.
|
72
84
|
rescue Yt::Error => e
|
73
|
-
try_again && rescue?(e) ? sleep(3) && within(days_range, country, state, dimension,
|
85
|
+
try_again && rescue?(e) ? sleep(3) && within(days_range, country, state, dimension, false) : raise
|
74
86
|
end
|
75
87
|
|
76
88
|
private
|
@@ -99,12 +111,12 @@ module Yt
|
|
99
111
|
@parent.reports_params.tap do |params|
|
100
112
|
params['start-date'] = @days_range.begin
|
101
113
|
params['end-date'] = @days_range.end
|
102
|
-
params['metrics'] = @
|
114
|
+
params['metrics'] = @metrics.keys.join(',').to_s.camelize(:lower)
|
103
115
|
params['dimensions'] = DIMENSIONS[@dimension][:name] unless @dimension == :range
|
104
116
|
params['max-results'] = 10 if @dimension == :video
|
105
117
|
params['max-results'] = 200 if @dimension == :playlist
|
106
118
|
params['max-results'] = 25 if @dimension.in? [:embedded_player_location, :related_video, :search_term]
|
107
|
-
params['sort'] = "-#{@
|
119
|
+
params['sort'] = "-#{@metrics.keys.join(',').to_s.camelize(:lower)}" if @dimension.in? [:video, :playlist, :embedded_player_location, :related_video, :search_term]
|
108
120
|
params[:filters] = ((params[:filters] || '').split(';') + ["country==US"]).compact.uniq.join(';') if @dimension == :state && !@state
|
109
121
|
params[:filters] = ((params[:filters] || '').split(';') + ["country==#{@country}"]).compact.uniq.join(';') if @country && !@state
|
110
122
|
params[:filters] = ((params[:filters] || '').split(';') + ["province==US-#{@state}"]).compact.uniq.join(';') if @state
|
data/lib/yt/models/channel.rb
CHANGED
data/lib/yt/models/playlist.rb
CHANGED
data/lib/yt/models/video.rb
CHANGED
data/lib/yt/version.rb
CHANGED
@@ -3,13 +3,13 @@ require 'yt/collections/reports'
|
|
3
3
|
require 'yt/models/content_owner'
|
4
4
|
|
5
5
|
describe Yt::Collections::Reports do
|
6
|
-
subject(:reports) { Yt::Collections::Reports.new
|
6
|
+
subject(:reports) { Yt::Collections::Reports.new(parent: content_owner).tap{|reports| reports.metrics = {views: Integer}} }
|
7
7
|
let(:content_owner) { Yt::ContentOwner.new owner_name: 'any-name' }
|
8
8
|
let(:error){ {reason: reason, message: message} }
|
9
9
|
let(:msg) { {response_body: {error: {errors: [error]}}}.to_json }
|
10
10
|
|
11
11
|
describe '#within' do
|
12
|
-
let(:result) { reports.within Range.new(5.days.ago, 4.days.ago), nil, nil, :day
|
12
|
+
let(:result) { reports.within Range.new(5.days.ago, 4.days.ago), nil, nil, :day }
|
13
13
|
context 'given the request raises error 400 with "Invalid Query" message' do
|
14
14
|
let(:reason) { 'badRequest' }
|
15
15
|
let(:message) { 'Invalid query. Query did not conform to the expectations' }
|
@@ -22,7 +22,7 @@ describe Yt::Collections::Reports do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
context 'but returns a success code 2XX the second time' do
|
25
|
-
before { try_again.and_return [
|
25
|
+
before { try_again.and_return [views: {total: 20}] }
|
26
26
|
it { expect{result}.not_to fail }
|
27
27
|
end
|
28
28
|
end
|
@@ -10,6 +10,39 @@ describe Yt::Channel, :partner do
|
|
10
10
|
context 'managed by the authenticated Content Owner' do
|
11
11
|
let(:id) { ENV['YT_TEST_PARTNER_CHANNEL_ID'] }
|
12
12
|
|
13
|
+
describe 'multiple reports can be retrieved at once' do
|
14
|
+
metrics = {views: Integer, uniques: Integer,
|
15
|
+
estimated_minutes_watched: Float, comments: Integer, likes: Integer,
|
16
|
+
dislikes: Integer, shares: Integer, subscribers_gained: Integer,
|
17
|
+
subscribers_lost: Integer, favorites_added: Integer,
|
18
|
+
favorites_removed: Integer, average_view_duration: Float,
|
19
|
+
average_view_percentage: Float, annotation_clicks: Integer,
|
20
|
+
annotation_click_through_rate: Float,
|
21
|
+
annotation_close_rate: Float, earnings: Float, impressions: Integer,
|
22
|
+
monetized_playbacks: Integer}
|
23
|
+
|
24
|
+
specify 'by day' do
|
25
|
+
range = {since: 5.days.ago.to_date, until: 3.days.ago.to_date}
|
26
|
+
result = channel.reports range.merge(only: metrics, by: :day)
|
27
|
+
metrics.each do |metric, type|
|
28
|
+
expect(result[metric].keys).to all(be_a Date)
|
29
|
+
expect(result[metric].values).to all(be_a type)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
specify 'by month' do
|
34
|
+
result = channel.reports only: metrics, by: :month, since: 1.month.ago
|
35
|
+
metrics.each do |metric, type|
|
36
|
+
expect(result[metric].keys).to all(be_a Range)
|
37
|
+
expect(result[metric].keys.map &:first).to all(be_a Date)
|
38
|
+
expect(result[metric].keys.map &:first).to eq result[metric].keys.map(&:first).map(&:beginning_of_month)
|
39
|
+
expect(result[metric].keys.map &:last).to all(be_a Date)
|
40
|
+
expect(result[metric].keys.map &:last).to eq result[metric].keys.map(&:last).map(&:end_of_month)
|
41
|
+
expect(result[metric].values).to all(be_a type)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
13
46
|
[:views, :uniques, :comments, :likes, :dislikes, :shares,
|
14
47
|
:subscribers_gained, :subscribers_lost, :favorites_added,
|
15
48
|
:favorites_removed, :estimated_minutes_watched, :average_view_duration,
|
@@ -24,14 +57,32 @@ describe Yt::Channel, :partner do
|
|
24
57
|
|
25
58
|
context 'with a given start and end (:since/:until option)' do
|
26
59
|
let(:options) { {by: :day, since: date_in, until: date_out} }
|
27
|
-
|
28
|
-
|
60
|
+
specify do
|
61
|
+
expect(result.keys.min).to eq date_in.to_date
|
62
|
+
expect(result.keys.max).to eq date_out.to_date
|
63
|
+
end
|
29
64
|
end
|
30
65
|
|
31
66
|
context 'with a given start and end (:from/:to option)' do
|
32
67
|
let(:options) { {by: :day, from: date_in, to: date_out} }
|
33
|
-
|
34
|
-
|
68
|
+
specify do
|
69
|
+
expect(result.keys.min).to eq date_in.to_date
|
70
|
+
expect(result.keys.max).to eq date_out.to_date
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#{metric} can be grouped by month" do
|
76
|
+
let(:metric) { metric }
|
77
|
+
|
78
|
+
let(:result) { channel.public_send metric, by: :month, since: 3.months.ago }
|
79
|
+
specify do
|
80
|
+
expect(result.keys).to eq(result.keys.sort_by{|range| range.first})
|
81
|
+
expect(result.keys).to all(be_a Range)
|
82
|
+
expect(result.keys.map &:first).to all(be_a Date)
|
83
|
+
expect(result.keys.map &:first).to eq result.keys.map(&:first).map(&:beginning_of_month)
|
84
|
+
expect(result.keys.map &:last).to all(be_a Date)
|
85
|
+
expect(result.keys.map &:last).to eq result.keys.map(&:last).map(&:end_of_month)
|
35
86
|
end
|
36
87
|
end
|
37
88
|
end
|
@@ -59,29 +110,24 @@ describe Yt::Channel, :partner do
|
|
59
110
|
it { expect(result).to be_nil }
|
60
111
|
end
|
61
112
|
end
|
62
|
-
end
|
63
113
|
|
64
|
-
{views: Integer, comments: Integer, likes: Integer, dislikes: Integer,
|
65
|
-
shares: Integer, subscribers_gained: Integer, subscribers_lost: Integer,
|
66
|
-
favorites_added: Integer, favorites_removed: Integer,
|
67
|
-
estimated_minutes_watched: Float, average_view_duration: Float,
|
68
|
-
average_view_percentage: Float, impressions: Integer,
|
69
|
-
monetized_playbacks: Integer, annotation_clicks: Integer,
|
70
|
-
annotation_click_through_rate: Float, annotation_close_rate: Float,
|
71
|
-
earnings: Float}.each do |metric, type|
|
72
114
|
describe "#{metric} can be grouped by range" do
|
73
115
|
let(:metric) { metric }
|
74
116
|
|
75
117
|
context 'without a :by option (default)' do
|
76
118
|
let(:result) { channel.public_send metric }
|
77
|
-
|
78
|
-
|
119
|
+
specify do
|
120
|
+
expect(result.size).to be 1
|
121
|
+
expect(result[:total]).to be_a type
|
122
|
+
end
|
79
123
|
end
|
80
124
|
|
81
125
|
context 'with the :by option set to :range' do
|
82
126
|
let(:result) { channel.public_send metric, by: :range }
|
83
|
-
|
84
|
-
|
127
|
+
specify do
|
128
|
+
expect(result.size).to be 1
|
129
|
+
expect(result[:total]).to be_a type
|
130
|
+
end
|
85
131
|
end
|
86
132
|
end
|
87
133
|
end
|
@@ -1398,7 +1444,7 @@ describe Yt::Channel, :partner do
|
|
1398
1444
|
end
|
1399
1445
|
|
1400
1446
|
describe 'annotation clicks can be grouped by country' do
|
1401
|
-
let(:range) { {since:
|
1447
|
+
let(:range) { {since: ENV['YT_TEST_PARTNER_VIDEO_DATE']} }
|
1402
1448
|
|
1403
1449
|
specify 'with the :by option set to :country' do
|
1404
1450
|
clicks = channel.annotation_clicks range.merge by: :country
|
@@ -1409,7 +1455,7 @@ describe Yt::Channel, :partner do
|
|
1409
1455
|
end
|
1410
1456
|
|
1411
1457
|
describe 'annotation clicks can be grouped by state' do
|
1412
|
-
let(:range) { {since:
|
1458
|
+
let(:range) { {since: ENV['YT_TEST_PARTNER_VIDEO_DATE']} }
|
1413
1459
|
|
1414
1460
|
specify 'with the :by option set to :state' do
|
1415
1461
|
clicks = channel.annotation_clicks range.merge by: :state
|
@@ -1508,7 +1554,7 @@ describe Yt::Channel, :partner do
|
|
1508
1554
|
end
|
1509
1555
|
|
1510
1556
|
describe 'annotation click-through rate can be grouped by state' do
|
1511
|
-
let(:range) { {since:
|
1557
|
+
let(:range) { {since: ENV['YT_TEST_PARTNER_VIDEO_DATE']} }
|
1512
1558
|
|
1513
1559
|
specify 'with the :by option set to :state' do
|
1514
1560
|
rate = channel.annotation_click_through_rate range.merge by: :state
|
@@ -10,8 +10,36 @@ describe Yt::Playlist, :partner do
|
|
10
10
|
context 'managed by the authenticated Content Owner' do
|
11
11
|
let(:id) { ENV['YT_TEST_PARTNER_PLAYLIST_ID'] }
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
describe 'multiple reports can be retrieved at once' do
|
14
|
+
metrics = {views: Integer, estimated_minutes_watched: Float,
|
15
|
+
average_view_duration: Float, playlist_starts: Integer,
|
16
|
+
average_time_in_playlist: Float, views_per_playlist_start: Float}
|
17
|
+
|
18
|
+
specify 'by day' do
|
19
|
+
range = {since: 5.days.ago.to_date, until: 3.days.ago.to_date}
|
20
|
+
result = playlist.reports range.merge(only: metrics, by: :day)
|
21
|
+
metrics.each do |metric, type|
|
22
|
+
expect(result[metric].keys).to all(be_a Date)
|
23
|
+
expect(result[metric].values).to all(be_a type)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
specify 'by month' do
|
28
|
+
result = playlist.reports only: metrics, by: :month, since: 1.month.ago
|
29
|
+
metrics.each do |metric, type|
|
30
|
+
expect(result[metric].keys).to all(be_a Range)
|
31
|
+
expect(result[metric].keys.map &:first).to all(be_a Date)
|
32
|
+
expect(result[metric].keys.map &:first).to eq result[metric].keys.map(&:first).map(&:beginning_of_month)
|
33
|
+
expect(result[metric].keys.map &:last).to all(be_a Date)
|
34
|
+
expect(result[metric].keys.map &:last).to eq result[metric].keys.map(&:last).map(&:end_of_month)
|
35
|
+
expect(result[metric].values).to all(be_a type)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
{views: Integer, estimated_minutes_watched: Float, average_view_duration: Float,
|
41
|
+
playlist_starts: Integer, average_time_in_playlist: Float,
|
42
|
+
views_per_playlist_start: Float}.each do |metric, type|
|
15
43
|
describe "#{metric} can be retrieved for a range of days" do
|
16
44
|
let(:date_in) { ENV['YT_TEST_PARTNER_VIDEO_DATE'] }
|
17
45
|
let(:date_out) { Date.parse(ENV['YT_TEST_PARTNER_VIDEO_DATE']) + 5 }
|
@@ -20,21 +48,33 @@ describe Yt::Playlist, :partner do
|
|
20
48
|
|
21
49
|
context 'with a given start and end (:since/:until option)' do
|
22
50
|
let(:options) { {by: :day, since: date_in, until: date_out} }
|
23
|
-
|
24
|
-
|
51
|
+
specify do
|
52
|
+
expect(result.keys.min).to eq date_in.to_date
|
53
|
+
expect(result.keys.max).to eq date_out.to_date
|
54
|
+
end
|
25
55
|
end
|
26
56
|
|
27
57
|
context 'with a given start and end (:from/:to option)' do
|
28
58
|
let(:options) { {by: :day, from: date_in, to: date_out} }
|
29
|
-
|
30
|
-
|
59
|
+
specify do
|
60
|
+
expect(result.keys.min).to eq date_in.to_date
|
61
|
+
expect(result.keys.max).to eq date_out.to_date
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#{metric} can be grouped by month" do
|
67
|
+
let(:metric) { metric }
|
68
|
+
let(:result) { playlist.public_send metric, by: :month, since: 1.month.ago }
|
69
|
+
specify do
|
70
|
+
expect(result.keys).to all(be_a Range)
|
71
|
+
expect(result.keys.map &:first).to all(be_a Date)
|
72
|
+
expect(result.keys.map &:first).to eq result.keys.map(&:first).map(&:beginning_of_month)
|
73
|
+
expect(result.keys.map &:last).to all(be_a Date)
|
74
|
+
expect(result.keys.map &:last).to eq result.keys.map(&:last).map(&:end_of_month)
|
31
75
|
end
|
32
76
|
end
|
33
|
-
end
|
34
77
|
|
35
|
-
{views: Integer, estimated_minutes_watched: Float, average_view_duration: Float,
|
36
|
-
playlist_starts: Integer, average_time_in_playlist: Float,
|
37
|
-
views_per_playlist_start: Float}.each do |metric, type|
|
38
78
|
describe "#{metric} can be retrieved for a specific day" do
|
39
79
|
let(:metric) { metric }
|
40
80
|
let(:result) { playlist.public_send "#{metric}_on", date }
|
@@ -55,14 +95,18 @@ describe Yt::Playlist, :partner do
|
|
55
95
|
|
56
96
|
context 'without a :by option (default)' do
|
57
97
|
let(:result) { playlist.public_send metric }
|
58
|
-
|
59
|
-
|
98
|
+
specify do
|
99
|
+
expect(result.size).to be 1
|
100
|
+
expect(result[:total]).to be_a type
|
101
|
+
end
|
60
102
|
end
|
61
103
|
|
62
104
|
context 'with the :by option set to :range' do
|
63
105
|
let(:result) { playlist.public_send metric, by: :range }
|
64
|
-
|
65
|
-
|
106
|
+
specify do
|
107
|
+
expect(result.size).to be 1
|
108
|
+
expect(result[:total]).to be_a type
|
109
|
+
end
|
66
110
|
end
|
67
111
|
end
|
68
112
|
|
@@ -27,14 +27,50 @@ describe Yt::Video, :partner do
|
|
27
27
|
|
28
28
|
context 'with a given start and end (:since/:until option)' do
|
29
29
|
let(:options) { {by: :day, since: date_in, until: date_out} }
|
30
|
-
|
31
|
-
|
30
|
+
specify do
|
31
|
+
expect(result.keys.min).to eq date_in.to_date
|
32
|
+
expect(result.keys.max).to eq date_out.to_date
|
33
|
+
end
|
32
34
|
end
|
33
35
|
|
34
36
|
context 'with a given start and end (:from/:to option)' do
|
35
37
|
let(:options) { {by: :day, from: date_in, to: date_out} }
|
36
|
-
|
37
|
-
|
38
|
+
specify do
|
39
|
+
expect(result.keys.min).to eq date_in.to_date
|
40
|
+
expect(result.keys.max).to eq date_out.to_date
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "#{metric} can be grouped by month" do
|
46
|
+
let(:metric) { metric }
|
47
|
+
|
48
|
+
let(:result) { video.public_send metric, by: :month, since: 1.month.ago }
|
49
|
+
specify do
|
50
|
+
expect(result.keys).to all(be_a Range)
|
51
|
+
expect(result.keys.map &:first).to all(be_a Date)
|
52
|
+
expect(result.keys.map &:first).to eq result.keys.map(&:first).map(&:beginning_of_month)
|
53
|
+
expect(result.keys.map &:last).to all(be_a Date)
|
54
|
+
expect(result.keys.map &:last).to eq result.keys.map(&:last).map(&:end_of_month)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#{metric} can be retrieved for a single country" do
|
59
|
+
let(:result) { video.public_send metric, options }
|
60
|
+
|
61
|
+
context 'and grouped by day' do
|
62
|
+
let(:date_in) { 5.days.ago }
|
63
|
+
let(:options) { {by: :day, since: date_in, in: location} }
|
64
|
+
|
65
|
+
context 'with the :in option set to the country code' do
|
66
|
+
let(:location) { 'US' }
|
67
|
+
it { expect(result.keys.min).to eq date_in.to_date }
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'with the :in option set to {country: country code}' do
|
71
|
+
let(:location) { {country: 'US'} }
|
72
|
+
it { expect(result.keys.min).to eq date_in.to_date }
|
73
|
+
end
|
38
74
|
end
|
39
75
|
end
|
40
76
|
end
|
@@ -73,14 +109,18 @@ describe Yt::Video, :partner do
|
|
73
109
|
|
74
110
|
context 'without a :by option (default)' do
|
75
111
|
let(:result) { video.public_send metric }
|
76
|
-
|
77
|
-
|
112
|
+
specify do
|
113
|
+
expect(result.size).to be 1
|
114
|
+
expect(result[:total]).to be_a type
|
115
|
+
end
|
78
116
|
end
|
79
117
|
|
80
118
|
context 'with the :by option set to :range' do
|
81
119
|
let(:result) { video.public_send metric, by: :range }
|
82
|
-
|
83
|
-
|
120
|
+
specify do
|
121
|
+
expect(result.size).to be 1
|
122
|
+
expect(result[:total]).to be_a type
|
123
|
+
end
|
84
124
|
end
|
85
125
|
end
|
86
126
|
end
|
@@ -92,39 +132,17 @@ describe Yt::Video, :partner do
|
|
92
132
|
|
93
133
|
context 'without a :by option (default)' do
|
94
134
|
let(:result) { video.public_send metric }
|
95
|
-
|
96
|
-
|
135
|
+
specify do
|
136
|
+
expect(result.size).to be 1
|
137
|
+
expect(result[:total]).to be_a type
|
138
|
+
end
|
97
139
|
end
|
98
140
|
|
99
141
|
context 'with the :by option set to :range' do
|
100
142
|
let(:result) { video.public_send metric, by: :range }
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
[:views, :uniques, :comments, :likes, :dislikes, :shares,
|
108
|
-
:subscribers_gained, :subscribers_lost, :favorites_added,
|
109
|
-
:favorites_removed, :estimated_minutes_watched, :average_view_duration,
|
110
|
-
:average_view_percentage, :impressions, :monetized_playbacks,
|
111
|
-
:annotation_clicks, :annotation_click_through_rate,
|
112
|
-
:annotation_close_rate, :earnings].each do |metric|
|
113
|
-
describe "#{metric} can be retrieved for a single country" do
|
114
|
-
let(:result) { video.public_send metric, options }
|
115
|
-
|
116
|
-
context 'and grouped by day' do
|
117
|
-
let(:date_in) { 5.days.ago }
|
118
|
-
let(:options) { {by: :day, since: date_in, in: location} }
|
119
|
-
|
120
|
-
context 'with the :in option set to the country code' do
|
121
|
-
let(:location) { 'US' }
|
122
|
-
it { expect(result.keys.min).to eq date_in.to_date }
|
123
|
-
end
|
124
|
-
|
125
|
-
context 'with the :in option set to {country: country code}' do
|
126
|
-
let(:location) { {country: 'US'} }
|
127
|
-
it { expect(result.keys.min).to eq date_in.to_date }
|
143
|
+
specify do
|
144
|
+
expect(result.size).to be 1
|
145
|
+
expect(result[:total]).to be_a type
|
128
146
|
end
|
129
147
|
end
|
130
148
|
end
|
@@ -176,6 +194,39 @@ describe Yt::Video, :partner do
|
|
176
194
|
end
|
177
195
|
end
|
178
196
|
|
197
|
+
describe 'multiple reports can be retrieved at once' do
|
198
|
+
metrics = {views: Integer, uniques: Integer,
|
199
|
+
estimated_minutes_watched: Float, comments: Integer, likes: Integer,
|
200
|
+
dislikes: Integer, shares: Integer, subscribers_gained: Integer,
|
201
|
+
subscribers_lost: Integer, favorites_added: Integer,
|
202
|
+
favorites_removed: Integer, average_view_duration: Float,
|
203
|
+
average_view_percentage: Float, annotation_clicks: Integer,
|
204
|
+
annotation_click_through_rate: Float,
|
205
|
+
annotation_close_rate: Float, earnings: Float, impressions: Integer,
|
206
|
+
monetized_playbacks: Integer}
|
207
|
+
|
208
|
+
specify 'by day' do
|
209
|
+
range = {since: 5.days.ago.to_date, until: 3.days.ago.to_date}
|
210
|
+
result = video.reports range.merge(only: metrics, by: :day)
|
211
|
+
metrics.each do |metric, type|
|
212
|
+
expect(result[metric].keys).to all(be_a Date)
|
213
|
+
expect(result[metric].values).to all(be_a type)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
specify 'by month' do
|
218
|
+
result = video.reports only: metrics, by: :month, since: 1.month.ago
|
219
|
+
metrics.each do |metric, type|
|
220
|
+
expect(result[metric].keys).to all(be_a Range)
|
221
|
+
expect(result[metric].keys.map &:first).to all(be_a Date)
|
222
|
+
expect(result[metric].keys.map &:first).to eq result[metric].keys.map(&:first).map(&:beginning_of_month)
|
223
|
+
expect(result[metric].keys.map &:last).to all(be_a Date)
|
224
|
+
expect(result[metric].keys.map &:last).to eq result[metric].keys.map(&:last).map(&:end_of_month)
|
225
|
+
expect(result[metric].values).to all(be_a type)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
179
230
|
describe 'earnings can be grouped by day' do
|
180
231
|
let(:range) { {since: 4.days.ago.to_date, until: 3.days.ago.to_date} }
|
181
232
|
let(:keys) { range.values }
|
@@ -271,7 +322,7 @@ describe Yt::Video, :partner do
|
|
271
322
|
end
|
272
323
|
|
273
324
|
describe 'views can be grouped by related video' do
|
274
|
-
let(:range) { {since:
|
325
|
+
let(:range) { {since: ENV['YT_TEST_PARTNER_VIDEO_DATE']} }
|
275
326
|
|
276
327
|
specify 'with the :by option set to :related_video' do
|
277
328
|
views = video.views range.merge by: :related_video
|
@@ -280,7 +331,7 @@ describe Yt::Video, :partner do
|
|
280
331
|
end
|
281
332
|
|
282
333
|
describe 'views can be grouped by search term' do
|
283
|
-
let(:range) { {since:
|
334
|
+
let(:range) { {since: ENV['YT_TEST_PARTNER_VIDEO_DATE']} }
|
284
335
|
|
285
336
|
specify 'with the :by option set to :search_term' do
|
286
337
|
views = video.views range.merge by: :search_term
|
@@ -289,7 +340,7 @@ describe Yt::Video, :partner do
|
|
289
340
|
end
|
290
341
|
|
291
342
|
describe 'views can be grouped by device type' do
|
292
|
-
let(:range) { {since:
|
343
|
+
let(:range) { {since: ENV['YT_TEST_PARTNER_VIDEO_DATE']} }
|
293
344
|
|
294
345
|
specify 'with the :by option set to :device_type' do
|
295
346
|
views = video.views range.merge by: :device_type
|
@@ -299,7 +350,7 @@ describe Yt::Video, :partner do
|
|
299
350
|
end
|
300
351
|
|
301
352
|
describe 'views can be grouped by country' do
|
302
|
-
let(:range) { {since:
|
353
|
+
let(:range) { {since: ENV['YT_TEST_PARTNER_VIDEO_DATE']} }
|
303
354
|
|
304
355
|
specify 'with the :by option set to :country' do
|
305
356
|
views = video.views range.merge by: :country
|
@@ -310,7 +361,7 @@ describe Yt::Video, :partner do
|
|
310
361
|
end
|
311
362
|
|
312
363
|
describe 'views can be grouped by state' do
|
313
|
-
let(:range) { {since:
|
364
|
+
let(:range) { {since: ENV['YT_TEST_PARTNER_VIDEO_DATE']} }
|
314
365
|
|
315
366
|
specify 'with the :by option set to :state' do
|
316
367
|
views = video.views range.merge by: :state
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.23.
|
4
|
+
version: 0.23.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claudio Baccigalupo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|