mirror of
https://github.com/thewesker/bug-em.git
synced 2025-12-22 04:51:05 -05:00
824 lines
24 KiB
JavaScript
824 lines
24 KiB
JavaScript
var assert = require('assert')
|
|
, EventEmitter = require('events').EventEmitter
|
|
, fs = require('fs')
|
|
, sinon = require('sinon')
|
|
, Twit = require('../lib/twitter')
|
|
, config1 = require('../config1')
|
|
, config2 = require('../config2')
|
|
, helpers = require('./helpers')
|
|
, util = require('util')
|
|
, async = require('async')
|
|
|
|
describe('REST API', function () {
|
|
var twit = null
|
|
|
|
before(function () {
|
|
twit = new Twit(config1);
|
|
})
|
|
|
|
it('GET `account/verify_credentials`', function (done) {
|
|
twit.get('account/verify_credentials', function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
assert.notEqual(reply.followers_count, undefined)
|
|
assert.notEqual(reply.friends_count, undefined)
|
|
assert.ok(reply.id_str)
|
|
|
|
checkResponse(response)
|
|
|
|
assert(response.headers['x-rate-limit-limit'])
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('GET `account/verify_credentials` using promise API only', function (done) {
|
|
twit
|
|
.get('account/verify_credentials', { skip_status: true })
|
|
.catch(function (err) {
|
|
console.log('catch err', err.stack)
|
|
})
|
|
.then(function (result) {
|
|
checkReply(null, result.data)
|
|
assert.notEqual(result.data.followers_count, undefined)
|
|
assert.notEqual(result.data.friends_count, undefined)
|
|
assert.ok(result.data.id_str)
|
|
checkResponse(result.resp)
|
|
assert(result.resp.headers['x-rate-limit-limit'])
|
|
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('GET `account/verify_credentials` using promise API AND callback API', function (done) {
|
|
var i = 0;
|
|
|
|
var _checkDataAndResp = function (data, resp) {
|
|
checkReply(null, data)
|
|
assert.notEqual(data.followers_count, undefined)
|
|
assert.notEqual(data.friends_count, undefined)
|
|
assert.ok(data.id_str)
|
|
checkResponse(resp)
|
|
assert(resp.headers['x-rate-limit-limit'])
|
|
|
|
i++;
|
|
if (i == 2) {
|
|
done()
|
|
}
|
|
}
|
|
|
|
var get = twit.get('account/verify_credentials', function (err, data, resp) {
|
|
assert(!err, err);
|
|
_checkDataAndResp(data, resp);
|
|
});
|
|
get.catch(function (err) {
|
|
console.log('Got error:', err.stack)
|
|
});
|
|
get.then(function (result) {
|
|
_checkDataAndResp(result.data, result.resp);
|
|
});
|
|
})
|
|
|
|
it('POST `account/update_profile`', function (done) {
|
|
twit.post('account/update_profile', function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
console.log('\nscreen name:', reply.screen_name)
|
|
checkResponse(response)
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('POST `statuses/update` and POST `statuses/destroy:id`', function (done) {
|
|
var tweetId = null
|
|
|
|
var params = {
|
|
status: '@tolga_tezel tweeting using github.com/ttezel/twit. ' + helpers.generateRandomString(7)
|
|
}
|
|
twit.post('statuses/update', params, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
console.log('\ntweeted:', reply.text)
|
|
|
|
tweetId = reply.id_str
|
|
assert(tweetId)
|
|
checkResponse(response)
|
|
|
|
var deleteParams = { id: tweetId }
|
|
// Try up to 2 times to delete the tweet.
|
|
// Even after a 200 response to statuses/update is returned, a delete might 404 so we retry.
|
|
exports.req_with_retries(twit, 2, 'post', 'statuses/destroy/:id', deleteParams, [404], function (err, body, response) {
|
|
checkReply(err, body)
|
|
checkTweet(body)
|
|
checkResponse(response)
|
|
|
|
done()
|
|
})
|
|
})
|
|
})
|
|
|
|
it('POST `statuses/update` with characters requiring escaping', function (done) {
|
|
var params = { status: '@tolga_tezel tweeting using github.com/ttezel/twit :) !' + helpers.generateRandomString(15) }
|
|
|
|
twit.post('statuses/update', params, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
|
|
console.log('\ntweeted:', reply.text)
|
|
|
|
checkResponse(response)
|
|
|
|
var text = reply.text
|
|
|
|
assert(reply.id_str)
|
|
|
|
twit.post('statuses/destroy/:id', { id: reply.id_str }, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
checkTweet(reply)
|
|
assert.equal(reply.text, text)
|
|
|
|
checkResponse(response)
|
|
|
|
done()
|
|
})
|
|
})
|
|
})
|
|
|
|
it('POST `statuses/update` with \'Hi!!\' works', function (done) {
|
|
var params = { status: 'Hi!!' }
|
|
|
|
twit.post('statuses/update', params, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
|
|
console.log('\ntweeted:', reply.text)
|
|
|
|
checkResponse(response)
|
|
|
|
var text = reply.text
|
|
|
|
var destroyRoute = 'statuses/destroy/'+reply.id_str
|
|
|
|
twit.post(destroyRoute, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
checkTweet(reply)
|
|
assert.equal(reply.text, text)
|
|
|
|
checkResponse(response)
|
|
|
|
done()
|
|
})
|
|
})
|
|
})
|
|
|
|
it('GET `statuses/home_timeline`', function (done) {
|
|
twit.get('statuses/home_timeline', function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
checkTweet(reply[0])
|
|
|
|
checkResponse(response)
|
|
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('GET `statuses/mentions_timeline`', function (done) {
|
|
twit.get('statuses/mentions_timeline', function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
checkTweet(reply[0])
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('GET `statuses/user_timeline`', function (done) {
|
|
var params = {
|
|
screen_name: 'tolga_tezel'
|
|
}
|
|
|
|
twit.get('statuses/user_timeline', params, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
checkTweet(reply[0])
|
|
|
|
checkResponse(response)
|
|
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('GET `search/tweets` { q: "a", since_id: 12345 }', function (done) {
|
|
var params = { q: 'a', since_id: 12345 }
|
|
twit.get('search/tweets', params, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
assert.ok(reply.statuses)
|
|
checkTweet(reply.statuses[0])
|
|
|
|
checkResponse(response)
|
|
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('GET `search/tweets` { q: "fun since:2011-11-11" }', function (done) {
|
|
var params = { q: 'fun since:2011-11-11', count: 100 }
|
|
twit.get('search/tweets', params, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
assert.ok(reply.statuses)
|
|
checkTweet(reply.statuses[0])
|
|
|
|
console.log('\nnumber of fun statuses:', reply.statuses.length)
|
|
|
|
checkResponse(response)
|
|
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('GET `search/tweets`, using `q` array', function (done) {
|
|
var params = {
|
|
q: [ 'banana', 'mango', 'peach' ]
|
|
}
|
|
|
|
twit.get('search/tweets', params, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
assert.ok(reply.statuses)
|
|
checkTweet(reply.statuses[0])
|
|
|
|
checkResponse(response)
|
|
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('GET `search/tweets` with count set to 100', function (done) {
|
|
var params = {
|
|
q: 'happy',
|
|
count: 100
|
|
}
|
|
|
|
twit.get('search/tweets', params, function (err, reply, res) {
|
|
checkReply(err, reply)
|
|
console.log('\nnumber of tweets from search:', reply.statuses.length)
|
|
// twitter won't always send back 100 tweets if we ask for 100,
|
|
// but make sure it's close to 100
|
|
assert(reply.statuses.length > 95)
|
|
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('GET `search/tweets` with geocode', function (done) {
|
|
var params = {
|
|
q: 'apple', geocode: [ '37.781157', '-122.398720', '1mi' ]
|
|
}
|
|
|
|
twit.get('search/tweets', params, function (err, reply) {
|
|
checkReply(err, reply)
|
|
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('GET `direct_messages`', function (done) {
|
|
twit.get('direct_messages', function (err, reply, response) {
|
|
checkResponse(response)
|
|
checkReply(err, reply)
|
|
assert.ok(Array.isArray(reply))
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('GET `followers/ids`', function (done) {
|
|
twit.get('followers/ids', function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
assert.ok(Array.isArray(reply.ids))
|
|
|
|
checkResponse(response)
|
|
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('GET `followers/ids` of screen_name tolga_tezel', function (done) {
|
|
twit.get('followers/ids', { screen_name: 'tolga_tezel' }, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
assert.ok(Array.isArray(reply.ids))
|
|
|
|
checkResponse(response)
|
|
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('POST `statuses/retweet`', function (done) {
|
|
// search for a tweet to retweet
|
|
twit.get('search/tweets', { q: 'apple' }, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
assert.ok(reply.statuses)
|
|
|
|
var tweet = reply.statuses[0]
|
|
checkTweet(tweet)
|
|
|
|
var tweetId = tweet.id_str
|
|
assert(tweetId)
|
|
|
|
twit.post('statuses/retweet/'+tweetId, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
|
|
var retweetId = reply.id_str
|
|
assert(retweetId)
|
|
|
|
twit.post('statuses/destroy/'+retweetId, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
|
|
done()
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
// 1.1.8 usage
|
|
it('POST `statuses/retweet/:id` without `id` in params returns error', function (done) {
|
|
twit.post('statuses/retweet/:id', function (err, reply, response) {
|
|
assert(err)
|
|
assert.equal(err.message, 'Twit: Params object is missing a required parameter for this request: `id`')
|
|
done()
|
|
})
|
|
})
|
|
|
|
// 1.1.8 usage
|
|
it('POST `statuses/retweet/:id`', function (done) {
|
|
// search for a tweet to retweet
|
|
twit.get('search/tweets', { q: 'banana' }, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
assert.ok(reply.statuses)
|
|
|
|
var tweet = reply.statuses[0]
|
|
checkTweet(tweet)
|
|
|
|
var tweetId = tweet.id_str
|
|
assert(tweetId)
|
|
|
|
twit.post('statuses/retweet/:id', { id: tweetId }, function (err, reply) {
|
|
checkReply(err, reply)
|
|
|
|
var retweetId = reply.id_str
|
|
assert(retweetId)
|
|
|
|
twit.post('statuses/destroy/:id', { id: retweetId }, function (err, reply, response) {
|
|
checkReply(err, reply)
|
|
|
|
done()
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
// 1.1.8 usage
|
|
// skip for now since this API call is having problems on Twitter's side (404)
|
|
it.skip('GET `users/suggestions/:slug`', function (done) {
|
|
twit.get('users/suggestions/:slug', { slug: 'funny' }, function (err, reply, res) {
|
|
checkReply(err, reply)
|
|
assert.equal(reply.slug, 'funny')
|
|
done()
|
|
})
|
|
})
|
|
|
|
// 1.1.8 usage
|
|
// skip for now since this API call is having problems on Twitter's side (404)
|
|
it.skip('GET `users/suggestions/:slug/members`', function (done) {
|
|
twit.get('users/suggestions/:slug/members', { slug: 'funny' }, function (err, reply, res) {
|
|
checkReply(err, reply)
|
|
|
|
assert(reply[0].id_str)
|
|
assert(reply[0].screen_name)
|
|
|
|
done()
|
|
})
|
|
})
|
|
|
|
// 1.1.8 usage
|
|
it('GET `geo/id/:place_id`', function (done) {
|
|
var placeId = 'df51dec6f4ee2b2c'
|
|
|
|
twit.get('geo/id/:place_id', { place_id: placeId }, function (err, reply, res) {
|
|
checkReply(err, reply)
|
|
|
|
assert(reply.country)
|
|
assert(reply.bounding_box)
|
|
assert.equal(reply.id, placeId)
|
|
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('POST `direct_messages/new`', function (done) {
|
|
var dmId
|
|
|
|
async.series({
|
|
postDm: function (next) {
|
|
|
|
var dmParams = {
|
|
screen_name: 'tolga_tezel',
|
|
text: 'hey this is a direct message from twit! :) ' + helpers.generateRandomString(15)
|
|
}
|
|
// post a direct message from the sender's account
|
|
twit.post('direct_messages/new', dmParams, function (err, reply) {
|
|
assert(!err, err)
|
|
assert(reply)
|
|
|
|
dmId = reply.id_str
|
|
|
|
exports.checkDm(reply)
|
|
|
|
assert.equal(reply.text, dmParams.text)
|
|
assert(dmId)
|
|
|
|
return next()
|
|
})
|
|
},
|
|
deleteDm: function (next) {
|
|
twit.post('direct_messages/destroy', { id: dmId }, function (err, reply) {
|
|
assert(!err, err)
|
|
exports.checkDm(reply)
|
|
assert.equal(reply.id, dmId)
|
|
|
|
return next()
|
|
})
|
|
}
|
|
}, done);
|
|
})
|
|
|
|
describe('Media Upload', function () {
|
|
var twit = null
|
|
|
|
before(function () {
|
|
twit = new Twit(config1)
|
|
})
|
|
|
|
it('POST media/upload with png', function (done) {
|
|
var b64content = fs.readFileSync(__dirname + '/img/cutebird.png', { encoding: 'base64' })
|
|
|
|
twit.post('media/upload', { media_data: b64content }, function (err, data, response) {
|
|
assert.equal(response.statusCode, 200)
|
|
assert(!err, err)
|
|
exports.checkMediaUpload(data)
|
|
assert(data.image.image_type == 'image/png' || data.image.image_type == 'image\/png')
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('POST media/upload with JPG', function (done) {
|
|
var b64content = fs.readFileSync(__dirname + '/img/bigbird.jpg', { encoding: 'base64' })
|
|
|
|
twit.post('media/upload', { media_data: b64content }, function (err, data, response) {
|
|
assert(!err, err)
|
|
exports.checkMediaUpload(data)
|
|
assert.equal(data.image.image_type, 'image/jpeg')
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('POST media/upload with static GIF', function (done) {
|
|
var b64content = fs.readFileSync(__dirname + '/img/twitterbird.gif', { encoding: 'base64' })
|
|
|
|
twit.post('media/upload', { media_data: b64content }, function (err, data, response) {
|
|
assert(!err, err)
|
|
exports.checkMediaUpload(data)
|
|
assert.equal(data.image.image_type, 'image/gif')
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('POST media/upload with animated GIF using `media_data` parameter', function (done) {
|
|
var b64content = fs.readFileSync(__dirname + '/img/snoopy-animated.gif', { encoding: 'base64' })
|
|
|
|
twit.post('media/upload', { media_data: b64content }, function (err, data, response) {
|
|
assert(!err, err)
|
|
exports.checkMediaUpload(data)
|
|
var expected_image_types = ['image/gif', 'image/animatedgif']
|
|
var image_type = data.image.image_type
|
|
assert.ok(expected_image_types.indexOf(image_type) !== -1, 'got unexpected image type:' + image_type)
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('POST media/upload with animated GIF, then POST a tweet referencing the media', function (done) {
|
|
var b64content = fs.readFileSync(__dirname + '/img/snoopy-animated.gif', { encoding: 'base64' });
|
|
|
|
twit.post('media/upload', { media_data: b64content }, function (err, data, response) {
|
|
assert(!err, err)
|
|
exports.checkMediaUpload(data)
|
|
var expected_image_types = ['image/gif', 'image/animatedgif']
|
|
var image_type = data.image.image_type
|
|
assert.ok(expected_image_types.indexOf(image_type) !== -1, 'got unexpected image type:' + image_type)
|
|
|
|
var mediaIdStr = data.media_id_string
|
|
assert(mediaIdStr)
|
|
var params = { status: '#nofilter', media_ids: [mediaIdStr] }
|
|
twit.post('statuses/update', params, function (err, data, response) {
|
|
assert(!err, err)
|
|
var tweetIdStr = data.id_str
|
|
assert(tweetIdStr)
|
|
|
|
exports.req_with_retries(twit, 3, 'post', 'statuses/destroy/:id', { id: tweetIdStr }, [404], function (err, data, response) {
|
|
checkReply(err, data)
|
|
done()
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
it('POST media/upload with animated GIF using `media` parameter', function (done) {
|
|
var b64Content = fs.readFileSync(__dirname + '/img/snoopy-animated.gif', { encoding: 'base64' });
|
|
|
|
twit.post('media/upload', { media: b64Content }, function (err, data, response) {
|
|
assert(!err, err)
|
|
exports.checkMediaUpload(data)
|
|
var expected_image_types = ['image/gif', 'image/animatedgif']
|
|
var image_type = data.image.image_type
|
|
assert.ok(expected_image_types.indexOf(image_type) !== -1, 'got unexpected image type:' + image_type)
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('POST media/upload with JPG, then POST media/metadata/create with alt text', function (done) {
|
|
var b64content = fs.readFileSync(__dirname + '/img/bigbird.jpg', { encoding: 'base64' })
|
|
|
|
twit.post('media/upload', { media_data: b64content }, function (err, data, response) {
|
|
assert(!err, err)
|
|
exports.checkMediaUpload(data)
|
|
assert.equal(data.image.image_type, 'image/jpeg')
|
|
|
|
var mediaIdStr = data.media_id_string
|
|
assert(mediaIdStr)
|
|
var altText = 'a very small Big Bird'
|
|
var params = { media_id: mediaIdStr, alt_text: { text: altText } }
|
|
twit.post('media/metadata/create', params, function (err, data, response) {
|
|
assert(!err, err)
|
|
// data is empty on media/metadata/create success; nothing more to assert
|
|
done();
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
it('POST account/update_profile_image', function (done) {
|
|
var b64content = fs.readFileSync(__dirname + '/img/snoopy-animated.gif', { encoding: 'base64' })
|
|
|
|
twit.post('account/update_profile_image', { image: b64content }, function (err, data, response) {
|
|
assert(!err, err);
|
|
exports.checkReply(err, data);
|
|
exports.checkUser(data);
|
|
|
|
done()
|
|
})
|
|
})
|
|
|
|
it('POST friendships/create', function (done) {
|
|
var params = { screen_name: 'tolga_tezel', follow: false };
|
|
twit.post('friendships/create', params, function (err, data, resp) {
|
|
assert(!err, err);
|
|
exports.checkReply(err, data);
|
|
exports.checkUser(data);
|
|
done();
|
|
});
|
|
})
|
|
|
|
describe('Favorites', function () {
|
|
it('POST favorites/create and POST favorites/destroy work', function (done) {
|
|
twit.post('favorites/create', { id: '583531943624597504' }, function (err, data, resp) {
|
|
assert(!err, err);
|
|
exports.checkReply(err, data);
|
|
var tweetIdStr = data.id_str;
|
|
assert(tweetIdStr);
|
|
|
|
twit.post('favorites/destroy', { id: tweetIdStr }, function (err, data, resp) {
|
|
assert(!err, err);
|
|
exports.checkReply(err, data);
|
|
assert(data.id_str);
|
|
assert(data.text);
|
|
|
|
done();
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('error handling', function () {
|
|
describe('handling errors from the twitter api', function () {
|
|
it('should callback with an Error object with all the info and a response object', function (done) {
|
|
var twit = new Twit({
|
|
consumer_key: 'a',
|
|
consumer_secret: 'b',
|
|
access_token: 'c',
|
|
access_token_secret: 'd'
|
|
})
|
|
twit.get('account/verify_credentials', function (err, reply, res) {
|
|
assert(err instanceof Error)
|
|
assert(err.statusCode === 401)
|
|
assert(err.code > 0)
|
|
assert(err.message.match(/token/))
|
|
assert(err.twitterReply)
|
|
assert(err.allErrors)
|
|
assert(res)
|
|
assert(res.headers)
|
|
assert.equal(res.statusCode, 401)
|
|
done()
|
|
})
|
|
})
|
|
})
|
|
describe('handling other errors', function () {
|
|
it('should just forward errors raised by underlying request lib', function (done) {
|
|
var twit = new Twit(config1);
|
|
var fakeError = new Error('derp')
|
|
|
|
var FakeRequest = function () {
|
|
EventEmitter.call(this)
|
|
}
|
|
util.inherits(FakeRequest, EventEmitter)
|
|
|
|
var stubGet = function () {
|
|
var fakeRequest = new FakeRequest()
|
|
process.nextTick(function () {
|
|
fakeRequest.emit('error', fakeError)
|
|
})
|
|
return fakeRequest
|
|
}
|
|
|
|
var request = require('request')
|
|
var stubGet = sinon.stub(request, 'get', stubGet)
|
|
|
|
twit.get('account/verify_credentials', function (err, reply, res) {
|
|
assert(err === fakeError)
|
|
|
|
// restore request.get
|
|
stubGet.restore()
|
|
|
|
done()
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('Request timeout', function () {
|
|
it('set to 1ms should return with a timeout error', function (done) {
|
|
config1.timeout_ms = 1;
|
|
var twit = new Twit(config1);
|
|
twit.get('account/verify_credentials', function (err, reply, res) {
|
|
assert(err)
|
|
assert.equal(err.message, 'ETIMEDOUT')
|
|
delete config1.timeout_ms
|
|
done()
|
|
})
|
|
})
|
|
})
|
|
});
|
|
});
|
|
|
|
describe('Twit agent_options config', function () {
|
|
it('config.trusted_cert_fingerprints works against cert fingerprint for api.twitter.com:443', function (done) {
|
|
config1.trusted_cert_fingerprints = [
|
|
'66:EA:47:62:D9:B1:4F:1A:AE:89:5F:68:BA:6B:8E:BB:F8:1D:BF:8E'
|
|
];
|
|
var t = new Twit(config1);
|
|
|
|
t.get('account/verify_credentials', function (err, data, resp) {
|
|
assert(!err, err)
|
|
assert(data)
|
|
assert(data.id_str)
|
|
assert(data.name)
|
|
assert(data.screen_name)
|
|
|
|
delete config1.trusted_cert_fingerprints
|
|
done();
|
|
})
|
|
})
|
|
|
|
it('config.trusted_cert_fingerprints responds with Error when fingerprint mismatch occurs', function (done) {
|
|
config1.trusted_cert_fingerprints = [
|
|
'AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA:AA'
|
|
];
|
|
var t = new Twit(config1);
|
|
|
|
t.get('account/verify_credentials', function (err, data, resp) {
|
|
assert(err)
|
|
assert(err.toString().indexOf('Trusted fingerprints are: ' + config1.trusted_cert_fingerprints[0]) !== -1)
|
|
|
|
delete config1.trusted_cert_fingerprints
|
|
done();
|
|
})
|
|
})
|
|
})
|
|
|
|
describe('Local time offset compensation', function () {
|
|
it('Compensates for local time being behind', function (done) {
|
|
var t1 = Date.now();
|
|
var t = new Twit(config2);
|
|
|
|
var stubNow = function () {
|
|
return 0;
|
|
}
|
|
var stubDateNow = sinon.stub(Date, 'now', stubNow);
|
|
|
|
t.get('account/verify_credentials', function (err, data, resp) {
|
|
assert(err);
|
|
|
|
t.get('account/verify_credentials', function (err, data, resp) {
|
|
assert(!err, err);
|
|
exports.checkReply(err, data);
|
|
exports.checkUser(data);
|
|
assert(t._twitter_time_minus_local_time_ms > 0)
|
|
|
|
stubDateNow.restore();
|
|
|
|
done();
|
|
})
|
|
})
|
|
})
|
|
})
|
|
|
|
/**
|
|
* Basic validation to verify we have no error and reply is an object
|
|
*
|
|
* @param {error} err error object (or null)
|
|
* @param {object} reply reply object received from twitter
|
|
*/
|
|
var checkReply = exports.checkReply = function (err, reply) {
|
|
assert.equal(err, null, 'reply err:'+util.inspect(err, true, 10, true))
|
|
assert.equal(typeof reply, 'object')
|
|
}
|
|
|
|
/**
|
|
* check the http response object and its headers
|
|
* @param {object} response http response object
|
|
*/
|
|
var checkResponse = exports.checkResponse = function (response) {
|
|
assert(response)
|
|
assert(response.headers)
|
|
assert.equal(response.statusCode, 200)
|
|
}
|
|
|
|
/**
|
|
* validate that @tweet is a tweet object
|
|
*
|
|
* @param {object} tweet `tweet` object received from twitter
|
|
*/
|
|
var checkTweet = exports.checkTweet = function (tweet) {
|
|
assert.ok(tweet)
|
|
assert.equal('string', typeof tweet.id_str, 'id_str wasnt string:'+tweet.id_str)
|
|
assert.equal('string', typeof tweet.text)
|
|
|
|
assert.ok(tweet.user)
|
|
assert.equal('string', typeof tweet.user.id_str)
|
|
assert.equal('string', typeof tweet.user.screen_name)
|
|
}
|
|
|
|
/**
|
|
* Validate that @dm is a direct message object
|
|
*
|
|
* @param {object} dm `direct message` object received from twitter
|
|
*/
|
|
exports.checkDm = function checkDm (dm) {
|
|
assert.ok(dm)
|
|
assert.equal('string', typeof dm.id_str)
|
|
assert.equal('string', typeof dm.text)
|
|
|
|
var recipient = dm.recipient
|
|
|
|
assert.ok(recipient)
|
|
assert.equal('string', typeof recipient.id_str)
|
|
assert.equal('string', typeof recipient.screen_name)
|
|
|
|
var sender = dm.sender
|
|
|
|
assert.ok(sender)
|
|
assert.equal('string', typeof sender.id_str)
|
|
assert.equal('string', typeof sender.screen_name)
|
|
|
|
assert.equal('string', typeof dm.text)
|
|
}
|
|
|
|
exports.checkMediaUpload = function checkMediaUpload (data) {
|
|
assert.ok(data)
|
|
assert.ok(data.image)
|
|
assert.ok(data.image.w)
|
|
assert.ok(data.image.h)
|
|
assert.ok(data.media_id)
|
|
assert.equal('string', typeof data.media_id_string)
|
|
assert.ok(data.size)
|
|
}
|
|
|
|
exports.checkUser = function checkUser (data) {
|
|
assert.ok(data)
|
|
assert.ok(data.id_str)
|
|
assert.ok(data.name)
|
|
assert.ok(data.screen_name)
|
|
}
|
|
|
|
exports.assertTweetHasText = function (tweet, text) {
|
|
assert(tweet.text.toLowerCase().indexOf(text) !== -1, 'expected to find '+text+' in text: '+tweet.text);
|
|
}
|
|
|
|
exports.req_with_retries = function (twit_instance, num_tries, verb, path, params, status_codes_to_retry, cb) {
|
|
twit_instance[verb](path, params, function (err, data, response) {
|
|
if (!num_tries || (status_codes_to_retry.indexOf(response.statusCode) === -1)) {
|
|
return cb(err, data, response)
|
|
}
|
|
|
|
exports.req_with_retries(twit_instance, num_tries - 1, verb, path, params, status_codes_to_retry, cb)
|
|
})
|
|
}
|