msp-youtube-g 0.4.7 → 0.4.8.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.
@@ -1,5 +1,15 @@
1
1
  == trunk
2
2
  * Move network dependent tests to integration-test [msp]
3
+ * Create a parser and a model for upload errors [msp]
4
+ * Stub driven tests for VideoFeedParser, VideosFeedParser, UploadErrorParser [msp]
5
+ * Added :page and :per_page options, this allows easier usage of the will_paginate
6
+ plugin with the library. The :offset and :max_results options are no longer available. [Daniel Insley]
7
+ * Added ability to get video responses on the instances of the YouTube::Model::Video object. [Daniel Insley]
8
+ * Added and improved the existing documentation [Daniel Insley]
9
+ * Fixed usage of deprecated yt:racy, now using media:rating [Daniel Insley]
10
+ * Renamed can_embed? method to embeddable? [Daniel Insley]
11
+ * Added ability for padingation and ordering on standard feeds. [Daniel Insley]
12
+ * Move network dependent tests to integration-test [msp]
3
13
  * Create a parser and a model for upload errors [msp]
4
14
  * Stub driven tests for VideoFeedParser, VideosFeedParser, UploadErrorParser [msp]
5
15
  * Add error-handling for video upload errors. [FiXato]
@@ -18,6 +18,9 @@ lib/youtube_g/model/video.rb
18
18
  lib/youtube_g/model/upload_error.rb
19
19
  lib/youtube_g/parser.rb
20
20
  lib/youtube_g/record.rb
21
+ lib/youtube_g/request/base_search.rb
22
+ lib/youtube_g/request/standard_search.rb
23
+ lib/youtube_g/request/user_search.rb
21
24
  lib/youtube_g/request/video_search.rb
22
25
  lib/youtube_g/request/video_upload.rb
23
26
  lib/youtube_g/response/video_search.rb
data/README.txt CHANGED
@@ -32,6 +32,7 @@ Create a client:
32
32
  Basic queries:
33
33
 
34
34
  client.videos_by(:query => "penguin")
35
+ client.videos_by(:query => "penguin", :page => 2, :per_page => 15)
35
36
  client.videos_by(:tags => ['tiger', 'leopard'])
36
37
  client.videos_by(:categories => [:news, :sports])
37
38
  client.videos_by(:categories => [:news, :sports], :tags => ['soccer', 'football'])
@@ -40,6 +41,7 @@ Basic queries:
40
41
  Standard feeds:
41
42
 
42
43
  client.videos_by(:most_viewed)
44
+ client.videos_by(:most_linked, :page => 3)
43
45
  client.videos_by(:top_rated, :time => :today)
44
46
 
45
47
  Advanced queries (with boolean operators OR (either), AND (include), NOT (exclude)):
data/Rakefile CHANGED
@@ -17,4 +17,9 @@ desc 'Tag release'
17
17
  task :tag do
18
18
  svn_root = 'svn+ssh://drummr77@rubyforge.org/var/svn/youtube-g'
