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
@@ -1,27 +0,0 @@
1
- require 'yt/collections/base'
2
- require 'yt/models/id'
3
-
4
- module Yt
5
- module Collections
6
- # @private
7
- class Ids < Base
8
-
9
- private
10
-
11
- def attributes_for_new_item(data)
12
- data['id']
13
- end
14
-
15
- def list_params
16
- super.tap do |params|
17
- params[:params] = ids_params
18
- params[:path] = "/youtube/v3/#{@parent.kind.pluralize}"
19
- end
20
- end
21
-
22
- def ids_params
23
- {for_username: @parent.username, part: 'id'}
24
- end
25
- end
26
- end
27
- end
@@ -1,54 +0,0 @@
1
- require 'yt/models/configuration'
2
-
3
- module Yt
4
- # Provides methods to read and write global configuration settings.
5
- #
6
- # A typical usage is to set the API keys retrieved from the
7
- # {http://console.developers.google.com Google Developers Console}.
8
- #
9
- # @example Set the API key for a server-only YouTube app:
10
- # Yt.configure do |config|
11
- # config.api_key = 'ABCDEFGHIJ1234567890'
12
- # end
13
- #
14
- # @example Set the API client id/secret for a web-client YouTube app:
15
- # Yt.configure do |config|
16
- # config.client_id = 'ABCDEFGHIJ1234567890'
17
- # config.client_secret = 'ABCDEFGHIJ1234567890'
18
- # end
19
- #
20
- # Note that Yt.configure has precedence over values through with
21
- # environment variables (see {Yt::Models::Configuration}).
22
- #
23
- module Config
24
- # Yields the global configuration to the given block.
25
- #
26
- # @example
27
- # Yt.configure do |config|
28
- # config.api_key = 'ABCDEFGHIJ1234567890'
29
- # end
30
- #
31
- # @yield [Yt::Models::Configuration] The global configuration.
32
- def configure
33
- yield configuration if block_given?
34
- end
35
-
36
- # Returns the global {Yt::Models::Configuration} object.
37
- #
38
- # While this method _can_ be used to read and write configuration settings,
39
- # it is easier to use {Yt::Config#configure} Yt.configure}.
40
- #
41
- # @example
42
- # Yt.configuration.api_key = 'ABCDEFGHIJ1234567890'
43
- #
44
- # @return [Yt::Models::Configuration] The global configuration.
45
- def configuration
46
- @configuration ||= Yt::Configuration.new
47
- end
48
- end
49
-
50
- # @note Config is the only module auto-loaded in the Yt module,
51
- # in order to have a syntax as easy as Yt.configure
52
-
53
- extend Config
54
- end
@@ -1,70 +0,0 @@
1
- module Yt
2
- module Models
3
- # Provides an object to store global configuration settings.
4
- #
5
- # This class is typically not used directly, but by calling
6
- # {Yt::Config#configure Yt.configure}, which creates and updates a single
7
- # instance of {Yt::Models::Configuration}.
8
- #
9
- # @example Set the API client id/secret for a web-client YouTube app:
10
- # Yt.configure do |config|
11
- # config.client_id = 'ABCDEFGHIJ1234567890'
12
- # config.client_secret = 'ABCDEFGHIJ1234567890'
13
- # end
14
- #
15
- # @see Yt::Config for more examples.
16
- #
17
- # An alternative way to set global configuration settings is by storing
18
- # them in the following environment variables:
19
- #
20
- # * +YT_CLIENT_ID+ to store the Client ID for web/device apps
21
- # * +YT_CLIENT_SECRET+ to store the Client Secret for web/device apps
22
- # * +YT_API_KEY+ to store the API key for server/browser apps
23
- # * +YT_LOG_LEVEL+ to store the verbosity level of the logs
24
- #
25
- # In case both methods are used together,
26
- # {Yt::Config#configure Yt.configure} takes precedence.
27
- #
28
- # @example Set the API client id/secret for a web-client YouTube app:
29
- # ENV['YT_CLIENT_ID'] = 'ABCDEFGHIJ1234567890'
30
- # ENV['YT_CLIENT_SECRET'] = 'ABCDEFGHIJ1234567890'
31
- #
32
- class Configuration
33
- # @return [String] the Client ID for web/device YouTube applications.
34
- # @see https://console.developers.google.com Google Developers Console
35
- attr_accessor :client_id
36
-
37
- # @return [String] the Client Secret for web/device YouTube applications.
38
- # @see https://console.developers.google.com Google Developers Console
39
- attr_accessor :client_secret
40
-
41
- # @return [String] the API key for server/browser YouTube applications.
42
- # @see https://console.developers.google.com Google Developers Console
43
- attr_accessor :api_key
44
-
45
- # @return [String] the level of output to print for debugging purposes.
46
- attr_accessor :log_level
47
-
48
- # Initialize the global configuration settings, using the values of
49
- # the specified following environment variables by default.
50
- def initialize
51
- @client_id = ENV['YT_CLIENT_ID']
52
- @client_secret = ENV['YT_CLIENT_SECRET']
53
- @api_key = ENV['YT_API_KEY']
54
- @log_level = ENV['YT_LOG_LEVEL']
55
- end
56
-
57
- # @return [Boolean] whether the logging output is extra-verbose.
58
- # Useful when developing (e.g., to print the curl of every request).
59
- def developing?
60
- log_level.to_s.in? %w(devel)
61
- end
62
-
63
- # @return [Boolean] whether the logging output is verbose.
64
- # Useful when debugging (e.g., to print the curl of failing requests).
65
- def debugging?
66
- log_level.to_s.in? %w(devel debug)
67
- end
68
- end
69
- end
70
- end
@@ -1,58 +0,0 @@
1
- require 'yt/models/url'
2
-
3
- module Yt
4
- module Models
5
- # Encapsulates information about the description of a resource, for
6
- # instance a channel.
7
- # @see https://developers.google.com/youtube/v3/docs/channels#resource
8
- #
9
- # The value has a maximum length of 1000 characters.
10
- class Description < String
11
- # @return [Boolean] whether the description includes a link to a video
12
- # @example
13
- # description = Yt::Models::Description.new 'Link to video: youtube.com/watch?v=MESycYJytkU'
14
- # description.has_link_to_video? #=> true
15
- #
16
- # @todo add an option to match the link to a specific video
17
- def has_link_to_video?
18
- links.any?{|link| link.kind == :video}
19
- end
20
-
21
- # @return [Boolean] whether the description includes a link to a channel
22
- # @example
23
- # description = Yt::Description.new 'Link to channel: youtube.com/fullscreen'
24
- # description.has_link_to_channel? #=> true
25
- #
26
- # @todo add an option to match the link to a specific channel
27
- def has_link_to_channel?(options = {})
28
- links.any?{|link| link.kind == :channel}
29
- end
30
-
31
- # @return [Boolean] whether the description includes a link to subscribe
32
- # @example
33
- # description = Yt::Description.new 'Link to subscribe: youtube.com/subscription_center?add_user=fullscreen'
34
- # description.has_link_to_subscribe? #=> true
35
- #
36
- # @todo add an option to match the link to subscribe to a specific channel
37
- def has_link_to_subscribe?(options = {})
38
- links.any?{|link| link.kind == :subscription}
39
- end
40
-
41
- # @return [Boolean] whether the description includes a link to a playlist
42
- # @example
43
- # description = Yt::Description.new 'Link to playlist: youtube.com/playlist?list=LLxO1tY8h1AhOz0T4ENwmpow'
44
- # description.has_link_to_playlist? #=> true
45
- #
46
- # @todo add an option to match the link to a specific playlist
47
- def has_link_to_playlist?
48
- links.any?{|link| link.kind == :playlist}
49
- end
50
-
51
- private
52
-
53
- def links
54
- @links ||= self.split(' ').map{|word| URL.new word}
55
- end
56
- end
57
- end
58
- end
@@ -1,91 +0,0 @@
1
- module Yt
2
- module Models
3
- # @private
4
- class URL
5
- attr_reader :kind
6
-
7
- def initialize(url)
8
- @url = url
9
- @kind ||= parse url
10
- @match_data ||= {}
11
- end
12
-
13
- def id
14
- @match_data[:id]
15
- rescue IndexError
16
- end
17
-
18
- def username
19
- @match_data[:username]
20
- rescue IndexError
21
- end
22
-
23
- private
24
-
25
- def parse(url)
26
- matching_pattern = patterns.find do |pattern|
27
- @match_data = url.match pattern[:regex]
28
- end
29
- matching_pattern[:kind] if matching_pattern
30
- end
31
-
32
- def patterns
33
- # @note: :channel *must* be the last since one of its regex eats the
34
- # remaining patterns. In short, don't change the following order
35
-
36
- @patterns ||= patterns_for :playlist, :subscription, :video, :channel
37
- end
38
-
39
- def patterns_for(*kinds)
40
- prefix = '^(?:https?://)?(?:www\.)?'
41
- suffix = '(?:|/)'
42
- kinds.map do |kind|
43
- patterns = send "#{kind}_patterns" # meta programming :/
44
- patterns.map do |pattern|
45
- {kind: kind, regex: %r{#{prefix}#{pattern}#{suffix}}}
46
- end
47
- end.flatten
48
- end
49
-
50
- def subscription_patterns
51
- name = '(?:[a-zA-Z0-9&_=-]*)'
52
-
53
- %W{
54
- subscription_center\\?add_user=#{name}
55
- subscribe_widget\\?p=#{name}
56
- channel/#{name}\\?sub_confirmation=1
57
- }.map{|path| "youtube\\.com/#{path}"}
58
- end
59
-
60
- def playlist_patterns
61
- playlist_id = '(?<id>[a-zA-Z0-9_-]+)'
62
-
63
- %W{
64
- playlist\\?list=#{playlist_id}
65
- }.map{|path| "youtube\\.com/#{path}"}
66
- end
67
-
68
- def video_patterns
69
- video_id = '(?<id>[a-zA-Z0-9_-]+)'
70
-
71
- %W{
72
- youtube\\.com/watch\\?v=#{video_id}
73
- youtu\\.be/#{video_id}
74
- youtube\\.com/embed/#{video_id}
75
- youtube\\.com/v/#{video_id}
76
- }
77
- end
78
-
79
- def channel_patterns
80
- channel_id = '(?<id>[a-zA-Z0-9_-]+)'
81
- username = '(?<username>[a-zA-Z0-9_-]+)'
82
-
83
- %W{
84
- channel/#{channel_id}
85
- user/#{username}
86
- #{username}
87
- }.map{|path| "youtube\\.com/#{path}"}
88
- end
89
- end
90
- end
91
- end
@@ -1,44 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Yt::Configuration do
4
- subject(:config) { Yt::Configuration.new }
5
-
6
- describe '#client_id' do
7
- context 'without an environment variable YT_CLIENT_ID' do
8
- before { ENV['YT_CLIENT_ID'] = nil }
9
- it {expect(config.client_id).to be_nil }
10
- end
11
-
12
- context 'given an environment variable YT_CLIENT_ID' do
13
- let(:client_id) { '1234567890.apps.googleusercontent.com' }
14
- before { ENV['YT_CLIENT_ID'] = client_id}
15
- it {expect(config.client_id).to eq client_id }
16
- end
17
- end
18
-
19
- describe '#client_secret' do
20
- context 'without an environment variable YT_CLIENT_SECRET' do
21
- before { ENV['YT_CLIENT_SECRET'] = nil }
22
- it {expect(config.client_secret).to be_nil }
23
- end
24
-
25
- context 'given an environment variable YT_CLIENT_SECRET' do
26
- let(:client_secret) { '1234567890' }
27
- before { ENV['YT_CLIENT_SECRET'] = client_secret}
28
- it {expect(config.client_secret).to eq client_secret }
29
- end
30
- end
31
-
32
- describe '#api_key' do
33
- context 'without an environment variable YT_API_KEY' do
34
- before { ENV['YT_API_KEY'] = nil }
35
- it {expect(config.api_key).to be_nil }
36
- end
37
-
38
- context 'given an environment variable YT_API_KEY' do
39
- let(:api_key) { '123456789012345678901234567890' }
40
- before { ENV['YT_API_KEY'] = api_key}
41
- it {expect(config.api_key).to eq api_key }
42
- end
43
- end
44
- end
@@ -1,94 +0,0 @@
1
- require 'spec_helper'
2
- require 'yt/models/description'
3
-
4
- describe Yt::Description do
5
- subject(:description) { Yt::Description.new text }
6
-
7
- describe '#text' do
8
- let(:text) { 'this is a description' }
9
- it { expect(description).to eq 'this is a description' }
10
- end
11
-
12
- describe '#length' do
13
- let(:text) { 'twenty one characters' }
14
- it { expect(description.length).to eq 21 }
15
- end
16
-
17
- describe '#has_link_to_video?' do
18
- context 'without a video URL' do
19
- let(:text) { 'Link to channel: youtube.com/fullscreen' }
20
- it { expect(description).not_to have_link_to_video }
21
- end
22
-
23
- context 'with a video long URL' do
24
- let(:text) { 'example.com and Link to video: youtube.com/watch?v=MESycYJytkU' }
25
- it { expect(description).to have_link_to_video }
26
- end
27
-
28
- context 'with a video short URL' do
29
- let(:text) { 'Link to video: youtu.be/MESycYJytkU' }
30
- it { expect(description).to have_link_to_video }
31
- end
32
-
33
- context 'with a playlist-embedded video URL' do
34
- let(:text) { 'Link to video in playlist: youtube.com/watch?v=MESycYJytkU&index=619&list=LLxO1tY8h1AhOz0T4ENwmpow' }
35
- it { expect(description).to have_link_to_video }
36
- end
37
- end
38
-
39
- describe '#has_link_to_channel?' do
40
- context 'without a channel URL' do
41
- let(:text) { 'youtu.be/MESycYJytkU is a video link' }
42
- it { expect(description).not_to have_link_to_channel }
43
- end
44
-
45
- context 'with a channel long URL' do
46
- let(:text) { 'Link to channel: youtube.com/channel/UCxO1tY8h1AhOz0T4ENwmpow' }
47
- it { expect(description).to have_link_to_channel }
48
- end
49
-
50
- context 'with a channel short URL' do
51
- let(:text) { 'Link to channel: youtube.com/fullscreen' }
52
- it { expect(description).to have_link_to_channel }
53
- end
54
-
55
- context 'with a channel user URL' do
56
- let(:text) { 'Link to channel: youtube.com/user/fullscreen' }
57
- it { expect(description).to have_link_to_channel }
58
- end
59
- end
60
-
61
- describe '#has_link_to_subscribe?' do
62
- context 'without a subscribe URL' do
63
- let(:text) { 'Link to video: youtu.be/MESycYJytkU' }
64
- it { expect(description).not_to have_link_to_subscribe }
65
- end
66
-
67
- context 'with a subscribe center URL' do
68
- let(:text) { 'Link to subscribe: youtube.com/subscription_center?add_user=fullscreen' }
69
- it { expect(description).to have_link_to_subscribe }
70
- end
71
-
72
- context 'with a subscribe short URL' do
73
- let(:text) { 'Link to subscribe: youtube.com/subscribe_widget?p=fullscreen' }
74
- it { expect(description).to have_link_to_subscribe }
75
- end
76
-
77
- context 'with a subscribe confirm URL' do
78
- let(:text) { 'Link to subscribe: youtube.com/channel/UCxO1tY8h1AhOz0T4ENwmpow?sub_confirmation=1' }
79
- it { expect(description).to have_link_to_subscribe }
80
- end
81
- end
82
-
83
- describe '#has_link_to_playlist?' do
84
- context 'without a playlist URL' do
85
- let(:text) { 'Link to video: youtu.be/MESycYJytkU' }
86
- it { expect(description).not_to have_link_to_playlist }
87
- end
88
-
89
- context 'with a playlist long URL' do
90
- let(:text) { 'Link to playlist: youtube.com/playlist?list=LLxO1tY8h1AhOz0T4ENwmpow' }
91
- it { expect(description).to have_link_to_playlist }
92
- end
93
- end
94
- end
@@ -1,84 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require 'spec_helper'
4
- require 'yt/models/url'
5
-
6
- describe Yt::URL do
7
- subject(:url) { Yt::URL.new text }
8
-
9
- context 'given a long video URL' do
10
- let(:text) { 'youtube.com/watch?v=MESycYJytkU' }
11
- it {expect(url.kind).to eq :video }
12
- it {expect(url.id).to eq 'MESycYJytkU' }
13
- it {expect(url.username).to be_nil }
14
- end
15
-
16
- context 'given a short video URL' do
17
- let(:text) { 'https://youtu.be/MESycYJytkU' }
18
- it {expect(url.kind).to eq :video }
19
- it {expect(url.id).to eq 'MESycYJytkU' }
20
- end
21
-
22
- context 'given an embed video URL' do
23
- let(:text) { 'https://www.youtube.com/embed/MESycYJytkU' }
24
- it {expect(url.kind).to eq :video }
25
- it {expect(url.id).to eq 'MESycYJytkU' }
26
- end
27
-
28
- context 'given a v video URL' do
29
- let(:text) { 'https://www.youtube.com/v/MESycYJytkU' }
30
- it {expect(url.kind).to eq :video }
31
- it {expect(url.id).to eq 'MESycYJytkU' }
32
- end
33
-
34
- context 'given a playlist-embedded video URL' do
35
- let(:text) { 'youtube.com/watch?v=MESycYJytkU&list=LLxO1tY8h1AhOz0T4ENwmpow' }
36
- it {expect(url.kind).to eq :video }
37
- it {expect(url.id).to eq 'MESycYJytkU' }
38
- end
39
-
40
- context 'given a long channel URL' do
41
- let(:text) { 'http://youtube.com/channel/UCxO1tY8h1AhOz0T4ENwmpow' }
42
- it {expect(url.kind).to eq :channel }
43
- it {expect(url.id).to eq 'UCxO1tY8h1AhOz0T4ENwmpow' }
44
- end
45
-
46
- context 'given a short channel URL' do
47
- let(:text) { 'https://www.youtube.com/Fullscreen' }
48
- it {expect(url.kind).to eq :channel }
49
- it {expect(url.username).to eq 'Fullscreen' }
50
- it {expect(url.id).to be_nil }
51
- end
52
-
53
- context 'given a user’s channel URL' do
54
- let(:text) { 'https://www.youtube.com/user/Fullscreen' }
55
- it {expect(url.kind).to eq :channel }
56
- it {expect(url.username).to eq 'Fullscreen' }
57
- end
58
-
59
- context 'given a subscription center URL' do
60
- let(:text) { 'youtube.com/subscription_center?add_user=Fullscreen' }
61
- it {expect(url.kind).to eq :subscription }
62
- end
63
-
64
- context 'given a subscription widget URL' do
65
- let(:text) { 'youtube.com/subscribe_widget?p=Fullscreen' }
66
- it {expect(url.kind).to eq :subscription }
67
- end
68
-
69
- context 'given a subscription confirmation URL' do
70
- let(:text) { 'youtube.com/channel/UCxO1tY8h1AhOz0T4ENwmpow?sub_confirmation=1' }
71
- it {expect(url.kind).to eq :subscription }
72
- end
73
-
74
- context 'given a long playlist URL' do
75
- let(:text) { 'youtube.com/playlist?list=LLxO1tY8h1AhOz0T4ENwmpow' }
76
- it {expect(url.kind).to eq :playlist }
77
- it {expect(url.id).to eq 'LLxO1tY8h1AhOz0T4ENwmpow' }
78
- end
79
-
80
- context 'given a valid URL with a trailing slash' do
81
- let(:text) { 'https://www.youtube.com/user/Fullscreen/' }
82
- it {expect(url.kind).to eq :channel }
83
- end
84
- end