animoto 0.0.0.alpha0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/README.md +39 -0
  2. data/lib/animoto/asset.rb +25 -0
  3. data/lib/animoto/client.rb +226 -0
  4. data/lib/animoto/content_type.rb +47 -0
  5. data/lib/animoto/directing_and_rendering_job.rb +19 -0
  6. data/lib/animoto/directing_and_rendering_manifest.rb +25 -0
  7. data/lib/animoto/directing_job.rb +18 -0
  8. data/lib/animoto/directing_manifest.rb +115 -0
  9. data/lib/animoto/errors.rb +3 -0
  10. data/lib/animoto/footage.rb +15 -0
  11. data/lib/animoto/image.rb +14 -0
  12. data/lib/animoto/job.rb +37 -0
  13. data/lib/animoto/manifest.rb +21 -0
  14. data/lib/animoto/rendering_job.rb +24 -0
  15. data/lib/animoto/rendering_manifest.rb +37 -0
  16. data/lib/animoto/resource.rb +153 -0
  17. data/lib/animoto/song.rb +16 -0
  18. data/lib/animoto/standard_envelope.rb +27 -0
  19. data/lib/animoto/storyboard.rb +22 -0
  20. data/lib/animoto/title_card.rb +26 -0
  21. data/lib/animoto/video.rb +29 -0
  22. data/lib/animoto/visual.rb +30 -0
  23. data/lib/animoto.rb +5 -0
  24. data/spec/animoto/asset_spec.rb +1 -0
  25. data/spec/animoto/client_spec.rb +119 -0
  26. data/spec/animoto/directing_and_rendering_job_spec.rb +45 -0
  27. data/spec/animoto/directing_and_rendering_manifest_spec.rb +143 -0
  28. data/spec/animoto/directing_job_spec.rb +48 -0
  29. data/spec/animoto/directing_manifest_spec.rb +186 -0
  30. data/spec/animoto/footage_spec.rb +56 -0
  31. data/spec/animoto/image_spec.rb +41 -0
  32. data/spec/animoto/job_spec.rb +128 -0
  33. data/spec/animoto/rendering_job_spec.rb +57 -0
  34. data/spec/animoto/rendering_manifest_spec.rb +115 -0
  35. data/spec/animoto/resource_spec.rb +55 -0
  36. data/spec/animoto/song_spec.rb +54 -0
  37. data/spec/animoto/standard_envelope_spec.rb +0 -0
  38. data/spec/animoto/storyboard_spec.rb +8 -0
  39. data/spec/animoto/title_card_spec.rb +42 -0
  40. data/spec/animoto/video_spec.rb +1 -0
  41. data/spec/animoto/visual_spec.rb +0 -0
  42. data/spec/animoto_spec.rb +5 -0
  43. data/spec/spec_helper.rb +10 -0
  44. metadata +127 -0
