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,153 @@
1
+ module Animoto
2
+ class Resource
3
+ include ContentType
4
+ include StandardEnvelope
5
+
6
+ # @overload endpoint(path)
7
+ # Sets the endpoint for this class. This is the URL where all requests related
8
+ # to this service will go.
9
+ #
10
+ # @param [String] path the path to set
11
+ # @return [String] the endpoint
12
+ #
13
+ # @overload endpoint()
14
+ # Returns the endpoint for this class.
15
+ #
16
+ # @return [String] the endpoint
17
+ def self.endpoint path = nil
18
+ @endpoint = path if path
19
+ @endpoint
20
+ end
21
+
22
+ # Returns the endpoint for this class.
23
+ #
24
+ # @return [String] the endpoint
25
+ def endpoint
26
+ self.class.endpoint
27
+ end
28
+
29
+ # @overload payload_key(key)
30
+ # Sets the payload key for this class. When building an instance of this class from
31
+ # a response body, the payload key determines which object in the response payload
32
+ # holds the attributes for the instance.
33
+ #
34
+ # @param [String] key the key to set
35
+ # @return [String] the key
36
+ #
37
+ # @overload payload_key()
38
+ # Returns the payload key for this class.
39
+ #
40
+ # @return [String] the key
41
+ def self.payload_key key = nil
42
+ @payload_key = key if key
43
+ @payload_key || infer_content_type
44
+ end
45
+
46
+ # Returns the payload key for this class.
47
+ #
48
+ # @return [String] the key
49
+ def payload_key
50
+ self.class.payload_key
51
+ end
52
+
53
+ # @private
54
+ #
55
+ # Makes a new instance of this class from a deserialized JSON response body. Note that
56
+ # it assumes the hash you're passing is structured correctly and does no format checking
57
+ # at all, so if the hash is not in the "standard envelope", this method will most likely
58
+ # raise an error.
59
+ #
60
+ # @param [Hash] body the deserialized JSON response body
61
+ # @return [Resource] an instance of this class
62
+ def self.load body
63
+ new unpack_standard_envelope(body)
64
+ end
65
+
66
+ class << self
67
+
68
+ # If an instance is instantiated with the same unique identifier (i.e. URL) as another,
69
+ # instead of creating a brand new object, will instead update and return the existing
70
+ # object. This way there should only be one object representing any one resource.
71
+ #
72
+ # @example
73
+ # client = Animoto::Client.new
74
+ # storyboard1 = Animoto::Storyboard.new :url => "https://api.animoto.com/storyboards/1"
75
+ # storyboard2 = client.find! Animoto::Storyboard, "https://api.animoto.com/storyboards/1"
76
+ # storyboard1.equal?(storyboard2) # => true
77
+ #
78
+ # @param [Hash] attributes a hash of attributes for this resource
79
+ # @return [Resource] either a new Resource instance, or an existing one with updated
80
+ # attributes
81
+ alias_method :original_new, :new
82
+ def new attributes = {}
83
+ if attributes[:url] && instances[attributes[:url]]
84
+ instances[attributes[:url]].instantiate attributes
85
+ else
86
+ original_new attributes
87
+ end
88
+ end
89
+
90
+ # @private
91
+ #
92
+ # Registers an instance in the identity map so that subsequent finds or instantiations
93
+ # of this resource with the same URL will return the same object.
94
+ #
95
+ # @param [Resource] instance the instance to register
96
+ # @raise [ArgumentError] if the instance isn't of this class
97
+ def register instance
98
+ raise ArgumentError unless instance.is_a?(self)
99
+ instances[instance.url] = instance
100
+ end
101
+
102
+ private
103
+
104
+ # Returns (or vivifies) the identity map for this class.
105
+ #
106
+ # @return [Hash<String,Resource>] the identity map
107
+ def instances
108
+ @instances ||= {}
109
+ end
110
+ end
111
+
112
+ attr_reader :url, :errors
113
+
114
+ def initialize attributes = {}
115
+ instantiate attributes
116
+ end
117
+
118
+ # @private
119
+ #
120
+ # Update this instance with new attributes from the response body.
121
+ #
122
+ # @param [Hash] body deserialized JSON from a response body
123
+ # @return [self] this instance, updated
124
+ def load body = {}
125
+ instantiate unpack_standard_envelope(body)
126
+ end
127
+
128
+ # @private
129
+ #
130
+ # Since Resources can be created a number of different ways, this method does
131
+ # the actual attribute setting for a Resource, acting much like a public version
132
+ # of #initialize.
133
+ #
134
+ # @param [Hash] attributes hash of attributes for this resource
135
+ # @return [self] this instance
136
+ def instantiate attributes = {}
137
+ @errors = (attributes[:errors] || []).collect { |e| wrap_error e }
138
+ @url = attributes[:url]
139
+ self.class.register(self) if @url
140
+ self
141
+ end
142
+
143
+ private
144
+
145
+ # Turns an error from a response body into a Ruby object.
146
+ #
147
+ # @param [Hash] error the error "object" from a response body
148
+ # @return [Error] a Ruby error object
149
+ def wrap_error error
150
+ Animoto::Error.new error['message']
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,16 @@
1
+ module Animoto
2
+ class Song < Animoto::Asset
3
+
4
+ attr_accessor :start_time, :duration, :title, :artist
5
+
6
+ def to_hash
7
+ hash = super
8
+ hash['start_time'] = start_time if start_time
9
+ hash['duration'] = duration if duration
10
+ hash['title'] = title if title
11
+ hash['artist'] = artist if artist
12
+ hash
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ module Animoto
2
+ module StandardEnvelope
3
+
4
+ def self.included base
5
+ base.class_eval {
6
+ include Animoto::StandardEnvelope::InstanceMethods
7
+ extend Animoto::StandardEnvelope::ClassMethods
8
+ }
9
+ end
10
+
11
+ module InstanceMethods
12
+ def unpack_standard_envelope body = {}
13
+ self.class.unpack_standard_envelope body
14
+ end
15
+ end
16
+
17
+ module ClassMethods
18
+ protected
19
+ def unpack_standard_envelope body = {}
20
+ {
21
+ :url => body['response']['payload'][payload_key]['links']['self'],
22
+ :errors => body['response']['status']['errors'] || []
23
+ }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+ module Animoto
2
+ class Storyboard < Animoto::Resource
3
+
4
+ def self.unpack_standard_envelope body = {}
5
+ super.merge({
6
+ :duration => body['response']['payload'][payload_key]['metadata']['duration'],
7
+ :visuals_count => body['response']['payload'][payload_key]['metadata']['visuals_count'],
8
+ :preview_url => body['response']['payload'][payload_key]['links']['preview']
9
+ })
10
+ end
11
+
12
+ attr_reader :duration, :visuals_count, :preview_url
13
+
14
+ def instantiate attributes = {}
15
+ @duration = attributes[:duration]
16
+ @visuals_count = attributes[:visuals_count]
17
+ @preview_url = attributes[:preview_url]
18
+ super
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,26 @@
1
+ module Animoto
2
+ class TitleCard
3
+ include Animoto::Visual
4
+
5
+ attr_accessor :title, :subtitle
6
+
7
+ # Creates a new TitleCard.
8
+ #
9
+ # @param [String] title the main text
10
+ # @param [String] subtitle the secondary text
11
+ def initialize title, subtitle = nil
12
+ @title, @subtitle = title, subtitle
13
+ end
14
+
15
+ # Returns a representation of this TitleCard as a Hash.
16
+ #
17
+ # @return [Hash] this TitleCard as a Hash
18
+ def to_hash
19
+ hash = super
20
+ hash['h1'] = title
21
+ hash['h2'] = subtitle if subtitle
22
+ hash['spotlit'] = spotlit? unless @spotlit.nil?
23
+ hash
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ module Animoto
2
+ class Video < Animoto::Resource
3
+
4
+ def self.unpack_standard_envelope body
5
+ super.merge({
6
+ :download_url => body['response']['payload'][payload_key]['links']['download'],
7
+ :storyboard_url => body['response']['payload'][payload_key]['links']['storyboard'],
8
+ :duration => body['response']['payload'][payload_key]['metadata']['duration'],
9
+ :format => body['response']['payload'][payload_key]['metadata']['format'],
10
+ :framerate => body['response']['payload'][payload_key]['metadata']['framerate'],
11
+ :resolution => body['response']['payload'][payload_key]['metadata']['vertical_resolution']
12
+ })
13
+ end
14
+
15
+ attr_reader :download_url, :storyboard_url, :storyboard, :duration, :format, :framerate, :resolution
16
+
17
+ def instantiate attributes = {}
18
+ @download_url = attributes[:download_url]
19
+ @storyboard_url = attributes[:storyboard_url]
20
+ @storyboard = Animoto::Storyboard.new(:url => @storyboard_url) if @storyboard_url
21
+ @duration = attributes[:duration]
22
+ @format = attributes[:format]
23
+ @framerate = attributes[:framerate]
24
+ @resolution = attributes[:resolution]
25
+ super
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ module Animoto
2
+ module Visual
3
+
4
+ # Setter for spotlighting, which instructs the director to give special attention
5
+ # to this visual when directing.
6
+ #
7
+ # @param [Boolean] bool true if this visual should receive special attention
8
+ def spotlit= bool
9
+ @spotlit = bool
10
+ end
11
+
12
+ # Returns true if this visual is spotlit.
13
+ #
14
+ # @return [Boolean] whether or not this visual is spotlit
15
+ def spotlit?
16
+ @spotlit
17
+ end
18
+
19
+ # Returns a representation of this Visual as a Hash
20
+ #
21
+ # @return [Hash] this Visual as a Hash
22
+ def to_hash
23
+ hash = super rescue {}
24
+ hash['spotlit'] = spotlit? unless @spotlit.nil?
25
+ hash['type'] = self.class.name.split('::').last.gsub(/(^)?([A-Z])/) { "#{'_' unless $1}#{$2.downcase}" }
26
+ hash
27
+ end
28
+
29
+ end
30
+ end
data/lib/animoto.rb ADDED
@@ -0,0 +1,5 @@
1
+ module Animoto
2
+ def self.version
3
+ "0.0.0.alpha0"
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
@@ -0,0 +1,119 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Animoto::Client do
4
+ def client options = {}
5
+ @client ||= Animoto::Client.new "joe", "secret", options
6
+ end
7
+
8
+ def object
9
+ @object ||= Object.new
10
+ end
11
+
12
+ describe "supplying credentials" do
13
+ describe "manually" do
14
+ it "should accept the key and secret as the first two parameters on initialization" do
15
+ c = Animoto::Client.new "key", "secret"
16
+ c.key.should == "key"
17
+ c.secret.should == "secret"
18
+ end
19
+
20
+ describe "when the secret isn't specified (i.e. only 1 parameter was passed)" do
21
+ before do
22
+ File.stubs(:exist?).returns(false) # <= to keep it from finding our .animotorc files
23
+ end
24
+
25
+ it "should raise an error" do
26
+ lambda { Animoto::Client.new "key" }.should raise_error
27
+ end
28
+ end
29
+ end
30
+
31
+ describe "automatically" do
32
+ before do
33
+ @home_path = File.expand_path("~/.animotorc")
34
+ @etc_path = "/etc/.animotorc"
35
+ @config = "key: joe\nsecret: secret"
36
+ end
37
+
38
+ describe "when ~/.animotorc exists" do
39
+ before do
40
+ File.stubs(:exist?).with(@home_path).returns(true)
41
+ File.stubs(:read).with(@home_path).returns(@config)
42
+ end
43
+
44
+ it "should configure itself based on the options in ~/.animotorc" do
45
+ c = Animoto::Client.new
46
+ c.key.should == "joe"
47
+ c.secret.should == "secret"
48
+ end
49
+ end
50
+
51
+ describe "when ~/.animotorc doesn't exist" do
52
+ before do
53
+ File.stubs(:exist?).with(@home_path).returns(false)
54
+ end
55
+
56
+ describe "when /etc/.animotorc exists" do
57
+ before do
58
+ File.stubs(:exist?).with(@etc_path).returns(true)
59
+ File.stubs(:read).with(@etc_path).returns(@config)
60
+ end
61
+
62
+ it "should configure itself based on the options in /etc/.animotorc" do
63
+ c = Animoto::Client.new
64
+ c.key.should == "joe"
65
+ c.secret.should == "secret"
66
+ end
67
+ end
68
+
69
+ describe "when /etc/.animotorc doesn't exist" do
70
+ it "should raise an error" do
71
+ lambda { Animoto::Client.new }.should raise_error
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ describe "finding an instance by identifier" do
79
+ before do
80
+ @url = "https://api.animoto.com/storyboards/1"
81
+ @body = {'response'=>{'status'=>{'code'=>200}},'payload'=>{'storyboard'=>{'links'=>{'self'=>@url}}}}
82
+ stub_request(:get, @url).to_return(:body => @body.to_json, :status => [200,"OK"])
83
+ end
84
+
85
+ it "should make a GET request to the given url" do
86
+ client.find(Animoto::Storyboard, @url)
87
+ WebMock.should have_requested(:get, @url)
88
+ end
89
+
90
+ it "should ask for a response in the proper format" do
91
+ client.find(Animoto::Storyboard, @url)
92
+ WebMock.should have_requested(:get, @url).with(:headers => { 'Accept' => "application/vnd.animoto.storyboard-v1+json"})
93
+ end
94
+
95
+ it "should not sent a request body" do
96
+ client.find(Animoto::Storyboard, @url)
97
+ WebMock.should have_requested(:get, @url).with(:body => "")
98
+ end
99
+
100
+ it "should return an instance of the correct resource type" do
101
+ client.find(Animoto::Storyboard, @url).should be_an_instance_of(Animoto::Storyboard)
102
+ end
103
+ end
104
+
105
+ describe "reloading an instance" do
106
+ before do
107
+ @url = 'https://api.animoto.com/jobs/directing/1'
108
+ @job = Animoto::DirectingJob.new :state => 'initial', :url => @url
109
+ @body = {'response'=>{'status'=>{'code'=>200}},'payload'=>{'directing_job'=>{'state'=>'retrieving_assets','links'=>{'self'=>@url}}}}
110
+ stub_request(:get, @url).to_return(:body => @body.to_json, :status => [200,"OK"])
111
+ @job.state.should == 'initial' # sanity check
112
+ end
113
+
114
+ it "should update the resource's attributes" do
115
+ client.reload!(@job)
116
+ @job.state.should == 'retrieving_assets'
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,45 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Animoto::DirectingAndRenderingJob do
4
+
5
+ it "should have endpoint '/jobs/directing_and_rendering'" do
6
+ Animoto::DirectingAndRenderingJob.endpoint.should == '/jobs/directing_and_rendering'
7
+ end
8
+
9
+ it "should have content_type 'application/vnd.animoto.directing_and_rendering_job'" do
10
+ Animoto::DirectingAndRenderingJob.content_type.should == 'directing_and_rendering_job'
11
+ end
12
+
13
+ it "should have payload key 'directing_and_rendering_job'" do
14
+ Animoto::DirectingAndRenderingJob.payload_key.should == 'directing_and_rendering_job'
15
+ end
16
+
17
+ describe "loading from a response body" do
18
+ before do
19
+ @body = {
20
+ 'response' => {
21
+ 'status' => { 'code' => 200 },
22
+ 'payload' => {
23
+ 'directing_and_rendering_job' => {
24
+ 'state' => 'completed',
25
+ 'links' => {
26
+ 'self' => 'http://animoto.com/jobs/directing_and_rendering/1',
27
+ 'video' => 'http://animoto.com/videos/1'
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
33
+ @job = Animoto::DirectingAndRenderingJob.load @body
34
+ end
35
+
36
+ it "should set the video url from the body" do
37
+ @job.video_url.should == 'http://animoto.com/videos/1'
38
+ end
39
+
40
+ it "should create a video from the video url" do
41
+ @job.video.should be_an_instance_of(Animoto::Video)
42
+ @job.video.url.should == @job.video_url
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,143 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Animoto::DirectingAndRenderingManifest do
4
+
5
+ def manifest options = {}
6
+ @manifest ||= Animoto::DirectingAndRenderingManifest.new options
7
+ end
8
+
9
+ describe "generating a hash" do
10
+ before do
11
+ manifest(:title => 'Funderful Wonderment', :producer => 'Senor Spielbergo', :pacing => 'double',
12
+ :resolution => "720p", :framerate => 24, :format => 'flv')
13
+ @image = manifest.add_image 'http://website.com/image.png'
14
+ @title_card = manifest.add_title_card 'woohoo', 'this is awesome'
15
+ @footage = manifest.add_footage 'http://website.com/movie.mp4'
16
+ @song_obj = manifest.add_song 'http://website.com/song.mp3'
17
+ end
18
+
19
+ it "should have top-level 'directing_and_rendering_job' object" do
20
+ manifest.to_hash.should have_key('directing_and_rendering_job')
21
+ manifest.to_hash['directing_and_rendering_job'].should be_a(Hash)
22
+ end
23
+
24
+ describe "when the callback url is set" do
25
+ before do
26
+ manifest.http_callback_url = 'http://website.com/callback'
27
+ end
28
+
29
+ describe "but the callback format isn't" do
30
+ it "should raise an error" do
31
+ lambda { manifest.to_hash }.should raise_error(ArgumentError)
32
+ end
33
+ end
34
+
35
+ describe "as well as the format" do
36
+ before do
37
+ manifest.http_callback_format = 'xml'
38
+ end
39
+
40
+ it "should have the HTTP callback URL in the job" do
41
+ manifest.to_hash['directing_and_rendering_job'].should have_key('http_callback')
42
+ manifest.to_hash['directing_and_rendering_job']['http_callback'].should == manifest.http_callback_url
43
+ end
44
+
45
+ it "should have the HTTP callback format in the job" do
46
+ manifest.to_hash['directing_and_rendering_job'].should have_key('http_callback_format')
47
+ manifest.to_hash['directing_and_rendering_job']['http_callback_format'].should == manifest.http_callback_format
48
+ end
49
+ end
50
+ end
51
+
52
+ it "should have a 'directing_manifest' object within the job" do
53
+ manifest.to_hash['directing_and_rendering_job'].should have_key('directing_manifest')
54
+ manifest.to_hash['directing_and_rendering_job']['directing_manifest'].should be_a(Hash)
55
+ end
56
+
57
+ describe "directing_manifest" do
58
+ before do
59
+ @hash = manifest.to_hash['directing_and_rendering_job']['directing_manifest']
60
+ end
61
+
62
+ it "should have a 'style' key in the manifest" do
63
+ @hash.should have_key('style')
64
+ @hash['style'].should == manifest.style
65
+ end
66
+
67
+ it "should have a 'pacing' key in the manifest" do
68
+ @hash.should have_key('pacing')
69
+ @hash['pacing'].should == manifest.pacing
70
+ end
71
+
72
+ it "should have a 'producer_name' key in the manifest" do
73
+ @hash.should have_key('producer_name')
74
+ @hash['producer_name'].should == manifest.producer
75
+ end
76
+
77
+ it "should have a 'visuals' key in the manifest" do
78
+ @hash.should have_key('visuals')
79
+ end
80
+
81
+ it "should have a 'song' object in the manifest" do
82
+ @hash.should have_key('song')
83
+ @hash['song'].should be_a(Hash)
84
+ end
85
+
86
+ describe "visuals array" do
87
+ before do
88
+ @visuals = @hash['visuals']
89
+ end
90
+
91
+ it "should have the visuals in the order they were added" do
92
+ @visuals[0].should == @image.to_hash
93
+ @visuals[1].should == @title_card.to_hash
94
+ @visuals[2].should == @footage.to_hash
95
+ end
96
+ end
97
+
98
+ describe "song" do
99
+ before do
100
+ @song = @hash['song']
101
+ end
102
+
103
+ it "should have info about the song" do
104
+ @song.should == @song_obj.to_hash
105
+ end
106
+ end
107
+ end
108
+
109
+ it "should have a 'rendering_manifest' object within the job" do
110
+ manifest.to_hash['directing_and_rendering_job'].should have_key('rendering_manifest')
111
+ manifest.to_hash['directing_and_rendering_job']['rendering_manifest'].should be_a(Hash)
112
+ end
113
+
114
+ describe "rendering_manifest" do
115
+ before do
116
+ @hash = manifest.to_hash['directing_and_rendering_job']['rendering_manifest']
117
+ end
118
+
119
+ it "should have a 'rendering_profile' object in the manifest" do
120
+ @hash.should have_key('rendering_profile')
121
+ @hash['rendering_profile'].should be_a(Hash)
122
+ end
123
+
124
+ describe "rendering_profile" do
125
+ before do
126
+ @profile = @hash['rendering_profile']
127
+ end
128
+
129
+ it "should have a 'vertical_resolution' key" do
130
+ @profile['vertical_resolution'].should == manifest.resolution
131
+ end
132
+
133
+ it "should have a 'framerate' key" do
134
+ @profile['framerate'].should == manifest.framerate
135
+ end
136
+
137
+ it "should have a 'format' key" do
138
+ @profile['format'].should == manifest.format
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+
3
+ describe Animoto::DirectingJob do
4
+
5
+ it "should have endpoint '/jobs/directing'" do
6
+ Animoto::DirectingJob.endpoint.should == '/jobs/directing'
7
+ end
8
+
9
+ it "should have content type 'application/vnd.animoto.directing_job'" do
10
+ Animoto::DirectingJob.content_type.should == 'directing_job'
11
+ end
12
+
13
+ it "should have payload key 'directing_job'" do
14
+ Animoto::DirectingJob.payload_key.should == 'directing_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
+ 'directing_job' => {
26
+ 'state' => 'completed',
27
+ 'links' => {
28
+ 'self' => 'http://animoto.com/jobs/directing/1',
29
+ 'storyboard' => 'http://animoto.com/storyboards/1'
30
+ }
31
+ }
32
+ }
33
+ }
34
+ }
35
+ @job = Animoto::DirectingJob.load @body
36
+ end
37
+
38
+ it "should set the storyboard url from the body" do
39
+ @job.storyboard_url.should == 'http://animoto.com/storyboards/1'
40
+ end
41
+
42
+ it "should create a storyboard from the storyboard url" do
43
+ @job.storyboard.should be_an_instance_of(Animoto::Storyboard)
44
+ @job.storyboard.url.should == @job.storyboard_url
45
+ end
46
+ end
47
+
48
+ end