UNPKG

13.4 kBJavaScriptView Raw
1var assert = require('assert')
2 , Twit = require('../lib/twitter')
3 , config1 = require('../config1')
4 , util = require('util')
5 , async = require('async')
6
7describe('REST API', function () {
8 var twit = null
9
10 before(function () {
11 twit = new Twit(config1);
12 })
13
14 it('GET `account/verify_credentials`', function (done) {
15 twit.get('account/verify_credentials', function (err, reply, response) {
16 checkReply(err, reply)
17 assert.notEqual(reply.followers_count, undefined)
18 assert.notEqual(reply.friends_count, undefined)
19 assert.ok(reply.id_str)
20
21 checkResponse(response)
22
23 assert(response.headers['x-rate-limit-limit'])
24
25 done()
26 })
27 })
28
29 it('POST `account/update_profile`', function (done) {
30 twit.post('account/update_profile', function (err, reply, response) {
31 checkReply(err, reply)
32 console.log('\nscreen name:', reply.screen_name)
33 checkResponse(response)
34 done()
35 })
36 })
37
38 var tweetId = null
39 , text = null
40
41 it('POST `statuses/update`', function (done) {
42 var params = { status: '@tolga_tezel tweeting using github.com/ttezel/twit' }
43 twit.post('statuses/update', params, function (err, reply, response) {
44 checkReply(err, reply)
45
46 console.log('\ntweeted:', reply.text)
47 console.log('tweeted on:', reply.created_at)
48
49 tweetId = reply.id_str
50 text = reply.text
51
52 checkResponse(response)
53
54 done()
55 })
56 })
57
58 it('POST `statuses/destroy:id`', function (done) {
59 var destroyRoute = 'statuses/destroy/'+tweetId
60
61 twit.post(destroyRoute, function (err, reply, response) {
62 checkReply(err, reply)
63 checkTweet(reply)
64 assert.equal(reply.text, text)
65
66 checkResponse(response)
67
68 done()
69 })
70 })
71
72 it('POST `statuses/update` with characters requiring escaping', function (done) {
73 var params = { status: '@tolga_tezel tweeting using github.com/ttezel/twit :) !' }
74
75 twit.post('statuses/update', params, function (err, reply, response) {
76 checkReply(err, reply)
77
78 console.log('\ntweeted:', reply.text)
79 console.log('tweeted on:', reply.created_at)
80
81 checkResponse(response)
82
83 var text = reply.text
84
85 assert(reply.id_str)
86
87 console.log('id_str', reply.id_str)
88
89 twit.post('statuses/destroy/:id', { id: reply.id_str }, function (err, reply, response) {
90 checkReply(err, reply)
91 checkTweet(reply)
92 assert.equal(reply.text, text)
93
94 checkResponse(response)
95
96 done()
97 })
98 })
99 })
100
101 it('POST `statuses/update` with \'Hi!!\' works', function (done) {
102 var params = { status: 'Hi!!' }
103
104 twit.post('statuses/update', params, function (err, reply, response) {
105 checkReply(err, reply)
106
107 console.log('\ntweeted:', reply.text)
108 console.log('tweeted on:', reply.created_at)
109
110 checkResponse(response)
111
112 var text = reply.text
113
114 var destroyRoute = 'statuses/destroy/'+reply.id_str
115
116 twit.post(destroyRoute, function (err, reply, response) {
117 checkReply(err, reply)
118 checkTweet(reply)
119 assert.equal(reply.text, text)
120
121 checkResponse(response)
122
123 done()
124 })
125 })
126 })
127
128 it('GET `statuses/home_timeline`', function (done) {
129 twit.get('statuses/home_timeline', function (err, reply, response) {
130 checkReply(err, reply)
131 checkTweet(reply[0])
132
133 checkResponse(response)
134
135 done()
136 })
137 })
138
139 it('GET `statuses/mentions_timeline`', function (done) {
140 twit.get('statuses/mentions_timeline', function (err, reply, response) {
141 checkReply(err, reply)
142 checkTweet(reply[0])
143 done()
144 })
145 })
146
147 it('GET `statuses/user_timeline`', function (done) {
148 var params = {
149 screen_name: 'tolga_tezel'
150 }
151
152 twit.get('statuses/user_timeline', params, function (err, reply, response) {
153 checkReply(err, reply)
154 checkTweet(reply[0])
155
156 checkResponse(response)
157
158 done()
159 })
160 })
161
162 it('GET `search/tweets` { q: "a", since_id: 12345 }', function (done) {
163 var params = { q: 'a', since_id: 12345 }
164 twit.get('search/tweets', params, function (err, reply, response) {
165 checkReply(err, reply)
166 assert.ok(reply.statuses)
167 checkTweet(reply.statuses[0])
168
169 checkResponse(response)
170
171 done()
172 })
173 })
174
175 it('GET `search/tweets` { q: "fun since:2011-11-11" }', function (done) {
176 var params = { q: 'fun since:2011-11-11', count: 100 }
177 twit.get('search/tweets', params, function (err, reply, response) {
178 checkReply(err, reply)
179 assert.ok(reply.statuses)
180 checkTweet(reply.statuses[0])
181
182 console.log('\nnumber of fun statuses:', reply.statuses.length)
183
184 checkResponse(response)
185
186 done()
187 })
188 })
189
190 it('GET `search/tweets`, using `q` array', function (done) {
191 var params = {
192 q: [ 'banana', 'mango', 'peach' ]
193 }
194
195 twit.get('search/tweets', params, function (err, reply, response) {
196 checkReply(err, reply)
197 assert.ok(reply.statuses)
198 checkTweet(reply.statuses[0])
199
200 checkResponse(response)
201
202 done()
203 })
204 })
205
206 it('GET `search/tweets` with count set to 100', function (done) {
207 var params = {
208 q: 'happy',
209 count: 100
210 }
211
212 twit.get('search/tweets', params, function (err, reply, res) {
213 checkReply(err, reply)
214 console.log('\nnumber of tweets from search:', reply.statuses.length)
215 // twitter won't always send back 100 tweets if we ask for 100,
216 // but make sure it's close to 100
217 assert(reply.statuses.length > 95)
218
219 done()
220 })
221 })
222
223 it('GET `search/tweets` with geocode', function (done) {
224 var params = {
225 q: 'apple', geocode: [ '37.781157', '-122.398720', '1mi' ]
226 }
227
228 twit.get('search/tweets', params, function (err, reply) {
229 checkReply(err, reply)
230
231 done()
232 })
233 })
234
235 it('GET `direct_messages`', function (done) {
236 twit.get('direct_messages', function (err, reply, response) {
237 checkReply(err, reply)
238 assert.ok(Array.isArray(reply))
239 exports.checkDm(reply[0])
240
241 checkResponse(response)
242
243 done()
244 })
245 })
246
247 it('GET `followers/ids`', function (done) {
248 twit.get('followers/ids', function (err, reply, response) {
249 checkReply(err, reply)
250 assert.ok(Array.isArray(reply.ids))
251
252 checkResponse(response)
253
254 done()
255 })
256 })
257
258 it('GET `followers/ids` of screen_name tolga_tezel', function (done) {
259 twit.get('followers/ids', { screen_name: 'tolga_tezel' }, function (err, reply, response) {
260 checkReply(err, reply)
261 assert.ok(Array.isArray(reply.ids))
262
263 checkResponse(response)
264
265 done()
266 })
267 })
268
269 it('POST `statuses/retweet`', function (done) {
270 // search for a tweet to retweet
271 twit.get('search/tweets', { q: 'apple' }, function (err, reply, response) {
272 checkReply(err, reply)
273 assert.ok(reply.statuses)
274
275 var tweet = reply.statuses[0]
276 checkTweet(tweet)
277
278 var tweetId = tweet.id_str
279 assert(tweetId)
280
281 twit.post('statuses/retweet/'+tweetId, function (err, reply, response) {
282 checkReply(err, reply)
283
284 var retweetId = reply.id_str
285 assert(retweetId)
286
287 twit.post('statuses/destroy/'+retweetId, function (err, reply, response) {
288 checkReply(err, reply)
289
290 done()
291 })
292 })
293 })
294 })
295
296 // 1.1.8 usage
297 it('POST `statuses/retweet/:id` without `id` in params returns error', function (done) {
298 twit.post('statuses/retweet/:id', function (err, reply, response) {
299 assert(err)
300 assert.equal(err.message, 'Twit: Params object is missing a required parameter for this request: `id`')
301 done()
302 })
303 })
304
305 // 1.1.8 usage
306 it('POST `statuses/retweet/:id`', function (done) {
307 // search for a tweet to retweet
308 twit.get('search/tweets', { q: 'banana' }, function (err, reply, response) {
309 checkReply(err, reply)
310 assert.ok(reply.statuses)
311
312 var tweet = reply.statuses[0]
313 checkTweet(tweet)
314
315 var tweetId = tweet.id_str
316 assert(tweetId)
317
318 twit.post('statuses/retweet/:id', { id: tweetId }, function (err, reply) {
319 checkReply(err, reply)
320
321 var retweetId = reply.id_str
322 assert(retweetId)
323
324 twit.post('statuses/destroy/:id', { id: retweetId }, function (err, reply, response) {
325 checkReply(err, reply)
326
327 done()
328 })
329 })
330 })
331 })
332
333 // 1.1.8 usage
334 it('GET `users/suggestions/:slug`', function (done) {
335 twit.get('users/suggestions/:slug', { slug: 'funny' }, function (err, reply, res) {
336 checkReply(err, reply)
337 assert.equal(reply.slug, 'funny')
338 done()
339 })
340 })
341
342 // 1.1.8 usage
343 it('GET `users/suggestions/:slug/members`', function (done) {
344 twit.get('users/suggestions/:slug/members', { slug: 'funny' }, function (err, reply, res) {
345 checkReply(err, reply)
346
347 assert(reply[0].id_str)
348 assert(reply[0].screen_name)
349
350 done()
351 })
352 })
353
354 // 1.1.8 usage
355 it('GET `geo/id/:place_id`', function (done) {
356 var placeId = 'df51dec6f4ee2b2c'
357
358 twit.get('geo/id/:place_id', { place_id: placeId }, function (err, reply, res) {
359 checkReply(err, reply)
360
361 assert(reply.country)
362 assert(reply.bounding_box)
363 assert.equal(reply.id, placeId)
364
365 done()
366 })
367 })
368
369 it('POST `direct_messages/new`', function (done) {
370 var dmId
371
372 async.series({
373 postDm: function (next) {
374
375 var dmParams = {
376 screen_name: 'tolga_tezel',
377 text: 'hey this is a direct message from twit! :)'
378 }
379 // post a direct message from the sender's account
380 twit.post('direct_messages/new', dmParams, function (err, reply) {
381 assert(!err, err)
382 assert(reply)
383
384 dmId = reply.id_str
385
386 exports.checkDm(reply)
387
388 assert.equal(reply.text, dmParams.text)
389 assert(dmId)
390
391 return next()
392 })
393 },
394 deleteDm: function (next) {
395 twit.post('direct_messages/destroy', { id: dmId }, function (err, reply) {
396 assert(!err, err)
397 exports.checkDm(reply)
398 assert.equal(reply.id, dmId)
399
400 return next()
401 })
402 }
403 }, done)
404 })
405
406 describe('error handling', function () {
407 describe('handling errors from the twitter api', function () {
408 it('should callback with an Error object with all the info and a response object', function (done) {
409 var twit = new Twit({
410 consumer_key: 'a',
411 consumer_secret: 'b',
412 access_token: 'c',
413 access_token_secret: 'd'
414 })
415 twit.get('account/verify_credentials', function (err, reply, res) {
416 assert(err instanceof Error)
417 assert(err.statusCode === 401)
418 assert(err.code > 0)
419 assert(err.message.match(/token/))
420 assert(err.twitterReply)
421 assert(err.allErrors)
422 assert(!reply)
423 checkResponse(res);
424 done()
425 })
426 })
427 })
428 describe('handling other errors', function () {
429 it('should just forward them', function (done) {
430 var twit = new Twit(config1);
431
432 var fakeError = new Error('derp')
433
434 // stub the makeRequest function to throw a fake error
435 var OARequest = require('../lib/oarequest')
436 var orig = OARequest.prototype.makeRequest
437 OARequest.prototype.makeRequest = function (cb) {
438 cb(fakeError);
439 }
440
441 twit.get('account/verify_credentials', function (err, reply, res) {
442 assert(err === fakeError)
443
444 // restore stub
445 OARequest.prototype.makeRequest = orig
446
447 done()
448 })
449 })
450 })
451 })
452
453})
454
455/**
456 * Basic validation to verify we have no error and reply is an object
457 *
458 * @param {error} err error object (or null)
459 * @param {object} reply reply object received from twitter
460 */
461function checkReply (err, reply) {
462 assert.equal(err, null, 'reply err:'+util.inspect(err, true, 10, true))
463 assert.equal(typeof reply, 'object')
464}
465
466/**
467 * check the http response object and its headers
468 * @param {object} response http response object
469 */
470function checkResponse (response) {
471 assert(response)
472 assert(response.headers)
473}
474
475/**
476 * validate that @tweet is a tweet object
477 *
478 * @param {object} tweet `tweet` object received from twitter
479 */
480var checkTweet = exports.checkTweet = function (tweet) {
481 assert.ok(tweet)
482 assert.equal('string', typeof tweet.id_str, 'id_str wasnt string:'+tweet.id_str)
483 assert.equal('string', typeof tweet.text)
484
485 assert.ok(tweet.user)
486 assert.equal('string', typeof tweet.user.id_str)
487 assert.equal('string', typeof tweet.user.screen_name)
488}
489
490/**
491 * Validate that @dm is a direct message object
492 *
493 * @param {object} dm `direct message` object received from twitter
494 */
495exports.checkDm = function checkDm (dm) {
496 assert.ok(dm)
497 assert.equal('string', typeof dm.id_str)
498 assert.equal('string', typeof dm.text)
499
500 var recipient = dm.recipient
501
502 assert.ok(recipient)
503 assert.equal('string', typeof recipient.id_str)
504 assert.equal('string', typeof recipient.screen_name)
505
506 var sender = dm.sender
507
508 assert.ok(sender)
509 assert.equal('string', typeof sender.id_str)
510 assert.equal('string', typeof sender.screen_name)
511
512 assert.equal('string', typeof dm.text)
513}
514
515exports.assertTweetHasText = function (tweet, text) {
516 assert(tweet.text.toLowerCase().indexOf(text) !== -1, 'expected to find '+text+' in text: '+tweet.text);
517 }