yt 0.25.26 → 0.25.27
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +9 -0
- data/lib/yt/actions/list.rb +2 -2
- data/lib/yt/collections/comment_threads.rb +41 -0
- data/lib/yt/models/comment_thread.rb +25 -5
- data/lib/yt/models/snippet.rb +5 -1
- data/lib/yt/models/video.rb +3 -0
- data/lib/yt/version.rb +1 -1
- data/spec/collections/comment_threads_spec.rb +46 -0
- data/spec/models/comment_thread_spec.rb +32 -0
- data/spec/requests/as_server_app/comment_thread_spec.rb +7 -0
- data/spec/requests/as_server_app/comment_threads_spec.rb +41 -0
- data/spec/requests/as_server_app/video_spec.rb +26 -5
- data/spec/requests/as_server_app/videos_spec.rb +2 -2
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c5e0f3c2d22ca139c343e25b12d546f27fab7426
|
4
|
+
data.tar.gz: ab8d1de072cd33417b2276923dcef81f40fa5063
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9817c82f21347ab5b0b5f2d1b866ae5de343ece03e8abfd51902a141618eb766bfa4499c2248d124a38cbd7493eb47cd743698db9eca637fdfeefb6b552573a
|
7
|
+
data.tar.gz: 9687e59b2d140f368083380fe593c18818c60f5d03c1184c6b4d604c5f7f2420b57d64138ba6b8b2427cf097527b90e493598aa64cc3899799f4ec7cf97f2c69
|
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.25.27 - 2016-03-28
|
10
|
+
|
11
|
+
* [FEATURE] Add `comment_threads` association to Yt::Video.
|
12
|
+
* [FEATURE] Add `top_level_comment` and delegate its attributes (`text_display`, `author_display_name`, `like_count`, `updated_at`) to Yt::CommentThread.
|
13
|
+
|
9
14
|
## 0.25.26 - 2016-03-24
|
10
15
|
|
11
16
|
* [FEATURE] Add Yt::Comment resource.
|
data/README.md
CHANGED
@@ -28,6 +28,9 @@ video.title #=> "Fullscreen Creator Platform"
|
|
28
28
|
video.comment_count #=> 308
|
29
29
|
video.hd? #=> true
|
30
30
|
video.annotations.count #=> 1
|
31
|
+
video.comment_threads #=> #<Yt::Collections::CommentThreads ...>
|
32
|
+
# Use #take to limit the number of pages need to fetch from server
|
33
|
+
video.comment_threads.take(99).map(&:author_display_name) #=> ["Paul", "Tommy", ...]
|
31
34
|
```
|
32
35
|
|
33
36
|
The **full documentation** is available at [rubydoc.info](http://www.rubydoc.info/gems/yt/frames).
|
@@ -130,6 +133,12 @@ comment_thread.video_id #=> "1234"
|
|
130
133
|
comment_thread.total_reply_count #=> 1
|
131
134
|
comment_thread.can_reply? #=> true
|
132
135
|
comment_thread.public? #=> true
|
136
|
+
|
137
|
+
comment_thread.top_level_comment #=> #<Yt::Models::Comment ...>
|
138
|
+
comment_thread.text_display #=> "funny video!"
|
139
|
+
comment_thread.like_count #=> 9
|
140
|
+
comment_thread.updated_at #=> 2016-03-22 12:56:56 UTC
|
141
|
+
comment_thread.author_display_name #=> "Joe"
|
133
142
|
```
|
134
143
|
|
135
144
|
Yt::Comment
|
data/lib/yt/actions/list.rb
CHANGED
@@ -6,7 +6,7 @@ require 'yt/config'
|
|
6
6
|
module Yt
|
7
7
|
module Actions
|
8
8
|
module List
|
9
|
-
delegate :any?, :count, :each, :each_cons, :each_slice, :find, :first,
|
9
|
+
delegate :any?, :count, :each, :each_cons, :each_slice, :find, :first, :take,
|
10
10
|
:flat_map, :map, :select, :size, to: :list
|
11
11
|
|
12
12
|
def first!
|
@@ -136,4 +136,4 @@ module Yt
|
|
136
136
|
end
|
137
137
|
end
|
138
138
|
end
|
139
|
-
end
|
139
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'yt/collections/base'
|
2
|
+
require 'yt/models/video'
|
3
|
+
require 'yt/models/channel'
|
4
|
+
|
5
|
+
module Yt
|
6
|
+
module Collections
|
7
|
+
# @private
|
8
|
+
class CommentThreads < Base
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def attributes_for_new_item(data)
|
13
|
+
{}.tap do |attributes|
|
14
|
+
attributes[:id] = data['id']
|
15
|
+
attributes[:snippet] = data['snippet']
|
16
|
+
attributes[:auth] = @auth
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Hash] the parameters to submit to YouTube to get the resource.
|
21
|
+
# @see https://developers.google.com/youtube/v3/docs/commentThreads#resource
|
22
|
+
def list_params
|
23
|
+
super.tap do |params|
|
24
|
+
params[:path] = "/youtube/v3/commentThreads"
|
25
|
+
params[:params] = comments_params
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def comments_params
|
30
|
+
apply_where_params!({max_results: 100, part: 'snippet'}).tap do |params|
|
31
|
+
case @parent
|
32
|
+
when Yt::Video
|
33
|
+
params[:videoId] = @parent.id
|
34
|
+
when Yt::Channel
|
35
|
+
params[:channelId] = @parent.id
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -2,21 +2,21 @@ require 'yt/models/resource'
|
|
2
2
|
|
3
3
|
module Yt
|
4
4
|
module Models
|
5
|
-
# Provides methods to interact with YouTube
|
5
|
+
# Provides methods to interact with YouTube comment thread.
|
6
6
|
# @see https://developers.google.com/youtube/v3/docs/commentThreads
|
7
7
|
class CommentThread < Resource
|
8
8
|
|
9
9
|
### SNIPPET ###
|
10
10
|
|
11
11
|
# @!attribute [r] video_id
|
12
|
-
# @return [String] the ID of the video that the
|
13
|
-
# any. If this property is not present or does not have a value, then
|
14
|
-
#
|
12
|
+
# @return [String] the ID of the video that the comment thread referto, if
|
13
|
+
# any. If this property is not present or does not have a value, then the
|
14
|
+
# thread applies to the channel and not to a specific video.
|
15
15
|
delegate :video_id, to: :snippet
|
16
16
|
|
17
17
|
# @!attribute [r] total_reply_count
|
18
18
|
# @return [String] The total number of replies that have been submitted
|
19
|
-
# in response to the top
|
19
|
+
# in response to the top level comment.
|
20
20
|
delegate :total_reply_count, to: :snippet
|
21
21
|
|
22
22
|
# @return [Boolean] whether the thread, including all of its comments and
|
@@ -25,6 +25,26 @@ module Yt
|
|
25
25
|
|
26
26
|
# @return [Boolean] whether the current viewer can reply to the thread.
|
27
27
|
delegate :can_reply?, to: :snippet
|
28
|
+
|
29
|
+
# @!attribute [r] top_level_comment
|
30
|
+
# @return [Yt::TopLevelComment] the top level comment object.
|
31
|
+
delegate :top_level_comment, to: :snippet
|
32
|
+
|
33
|
+
# @!attribute [r] text_display
|
34
|
+
# @return [String] the top level comment's display text.
|
35
|
+
delegate :text_display, to: :top_level_comment
|
36
|
+
|
37
|
+
# @!attribute [r] author_display_name
|
38
|
+
# @return [String] the top level comment's author name.
|
39
|
+
delegate :author_display_name, to: :top_level_comment
|
40
|
+
|
41
|
+
# @!attribute [r] like_count
|
42
|
+
# @return [String] the top level comment's likes count.
|
43
|
+
delegate :like_count, to: :top_level_comment
|
44
|
+
|
45
|
+
# @!attribute [r] updated_at
|
46
|
+
# @return [String] the top level comment's last updated time.
|
47
|
+
delegate :updated_at, to: :top_level_comment
|
28
48
|
end
|
29
49
|
end
|
30
50
|
end
|
data/lib/yt/models/snippet.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'yt/models/description'
|
2
|
+
require 'yt/models/comment'
|
2
3
|
|
3
4
|
module Yt
|
4
5
|
module Models
|
@@ -38,7 +39,6 @@ module Yt
|
|
38
39
|
has_attribute :like_count, type: Integer
|
39
40
|
has_attribute :updated_at, type: Time
|
40
41
|
|
41
|
-
|
42
42
|
def thumbnail_url(size = :default)
|
43
43
|
thumbnails.fetch(size.to_s, {})['url']
|
44
44
|
end
|
@@ -51,6 +51,10 @@ module Yt
|
|
51
51
|
@can_reply ||= data.fetch 'canReply', false
|
52
52
|
end
|
53
53
|
|
54
|
+
def top_level_comment
|
55
|
+
@top_level_comment ||= Yt::Comment.new data['topLevelComment'].symbolize_keys
|
56
|
+
end
|
57
|
+
|
54
58
|
# Returns whether YouTube API includes all attributes in this snippet.
|
55
59
|
# For instance, YouTube API only returns tags and categoryId on
|
56
60
|
# Videos#list, not on Videos#search. And returns position on
|
data/lib/yt/models/video.rb
CHANGED
@@ -369,6 +369,9 @@ module Yt
|
|
369
369
|
delegate :concurrent_viewers, to: :live_streaming_detail
|
370
370
|
|
371
371
|
### ASSOCIATIONS ###
|
372
|
+
# @!attribute [r] comments
|
373
|
+
# @return [Yt::Collections::Comments] the video’s comments.
|
374
|
+
has_many :comment_threads
|
372
375
|
|
373
376
|
# @!attribute [r] annotations
|
374
377
|
# @return [Yt::Collections::Annotations] the video’s annotations.
|
data/lib/yt/version.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'yt/collections/comment_threads'
|
3
|
+
require 'yt/models/video'
|
4
|
+
require 'yt/models/channel'
|
5
|
+
|
6
|
+
describe Yt::Collections::CommentThreads do
|
7
|
+
subject(:collection) { Yt::Collections::CommentThreads.new parent: parent}
|
8
|
+
|
9
|
+
describe '#size', :ruby2 do
|
10
|
+
describe 'sends only one request and return the total results' do
|
11
|
+
let(:total_results) { 1234 }
|
12
|
+
let(:parent) { Yt::Video.new id: 'any-id' }
|
13
|
+
|
14
|
+
before do
|
15
|
+
expect_any_instance_of(Yt::Request).to receive(:run).once do
|
16
|
+
double(body: {'pageInfo'=>{'totalResults'=>total_results}})
|
17
|
+
end
|
18
|
+
end
|
19
|
+
it { expect(collection.size).to be total_results }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#count' do
|
24
|
+
let(:query) { {q: 'search string'} }
|
25
|
+
let(:parent) { Yt::Video.new id: 'any-id' }
|
26
|
+
let(:page) { {items: [], token: 'any-token'} }
|
27
|
+
|
28
|
+
context 'called once with .where(query) and once without' do
|
29
|
+
after do
|
30
|
+
collection.where(query).count
|
31
|
+
collection.count
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'only applies the query on the first call' do
|
35
|
+
expect(collection).to receive(:fetch_page) do |options|
|
36
|
+
expect(options[:params]).to include query
|
37
|
+
page
|
38
|
+
end
|
39
|
+
expect(collection).to receive(:fetch_page) do |options|
|
40
|
+
expect(options[:params]).not_to include query
|
41
|
+
page
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -23,6 +23,38 @@ describe Yt::CommentThread do
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
describe '#top_level_comment' do
|
27
|
+
context 'given a snippet with a top level comment' do
|
28
|
+
let(:attrs) { {snippet: {"topLevelComment"=> {}}} }
|
29
|
+
it { expect(comment_thread.top_level_comment).to be_a Yt::Comment }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe 'attributes from #top_level_comment delegations' do
|
34
|
+
context 'with values' do
|
35
|
+
let(:attrs) { {snippet: {"topLevelComment"=> {"id" => "xyz123", "snippet" => {
|
36
|
+
"textDisplay" => "funny video!",
|
37
|
+
"authorDisplayName" => "fullscreen",
|
38
|
+
"likeCount" => 99,
|
39
|
+
"updatedAt" => "2016-03-22T12:56:56.3Z"}}}} }
|
40
|
+
|
41
|
+
it { expect(comment_thread.top_level_comment.id).to eq 'xyz123' }
|
42
|
+
it { expect(comment_thread.text_display).to eq 'funny video!' }
|
43
|
+
it { expect(comment_thread.author_display_name).to eq 'fullscreen' }
|
44
|
+
it { expect(comment_thread.like_count).to eq 99 }
|
45
|
+
it { expect(comment_thread.updated_at).to eq Time.parse('2016-03-22T12:56:56.3Z') }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'without values' do
|
49
|
+
let(:attrs) { {snippet: {"topLevelComment"=> {"snippet" => {}}}} }
|
50
|
+
|
51
|
+
it { expect(comment_thread.text_display).to be_nil }
|
52
|
+
it { expect(comment_thread.author_display_name).to be_nil }
|
53
|
+
it { expect(comment_thread.like_count).to be_nil }
|
54
|
+
it { expect(comment_thread.updated_at).to be_nil }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
26
58
|
describe '#total_reply_count' do
|
27
59
|
context 'given a snippet with a total reply count' do
|
28
60
|
let(:attrs) { {snippet: {"totalReplyCount"=>1}} }
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'yt/models/comment_thread'
|
3
|
+
require 'yt/models/comment'
|
3
4
|
|
4
5
|
describe Yt::CommentThread, :server_app do
|
5
6
|
subject(:comment_thread) { Yt::CommentThread.new attrs }
|
@@ -11,6 +12,12 @@ describe Yt::CommentThread, :server_app do
|
|
11
12
|
it { expect(comment_thread.total_reply_count).to be_an Integer }
|
12
13
|
it { expect(comment_thread.can_reply?).to be false }
|
13
14
|
it { expect(comment_thread).to be_public }
|
15
|
+
|
16
|
+
it { expect(comment_thread.top_level_comment).to be_a Yt::Comment }
|
17
|
+
it { expect(comment_thread.text_display).not_to be_empty }
|
18
|
+
it { expect(comment_thread.author_display_name).not_to be_empty }
|
19
|
+
it { expect(comment_thread.updated_at).to be_a Time }
|
20
|
+
it { expect(comment_thread.like_count).to be_a Integer }
|
14
21
|
end
|
15
22
|
|
16
23
|
context 'given an comment thread ID about a video' do
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'yt/collections/comment_threads'
|
4
|
+
require 'yt/models/video'
|
5
|
+
require 'yt/models/channel'
|
6
|
+
|
7
|
+
describe Yt::Collections::CommentThreads, :server_app do
|
8
|
+
context "without parent association", :ruby2 do
|
9
|
+
subject(:comment_threads) { Yt::Collections::CommentThreads.new }
|
10
|
+
|
11
|
+
specify 'without given any of id, videoId, channelId or allThreadsRelatedToChannelId param, raise request error', :ruby2 do
|
12
|
+
expect{ comment_threads.size }.to raise_error(Yt::Errors::RequestError)
|
13
|
+
end
|
14
|
+
|
15
|
+
specify 'with a id param, only return one comment thread' do
|
16
|
+
expect(comment_threads.where(id: 'z13zytsilxbexh30e233gdyyttngfjfz104').size).to eq 1
|
17
|
+
end
|
18
|
+
|
19
|
+
specify 'with a videoId param, returns comment threads for the video', focus: true do
|
20
|
+
expect(comment_threads.where(videoId: 'MsplPPW7tFo').size).to be > 0
|
21
|
+
end
|
22
|
+
|
23
|
+
specify 'with a channelId param, returns comment threads for the channel' do
|
24
|
+
expect(comment_threads.where(channelId: 'UC-lHJZR3Gqxm24_Vd_AJ5Yw').size).to be > 0
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "with parent association", :ruby2 do
|
29
|
+
subject(:comment_threads) { Yt::Collections::CommentThreads.new parent: parent}
|
30
|
+
|
31
|
+
context "parent as video" do
|
32
|
+
let(:parent) { Yt::Models::Video.new id: 'MsplPPW7tFo' }
|
33
|
+
it { expect(comment_threads.size).to be > 0 }
|
34
|
+
end
|
35
|
+
|
36
|
+
context "parent as channel" do
|
37
|
+
let(:parent) { Yt::Models::Channel.new id: 'UC-lHJZR3Gqxm24_Vd_AJ5Yw' }
|
38
|
+
it { expect(comment_threads.size).to be > 0 }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'yt/models/video'
|
3
|
+
require 'yt/collections/comment_threads'
|
3
4
|
|
4
5
|
describe Yt::Video, :server_app do
|
5
6
|
subject(:video) { Yt::Video.new attrs }
|
6
7
|
|
7
8
|
context 'given an existing video ID' do
|
8
|
-
let(:attrs) { {id: '
|
9
|
+
let(:attrs) { {id: 'L3JDXvz7G6c'} }
|
9
10
|
|
10
11
|
it { expect(video.content_detail).to be_a Yt::ContentDetail }
|
11
12
|
|
@@ -27,11 +28,11 @@ describe Yt::Video, :server_app do
|
|
27
28
|
end
|
28
29
|
|
29
30
|
context 'given an existing video URL' do
|
30
|
-
let(:attrs) { {url: 'https://www.youtube.com/watch?v=
|
31
|
+
let(:attrs) { {url: 'https://www.youtube.com/watch?v=L3JDXvz7G6c'} }
|
31
32
|
|
32
33
|
specify 'provides access to its data' do
|
33
|
-
expect(video.id).to eq '
|
34
|
-
expect(video.title).to eq
|
34
|
+
expect(video.id).to eq 'L3JDXvz7G6c'
|
35
|
+
expect(video.title).to eq "you’re in fullscreen"
|
35
36
|
expect(video.privacy_status).to eq 'public'
|
36
37
|
end
|
37
38
|
end
|
@@ -55,4 +56,24 @@ describe Yt::Video, :server_app do
|
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
58
|
-
|
59
|
+
describe 'associations' do
|
60
|
+
let(:attrs) { {id: 'MsplPPW7tFo'} }
|
61
|
+
|
62
|
+
describe '#comment_threads' do
|
63
|
+
it { expect(video.comment_threads).to be_a Yt::Collections::CommentThreads }
|
64
|
+
it { expect(video.comment_threads.first.top_level_comment).to be_a Yt::Models::Comment }
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#comment_threads.each_cons' do
|
68
|
+
it {
|
69
|
+
comment_threads = []
|
70
|
+
video.comment_threads.each_cons(2).take_while do |items|
|
71
|
+
comment_threads += items
|
72
|
+
comment_threads.size < 6
|
73
|
+
end
|
74
|
+
expect(comment_threads.size).to be 6
|
75
|
+
}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
@@ -22,7 +22,7 @@ describe Yt::Collections::Videos, :server_app do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
specify 'with a chart parameter, only returns videos of that chart', :ruby2 do
|
25
|
-
expect(videos.where(chart: 'mostPopular').size).to be
|
25
|
+
expect(videos.where(chart: 'mostPopular').size).to be 200
|
26
26
|
end
|
27
27
|
|
28
28
|
context 'with a list of parts' do
|
@@ -37,4 +37,4 @@ describe Yt::Collections::Videos, :server_app do
|
|
37
37
|
expect(video.instance_variable_defined? :@content_detail).to be true
|
38
38
|
end
|
39
39
|
end
|
40
|
-
end
|
40
|
+
end
|
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.25.
|
4
|
+
version: 0.25.27
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claudio Baccigalupo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -137,6 +137,7 @@ files:
|
|
137
137
|
- lib/yt/collections/channels.rb
|
138
138
|
- lib/yt/collections/claim_histories.rb
|
139
139
|
- lib/yt/collections/claims.rb
|
140
|
+
- lib/yt/collections/comment_threads.rb
|
140
141
|
- lib/yt/collections/content_details.rb
|
141
142
|
- lib/yt/collections/content_owner_details.rb
|
142
143
|
- lib/yt/collections/content_owners.rb
|
@@ -229,6 +230,7 @@ files:
|
|
229
230
|
- lib/yt/request.rb
|
230
231
|
- lib/yt/version.rb
|
231
232
|
- spec/collections/claims_spec.rb
|
233
|
+
- spec/collections/comment_threads_spec.rb
|
232
234
|
- spec/collections/playlist_items_spec.rb
|
233
235
|
- spec/collections/playlists_spec.rb
|
234
236
|
- spec/collections/policies_spec.rb
|
@@ -300,6 +302,7 @@ files:
|
|
300
302
|
- spec/requests/as_server_app/channel_spec.rb
|
301
303
|
- spec/requests/as_server_app/comment_spec.rb
|
302
304
|
- spec/requests/as_server_app/comment_thread_spec.rb
|
305
|
+
- spec/requests/as_server_app/comment_threads_spec.rb
|
303
306
|
- spec/requests/as_server_app/playlist_item_spec.rb
|
304
307
|
- spec/requests/as_server_app/playlist_spec.rb
|
305
308
|
- spec/requests/as_server_app/video_spec.rb
|
@@ -336,6 +339,7 @@ summary: Yt makes it easy to interact with Youtube V3 API by providing a modular
|
|
336
339
|
intuitive and tested Ruby-style API.
|
337
340
|
test_files:
|
338
341
|
- spec/collections/claims_spec.rb
|
342
|
+
- spec/collections/comment_threads_spec.rb
|
339
343
|
- spec/collections/playlist_items_spec.rb
|
340
344
|
- spec/collections/playlists_spec.rb
|
341
345
|
- spec/collections/policies_spec.rb
|
@@ -407,6 +411,7 @@ test_files:
|
|
407
411
|
- spec/requests/as_server_app/channel_spec.rb
|
408
412
|
- spec/requests/as_server_app/comment_spec.rb
|
409
413
|
- spec/requests/as_server_app/comment_thread_spec.rb
|
414
|
+
- spec/requests/as_server_app/comment_threads_spec.rb
|
410
415
|
- spec/requests/as_server_app/playlist_item_spec.rb
|
411
416
|
- spec/requests/as_server_app/playlist_spec.rb
|
412
417
|
- spec/requests/as_server_app/video_spec.rb
|