UNPKG

8.74 kBJavaScriptView Raw
1require('./common');
2var crypto = require("crypto");
3var _ = require("underscore");
4var querystring = require("querystring");
5var fakes = require("./fakes");
6var LastFmRequest = fakes.LastFmRequest;
7
8(function() {
9 var gently, lastfm, client;
10 var options, expectations;
11 var notExpected;
12
13 describe("a lastfm request");
14
15 before(function() {
16 gently = new Gently();
17 options = {};
18 expectations = {
19 pairs:[],
20 handlers:[]
21 };
22 notExpected = {
23 keys:[]
24 }
25 lastfm = new LastFmNode({
26 api_key: "key",
27 secret: "secret"
28 });
29 client = new fakes.Client();
30 gently.expect(GENTLY_HIJACK.hijacked.http, "createClient", function(port, host) {
31 verifyCreateClient(port, host);
32 return client;
33 });
34 gently.expect(client, "request", function(method, url, header) {
35 var request = new fakes.ClientRequest();
36 if (method == "POST") {
37 gently.expect(request, "write", function(data) {
38 verifyRequest(method, url, header, data);
39 });
40 }
41 else {
42 verifyRequest(method, url, header);
43 }
44 return request;
45 });
46 });
47
48 after(function() {
49 var request = doRequest();
50 verifyHandlers(request);
51 });
52
53 function verifyCreateClient(port, host) {
54 if (expectations.port) {
55 assert.equal(expectations.port, port);
56 }
57 if (expectations.host) {
58 assert.equal(expectations.host, host);
59 }
60 }
61
62 function verifyRequest(method, url, header, data) {
63 if (expectations.url) {
64 assert.equal(expectations.url, url);
65 }
66 var pairs = querystring.parse(data || url.substr("/2.0?".length));
67 _(Object.keys(expectations.pairs)).each(function(key) {
68 assert.equal(expectations.pairs[key], pairs[key]);
69 });
70 if (expectations.signed || expectations.signatureHash) {
71 assert.ok(pairs.api_sig);
72 }
73 else if (expectations.signed === false) {
74 assert.ok(!pairs.api_sig);
75 }
76 if (expectations.signatureHash) {
77 assert.equal(expectations.signatureHash, pairs.api_sig);
78 }
79 if (expectations.method) {
80 assert.equal(expectations.method, method);
81 }
82 _(notExpected.keys).each(function(key) {
83 assert.ok(!pairs[key]);
84 });
85 if (expectations.requestData) {
86 assert.ok(data);
87 }
88 }
89
90 function whenMethodIs(method) {
91 options.method = method;
92 }
93
94 function andParamsAre(params) {
95 options.params = params;
96 }
97
98 function expectHttpMethod(method) {
99 expectations.method = method;
100 }
101
102 function expectDataPair(key, value) {
103 expectations.pairs[key] = value;
104 }
105
106 function expectSignature() {
107 expectations.signed = true;
108 }
109
110 function expectUrl(url) {
111 expectations.url = url;
112 }
113
114 function expectSignatureHashOf(unhashed) {
115 var expectedHash = crypto.createHash("md5").update(unhashed, "utf8").digest("hex");
116 expectSignatureHashToBe(expectedHash);
117 };
118
119 this.expectSignatureHashToBe = function(hash) {
120 expectations.signatureHash = hash;
121 }
122
123 function expectRequestOnPort(port) {
124 expectations.port = port;
125 }
126
127 function expectRequestToHost(host) {
128 expectations.host = host;
129 }
130
131 function expectHandlerFor(event) {
132 expectations.handlers.push(event);
133 }
134
135 function expectRequestData() {
136 expectations.requestData = true;
137 }
138
139 function doNotExpectDataKey(key) {
140 notExpected.keys.push(key);
141 }
142
143 function doRequest() {
144 return lastfm.request(options.method, options.params);
145 }
146
147 function verifyHandlers(request) {
148 _(expectations.handlers).each(function(event) {
149 var listeners = request.listeners(event);
150 assert.equal(1, listeners.length, "No handler for event: " + event);
151 });
152 }
153
154 it("default to port 80", function() {
155 whenMethodIs("any.method");
156 expectRequestOnPort(80);
157 });
158
159 it("makes request to audioscrobbler", function() {
160 whenMethodIs("any.method");
161 expectRequestToHost("ws.audioscrobbler.com");
162 });
163
164 it("always requests as json", function() {
165 whenMethodIs("any.method");
166 expectDataPair("format", "json");
167 });
168
169 it("always passes api_key", function() {
170 whenMethodIs("any.method");
171 expectDataPair("api_key", "key");
172 });
173
174 it("defaults to get request", function() {
175 whenMethodIs("any.method");
176 expectHttpMethod("GET");
177 });
178
179 it("calls the method specified", function() {
180 whenMethodIs("user.getinfo");
181 expectDataPair("method", "user.getinfo");
182 });
183
184 it("passes through parameters", function() {
185 whenMethodIs("user.getinfo");
186 andParamsAre({ user: "jammus" });
187 expectDataPair("user", "jammus");
188 });
189
190 it("does not pass through event handler parameters", function() {
191 whenMethodIs("any.method");
192 andParamsAre({ handlers: "handlers"});
193 doNotExpectDataKey("handlers");
194 });
195
196 it("auth.getsession has signature", function() {
197 whenMethodIs("auth.getsession");
198 expectSignature();
199 });
200
201 it("attaches handlers to returned request", function() {
202 whenMethodIs("any.method");
203 andParamsAre({ handlers: {
204 error: function() {console.log("errrors");},
205 success: function() {},
206 arbitrary: function() {},
207 }});
208 expectHandlerFor("error");
209 expectHandlerFor("success");
210 expectHandlerFor("arbitrary");
211 });
212
213 it("uses signed param to force signature", function() {
214 whenMethodIs("any.method");
215 andParamsAre({
216 signed: true
217 });
218 expectSignature();
219 });
220
221 it("signature hashes api_key, method and secret", function() {
222 whenMethodIs("auth.getsession");
223 expectSignatureHashOf("api_keykeymethodauth.getsessionsecret");
224 });
225
226 it("signature includes other parameters", function() {
227 whenMethodIs("auth.getsession");
228 andParamsAre({ foo: "bar" });
229 expectSignatureHashOf("api_keykeyfoobarmethodauth.getsessionsecret");
230 });
231
232 it("signature hashes all params alphabetically", function() {
233 whenMethodIs("auth.getsession");
234 andParamsAre({ foo : "bar", baz: "bash", flip : "flop" });
235 expectSignatureHashOf("api_keykeybazbashflipflopfoobarmethodauth.getsessionsecret");
236 });
237
238 it("signature hash ignores format parameter", function() {
239 whenMethodIs("auth.getsession");
240 andParamsAre({ format: "json" });
241 expectSignatureHashOf("api_keykeymethodauth.getsessionsecret");
242 });
243
244 it("signature hash ignores handlers parameter", function() {
245 whenMethodIs("auth.getsession");
246 andParamsAre({ handlers: "handlers" });
247 expectSignatureHashOf("api_keykeymethodauth.getsessionsecret");
248 });
249
250 it("signature hash ignores write parameter", function() {
251 whenMethodIs("auth.getsession");
252 andParamsAre({ write: true });
253 expectSignatureHashOf("api_keykeymethodauth.getsessionsecret");
254 });
255
256 it("signature hash ignores signed parameter", function() {
257 whenMethodIs("any.method");
258 andParamsAre({ signed: true });
259 expectSignatureHashOf("api_keykeymethodany.methodsecret");
260 });
261
262 it("signature hash handles high characters as expected by last.fm (utf8)", function() {
263 whenMethodIs("auth.getsession");
264 andParamsAre({ track: "Tony’s Theme (Remastered)" });
265 expectSignatureHashToBe("15f5159046bf1e76774b9dd46a4ed993");
266 });
267
268 it("write requests use post", function() {
269 whenMethodIs("any.method");
270 andParamsAre({ write: true });
271 expectHttpMethod("POST");
272 });
273
274 it("write requests don't use get parameters", function() {
275 whenMethodIs("any.method");
276 andParamsAre({ write: true });
277 expectUrl("/2.0");
278 });
279
280 it("write requests send data in request", function() {
281 whenMethodIs("any.method");
282 andParamsAre({
283 write: true,
284 foo: "bar"
285 });
286 expectRequestData();
287 expectDataPair("foo", "bar");
288 });
289
290 it("write requests are always signed", function() {
291 whenMethodIs("album.removeTag");
292 andParamsAre({
293 write: true
294 });
295 expectSignature();
296 });
297
298 _(["album.addTags", "album.removeTag", "album.share",
299 "artist.addTags", "artist.removeTag", "artist.share", "artist.shout",
300 "event.attend", "event.share", "event.shout",
301 "library.addAlbum", "library.addArtist", "library.addTrack",
302 "playlist.addTrack", "playlist.create",
303 "radio.tune",
304 "track.addTags", "track.ban", "track.love", "track.removeTag",
305 "track.scrobble", "track.share", "track.unban", "track.unlove",
306 "track.updateNowPlaying",
307 "user.shout"]).each(function(method) {
308 it(method + " is a write (post) request", function() {
309 whenMethodIs(method);
310 expectHttpMethod("POST");
311 });
312 });
313
314 _(["auth.getMobileSession", "auth.getSession", "auth.getToken",
315 "radio.getPlaylist"]).each(function(method) {
316 it(method + " is signed", function() {
317 whenMethodIs(method);
318 expectSignature();
319 });
320 });
321})();