19
19
  sh %(svn cp #{svn_root}/trunk #{svn_root}/tags/release-#{YouTubeG::VERSION} -m "Tag YouTubeG release #{YouTubeG::VERSION}")
20
+ end
21
+
22
+ desc 'Load the library in an IRB session'
23
+ task :console do
24
+ sh %(irb -r lib/youtube_g.rb)
20
25
  end
data/TODO.txt CHANGED
@@ -1,12 +1,10 @@
1
1
  [ ] stub out http request/response cycle for tests (partially done in test_parser, need to do the same for pre-existing tests [msp])
2
- [ ] consider defaulting the client to no-logger, rather than outputting to STDOUT.
3
2
  [ ] allow specifying values as single items where you don't need to wrap in a list, e.g. :tags => :chickens instead of :tags => [ 'chickens' ]
4
3
  [ ] make sure symbols will work as well as tags everywhere (again, :tags => :chickens is same as :tags => 'chickens')
5
4
  [ ] figure out better structure for class/file (either rename request/video_search.rb or split into one class per file again)
6
5
  [ ] restore spaces after method def names
7
6
  [ ] use a proxy for testing with static sample result xml so we have repeatable tests (see above [msp])
8
7
  [ ] Clean up tests using Shoulda to define contexts
9
- [ ] Consolidate requires
10
8
  [ ] Allow :category and :categories for query DSL
11
9
  [ ] Exception handling
12
10
 
@@ -0,0 +1,256 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'pp'
4
+
5
+ require 'youtube_g'
6
+
7
+ class TestClient < Test::Unit::TestCase
8
+ def setup
9
+ @client = YouTubeG::Client.new
10
+ end
11
+
12
+ def test_should_respond_to_a_basic_query
13
+ response = @client.videos_by(:query => "penguin")
14
+
15
+ assert_equal "http://gdata.youtube.com/feeds/api/videos", response.feed_id
16
+ assert_equal 25, response.max_result_count
17
+ assert_equal 25, response.videos.length
18
+ assert_equal 1, response.offset
19
+ assert(response.total_result_count > 100)
20
+ assert_instance_of Time, response.updated_at
21
+
22
+ response.videos.each { |v| assert_valid_video v }
23
+ end
24
+
25
+ def test_should_respond_to_a_basic_query_with_offset_and_max_results
26
+ response = @client.videos_by(:query => "penguin", :offset => 15, :max_results => 30)
27
+
28
+ assert_equal "http://gdata.youtube.com/feeds/api/videos", response.feed_id
29
+ assert_equal 30, response.max_result_count
30
+ assert_equal 30, response.videos.length
31
+ assert_equal 15, response.offset
32
+ assert(response.total_result_count > 100)
33
+ assert_instance_of Time, response.updated_at
34
+
35
+ response.videos.each { |v| assert_valid_video v }
36
+ end
37
+
38
+ def test_should_respond_to_a_basic_query_with_paging
39
+ response = @client.videos_by(:query => "penguin")
40
+ assert_equal "http://gdata.youtube.com/feeds/api/videos", response.feed_id
41
+ assert_equal 25, response.max_result_count
42
+ assert_equal 1, response.offset
43
+
44
+ response = @client.videos_by(:query => "penguin", :page => 2)
45
+ assert_equal "http://gdata.youtube.com/feeds/api/videos", response.feed_id
46
+ assert_equal 25, response.max_result_count
47
+ assert_equal 26, response.offset
48
+
49
+ response2 = @client.videos_by(:query => "penguin", :page => 3)
50
+ assert_equal "http://gdata.youtube.com/feeds/api/videos", response2.feed_id
51
+ assert_equal 25, response2.max_result_count
52
+ assert_equal 51, response2.offset
53
+ end
54
+
55
+
56
+ def test_should_get_videos_for_multiword_metasearch_query
57
+ response = @client.videos_by(:query => 'christina ricci')
58
+
59
+ assert_equal "http://gdata.youtube.com/feeds/api/videos", response.feed_id
60
+ assert_equal 25, response.max_result_count
61
+ assert_equal 25, response.videos.length
62
+ assert_equal 1, response.offset
63
+ assert(response.total_result_count > 100)
64
+ assert_instance_of Time, response.updated_at
65
+
66
+ response.videos.each { |v| assert_valid_video v }
67
+ end
68
+
69
+ def test_should_handle_video_not_yet_viewed
70
+ response = @client.videos_by(:query => "YnqHZDh_t2Q")
71
+
72
+ assert_equal 1, response.videos.length
73
+ response.videos.each { |v| assert_valid_video v }
74
+ end
75
+
76
+ # TODO: this doesn't work because the returned feed is in an unknown format
77
+ # def test_should_get_video_for_search_by_video_id
78
+ # response = @client.videos_by(:video_id => "T7YazwP8GtY")
79
+ # response.videos.each { |v| assert_valid_video v }
80
+ # end
81
+
82
+ def test_should_get_videos_for_one_tag
83
+ response = @client.videos_by(:tags => ['panther'])
84
+ response.videos.each { |v| assert_valid_video v }
85
+ end
86
+
87
+ def test_should_get_videos_for_multiple_tags
88
+ response = @client.videos_by(:tags => ['tiger', 'leopard'])
89
+ response.videos.each { |v| assert_valid_video v }
90
+ end
91
+
92
+ def test_should_get_videos_for_one_category
93
+ response = @client.videos_by(:categories => [:news])
94
+ response.videos.each { |v| assert_valid_video v }
95
+ end
96
+
97
+ def test_should_get_videos_for_multiple_categories
98
+ response = @client.videos_by(:categories => [:news, :sports])
99
+ response.videos.each { |v| assert_valid_video v }
100
+ end
101
+
102
+ # TODO: Need to do more specific checking in these tests
103
+ # Currently, if a URL is valid, and videos are found, the test passes regardless of search criteria
104
+ def test_should_get_videos_for_categories_and_tags
105
+ response = @client.videos_by(:categories => [:news, :sports], :tags => ['soccer', 'football'])
106
+ response.videos.each { |v| assert_valid_video v }
107
+ end
108
+
109
+ def test_should_get_most_viewed_videos
110
+ response = @client.videos_by(:most_viewed)
111
+ response.videos.each { |v| assert_valid_video v }
112
+ end
113
+
114
+ def test_should_get_top_rated_videos_for_today
115
+ response = @client.videos_by(:top_rated, :time => :today)
116
+ response.videos.each { |v| assert_valid_video v }
117
+ end
118
+
119
+ def test_should_get_videos_for_categories_and_tags_with_category_boolean_operators
120
+ response = @client.videos_by(:categories => { :either => [:news, :sports], :exclude => [:comedy] },
121
+ :tags => { :include => ['football'], :exclude => ['soccer'] })
122
+ response.videos.each { |v| assert_valid_video v }
123
+ end
124
+
125
+ def test_should_get_videos_for_categories_and_tags_with_tag_boolean_operators
126
+ response = @client.videos_by(:categories => { :either => [:news, :sports], :exclude => [:comedy] },
127
+ :tags => { :either => ['football', 'soccer', 'polo'] })
128
+ response.videos.each { |v| assert_valid_video v }
129
+ end
130
+
131
+ def test_should_get_videos_by_user
132
+ response = @client.videos_by(:user => 'liz')
133
+ response.videos.each { |v| assert_valid_video v }
134
+ end
135
+
136
+ # HTTP 403 Error
137
+ # def test_should_get_favorite_videos_by_user
138
+ # response = @client.videos_by(:favorites, :user => 'liz')
139
+ # response.videos.each { |v| assert_valid_video v }
140
+ # end
141
+
142
+ def test_should_get_videos_for_query_search_with_categories_excluded
143
+ video = @client.video_by("EkF4JD2rO3Q")
144
+ assert_equal "<object width=\"425\" height=\"350\">\n <param name=\"movie\" value=\"http://www.youtube.com/v/EkF4JD2rO3Q\"></param>\n <param name=\"wmode\" value=\"transparent\"></param>\n <embed src=\"http://www.youtube.com/v/EkF4JD2rO3Q\" type=\"application/x-shockwave-flash\" \n wmode=\"transparent\" width=\"425\" height=\"350\"></embed>\n</object>\n", video.embed_html
145
+ assert_valid_video video
146
+ end
147
+
148
+ def test_should_disable_debug_if_debug_is_set_to_false
149
+ @client = YouTubeG::Client.new
150
+ assert_nil @client.logger
151
+ end
152
+
153
+ def test_should_enable_logger_if_debug_is_true
154
+ @client = YouTubeG::Client.new(true)
155
+ assert_not_nil @client.logger
156
+ end
157
+
158
+ def test_should_determine_if_nonembeddable_video_is_embeddable
159
+ response = @client.videos_by(:query => "avril lavigne girlfriend")
160
+
161
+ video = response.videos.first
162
+ assert !video.embeddable?
163
+ end
164
+
165
+ def test_should_determine_if_embeddable_video_is_embeddable
166
+ response = @client.videos_by(:query => "strongbad")
167
+
168
+ video = response.videos.first
169
+ assert video.embeddable?
170
+ end
171
+
172
+ def test_should_retrieve_video_by_id
173
+ video = @client.video_by("http://gdata.youtube.com/feeds/videos/EkF4JD2rO3Q")
174
+ assert_valid_video video
175
+
176
+ video = @client.video_by("EkF4JD2rO3Q")
177
+ assert_valid_video video
178
+ end
179
+
180
+ private
181
+
182
+ def assert_valid_video (video)
183
+ # pp video
184
+
185
+ # check general attributes
186
+ assert_instance_of YouTubeG::Model::Video, video
187
+ assert_instance_of Fixnum, video.duration
188
+ assert(video.duration > 0)
189
+ #assert_match(/^<div style=.*?<\/div>/m, video.html_content)
190
+ assert_instance_of String, video.html_content
191
+
192
+ # validate media content records
193
+ video.media_content.each do |media_content|
194
+ # http://www.youtube.com/v/IHVaXG1thXM
195
+ assert_valid_url media_content.url
196
+ assert(media_content.duration > 0)
197
+ assert_instance_of YouTubeG::Model::Video::Format, media_content.format
198
+ assert_instance_of String, media_content.mime_type
199
+ assert_match(/^[^\/]+\/[^\/]+$/, media_content.mime_type)
200
+ end
201
+
202
+ default_content = video.default_media_content
203
+ if default_content
204
+ assert_instance_of YouTubeG::Model::Content, default_content
205
+ assert default_content.is_default?
206
+ end
207
+
208
+ # validate keywords
209
+ video.keywords.each { |kw| assert_instance_of(String, kw) }
210
+
211
+ # http://www.youtube.com/watch?v=IHVaXG1thXM
212
+ assert_valid_url video.player_url
213
+ assert_instance_of Time, video.published_at
214
+
215
+ # validate optionally-present rating
216
+ if video.rating
217
+ assert_instance_of YouTubeG::Model::Rating, video.rating
218
+ assert_instance_of Float, video.rating.average
219
+ assert_instance_of Fixnum, video.rating.max
220
+ assert_instance_of Fixnum, video.rating.min
221
+ assert_instance_of Fixnum, video.rating.rater_count
222
+ end
223
+
224
+ # validate thumbnails
225
+ assert(video.thumbnails.size > 0)
226
+
227
+ assert_not_nil video.title
228
+ assert_instance_of String, video.title
229
+ assert(video.title.length > 0)
230
+
231
+ assert_instance_of Time, video.updated_at
232
+ # http://gdata.youtube.com/feeds/videos/IHVaXG1thXM
233
+ assert_valid_url video.video_id
234
+ assert_instance_of Fixnum, video.view_count
235
+
236
+ # validate author
237
+ assert_instance_of YouTubeG::Model::Author, video.author
238
+ assert_instance_of String, video.author.name
239
+ assert(video.author.name.length > 0)
240
+ assert_valid_url video.author.uri
241
+
242
+ # validate categories
243
+ video.categories.each do |cat|
244
+ assert_instance_of YouTubeG::Model::Category, cat
245
+ assert_instance_of String, cat.label
246
+ assert_instance_of String, cat.term
247
+ end
248
+ end
249
+
250
+ def assert_valid_url (url)
251
+ URI::parse(url)
252
+ return true
253
+ rescue
254
+ return false
255
+ end
256
+ end
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'pp'
4
+
5
+ require 'youtube_g'
6
+
7
+ class TestVideo < Test::Unit::TestCase
8
+ def test_should_extract_unique_id_from_video_id
9
+ video = YouTubeG::Model::Video.new(:video_id => "http://gdata.youtube.com/feeds/videos/ZTUVgYoeN_o")
10
+ assert_equal "ZTUVgYoeN_o", video.unique_id
11
+ end
12
+
13
+ def test_should_extract_unique_id_with_hypen_from_video_id
14
+ video = YouTubeG::Model::Video.new(:video_id => "http://gdata.youtube.com/feeds/videos/BDqs-OZWw9o")
15
+ assert_equal "BDqs-OZWw9o", video.unique_id
16
+ end
17
+
18
+ def test_should_have_related_videos
19
+ video = YouTubeG::Model::Video.new(:video_id => "http://gdata.youtube.com/feeds/videos/BDqs-OZWw9o")
20
+ response = video.related
21
+
22
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/BDqs-OZWw9o/related", response.feed_id
23
+ assert_equal 25, response.max_result_count
24
+ assert_equal 25, response.videos.length
25
+ assert_equal 1, response.offset
26
+ assert(response.total_result_count > 0)
27
+ assert_instance_of Time, response.updated_at
28
+ end
29
+
30
+ def test_should_have_response_videos
31
+ video = YouTubeG::Model::Video.new(:video_id => "http://gdata.youtube.com/feeds/videos/BDqs-OZWw9o")
32
+ response = video.responses
33
+
34
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/BDqs-OZWw9o/responses", response.feed_id
35
+ assert_equal 25, response.max_result_count
36
+ assert_equal 25, response.videos.length
37
+ assert_equal 1, response.offset
38
+ assert(response.total_result_count > 0)
39
+ assert_instance_of Time, response.updated_at
40
+ end
41
+
42
+ end
@@ -0,0 +1,128 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'pp'
4
+
5
+ require 'youtube_g'
6
+
7
+ class TestVideoSearch < Test::Unit::TestCase
8
+
9
+ def test_should_build_basic_query_url
10
+ request = YouTubeG::Request::VideoSearch.new(:query => "penguin")
11
+ assert_equal "http://gdata.youtube.com/feeds/api/videos?vq=penguin", request.url
12
+ end
13
+
14
+ def test_should_build_multiword_metasearch_query_url
15
+ request = YouTubeG::Request::VideoSearch.new(:query => 'christina ricci')
16
+ assert_equal "http://gdata.youtube.com/feeds/api/videos?vq=christina+ricci", request.url
17
+ end
18
+
19
+ def test_should_build_video_id_url
20
+ request = YouTubeG::Request::VideoSearch.new(:video_id => 'T7YazwP8GtY')
21
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/T7YazwP8GtY", request.url
22
+ end
23
+
24
+ def test_should_build_one_tag_querl_url
25
+ request = YouTubeG::Request::VideoSearch.new(:tags => ['panther'])
26
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/-/panther/", request.url
27
+ end
28
+
29
+ def test_should_build_multiple_tags_query_url
30
+ request = YouTubeG::Request::VideoSearch.new(:tags => ['tiger', 'leopard'])
31
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/-/tiger/leopard/", request.url
32
+ end
33
+
34
+ def test_should_build_one_category_query_url
35
+ request = YouTubeG::Request::VideoSearch.new(:categories => [:news])
36
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/-/News/", request.url
37
+ end
38
+
39
+ def test_should_build_multiple_categories_query_url
40
+ request = YouTubeG::Request::VideoSearch.new(:categories => [:news, :sports])
41
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/-/News/Sports/", request.url
42
+ end
43
+
44
+ def test_should_build_categories_and_tags_query_url
45
+ request = YouTubeG::Request::VideoSearch.new(:categories => [:news, :sports], :tags => ['soccer', 'football'])
46
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/-/News/Sports/soccer/football/", request.url
47
+ end
48
+
49
+ def test_should_build_categories_and_tags_url_with_max_results
50
+ request = YouTubeG::Request::VideoSearch.new(:categories => [:music], :tags => ['classic', 'rock'], :max_results => 2)
51
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/-/Music/classic/rock/?max-results=2", request.url
52
+ end
53
+
54
+ def test_should_build_author_query_url
55
+ request = YouTubeG::Request::VideoSearch.new(:author => "davidguetta")
56
+ assert_equal "http://gdata.youtube.com/feeds/api/videos?author=davidguetta", request.url
57
+ end
58
+ # -- Standard Feeds --------------------------------------------------------------------------------
59
+
60
+ def test_should_build_url_for_most_viewed
61
+ request = YouTubeG::Request::StandardSearch.new(:most_viewed)
62
+ assert_equal "http://gdata.youtube.com/feeds/api/standardfeeds/most_viewed", request.url
63
+ end
64
+
65
+ def test_should_build_url_for_top_rated_for_today
66
+ request = YouTubeG::Request::StandardSearch.new(:top_rated, :time => :today)
67
+ assert_equal "http://gdata.youtube.com/feeds/api/standardfeeds/top_rated?time=today", request.url
68
+ end
69
+
70
+ def test_should_build_url_for_most_viewed_offset_and_max_results_without_time
71
+ request = YouTubeG::Request::StandardSearch.new(:top_rated, :offset => 5, :max_results => 10)
72
+ assert_equal "http://gdata.youtube.com/feeds/api/standardfeeds/top_rated?max-results=10&start-index=5", request.url
73
+ end
74
+
75
+ def test_should_build_url_for_most_viewed_offset_and_max_results_with_time
76
+ request = YouTubeG::Request::StandardSearch.new(:top_rated, :offset => 5, :max_results => 10, :time => :today)
77
+ assert_equal "http://gdata.youtube.com/feeds/api/standardfeeds/top_rated?time=today&max-results=10&start-index=5", request.url
78
+ end
79
+
80
+ def test_should_raise_exception_for_invalid_type
81
+ assert_raise RuntimeError do
82
+ request = YouTubeG::Request::StandardSearch.new(:most_viewed_yo)
83
+ end
84
+ end
85
+
86
+ # -- Complex Video Queries -------------------------------------------------------------------------
87
+
88
+ def test_should_build_url_for_boolean_or_case_for_categories
89
+ request = YouTubeG::Request::VideoSearch.new(:categories => { :either => [:news, :sports] })
90
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/-/News%7CSports/", request.url
91
+ end
92
+
93
+ def test_should_build_url_for_boolean_or_and_exclude_case_for_categories
94
+ request = YouTubeG::Request::VideoSearch.new(:categories => { :either => [:news, :sports], :exclude => [:comedy] })
95
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/-/News%7CSports/-Comedy/", request.url
96
+ end
97
+
98
+ def test_should_build_url_for_exclude_case_for_tags
99
+ request = YouTubeG::Request::VideoSearch.new(:categories => { :either => [:news, :sports], :exclude => [:comedy] },
100
+ :tags => { :include => ['football'], :exclude => ['soccer'] })
101
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/-/News%7CSports/-Comedy/football/-soccer/", request.url
102
+ end
103
+
104
+ def test_should_build_url_for_either_case_for_tags
105
+ request = YouTubeG::Request::VideoSearch.new(:categories => { :either => [:news, :sports], :exclude => [:comedy] },
106
+ :tags => { :either => ['soccer', 'football', 'donkey'] })
107
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/-/News%7CSports/-Comedy/soccer%7Cfootball%7Cdonkey/", request.url
108
+ end
109
+
110
+ def test_should_build_url_for_query_search_with_categories_excluded
111
+ request = YouTubeG::Request::VideoSearch.new(:query => 'bench press',
112
+ :categories => { :exclude => [:comedy, :entertainment] },
113
+ :max_results => 10)
114
+ assert_equal "http://gdata.youtube.com/feeds/api/videos/-/-Comedy/-Entertainment/?vq=bench+press&max-results=10", request.url
115
+ end
116
+
117
+ # -- User Queries ---------------------------------------------------------------------------------
118
+
119
+ def test_should_build_url_for_videos_by_user
120
+ request = YouTubeG::Request::UserSearch.new(:user => 'liz')
121
+ assert_equal "http://gdata.youtube.com/feeds/api/users/liz/uploads", request.url
122
+ end
123
+
124
+ def test_should_build_url_for_favorite_videos_by_user
125
+ request = YouTubeG::Request::UserSearch.new(:favorites, :user => 'liz')
126
+ assert_equal "http://gdata.youtube.com/feeds/api/users/liz/favorites", request.url
127
+ end
128
+ end