bassnode-ruby-echonest 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,110 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'spec_helper'
4
+
5
+ include SpecHelper
6
+
7
+ describe Echonest::Analysis do
8
+ before do
9
+ @analysis = Echonest::Analysis.new(open(fixture('analysis.json')).read)
10
+ end
11
+
12
+ it "should have beats" do
13
+ beats = @analysis.beats
14
+
15
+ beats.size.should eql(324)
16
+ beats.first.start.should eql(0.27661)
17
+ beats.first.duration.should eql(0.36476)
18
+ beats.first.confidence.should eql(0.468)
19
+ end
20
+
21
+ it "should have segments" do
22
+ segments = @analysis.segments
23
+ segment = segments.first
24
+
25
+ segments.size.should eql(274)
26
+ segment.start.should eql(0.0)
27
+ segment.duration.should eql(0.43909)
28
+ segment.confidence.should eql(1.0)
29
+ segment.loudness.time.should eql(0.0)
30
+ segment.loudness.value.should eql(-60.0)
31
+ segment.max_loudness.time.should eql(0.11238)
32
+ segment.max_loudness.value.should eql(-33.563)
33
+ segment.pitches.size.should eql(12)
34
+ segment.pitches.first.should eql(0.138)
35
+ segment.timbre.size.should eql(12)
36
+ segment.timbre.first.should eql(11.525)
37
+ end
38
+
39
+ it "should have bars" do
40
+ bars = @analysis.bars
41
+
42
+ bars.size.should eql(80)
43
+ bars.first.start.should eql(1.00704)
44
+ bars.first.duration.should eql(1.48532)
45
+ bars.first.confidence.should eql(0.188)
46
+ end
47
+
48
+ it "should have tempo" do
49
+ @analysis.tempo.should eql(168.460)
50
+ end
51
+
52
+ it "should have sections" do
53
+ sections = @analysis.sections
54
+ section = sections.first
55
+
56
+ sections.size.should eql(7)
57
+ section.start.should eql(0.0)
58
+ section.duration.should eql(20.04271)
59
+ section.confidence.should eql(1.0)
60
+ end
61
+
62
+ it "should have durtion" do
63
+ @analysis.duration.should eql(120.68526)
64
+ end
65
+
66
+ it "should have end of fade in" do
67
+ @analysis.end_of_fade_in.should eql(0.0)
68
+ end
69
+
70
+ it "should have start of fade out" do
71
+ @analysis.start_of_fade_out.should eql(113.557)
72
+ end
73
+
74
+ it "should have key" do
75
+ @analysis.key.should eql(7)
76
+ end
77
+
78
+ it "should derive key letter from key" do
79
+ @analysis.key_letter.should eql(Echonest::Analysis::CHROMATIC[7])
80
+ end
81
+
82
+ it "should have loudness" do
83
+ @analysis.loudness.should eql(-19.140)
84
+ end
85
+
86
+ it "should have mode" do
87
+ @analysis.mode.should eql(1)
88
+ end
89
+
90
+ it "should derive major? from mode" do
91
+ @analysis.major?.should eql(true)
92
+ end
93
+
94
+ it "should derive minor? from mode" do
95
+ @analysis.minor?.should eql(false)
96
+ end
97
+
98
+ it "should have time signature" do
99
+ @analysis.time_signature.should eql(4)
100
+ end
101
+
102
+ it "should have tatums" do
103
+ tatums = @analysis.tatums
104
+
105
+ tatums.size.should eql(648)
106
+ tatums.first.start.should eql(0.09469)
107
+ tatums.first.duration.should eql(0.18193)
108
+ tatums.first.confidence.should eql(0.286)
109
+ end
110
+ end
data/spec/api_spec.rb ADDED
@@ -0,0 +1,144 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'spec_helper'
4
+ require "echonest"
5
+
6
+ include SpecHelper
7
+
8
+ describe Echonest::Api do
9
+ before do
10
+ @api = Echonest::Api.new('8TPE3VC60ODJTNTFE')
11
+ end
12
+
13
+ it "should build parameters" do
14
+ params = @api.build_params(:id => 'TRXXHTJ1294CD8F3B3')
15
+ params.keys.size.should eql(3)
16
+ params[:api_key].should eql('8TPE3VC60ODJTNTFE')
17
+ params[:id].should eql('TRXXHTJ1294CD8F3B3')
18
+ params[:format].should eql('json')
19
+ end
20
+
21
+ it "should build parameters to list" do
22
+ params = @api.build_params_to_list(:id => 'TRXXHTJ1294CD8F3B3')
23
+ params.length.should eql(3)
24
+ params[0].should eql(['id', 'TRXXHTJ1294CD8F3B3'])
25
+ params.should be_include(['api_key', '8TPE3VC60ODJTNTFE'])
26
+ params.should be_include(['format', 'json'])
27
+ end
28
+
29
+ it "should pass arguments to user agent" do
30
+ @api.user_agent.should_receive(:get_content).
31
+ with(
32
+ URI('http://developer.echonest.com/api/v4/xxx/yyy'),
33
+ [
34
+ ['foo', 'bar'],
35
+ ['api_key', '8TPE3VC60ODJTNTFE'],
36
+ ['format', 'json']
37
+ ]).and_return(open(fixture('profile.json')).read)
38
+
39
+ @api.request('xxx/yyy', :get, :foo => 'bar')
40
+ end
41
+
42
+ it "should pass arguments including a file to user agent" do
43
+ file = open(fixture('sample.mp3'))
44
+ file.should_receive(:read).and_return('content')
45
+
46
+
47
+ @api.user_agent.should_receive(:post_async).
48
+ with(
49
+ URI('http://developer.echonest.com/api/v4/xxx/zzz?api_key=8TPE3VC60ODJTNTFE&bar=baz&format=json'),
50
+ 'content',
51
+ {
52
+ 'Content-Type' => 'application/octet-stream'
53
+ }).and_return(open(fixture('profile.json')).read)
54
+
55
+ @api.request('xxx/zzz', :post, { :bar => 'baz' }, file)
56
+ end
57
+
58
+ it "should call api method" do
59
+ content = open(fixture('profile.json')).read
60
+
61
+ make_connection_stub(content, :post)
62
+ response = @api.request('track/profile', :post, :id => 'TRXXHTJ1294CD8F3B3')
63
+ response.should be_success
64
+ response.body.status.version.should eql("4.2")
65
+ end
66
+
67
+ it "should raise error when api method call was failed" do
68
+ make_connection_stub(open(fixture('profile_failure.json')).read, :post)
69
+
70
+ lambda {
71
+ @api.request('track/profile', :post, :id => 'TRXXHTJ1294CD8F3B3')
72
+ }.should raise_error(Echonest::Api::Error, 'api_key - Invalid key: "XXXXX" is not a valid, active api key')
73
+ end
74
+
75
+ it "should raise error when unknown api method was called" do
76
+ @api.user_agent.stub!('get_content').and_raise(HTTPClient::BadResponseError.new('error message'))
77
+
78
+ lambda {
79
+ @api.request('track/xxxx', :get, :id => 'TRXXHTJ1294CD8F3B3')
80
+ }.should raise_error(Echonest::Api::Error, 'track/xxxx: error message')
81
+ end
82
+
83
+ it "should make http request with agent name" do
84
+ @api.user_agent.agent_name.should eql('ruby-echonest/' + Echonest::VERSION)
85
+ end
86
+
87
+ describe '#track' do
88
+ it 'should return track methods' do
89
+ track = @api.track
90
+ track.class.should eql(Echonest::ApiMethods::Track)
91
+ track.instance_eval { @api }.should eql(@api)
92
+ end
93
+ end
94
+
95
+ describe '#artist' do
96
+ it 'should return artist methods' do
97
+ artist = @api.artist('Weezer')
98
+ artist.class.should eql(Echonest::ApiMethods::Artist)
99
+ artist.instance_eval {@api}.should eql(@api)
100
+ end
101
+
102
+ it 'should return artist methods even artist name was empty' do
103
+ artist = @api.artist
104
+ artist.class.should eql(Echonest::ApiMethods::Artist)
105
+ artist.instance_eval {@api}.should eql(@api)
106
+ end
107
+ end
108
+
109
+ describe '#song' do
110
+ it 'should return song methods' do
111
+ song = @api.song
112
+ song.class.should eql(Echonest::ApiMethods::Song)
113
+ song.instance_eval {@api}.should eql(@api)
114
+ end
115
+ end
116
+
117
+ describe '#playlist' do
118
+ it 'should return playlist methods' do
119
+ playlist = @api.playlist
120
+ playlist.class.should eql(Echonest::ApiMethods::Playlist)
121
+ playlist.instance_eval {@api}.should eql(@api)
122
+ end
123
+ end
124
+
125
+ it 'should have traditional API methods' do
126
+ filename = fixture('sample.mp3')
127
+ analysis = Echonest::Analysis.new(open(fixture('analysis.json')).read)
128
+ track = Echonest::ApiMethods::Track.new(@api)
129
+
130
+ %w/tempo duration end_of_fade_in key loudness mode start_of_fade_out time_signature bars beats sections tatums segments/.
131
+ each do |method|
132
+
133
+ @api.should_receive(:track).and_return(track)
134
+ track.should_receive(:analysis).with(filename).and_return(analysis)
135
+ analysis.should_receive(method.to_sym)
136
+
137
+ @api.send('get_' + method, filename)
138
+ end
139
+ end
140
+
141
+ def make_connection_stub(content, method)
142
+ @api.user_agent.stub!(method.to_s + '_content').and_return(content)
143
+ end
144
+ end
@@ -0,0 +1,207 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'spec_helper'
4
+ require "echonest"
5
+
6
+ include SpecHelper
7
+
8
+ describe Echonest::ApiMethods::Base do
9
+ before do
10
+ @api = Echonest::Api.new('8TPE3VC60ODJTNTFE')
11
+ @base = Echonest::ApiMethods::Base.new(@api)
12
+ end
13
+
14
+ it "should call @api.request" do
15
+ @api.should_receive(:request).with(:get, 'method_foo', {:hash => 'paramerter'})
16
+ @base.request(:get, 'method_foo', {:hash => 'paramerter'})
17
+ end
18
+
19
+ describe ".build_params_with_validation" do
20
+ it "should pass validation for required key" do
21
+ args = {
22
+ :required => {
23
+ :key1 => 'value1',
24
+ },
25
+ }
26
+ Echonest::ApiMethods::Base.build_params_with_validation(
27
+ args,
28
+ %w[key1],
29
+ [],
30
+ []).should == {:key1 => 'value1'}
31
+ end
32
+
33
+ it "should raise error if required key not exist in parametor" do
34
+ lambda {
35
+ args = {
36
+ :required => {
37
+ :key2 => 'value2',
38
+ },
39
+ }
40
+ Echonest::ApiMethods::Base.build_params_with_validation(
41
+ args,
42
+ %w[key1],
43
+ [],
44
+ [])
45
+ }.should raise_error(ArgumentError, 'key1 is required')
46
+ end
47
+
48
+ it "should pass validation for required_any key" do
49
+ args = {
50
+ :required_any => {
51
+ :key1 => 'value1',
52
+ },
53
+ }
54
+ Echonest::ApiMethods::Base.build_params_with_validation(
55
+ args,
56
+ [],
57
+ %w[key1 key2],
58
+ []).should == {:key1 => 'value1'}
59
+
60
+ args = {
61
+ :required_any => {
62
+ :key2 => 'value2',
63
+ },
64
+ }
65
+ Echonest::ApiMethods::Base.build_params_with_validation(
66
+ args,
67
+ [],
68
+ %w[key1 key2],
69
+ []).should == {:key2 => 'value2'}
70
+ end
71
+
72
+ it "should raise error if required_any key not exist in parametor" do
73
+ lambda {
74
+ args = {
75
+ :required_any => {
76
+ :key3 => 'value3',
77
+ },
78
+ }
79
+ Echonest::ApiMethods::Base.build_params_with_validation(
80
+ args,
81
+ [],
82
+ %w[key1 key2],
83
+ [])
84
+ }.should raise_error(ArgumentError, 'key1 or key2 is required')
85
+ end
86
+
87
+ it "should pass validation for option key" do
88
+ args = {
89
+ :option => {
90
+ :key1 => 'value1',
91
+ },
92
+ }
93
+ Echonest::ApiMethods::Base.build_params_with_validation(
94
+ args,
95
+ [],
96
+ [],
97
+ %w[key1 key2]).should == {:key1 => 'value1'}
98
+ end
99
+
100
+ it "should empty hash for option if keys for option not exist in parametor" do
101
+ args = {
102
+ :option => {
103
+ :key3 => 'value3',
104
+ },
105
+ }
106
+ Echonest::ApiMethods::Base.build_params_with_validation(
107
+ args,
108
+ [],
109
+ [],
110
+ %w[key1 key2]).should == {}
111
+ end
112
+
113
+ it "should pass validation for required, required_any and option keys" do
114
+ args = {
115
+ :required => {
116
+ :key1 => 'value1',
117
+ },
118
+ :required_any => {
119
+ :key3 => 'value3',
120
+ },
121
+ :option => {
122
+ :key4 => 'value4',
123
+ :key5 => 'value5',
124
+ },
125
+ }
126
+ Echonest::ApiMethods::Base.build_params_with_validation(
127
+ args,
128
+ %w[key1],
129
+ %w[key2 key3],
130
+ %w[key4 key5 key6]).should == {
131
+ :key1 => 'value1',
132
+ :key3 => 'value3',
133
+ :key4 => 'value4',
134
+ :key5 => 'value5',
135
+ }
136
+ end
137
+ end
138
+
139
+ describe ".validator" do
140
+ it "should return Proc instance" do
141
+ Echonest::ApiMethods::Base.validator(%w[required], %w[required_any], %w[option]).should be_an_instance_of(Proc)
142
+ end
143
+ end
144
+
145
+ describe ".method_with_option" do
146
+ before do
147
+ class FooBar < Echonest::ApiMethods::Base
148
+ end
149
+ @foobar = FooBar.new('dummy')
150
+ end
151
+
152
+ it "should define_method with option parametor" do
153
+ @foobar.class.class_eval do
154
+ def request(p1, p2, p3)
155
+ p1.should == 'foobar/baz'
156
+ p2.should == :get
157
+ p3.should == {:k1 => 'v1'}
158
+ 'test response'
159
+ end
160
+
161
+ method_with_option('baz', %w[k1 k2]) do |response|
162
+ response.should == 'test response'
163
+ end
164
+ end
165
+
166
+ @foobar.baz(:k1 => 'v1')
167
+ end
168
+ end
169
+
170
+ describe ".method_with_required_any" do
171
+ before do
172
+ class FooBar < Echonest::ApiMethods::Base
173
+ end
174
+ @foobar = FooBar.new('dummy')
175
+ end
176
+
177
+ it "should define_method with option parametor" do
178
+ @foobar.class.class_eval do
179
+ def request(p1, p2, p3)
180
+ p1.should == 'category/baz'
181
+ p2.should == :get
182
+ p3.should == {
183
+ :rk1 => 'rv1',
184
+ :rak1 => 'ravv1',
185
+ :ok1 => 'ov1'
186
+ }
187
+ 'test response'
188
+ end
189
+
190
+ method_with_required_any(
191
+ 'Category',
192
+ 'baz',
193
+ :get,
194
+ %w[rk1],
195
+ %w[rak1 rak2],
196
+ %w[ok1 ok2],
197
+ lambda{|s| {:rak1 => 'ravv1'}},
198
+ lambda{|response| response.should == 'test response'})
199
+ end
200
+
201
+ @foobar.baz(
202
+ :rk1 => 'rv1',
203
+ :ok1 => 'ov1')
204
+ end
205
+ end
206
+
207
+ end
@@ -0,0 +1,184 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'spec_helper'
4
+ require "echonest"
5
+
6
+ include SpecHelper
7
+
8
+ describe Echonest::ApiMethods::Artist do
9
+ before do
10
+ @api = Echonest::Api.new('8TPE3VC60ODJTNTFE')
11
+ @artist = Echonest::ApiMethods::Artist.new(@api)
12
+ end
13
+
14
+ def self.describe_bundle_for_artist(method, options=nil)
15
+ describe "#{method}" do
16
+ it "should request to artist/#{method} with name" do
17
+ @api.should_receive(:request).with(
18
+ "artist/#{method}",
19
+ :get,
20
+ :name => 'Weezer').and_return{ Echonest::Response.new('{"hello":"world"}') }
21
+
22
+ @artist.artist_name = 'Weezer'
23
+ @artist.send(method)
24
+ end
25
+
26
+ it "should request to artist/#{method} with id" do
27
+ @api.should_receive(:request).with(
28
+ "artist/#{method}",
29
+ :get,
30
+ :id => '1234').and_return{ Echonest::Response.new('{"hello":"world"}') }
31
+
32
+ @artist.artist_id = '1234'
33
+ @artist.send(method)
34
+ end
35
+
36
+ it "should request to artist/#{method} with option" do
37
+ options.each do |opt|
38
+ @api.should_receive(:request).with(
39
+ "artist/#{method}",
40
+ :get,
41
+ opt.merge(:name => 'Weezer')).and_return{ Echonest::Response.new('{"hello":"world"}') }
42
+
43
+ @artist.artist_name = 'Weezer'
44
+ @artist.send(method, opt)
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ def self.describe_bundle_for_option(method, options=nil)
51
+ describe "#{method}" do
52
+ it "should request to artist/#{method}" do
53
+ @api.should_receive(:request).with(
54
+ "artist/#{method}",
55
+ :get,
56
+ {}).and_return{ Echonest::Response.new('{"hello":"world"}') }
57
+
58
+ @artist.send(method)
59
+ end
60
+
61
+ it "should request to artist/#{method} with option" do
62
+ options.each do |opt|
63
+ @api.should_receive(:request).with(
64
+ "artist/#{method}",
65
+ :get,
66
+ opt).and_return{ Echonest::Response.new('{"hello":"world"}') }
67
+
68
+ @artist.send(method, opt)
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ describe_bundle_for_artist('audio', [
75
+ {:format => 'json'},
76
+ {:format => 'json', :results => 100},
77
+ {:format => 'json', :results => 100, :start => 20}
78
+ ])
79
+
80
+ describe_bundle_for_artist('biographies', [
81
+ {:format => 'json'},
82
+ {:format => 'json', :results => 100},
83
+ {:format => 'json', :results => 100, :start => 20},
84
+
85
+ {:format => 'json', :results => 100, :start => 20, :license => 'echo-source'},
86
+ {:format => 'json', :results => 100, :start => 20, :license => ['echo-source', 'cc-by-nc']}
87
+ ])
88
+
89
+ describe_bundle_for_artist('blogs', [
90
+ {:format => 'json'},
91
+ {:format => 'json', :results => 100},
92
+ {:format => 'json', :results => 100, :start => 20}
93
+ ])
94
+
95
+ describe_bundle_for_artist('familiarity', [
96
+ {:format => 'json'},
97
+ {:format => 'json', :results => 100},
98
+ {:format => 'json', :results => 100, :start => 20}
99
+ ])
100
+
101
+ describe_bundle_for_artist('hotttnesss', [
102
+ {:format => 'json'},
103
+ {:format => 'json', :results => 100},
104
+ {:format => 'json', :results => 100, :start => 20}
105
+ ])
106
+
107
+ describe_bundle_for_artist('images', [
108
+ {:format => 'json'},
109
+ {:format => 'json', :results => 100},
110
+ {:format => 'json', :results => 100, :start => 20},
111
+ {:format => 'json', :results => 100, :start => 20, :license => 'echo-source'},
112
+ {:format => 'json', :results => 100, :start => 20, :license => ['echo-source', 'cc-by-nc']}
113
+ ])
114
+
115
+ describe_bundle_for_artist('news', [
116
+ {:format => 'json'},
117
+ {:format => 'json', :results => 100},
118
+ {:format => 'json', :results => 100, :start => 20}
119
+ ])
120
+
121
+ describe_bundle_for_artist('profile', [
122
+ {:format => 'json'},
123
+ {:format => 'json', :results => 100},
124
+ {:format => 'json', :results => 100, :start => 20},
125
+ {:format => 'json', :results => 100, :start => 20, :bucket => 'audio'},
126
+ {:format => 'json', :results => 100, :start => 20, :bucket => ['audio', 'video']}
127
+ ])
128
+
129
+ describe_bundle_for_artist('reviews', [
130
+ {:format => 'json'},
131
+ {:format => 'json', :results => 100},
132
+ {:format => 'json', :results => 100, :start => 20}
133
+ ])
134
+
135
+ describe_bundle_for_option('search', [
136
+ {:format => 'json'},
137
+ {:format => 'json', :results => 100},
138
+ {:format => 'json', :results => 100, :bucket => 'audio'},
139
+ {:format => 'json', :results => 100, :bucket => %w[audio biographies blogs id:musicbrainz]}
140
+ ])
141
+
142
+ describe_bundle_for_artist('songs', [
143
+ {:format => 'json'},
144
+ {:format => 'json', :results => 100},
145
+ {:format => 'json', :results => 100, :bucket => 'audio'},
146
+ {:format => 'json', :results => 100, :bucket => %w[audio biographies blogs id:musicbrainz]}
147
+ ])
148
+
149
+ describe_bundle_for_artist('similar', [
150
+ {:format => 'json'},
151
+ {:format => 'json', :results => 100},
152
+ {:format => 'json', :results => 100, :max_familiarity => 0.9},
153
+ {:format => 'json', :results => 100, :bucket => 'audio'},
154
+ {:format => 'json', :results => 100, :bucket => %w[audio biographies blogs id:musicbrainz]}
155
+ ])
156
+
157
+ describe_bundle_for_artist('terms', [
158
+ {:format => 'json'},
159
+ {:format => 'json', :sort => 'weight'}
160
+ ])
161
+
162
+ describe_bundle_for_option('top_hottt', [
163
+ {:format => 'json'},
164
+ {:format => 'json', :results => 100},
165
+ {:format => 'json', :results => 100, :type => 'normal'},
166
+ {:format => 'json', :results => 100, :bucket => 'audio'},
167
+ {:format => 'json', :results => 100, :bucket => %w[audio biographies blogs id:musicbrainz]}
168
+ ])
169
+
170
+ describe_bundle_for_option('top_terms', [
171
+ {:format => 'json'},
172
+ {:format => 'json', :results => 100}
173
+ ])
174
+
175
+ describe_bundle_for_artist('urls', [
176
+ {:format => 'json'}
177
+ ])
178
+
179
+ describe_bundle_for_artist('video', [
180
+ {:format => 'json'},
181
+ {:format => 'json', :results => 100},
182
+ {:format => 'json', :results => 100, :start => 20}
183
+ ])
184
+ end
@@ -0,0 +1,12 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'spec_helper'
4
+ require "echonest"
5
+
6
+ include SpecHelper
7
+
8
+ describe Echonest do
9
+ it "should return an instance of Echonest::Api" do
10
+ Echonest('XXXXXXXX').should be_an_instance_of(Echonest::Api)
11
+ end
12
+ end