@@ -0,0 +1,186 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Animoto::DirectingManifest do
4
+
5
+ def manifest options = {}
6
+ @manifest ||= Animoto::DirectingManifest.new(options)
7
+ end
8
+
9
+ describe "initializing" do
10
+ it "should specify the title of the manifest as the first argument" do
11
+ manifest(:title => "Funderful Wonderment").title.should == "Funderful Wonderment"
12
+ end
13
+
14
+ it "should default to 'default' pacing" do
15
+ manifest.pacing.should == 'default'
16
+ end
17
+
18
+ it "should be able to specify the pacing with a :pacing parameter" do
19
+ manifest(:pacing => 'double').pacing.should == 'double'
20
+ end
21
+
22
+ it "should default to 'original' style" do
23
+ manifest.style.should == 'original'
24
+ end
25
+
26
+ it "should default to no producer" do
27
+ manifest.producer.should be_nil
28
+ end
29
+
30
+ it "should be able to specify the producer with a :producer parameter" do
31
+ manifest(:producer => "Senor Spielbergo").producer.should == "Senor Spielbergo"
32
+ end
33
+
34
+ it "should default to having to visuals" do
35
+ manifest.visuals.should be_empty
36
+ end
37
+ end
38
+
39
+ describe "adding assets" do
40
+ describe "using the append operator" do
41
+ before do
42
+ @title_card = Animoto::TitleCard.new "woohoo!"
43
+ end
44
+
45
+ it "should add the asset to this manifest's visuals" do
46
+ manifest << @title_card
47
+ manifest.visuals.should include(@title_card)
48
+ end
49
+
50
+ it "should raise an error if the object being added isn't a visual" do
51
+ lambda { manifest << "beef hearts" }.should raise_error
52
+ end
53
+ end
54
+
55
+ describe "using a convenience method" do
56
+ it "should append the asset to this manifest's visuals" do
57
+ manifest.add_title_card("woohoo!")
58
+ vis = manifest.visuals.last
59
+ vis.should be_an_instance_of(Animoto::TitleCard)
60
+ vis.title.should == "woohoo!"
61
+ end
62
+
63
+ it "should send the parameters to the asset initializer" do
64
+ manifest.add_title_card("woohoo!", "everything is great!")
65
+ vis = manifest.visuals.last
66
+ vis.title.should == "woohoo!"
67
+ vis.subtitle.should == "everything is great!"
68
+ end
69
+ end
70
+ end
71
+
72
+ describe "adding a song" do
73
+ it "should use the append operator" do
74
+ song = Animoto::Song.new "http://song.org/song.mp3"
75
+ manifest << song
76
+ manifest.song.should == song
77
+ end
78
+
79
+ it "should use the add_song method" do
80
+ song = manifest.add_song("http://song.org/song.mp3")
81
+ manifest.song.should == song
82
+ end
83
+
84
+ it "should replace an existing song" do
85
+ song = Animoto::Song.new "http://song.org/song.mp3"
86
+ song2 = Animoto::Song.new "http://song.org/song2.mp3"
87
+ manifest << song
88
+ manifest << song2
89
+ manifest.song.should == song2
90
+ end
91
+ end
92
+
93
+ describe "generating a hash" do
94
+ before do
95
+ manifest(:title => 'Funderful Wonderment', :producer => 'Senor Spielbergo', :pacing => 'double')
96
+ @image = manifest.add_image 'http://website.com/image.png'
97
+ @title_card = manifest.add_title_card 'woohoo', 'this is awesome'
98
+ @footage = manifest.add_footage 'http://website.com/movie.mp4'
99
+ @song_obj = manifest.add_song 'http://website.com/song.mp3'
100
+ end
101
+
102
+ it "should have top-level 'directing_job' object" do
103
+ manifest.to_hash.should have_key('directing_job')
104
+ manifest.to_hash['directing_job'].should be_a(Hash)
105
+ end
106
+
107
+ it "should have a 'directing_manifest' object within the 'directing_job'" do
108
+ manifest.to_hash['directing_job'].should have_key('directing_manifest')
109
+ manifest.to_hash['directing_job']['directing_manifest'].should be_a(Hash)
110
+ end
111
+
112
+ it "should have a 'style' key in the manifest" do
113
+ manifest.to_hash['directing_job']['directing_manifest'].should have_key('style')
114
+ manifest.to_hash['directing_job']['directing_manifest']['style'].should == manifest.style
115
+ end
116
+
117
+ it "should have a 'pacing' key in the manifest" do
118
+ manifest.to_hash['directing_job']['directing_manifest'].should have_key('pacing')
119
+ manifest.to_hash['directing_job']['directing_manifest']['pacing'].should == manifest.pacing
120
+ end
121
+
122
+ it "should have a 'producer_name' key in the manifest" do
123
+ manifest.to_hash['directing_job']['directing_manifest'].should have_key('producer_name')
124
+ manifest.to_hash['directing_job']['directing_manifest']['producer_name'].should == manifest.producer
125
+ end
126
+
127
+ it "should have a 'visuals' key in the manifest" do
128
+ manifest.to_hash['directing_job']['directing_manifest'].should have_key('visuals')
129
+ end
130
+
131
+ it "should have a 'song' object in the manifest" do
132
+ manifest.to_hash['directing_job']['directing_manifest'].should have_key('song')
133
+ manifest.to_hash['directing_job']['directing_manifest']['song'].should be_a(Hash)
134
+ end
135
+
136
+ describe "when the callback url is set" do
137
+ before do
138
+ manifest.http_callback_url = 'http://website.com/callback'
139
+ end
140
+
141
+ describe "but the callback format isn't" do
142
+ it "should raise an error" do
143
+ lambda { manifest.to_hash }.should raise_error(ArgumentError)
144
+ end
145
+ end
146
+
147
+ describe "as well as the format" do
148
+ before do
149
+ manifest.http_callback_format = 'xml'
150
+ end
151
+
152
+ it "should have the HTTP callback URL in the job" do
153
+ manifest.to_hash['directing_job'].should have_key('http_callback')
154
+ manifest.to_hash['directing_job']['http_callback'].should == manifest.http_callback_url
155
+ end
156
+
157
+ it "should have the HTTP callback format in the job" do
158
+ manifest.to_hash['directing_job'].should have_key('http_callback_format')
159
+ manifest.to_hash['directing_job']['http_callback_format'].should == manifest.http_callback_format
160
+ end
161
+ end
162
+ end
163
+
164
+ describe "visuals array" do
165
+ before do
166
+ @visuals = manifest.to_hash['directing_job']['directing_manifest']['visuals']
167
+ end
168
+
169
+ it "should have the visuals in the order they were added" do
170
+ @visuals[0].should == @image.to_hash
171
+ @visuals[1].should == @title_card.to_hash
172
+ @visuals[2].should == @footage.to_hash
173
+ end
174
+ end
175
+
176
+ describe "song" do
177
+ before do
178
+ @song = manifest.to_hash['directing_job']['directing_manifest']['song']
179
+ end
180
+
181
+ it "should have info about the song" do
182
+ @song.should == @song_obj.to_hash
183
+ end
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,56 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Animoto::Footage do
4
+
5
+ it "should be a visual" do
6
+ Animoto::Footage.should include(Animoto::Visual)
7
+ end
8
+
9
+ describe "#to_hash" do
10
+ before do
11
+ @footage = Animoto::Footage.new 'http://website.com/movie.mp4'
12
+ end
13
+
14
+ it "should have a 'source_url' key with the url" do
15
+ @footage.to_hash.should have_key('source_url')
16
+ @footage.to_hash['source_url'].should == @footage.source_url
17
+ end
18
+
19
+ it "should not have a 'spotlit' key" do
20
+ @footage.to_hash.should_not have_key('spotlit')
21
+ end
22
+
23
+ describe "if audio mixing is turned on" do
24
+ before do
25
+ @footage.audio_mix = true
26
+ end
27
+
28
+ it "should have an 'audio_mix' key telling how to mix" do
29
+ @footage.to_hash.should have_key('audio_mix')
30
+ @footage.to_hash['audio_mix'].should == 'MIX'
31
+ end
32
+ end
33
+
34
+ describe "if using a different start time" do
35
+ before do
36
+ @footage.start_time = 10.5
37
+ end
38
+
39
+ it "should have a 'start_time' key with the starting time" do
40
+ @footage.to_hash.should have_key('start_time')
41
+ @footage.to_hash['start_time'].should == @footage.start_time
42
+ end
43
+ end
44
+
45
+ describe "if a duration was specified" do
46
+ before do
47
+ @footage.duration = 300
48
+ end
49
+
50
+ it "should have a 'duration' key with the duration" do
51
+ @footage.to_hash.should have_key('duration')
52
+ @footage.to_hash['duration'].should == @footage.duration
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Animoto::Image do
4
+
5
+ it "should be a visual" do
6
+ Animoto::Image.should include(Animoto::Visual)
7
+ end
8
+
9
+ describe "#to_hash" do
10
+ before do
11
+ @image = Animoto::Image.new 'http://website.com/image.png'
12
+ end
13
+
14
+ it "should have a 'source_url' key with the url" do
15
+ @image.to_hash.should have_key('source_url')
16
+ @image.to_hash['source_url'].should == @image.source_url
17
+ end
18
+
19
+ describe "if rotated" do
20
+ before do
21
+ @image.rotation = 2
22
+ end
23
+
24
+ it "should have a 'rotation' key with the EXIF rotation value" do
25
+ @image.to_hash.should have_key('rotation')
26
+ @image.to_hash['rotation'].should == @image.rotation
27
+ end
28
+ end
29
+
30
+ describe "if spotlit" do
31
+ before do
32
+ @image.spotlit = true
33
+ end
34
+
35
+ it "should have a 'spotlit' key telling whether or not this image is spotlit" do
36
+ @image.to_hash.should have_key('spotlit')
37
+ @image.to_hash['spotlit'].should == @image.spotlit?
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,128 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Animoto::Job do
4
+
5
+ describe "initialization" do
6
+ before do
7
+ @body = {
8
+ 'response' => {
9
+ 'status' => {
10
+ 'code' => 200
11
+ },
12
+ 'payload' => {
13
+ 'job' => {
14
+ 'state' => 'initial',
15
+ 'links' => {
16
+ 'self' => "http://animoto.com/jobs/1"
17
+ }
18
+ }
19
+ }
20
+ }
21
+ }
22
+ @job = Animoto::Job.load @body
23
+ end
24
+
25
+ it "should set its state from the job state given" do
26
+ @job.state.should == 'initial'
27
+ end
28
+
29
+ it "should set its url from the 'self' link given" do
30
+ @job.url.should == 'http://animoto.com/jobs/1'
31
+ end
32
+ end
33
+
34
+ describe "when there are errors" do
35
+ before do
36
+ @body = {
37
+ 'response' => {
38
+ 'status' => {
39
+ 'code' => 400,
40
+ 'errors' => [
41
+ {
42
+ 'code' => 'FORMAT',
43
+ 'description' => 'There is an item in the request that is incorrectly formatted'
44
+ }
45
+ ]
46
+ },
47
+ 'payload' => {
48
+ 'job' => {
49
+ 'state' => 'failed',
50
+ 'links' => {
51
+ 'self' => 'http://animoto.com/jobs/1'
52
+ }
53
+ }
54
+ }
55
+ }
56
+ }
57
+ @job = Animoto::Job.load @body
58
+ end
59
+
60
+ it "should have 'failed' state" do
61
+ @job.state.should == 'failed'
62
+ end
63
+
64
+ it "should have non-empty errors" do
65
+ @job.errors.should_not be_empty
66
+ end
67
+
68
+ it "should wrap the errors in error objects" do
69
+ @job.errors.first.should be_an_instance_of(Animoto::Error)
70
+ end
71
+ end
72
+
73
+ describe "returning state" do
74
+ before do
75
+ @job = Animoto::Job.load 'response'=>{'status'=>{'code'=>200},'payload'=>{'job'=>{'state'=>'initial','links'=>{'self'=>'http://animoto.com/jobs/1'}}}}
76
+ end
77
+
78
+ describe "when 'initial'" do
79
+ it "should not be failed" do
80
+ @job.should_not be_failed
81
+ end
82
+
83
+ it "should not be completed" do
84
+ @job.should_not be_completed
85
+ end
86
+
87
+ it "should be pending" do
88
+ @job.should be_pending
89
+ end
90
+ end
91
+
92
+ describe "when 'failed'" do
93
+ before do
94
+ @job.instance_variable_set :@state, 'failed'
95
+ end
96
+
97
+ it "should be failed" do
98
+ @job.should be_failed
99
+ end
100
+
101
+ it "should not be completed" do
102
+ @job.should_not be_completed
103
+ end
104
+
105
+ it "should not be pending" do
106
+ @job.should_not be_pending
107
+ end
108
+ end
109
+
110
+ describe "when 'completed'" do
111
+ before do
112
+ @job.instance_variable_set :@state, 'completed'
113
+ end
114
+
115
+ it "should not be failed" do
116
+ @job.should_not be_failed
117
+ end
118
+
119
+ it "should be completed" do
120
+ @job.should be_completed
121
+ end
122
+
123
+ it "should not be pending" do
124
+ @job.should_not be_pending
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,57 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Animoto::RenderingJob do
4
+
5
+ it "should have endpoint /jobs/rendering" do
6
+ Animoto::RenderingJob.endpoint.should == '/jobs/rendering'
7
+ end
8
+
9
+ it "should have content type 'application/vnd.animoto.rendering_job'" do
10
+ Animoto::RenderingJob.content_type.should == 'rendering_job'
11
+ end
12
+
13
+ it "should have payload key 'rendering_job'" do
14
+ Animoto::RenderingJob.payload_key.should == 'rendering_job'
15
+ end
16
+
17
+ describe "loading from a response body" do
18
+ before do
19
+ @body = {
20
+ 'response' => {
21
+ 'status' => {
22
+ 'code' => 200
23
+ },
24
+ 'payload' => {
25
+ 'rendering_job' => {
26
+ 'state' => 'completed',
27
+ 'links' => {
28
+ 'self' => 'http://animoto.com/jobs/rendering/1',
29
+ 'storyboard' => 'http://animoto.com/storyboards/1',
30
+ 'video' => 'http://animoto.com/videos/1'
31
+ }
32
+ }
33
+ }
34
+ }
35
+ }
36
+ @job = Animoto::RenderingJob.load @body
37
+ end
38
+
39
+ it "should set the storyboard url from the body" do
40
+ @job.storyboard_url.should == "http://animoto.com/storyboards/1"
41
+ end
42
+
43
+ it "should set the video url from the body" do
44
+ @job.video_url.should == "http://animoto.com/videos/1"
45
+ end
46
+
47
+ it "should create a storyboard from the storyboard url" do
48
+ @job.storyboard.should be_an_instance_of(Animoto::Storyboard)
49
+ @job.storyboard.url.should == @job.storyboard_url
50
+ end
51
+
52
+ it "should create a video from the video url" do
53
+ @job.video.should be_an_instance_of(Animoto::Video)
54
+ @job.video.url.should == @job.video_url
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,115 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Animoto::RenderingManifest do
4
+
5
+ def manifest *args
6
+ @manifest ||= begin
7
+ options = args.last.is_a?(Hash) ? args.pop : {}
8
+ @storyboard = args[0] || Animoto::Storyboard.new
9
+ Animoto::RenderingManifest.new @storyboard, options
10
+ end
11
+ end
12
+
13
+ describe "initialization" do
14
+ before do
15
+ @storyboard = Animoto::Storyboard.new
16
+ end
17
+
18
+ it "should take a storyboard as the first argument" do
19
+ Animoto::RenderingManifest.new(@storyboard).storyboard = @storyboard
20
+ end
21
+
22
+ it "should take a :resolution parameter to set the resolution" do
23
+ manifest(:resolution => "720p").resolution.should == "720p"
24
+ end
25
+
26
+ it "should take a :framerate parameter to set the framerate" do
27
+ manifest(:framerate => 24).framerate.should == 24
28
+ end
29
+
30
+ it "should take a :format parameter to set the format" do
31
+ manifest(:format => 'flv').format.should == 'flv'
32
+ end
33
+
34
+ it "should take :http_callback_url and :http_callback_format parameters to set the callback" do
35
+ manifest(:http_callback_url => "http://website.com/callback", :http_callback_format => 'xml')
36
+ manifest.http_callback_url.should == "http://website.com/callback"
37
+ manifest.http_callback_format.should == 'xml'
38
+ end
39
+ end
40
+
41
+ describe "generating a hash" do
42
+ before do
43
+ @storyboard = Animoto::Storyboard.new
44
+ @url = "http://animoto.com/storyboards/1"
45
+ @storyboard.instance_variable_set(:@url, @url)
46
+ manifest(@storyboard, :resolution => "720p", :framerate => 24, :format => 'flv')
47
+ end
48
+
49
+ it "should have a top-level 'rendering_job' object" do
50
+ manifest.to_hash.should have_key('rendering_job')
51
+ manifest.to_hash['rendering_job'].should be_a(Hash)
52
+ end
53
+
54
+ it "should have a 'rendering_manifest' object in the 'rendering_job'" do
55
+ manifest.to_hash['rendering_job'].should have_key('rendering_manifest')
56
+ manifest.to_hash['rendering_job']['rendering_manifest'].should be_a(Hash)
57
+ end
58
+
59
+ it "should have a 'storyboard_url' key in the manifest" do
60
+ manifest.to_hash['rendering_job']['rendering_manifest'].should have_key('storyboard_url')
61
+ manifest.to_hash['rendering_job']['rendering_manifest']['storyboard_url'].should == @storyboard.url
62
+ end
63
+
64
+ it "should have a 'rendering_profile' object in the manifest" do
65
+ manifest.to_hash['rendering_job']['rendering_manifest'].should have_key('rendering_profile')
66
+ manifest.to_hash['rendering_job']['rendering_manifest']['rendering_profile'].should be_a(Hash)
67
+ end
68
+
69
+ describe "rendering profile" do
70
+ before do
71
+ @profile = manifest.to_hash['rendering_job']['rendering_manifest']['rendering_profile']
72
+ end
73
+
74
+ it "should have a 'vertical_resolution' key" do
75
+ @profile['vertical_resolution'].should == manifest.resolution
76
+ end
77
+
78
+ it "should have a 'framerate' key" do
79
+ @profile['framerate'].should == manifest.framerate
80
+ end
81
+
82
+ it "should have a 'format' key" do
83
+ @profile['format'].should == manifest.format
84
+ end
85
+ end
86
+
87
+ describe "when an HTTP callback is set" do
88
+ before do
89
+ manifest.http_callback_url = "http://website.com/callback"
90
+ end
91
+
92
+ describe "but a format isn't" do
93
+ it "should raise an error" do
94
+ lambda { manifest.to_hash }.should raise_error(ArgumentError)
95
+ end
96
+ end
97
+
98
+ describe "as well as the format" do
99
+ before do
100
+ manifest.http_callback_format = 'xml'
101
+ end
102
+
103
+ it "should have the HTTP callback URL in the job" do
104
+ manifest.to_hash['rendering_job'].should have_key('http_callback')
105
+ manifest.to_hash['rendering_job']['http_callback'].should == manifest.http_callback_url
106
+ end
107
+
108
+ it "should have the HTTP callback format in the job" do
109
+ manifest.to_hash['rendering_job'].should have_key('http_callback_format')
110
+ manifest.to_hash['rendering_job']['http_callback_format'].should == manifest.http_callback_format
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,55 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Animoto::Resource do
4
+
5
+ def define_thing options = {}
6
+ Object.__send__ :remove_const, :Thing if defined?(Thing)
7
+ Object.__send__ :const_set, :Thing, Class.new(Animoto::Resource)
8
+ options.each { |k,v| Thing.__send__(k, v) }
9
+ end
10
+
11
+ describe "inferring the content type" do
12
+ it "should be the underscored, lowercase version of the base class name" do
13
+ class Animoto::ThisIsALongAndStupidName < Animoto::Resource; end
14
+ Animoto::ThisIsALongAndStupidName.content_type.should == 'this_is_a_long_and_stupid_name'
15
+ end
16
+ end
17
+
18
+ describe "identity mapping" do
19
+ before do
20
+ @url = "https://api.animoto.com/videos/1"
21
+ @video = Animoto::Video.new :url => @url
22
+ @body = {
23
+ 'response' => {
24
+ 'status' => { 'code' => 200 },
25
+ 'payload' => {
26
+ 'video' => {
27
+ 'links' => {
28
+ 'download' => "http://animoto.com/videos/1",
29
+ 'storyboard' => "https://api.animoto.com/storyboards/1",
30
+ 'self' => @url
31
+ },
32
+ 'metadata' => {
33
+ 'duration' => 300,
34
+ 'format' => 'h264',
35
+ 'framerate' => 30,
36
+ 'vertical_resolution' => "720p"
37
+ }
38
+ }
39
+ }
40
+ }
41
+ }
42
+ end
43
+
44
+ it "should ensure that two instances instantiated with the same unique identifier will both be the same object" do
45
+ @video.should equal(Animoto::Video.load(@body))
46
+ end
47
+
48
+ it "should update the original instance with the initialization parameters of the new one" do
49
+ @video.duration.should be_nil
50
+ video = Animoto::Video.load(@body)
51
+ video.duration.should == 300
52
+ @video.duration.should == 300
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,54 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Animoto::Song do
4
+
5
+ describe "#to_hash" do
6
+ before do
7
+ @song = Animoto::Song.new 'http://website.com/song.mp3'
8
+ end
9
+
10
+ it "should have a 'source_url' key with the url" do
11
+ @song.to_hash.should have_key('source_url')
12
+ @song.to_hash['source_url'].should == @song.source_url
13
+ end
14
+
15
+ describe "if a start time was specified" do
16
+ before do
17
+ @song.start_time = 30.2
18
+ end
19
+
20
+ it "should have a 'start_time' key with the start time" do
21
+ @song.to_hash.should have_key('start_time')
22
+ @song.to_hash['start_time'].should == @song.start_time
23
+ end
24
+ end
25
+
26
+ describe "if a duration was specified" do
27
+ before do
28
+ @song.duration = 300
29
+ end
30
+
31
+ it "should have a 'duration' key with the duration" do
32
+ @song.to_hash.should have_key('duration')
33
+ @song.to_hash['duration'].should == @song.duration
34
+ end
35
+ end
36
+
37
+ describe "if a title and/or artist was specified" do
38
+ before do
39
+ @song.title = "Antarctican Drinking Song"
40
+ @song.artist = "Gwar"
41
+ end
42
+
43
+ it "should have an 'artist' key with the artist" do
44
+ @song.to_hash.should have_key('artist')
45
+ @song.to_hash['artist'].should == @song.artist
46
+ end
47
+
48
+ it "should have a 'title' key with the title" do
49
+ @song.to_hash.should have_key('title')
50
+ @song.to_hash['title'].should == @song.title
51
+ end
52
+ end
53
+ end
54
+ end