From d31b0b16bb7d426c5632c3ddaaf4e5171b40ed26 Mon Sep 17 00:00:00 2001 From: Jelte Fennema Date: Mon, 17 Sep 2018 14:30:43 +0200 Subject: [PATCH] prettify + fix lints --- karma.ci.config.js | 135 +- karma.config.js | 140 +- src/getstream.js | 9 +- src/lib/batch_operations.js | 91 +- src/lib/client.js | 317 +++-- src/lib/cloud.js | 16 +- src/lib/collections.js | 102 +- src/lib/errors.js | 6 +- src/lib/feed.js | 276 ++-- src/lib/files.js | 34 +- src/lib/images.js | 55 +- src/lib/personalization.js | 90 +- src/lib/promise.js | 2 +- src/lib/signing.js | 28 +- src/lib/user.js | 92 +- src/lib/utils.js | 26 +- test/integration/browser/client_test.js | 68 +- test/integration/cloud/activities.js | 52 +- test/integration/cloud/enrich.js | 543 ++++---- test/integration/cloud/files.js | 54 +- test/integration/cloud/follow_list.js | 122 +- test/integration/cloud/images.js | 95 +- test/integration/cloud/object_store.js | 340 +++-- test/integration/cloud/open_graph.js | 83 +- test/integration/cloud/permissions.js | 258 ++-- test/integration/cloud/personalized_feed.js | 29 +- test/integration/cloud/profile.js | 242 ++-- test/integration/cloud/reaction.js | 450 +++---- test/integration/cloud/utils.js | 491 ++++--- test/integration/common/client_test.js | 925 ++++++------- test/integration/common/faye_test.js | 273 ++-- test/integration/common/promise_test.js | 70 +- test/integration/node/client_test.js | 1334 ++++++++++--------- test/integration/utils/config.js | 14 +- test/integration/utils/hooks.js | 182 +-- test/integration/utils/index.js | 48 +- test/unit/browser/client_test.js | 145 +- test/unit/common/client_test.js | 607 +++++---- test/unit/common/faye_test.js | 57 +- test/unit/common/feed_test.js | 1059 ++++++++------- test/unit/common/jwt_test.js | 16 +- test/unit/common/utils_test.js | 40 +- test/unit/node/batch_test.js | 258 ++-- test/unit/node/client_test.js | 834 +++++++----- test/unit/node/collections_test.js | 456 ++++--- test/unit/node/heroku_test.js | 224 ++-- test/unit/node/jwt_test.js | 20 +- test/unit/node/personalization_test.js | 641 +++++---- test/unit/node/redirect_test.js | 273 ++-- test/unit/node/token_test.js | 84 +- test/unit/utils/config.js | 11 +- test/unit/utils/hooks.js | 12 +- test/unit/utils/jwt.js | 33 +- types/getstream/index.d.ts | 123 +- types/getstream/tests-getstream.ts | 44 +- webpack.config.js | 58 +- 56 files changed, 6384 insertions(+), 5703 deletions(-) diff --git a/karma.ci.config.js b/karma.ci.config.js index d75b4e97..e6593b5b 100644 --- a/karma.ci.config.js +++ b/karma.ci.config.js @@ -1,79 +1,78 @@ var baseConfig = require('./karma.config.js'); module.exports = function(config) { + baseConfig(config); - baseConfig(config); + var customLaunchers = { + SL_Chrome: { + base: 'SauceLabs', + browserName: 'chrome', + }, + SL_FireFox: { + base: 'SauceLabs', + browserName: 'firefox', + }, + SL_Safari: { + base: 'SauceLabs', + browserName: 'safari', + }, + SL_IE_10: { + base: 'SauceLabs', + browserName: 'internet explorer', + platform: 'Windows 8', + version: '10', + }, + SL_IE_11: { + base: 'SauceLabs', + browserName: 'internet explorer', + platform: 'Windows 8.1', + version: '11', + }, + // 'SL_IE_13': { + // base: 'SauceLabs', + // browserName: 'microsoftedge', + // version: '13', + // platform: 'Windows 10', + // }, + SL_IE_14: { + base: 'SauceLabs', + browserName: 'microsoftedge', + version: '14', + platform: 'Windows 10', + }, + }; - var customLaunchers = { - 'SL_Chrome': { - base: 'SauceLabs', - browserName: 'chrome', - }, - 'SL_FireFox': { - base: 'SauceLabs', - browserName: 'firefox', - }, - 'SL_Safari': { - base: 'SauceLabs', - browserName: 'safari', - }, - 'SL_IE_10': { - base: 'SauceLabs', - browserName: 'internet explorer', - platform: 'Windows 8', - version: '10', - }, - 'SL_IE_11': { - base: 'SauceLabs', - browserName: 'internet explorer', - platform: 'Windows 8.1', - version: '11', - }, - // 'SL_IE_13': { - // base: 'SauceLabs', - // browserName: 'microsoftedge', - // version: '13', - // platform: 'Windows 10', - // }, - 'SL_IE_14': { - base: 'SauceLabs', - browserName: 'microsoftedge', - version: '14', - platform: 'Windows 10', - }, - }; + config.set({ + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + sauceLabs: { + testName: 'Stream-JS Browser Tests', + public: 'public', + connectOptions: { + // verbose: true, + // verboseDebugging: true, + }, + }, + customLaunchers: customLaunchers, + browsers: Object.keys(customLaunchers), - config.set({ - // start these browsers - // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher - sauceLabs: { - testName: 'Stream-JS Browser Tests', - public: "public", - connectOptions: { - // verbose: true, - // verboseDebugging: true, - } - }, - customLaunchers: customLaunchers, - browsers: Object.keys(customLaunchers), + reporters: ['dots', 'saucelabs'], - reporters: ['dots', 'saucelabs'], + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: true, - // Continuous Integration mode - // if true, Karma captures browsers, runs the tests and exits - singleRun: true, + captureTimeout: 60000, + // Somehow karma doesn't capture intermediate behavior and only + // captures once an entire suite is complete. This timeout will + // guarantee that the browser will have enough time to do this: - captureTimeout: 60000, - // Somehow karma doesn't capture intermediate behavior and only - // captures once an entire suite is complete. This timeout will - // guarantee that the browser will have enough time to do this: + // Integration tests can take very long we will give the browser + // 300 seconds to complete these. + browserNoActivityTimeout: 300 * 1000, - // Integration tests can take very long we will give the browser - // 300 seconds to complete these. - browserNoActivityTimeout: 300 * 1000, - - // Concurrency level - // how many browser should be started simultaneous - concurrency: 3 - }); + // Concurrency level + // how many browser should be started simultaneous + concurrency: 3, + }); }; diff --git a/karma.config.js b/karma.config.js index 03b74384..ee9e2404 100644 --- a/karma.config.js +++ b/karma.config.js @@ -7,80 +7,78 @@ delete webpackConfig['entry']; delete webpackConfig['output']; webpackConfig['devtool'] = 'inline-source-map'; webpackConfig['plugins'] = [ - new webpack.EnvironmentPlugin([ - 'STREAM_API_KEY', - 'STREAM_API_SECRET', - 'STREAM_APP_ID', - ]) + new webpack.EnvironmentPlugin([ + 'STREAM_API_KEY', + 'STREAM_API_SECRET', + 'STREAM_APP_ID', + ]), ]; webpackConfig['node']['Buffer'] = true; -webpackConfig['module']['rules'].push({ test: /\.json$/, exclude:/node_modules/, loader: 'json-loader' }); +webpackConfig['module']['rules'].push({ + test: /\.json$/, + exclude: /node_modules/, + loader: 'json-loader', +}); // Karma config module.exports = function(config) { - - config.set({ - // base path that will be used to resolve all patterns (eg. files, exclude) - basePath: '', - - // frameworks to use - // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks: ['mocha'], - - // list of files / patterns to load in the browser - files: [ - 'test/unit/common/**/*_test.js', - 'test/unit/browser/**/*_test.js', - ], - - // list of files to exclude - exclude: [ - ], - - // preprocess matching files before serving them to the browser - // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor - preprocessors: { - 'test/unit/common/**/*_test.js': [ 'webpack', 'sourcemap' ], - 'test/unit/browser/**/*_test.js': [ 'webpack', 'sourcemap' ], - }, - - // Webpack configuration for webpack preprocessor - webpack: webpackConfig, - webpackMiddleware: { - // webpack-dev-middleware configuration - // i. e. - stats: 'errors-only' - }, - - // test results reporter to use - // possible values: 'dots', 'progress' - // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ['mocha'], - - // web server port - port: 9876, - - // enable / disable colors in the output (reporters and logs) - colors: true, - - // level of logging - // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG - logLevel: config.LOG_INFO, - - // enable / disable watching file and executing tests whenever any file changes - autoWatch: true, - - // start these browsers - // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher - browsers: ['Chrome'], - - // Continuous Integration mode - // if true, Karma captures browsers, runs the tests and exits - singleRun: false, - - // Concurrency level - // how many browser should be started simultaneous - concurrency: Infinity, - - }); + config.set({ + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['mocha'], + + // list of files / patterns to load in the browser + files: ['test/unit/common/**/*_test.js', 'test/unit/browser/**/*_test.js'], + + // list of files to exclude + exclude: [], + + // preprocess matching files before serving them to the browser + // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + preprocessors: { + 'test/unit/common/**/*_test.js': ['webpack', 'sourcemap'], + 'test/unit/browser/**/*_test.js': ['webpack', 'sourcemap'], + }, + + // Webpack configuration for webpack preprocessor + webpack: webpackConfig, + webpackMiddleware: { + // webpack-dev-middleware configuration + // i. e. + stats: 'errors-only', + }, + + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['mocha'], + + // web server port + port: 9876, + + // enable / disable colors in the output (reporters and logs) + colors: true, + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: true, + + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: ['Chrome'], + + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: false, + + // Concurrency level + // how many browser should be started simultaneous + concurrency: Infinity, + }); }; diff --git a/src/getstream.js b/src/getstream.js index ecd9acf9..2a1c6827 100644 --- a/src/getstream.js +++ b/src/getstream.js @@ -28,8 +28,10 @@ function connect(apiKey, apiSecret, appId, options) { * @example where streamURL looks like * "https://thierry:pass@gestream.io/?app=1" */ - if (typeof (process) !== 'undefined' && process.env.STREAM_URL && !apiKey) { - var parts = /https\:\/\/(\w+)\:(\w+)\@([\w-]*).*\?app_id=(\d+)/.exec(process.env.STREAM_URL); // eslint-disable-line no-useless-escape + if (typeof process !== 'undefined' && process.env.STREAM_URL && !apiKey) { + var parts = /https\:\/\/(\w+)\:(\w+)\@([\w-]*).*\?app_id=(\d+)/.exec( + process.env.STREAM_URL + ); // eslint-disable-line no-useless-escape apiKey = parts[1]; apiSecret = parts[2]; var location = parts[3]; @@ -46,7 +48,7 @@ function connect(apiKey, apiSecret, appId, options) { return new StreamClient(apiKey, apiSecret, appId, options); } -function connectCloud(apiKey, appId, options={}) { +function connectCloud(apiKey, appId, options = {}) { /** * Create StreamCloudClient that's compatible with StreamCloud * @method connect @@ -68,7 +70,6 @@ function connectCloud(apiKey, appId, options={}) { return new cloud.StreamCloudClient(apiKey, null, appId, options); } - module.exports.connect = connect; module.exports.connectCloud = connectCloud; module.exports.errors = errors; diff --git a/src/lib/batch_operations.js b/src/lib/batch_operations.js index ded5bba4..8c7461fb 100644 --- a/src/lib/batch_operations.js +++ b/src/lib/batch_operations.js @@ -15,16 +15,19 @@ module.exports = { * @param {requestCallback} callback Callback called on completion * @return {Promise} Promise object */ - return this.makeSignedRequest({ - url: 'feed/add_to_many/', - body: { - activity: activity, - feeds: feeds, + return this.makeSignedRequest( + { + url: 'feed/add_to_many/', + body: { + activity: activity, + feeds: feeds, + }, }, - }, callback); + callback + ); }, - followMany: function(follows, callbackOrActivityCopyLimit, callback) { + followMany: function(follows, callbackOrActivityCopyLimit, callback) { /** * Follow multiple feeds with one API call * @method followMany @@ -35,13 +38,17 @@ module.exports = { * @param {requestCallback} [callback] Callback called on completion * @return {Promise} Promise object */ - var activityCopyLimit, qs = {}; + var activityCopyLimit, + qs = {}; if (typeof callbackOrActivityCopyLimit === 'number') { activityCopyLimit = callbackOrActivityCopyLimit; } - if (callbackOrActivityCopyLimit && typeof callbackOrActivityCopyLimit === 'function') { + if ( + callbackOrActivityCopyLimit && + typeof callbackOrActivityCopyLimit === 'function' + ) { callback = callbackOrActivityCopyLimit; } @@ -49,14 +56,17 @@ module.exports = { qs['activity_copy_limit'] = activityCopyLimit; } - return this.makeSignedRequest({ - url: 'follow_many/', - body: follows, - qs: qs, - }, callback); + return this.makeSignedRequest( + { + url: 'follow_many/', + body: follows, + qs: qs, + }, + callback + ); }, - unfollowMany: function (unfollows, callback) { + unfollowMany: function(unfollows, callback) { /** * Unfollow multiple feeds with one API call * @method unfollowMany @@ -66,10 +76,13 @@ module.exports = { * @param {requestCallback} [callback] Callback called on completion * @return {Promise} Promise object */ - return this.makeSignedRequest({ - url: 'unfollow_many/', - body: unfollows, - }, callback); + return this.makeSignedRequest( + { + url: 'unfollow_many/', + body: unfollows, + }, + callback + ); }, makeSignedRequest: function(kwargs, cb) { @@ -84,28 +97,32 @@ module.exports = { * @return {Promise} Promise object */ if (!this.apiSecret) { - throw new errors.SiteError('Missing secret, which is needed to perform signed requests, use var client = stream.connect(key, secret);'); + throw new errors.SiteError( + 'Missing secret, which is needed to perform signed requests, use var client = stream.connect(key, secret);' + ); } - return new Promise(function(fulfill, reject) { - this.send('request', 'post', kwargs, cb); + return new Promise( + function(fulfill, reject) { + this.send('request', 'post', kwargs, cb); - kwargs.url = this.enrichUrl(kwargs.url); - kwargs.json = true; - kwargs.method = 'POST'; - kwargs.headers = { 'X-Api-Key': this.apiKey }; - // Make sure withCredentials is not enabled, different browser - // fallbacks handle it differently by default (meteor) - kwargs.withCredentials = false; + kwargs.url = this.enrichUrl(kwargs.url); + kwargs.json = true; + kwargs.method = 'POST'; + kwargs.headers = { 'X-Api-Key': this.apiKey }; + // Make sure withCredentials is not enabled, different browser + // fallbacks handle it differently by default (meteor) + kwargs.withCredentials = false; - var callback = this.wrapPromiseTask(cb, fulfill, reject); - var req = request(kwargs, callback); + var callback = this.wrapPromiseTask(cb, fulfill, reject); + var req = request(kwargs, callback); - httpSignature.sign(req, { - algorithm: 'hmac-sha256', - key: this.apiSecret, - keyId: this.apiKey, - }); - }.bind(this)); + httpSignature.sign(req, { + algorithm: 'hmac-sha256', + key: this.apiSecret, + keyId: this.apiKey, + }); + }.bind(this) + ); }, }; diff --git a/src/lib/client.js b/src/lib/client.js index c316ec28..d9b9d016 100644 --- a/src/lib/client.js +++ b/src/lib/client.js @@ -58,27 +58,35 @@ StreamClient.prototype = { this.group = this.options.group || 'unspecified'; // track subscriptions made on feeds created by this client this.subscriptions = {}; - this.expireTokens = this.options.expireTokens ? this.options.expireTokens : false; + this.expireTokens = this.options.expireTokens + ? this.options.expireTokens + : false; // which data center to use this.location = this.options.location; this.baseUrl = this.getBaseUrl(); - if (typeof (process) !== 'undefined' && process.env.LOCAL_FAYE) { + if (typeof process !== 'undefined' && process.env.LOCAL_FAYE) { this.fayeUrl = 'http://localhost:9999/faye/'; } - if (typeof (process) !== 'undefined' && process.env.STREAM_ANALYTICS_BASE_URL) { + if ( + typeof process !== 'undefined' && + process.env.STREAM_ANALYTICS_BASE_URL + ) { this.baseAnalyticsUrl = process.env.STREAM_ANALYTICS_BASE_URL; } this.handlers = {}; - this.browser = typeof(this.options.browser) !== undefined ? this.options.browser : typeof (window) !== 'undefined'; + this.browser = + typeof this.options.browser !== undefined + ? this.options.browser + : typeof window !== 'undefined'; this.node = !this.browser; if (!this.browser) { var keepAlive = this.options.keepAlive; if (keepAlive === undefined) { - keepAlive = true + keepAlive = true; } var http = require('http'); @@ -94,7 +102,9 @@ StreamClient.prototype = { keepAliveMsecs: 3000, }); - this.requestAgent = this.baseUrl.startsWith('https://') ? httpsAgent : httpAgent; + this.requestAgent = this.baseUrl.startsWith('https://') + ? httpsAgent + : httpAgent; } this.personalization = new Personalization(this); @@ -102,7 +112,9 @@ StreamClient.prototype = { /* istanbul ignore next */ if (this.browser && this.apiSecret) { - throw new errors.FeedError('You are publicly sharing your App Secret. Do not expose the App Secret in browsers, "native" mobile apps, or other non-trusted environments.'); + throw new errors.FeedError( + 'You are publicly sharing your App Secret. Do not expose the App Secret in browsers, "native" mobile apps, or other non-trusted environments.' + ); } }, @@ -112,10 +124,16 @@ StreamClient.prototype = { } if (this.apiSecret) { - this._personalizationToken = signing.JWTScopeToken( - this.apiSecret, 'personalization', '*', {userId: '*', feedId: '*', expireTokens: this.expireTokens }); + this._personalizationToken = signing.JWTScopeToken( + this.apiSecret, + 'personalization', + '*', + { userId: '*', feedId: '*', expireTokens: this.expireTokens } + ); } else { - throw new errors.SiteError('Missing secret, which is needed to perform signed requests, use var client = stream.connect(key, secret);'); + throw new errors.SiteError( + 'Missing secret, which is needed to perform signed requests, use var client = stream.connect(key, secret);' + ); } return this._personalizationToken; @@ -127,39 +145,61 @@ StreamClient.prototype = { } if (this.apiSecret) { - this._collectionsToken = signing.JWTScopeToken( - this.apiSecret, 'collections', '*', {userId: '*', feedId: '*', expireTokens: this.expireTokens }); + this._collectionsToken = signing.JWTScopeToken( + this.apiSecret, + 'collections', + '*', + { userId: '*', feedId: '*', expireTokens: this.expireTokens } + ); } else { - throw new errors.SiteError('Missing secret, which is needed to perform signed requests, use var client = stream.connect(key, secret);'); + throw new errors.SiteError( + 'Missing secret, which is needed to perform signed requests, use var client = stream.connect(key, secret);' + ); } return this._collectionsToken; }, - getAnalyticsToken: function() { - if (this.apiSecret) { - return signing.JWTScopeToken( - this.apiSecret, 'analytics', '*', {userId: '*', expireTokens: this.expireTokens }); - } else { - throw new errors.SiteError('Missing secret, which is needed to perform signed requests, use var client = stream.connect(key, secret);'); - } - }, + getAnalyticsToken: function() { + if (this.apiSecret) { + return signing.JWTScopeToken(this.apiSecret, 'analytics', '*', { + userId: '*', + expireTokens: this.expireTokens, + }); + } else { + throw new errors.SiteError( + 'Missing secret, which is needed to perform signed requests, use var client = stream.connect(key, secret);' + ); + } + }, - getBaseUrl: function(serviceName) { + getBaseUrl: function(serviceName) { if (!serviceName) { serviceName = 'api'; } var url = this.baseUrl; if (serviceName != 'api') { - url = 'https://' + serviceName + '.stream-io-api.com/' + serviceName + '/'; + url = + 'https://' + serviceName + '.stream-io-api.com/' + serviceName + '/'; } if (this.location) { - var protocol = this.options.protocol || 'https'; - url = protocol + '://' + this.location + '-' + serviceName + '.stream-io-api.com/' + serviceName + '/'; - } - - if ((typeof (process) !== 'undefined' && process.env.LOCAL) || this.options.local) { + var protocol = this.options.protocol || 'https'; + url = + protocol + + '://' + + this.location + + '-' + + serviceName + + '.stream-io-api.com/' + + serviceName + + '/'; + } + + if ( + (typeof process !== 'undefined' && process.env.LOCAL) || + this.options.local + ) { url = 'http://localhost:8000/' + serviceName + '/'; } @@ -169,7 +209,7 @@ StreamClient.prototype = { } else { urlEnvironmentKey = 'STREAM_' + serviceName.toUpperCase() + '_URL'; } - if (typeof (process) !== 'undefined' && process.env[urlEnvironmentKey]) { + if (typeof process !== 'undefined' && process.env[urlEnvironmentKey]) { url = process.env[urlEnvironmentKey]; } if (this.options.urlOverride && this.options.urlOverride[serviceName]) { @@ -244,7 +284,15 @@ StreamClient.prototype = { if (error) { reject(new errors.StreamApiError(error, body, response)); } else if (!/^2/.test('' + response.statusCode)) { - reject(new errors.StreamApiError(JSON.stringify(body) + ' with HTTP status code ' + response.statusCode, body, response)); + reject( + new errors.StreamApiError( + JSON.stringify(body) + + ' with HTTP status code ' + + response.statusCode, + body, + response + ) + ); } else { fulfill(body); } @@ -282,7 +330,7 @@ StreamClient.prototype = { * @memberof StreamClient.prototype * @return {string} current user agent */ - var description = (this.node) ? 'node' : 'browser'; + var description = this.node ? 'node' : 'browser'; // TODO: get the version here in a way which works in both and browserify var version = 'unknown'; return 'stream-javascript-client-' + description + '-' + version; @@ -336,10 +384,12 @@ StreamClient.prototype = { // create the token in server side mode if (this.apiSecret && !token) { - options = options || {} + options = options || {}; var feedId = '' + feedSlug + userId; // use scoped token if read-only access is necessary - token = options.readOnly ? this.getReadOnlyToken(feedSlug, userId) : signing.sign(this.apiSecret, feedId); + token = options.readOnly + ? this.getReadOnlyToken(feedSlug, userId) + : signing.sign(this.apiSecret, feedId); } var feed = new StreamFeed(this, feedSlug, userId, token, siteId); @@ -456,7 +506,7 @@ StreamClient.prototype = { * @return {object} Faye authorization middleware */ var apiKey = this.apiKey, - self = this; + self = this; return { incoming: function(message, callback) { @@ -468,11 +518,10 @@ StreamClient.prototype = { var subscription = self.subscriptions[message.subscription]; message.ext = { - 'user_id': subscription.userId, - 'api_key': apiKey, - 'signature': subscription.token, + user_id: subscription.userId, + api_key: apiKey, + signature: subscription.token, }; - } callback(message); @@ -489,7 +538,7 @@ StreamClient.prototype = { * @return {object} Faye client */ if (this.fayeClient === null) { - this.fayeClient = new Faye.Client(this.fayeUrl, {timeout: 10}); + this.fayeClient = new Faye.Client(this.fayeUrl, { timeout: 10 }); var authExtension = this.getFayeAuthorization(); this.fayeClient.addExtension(authExtension); } @@ -507,14 +556,16 @@ StreamClient.prototype = { * @param {requestCallback} cb Callback to call on completion * @return {Promise} Promise object */ - return new Promise(function(fulfill, reject) { - this.send('request', 'get', kwargs, cb); - kwargs = this.enrichKwargs(kwargs); - kwargs.method = 'GET'; - kwargs.gzip = true; - var callback = this.wrapPromiseTask(cb, fulfill, reject); - this.request(kwargs, callback); - }.bind(this)); + return new Promise( + function(fulfill, reject) { + this.send('request', 'get', kwargs, cb); + kwargs = this.enrichKwargs(kwargs); + kwargs.method = 'GET'; + kwargs.gzip = true; + var callback = this.wrapPromiseTask(cb, fulfill, reject); + this.request(kwargs, callback); + }.bind(this) + ); }, post: function(kwargs, cb) { @@ -527,17 +578,19 @@ StreamClient.prototype = { * @param {requestCallback} cb Callback to call on completion * @return {Promise} Promise object */ - return new Promise(function(fulfill, reject) { - this.send('request', 'post', kwargs, cb); - kwargs = this.enrichKwargs(kwargs); - kwargs.method = 'POST'; - kwargs.gzip = true; - var callback = this.wrapPromiseTask(cb, fulfill, reject); - this.request(kwargs, callback); - }.bind(this)); + return new Promise( + function(fulfill, reject) { + this.send('request', 'post', kwargs, cb); + kwargs = this.enrichKwargs(kwargs); + kwargs.method = 'POST'; + kwargs.gzip = true; + var callback = this.wrapPromiseTask(cb, fulfill, reject); + this.request(kwargs, callback); + }.bind(this) + ); }, - 'delete': function(kwargs, cb) { + delete: function(kwargs, cb) { /** * Shorthand function for delete request * @method delete @@ -547,14 +600,16 @@ StreamClient.prototype = { * @param {requestCallback} cb Callback to call on completion * @return {Promise} Promise object */ - return new Promise(function(fulfill, reject) { - this.send('request', 'delete', kwargs, cb); - kwargs = this.enrichKwargs(kwargs); - kwargs.gzip = true; - kwargs.method = 'DELETE'; - var callback = this.wrapPromiseTask(cb, fulfill, reject); - this.request(kwargs, callback); - }.bind(this)); + return new Promise( + function(fulfill, reject) { + this.send('request', 'delete', kwargs, cb); + kwargs = this.enrichKwargs(kwargs); + kwargs.gzip = true; + kwargs.method = 'DELETE'; + var callback = this.wrapPromiseTask(cb, fulfill, reject); + this.request(kwargs, callback); + }.bind(this) + ); }, put: function(kwargs, cb) { @@ -567,23 +622,30 @@ StreamClient.prototype = { * @param {requestCallback} cb Callback to call on completion * @return {Promise} Promise object */ - return new Promise(function(fulfill, reject) { - this.send('request', 'put', kwargs, cb); - kwargs = this.enrichKwargs(kwargs); - kwargs.method = 'PUT'; - kwargs.gzip = true; - var callback = this.wrapPromiseTask(cb, fulfill, reject); - this.request(kwargs, callback); - }.bind(this)); + return new Promise( + function(fulfill, reject) { + this.send('request', 'put', kwargs, cb); + kwargs = this.enrichKwargs(kwargs); + kwargs.method = 'PUT'; + kwargs.gzip = true; + var callback = this.wrapPromiseTask(cb, fulfill, reject); + this.request(kwargs, callback); + }.bind(this) + ); }, createUserSession: function(userToken) { var cloud = require('./cloud'); - var cClient = new cloud.StreamCloudClient(this.apiKey, null, this.appId, this.options); + var cClient = new cloud.StreamCloudClient( + this.apiKey, + null, + this.appId, + this.options + ); return cClient.createUserSession(userToken); }, - createUserSessionToken: function(userId, extraData={}){ + createUserSessionToken: function(userId, extraData = {}) { return signing.JWTUserSessionToken(this.apiSecret, userId, extraData); }, @@ -594,21 +656,27 @@ StreamClient.prototype = { * @param {array} activities list of activities to update * @return {Promise} */ - if (! (activities instanceof Array)) { + if (!(activities instanceof Array)) { throw new TypeError('The activities argument should be an Array'); } - var authToken = signing.JWTScopeToken(this.apiSecret, 'activities', '*', { feedId: '*', expireTokens: this.expireTokens }); + var authToken = signing.JWTScopeToken(this.apiSecret, 'activities', '*', { + feedId: '*', + expireTokens: this.expireTokens, + }); var data = { activities: activities, }; - return this.post({ - url: 'activities/', - body: data, - signature: authToken, - }, callback); + return this.post( + { + url: 'activities/', + body: data, + signature: authToken, + }, + callback + ); }, updateActivity: function(activity, callback) { @@ -618,10 +686,10 @@ StreamClient.prototype = { * @param {object} activity The activity to update * @return {Promise} */ - return this.updateActivities([activity], callback); + return this.updateActivities([activity], callback); }, - getActivities: function (params, callback) { + getActivities: function(params, callback) { /** * Retrieve activities by ID or foreign ID and time * @since 3.19.0 @@ -630,13 +698,13 @@ StreamClient.prototype = { */ var qs = {}; if (params.ids) { - var ids = params.ids + var ids = params.ids; if (!(ids instanceof Array)) { throw new TypeError('The ids argument should be an Array'); } qs['ids'] = ids.join(','); } else if (params.foreignIDTimes) { - var list = params.foreignIDTimes + var list = params.foreignIDTimes; if (!(list instanceof Array)) { throw new TypeError('The foreignIDTimes argument should be an Array'); } @@ -654,15 +722,21 @@ StreamClient.prototype = { } else { throw new TypeError('Missing ids or foreignIDTimes params'); } - var authToken = signing.JWTScopeToken(this.apiSecret, 'activities', '*', { feedId: '*', expireTokens: this.expireTokens }); - return this.get({ - url: 'activities/', - qs: qs, - signature: authToken, - }, callback); + var authToken = signing.JWTScopeToken(this.apiSecret, 'activities', '*', { + feedId: '*', + expireTokens: this.expireTokens, + }); + return this.get( + { + url: 'activities/', + qs: qs, + signature: authToken, + }, + callback + ); }, - activityPartialUpdate: function (data, callback) { + activityPartialUpdate: function(data, callback) { /** * Update a single activity with partial operations. * @since 3.20.0 @@ -699,27 +773,39 @@ StreamClient.prototype = { data['foreign_id'] = data.foreignID; delete data.foreignID; } - if ((data.id === undefined) && (data.foreign_id === undefined || data.time === undefined)) { - throw new TypeError('Missing id or foreign ID and time') + if ( + data.id === undefined && + (data.foreign_id === undefined || data.time === undefined) + ) { + throw new TypeError('Missing id or foreign ID and time'); } if (data.set && !(data.set instanceof Object)) { - throw new TypeError('set field should be an Object') + throw new TypeError('set field should be an Object'); } if (data.unset && !(data.unset instanceof Array)) { - throw new TypeError('unset field should be an Array') - } - var authToken = signing.JWTScopeToken(this.apiSecret, 'activities', '*', { feedId: '*', expireTokens: this.expireTokens }); - return this.post({ - url: 'activity/', - body: data, - signature: authToken, - }, callback); + throw new TypeError('unset field should be an Array'); + } + var authToken = signing.JWTScopeToken(this.apiSecret, 'activities', '*', { + feedId: '*', + expireTokens: this.expireTokens, + }); + return this.post( + { + url: 'activity/', + body: data, + signature: authToken, + }, + callback + ); }, - }; if (qs) { - StreamClient.prototype.createRedirectUrl = function(targetUrl, userId, events) { + StreamClient.prototype.createRedirectUrl = function( + targetUrl, + userId, + events + ) { /** * Creates a redirect url for tracking the given events in the context of * an email using Stream's analytics platform. Learn more at @@ -734,17 +820,24 @@ if (qs) { var uri = url.parse(targetUrl); if (!(uri.host || (uri.hostname && uri.port)) && !uri.isUnix) { - throw new errors.MissingSchemaError('Invalid URI: "' + url.format(uri) + '"'); + throw new errors.MissingSchemaError( + 'Invalid URI: "' + url.format(uri) + '"' + ); } - var authToken = signing.JWTScopeToken(this.apiSecret, 'redirect_and_track', '*', { userId: "*", expireTokens: this.expireTokens }); + var authToken = signing.JWTScopeToken( + this.apiSecret, + 'redirect_and_track', + '*', + { userId: '*', expireTokens: this.expireTokens } + ); var analyticsUrl = this.baseAnalyticsUrl + 'redirect/'; var kwargs = { - 'auth_type': 'jwt', - 'authorization': authToken, - 'url': targetUrl, - 'api_key': this.apiKey, - 'events': JSON.stringify(events), + auth_type: 'jwt', + authorization: authToken, + url: targetUrl, + api_key: this.apiKey, + events: JSON.stringify(events), }; var qString = utils.rfc3986(qs.stringify(kwargs, null, null, {})); diff --git a/src/lib/cloud.js b/src/lib/cloud.js index ed7b1336..258e8f76 100644 --- a/src/lib/cloud.js +++ b/src/lib/cloud.js @@ -18,7 +18,7 @@ function StreamCloudClient() { if (options.location) { location = options.location + '-cloud'; } - options = {...options, location}; + options = { ...options, location }; StreamClient.apply(this, [arguments[0], arguments[1], arguments[2], options]); } @@ -50,10 +50,9 @@ StreamCloudClient.prototype.permissions = function(token) { return new StreamPermissions(this, token); }; - StreamCloudClient.prototype.createUserSession = function( userId, - userAuthToken, + userAuthToken ) { return new StreamUserSession(this, userId, userAuthToken); }; @@ -96,14 +95,14 @@ StreamCloudFeed.prototype.get = function(options, callback) { qs: options, signature: this.signature, }, - callback, + callback ); }; function replaceStreamObjects(obj) { let cloned = obj; if (Array.isArray(obj)) { - cloned = obj.map(v => replaceStreamObjects(v)); + cloned = obj.map((v) => replaceStreamObjects(v)); } else if (isPlainObject(obj)) { cloned = {}; for (let k in obj) { @@ -129,11 +128,10 @@ StreamCloudFeed.prototype.addActivities = function(activities, callback) { return this._addActivitiesOriginal(activities, callback); }; - StreamCloudFeed.prototype.getActivityDetail = function( activity_id, options, - callback, + callback ) { /** * Retrieves one activity from a feed and adds enrichment @@ -152,9 +150,9 @@ StreamCloudFeed.prototype.getActivityDetail = function( return this.get( Object.assign( { id_lte: activity_id, id_gte: activity_id, limit: 1 }, - options, + options ), - callback, + callback ); }; diff --git a/src/lib/collections.js b/src/lib/collections.js index 82438fdb..3a41ecfa 100644 --- a/src/lib/collections.js +++ b/src/lib/collections.js @@ -9,39 +9,38 @@ var Collections = function() { this.initialize.apply(this, arguments); }; - Collections.prototype = { initialize: function(client) { this.client = client; }, createReference: function(collectionName, id) { - return "SO:" + collectionName + ":" + id; + return 'SO:' + collectionName + ':' + id; }, createUserReference: function(id) { - return this.createReference("user", id); + return this.createReference('user', id); }, upsert: function(collectionName, data, callback) { - /** - * Upsert one or more items within a collection. - * - * @method upsert - * @memberof Collections.prototype - * @param {object} collectionName - The name of the collection - * @param {object or array} data - A single json object or an array of objects - * @param {requestCallback} callback - Callback to call on completion - * @return {Promise} Promise object. - */ + /** + * Upsert one or more items within a collection. + * + * @method upsert + * @memberof Collections.prototype + * @param {object} collectionName - The name of the collection + * @param {object or array} data - A single json object or an array of objects + * @param {requestCallback} callback - Callback to call on completion + * @return {Promise} Promise object. + */ var last = arguments[arguments.length - 1]; // callback is always the last argument - callback = (last.call) ? last : undefined; + callback = last.call ? last : undefined; if (!Array.isArray(data)) { data = [data]; } - var data_json = {data: {}}; + var data_json = { data: {} }; data_json['data'][collectionName] = data; return this.client.post( @@ -49,31 +48,36 @@ Collections.prototype = { url: 'meta/', serviceName: 'api', body: data_json, - signature: this.client.getCollectionsToken() + signature: this.client.getCollectionsToken(), }, - callback); + callback + ); }, select: function(collectionName, ids, callback) { - /** - * Select all objects with ids from the collection. - * - * @method select - * @memberof Collections.prototype - * @param {object} collectionName - The name of the collection - * @param {object or array} ids - A single json object or an array of objects - * @param {requestCallback} callback - Callback to call on completion - * @return {Promise} Promise object. - */ + /** + * Select all objects with ids from the collection. + * + * @method select + * @memberof Collections.prototype + * @param {object} collectionName - The name of the collection + * @param {object or array} ids - A single json object or an array of objects + * @param {requestCallback} callback - Callback to call on completion + * @return {Promise} Promise object. + */ var last = arguments[arguments.length - 1]; // callback is always the last argument - callback = (last.call) ? last : undefined; + callback = last.call ? last : undefined; if (!Array.isArray(ids)) { ids = [ids]; } var params = { - foreign_ids: ids.map(function(id) { return collectionName + ":" + id;}).join(',') + foreign_ids: ids + .map(function(id) { + return collectionName + ':' + id; + }) + .join(','), }; return this.client.get( @@ -81,34 +85,39 @@ Collections.prototype = { url: 'meta/', serviceName: 'api', qs: params, - signature: this.client.getCollectionsToken() + signature: this.client.getCollectionsToken(), }, - callback); + callback + ); }, delete: function(collectionName, ids, callback) { - /** - * Remove all objects by id from the collection. - * - * @method delete - * @memberof Collections.prototype - * @param {object} collectionName - The name of the collection - * @param {object or array} ids - A single json object or an array of objects - * @param {requestCallback} callback - Callback to call on completion - * @return {Promise} Promise object. - */ + /** + * Remove all objects by id from the collection. + * + * @method delete + * @memberof Collections.prototype + * @param {object} collectionName - The name of the collection + * @param {object or array} ids - A single json object or an array of objects + * @param {requestCallback} callback - Callback to call on completion + * @return {Promise} Promise object. + */ var last = arguments[arguments.length - 1]; // callback is always the last argument - callback = (last.call) ? last : undefined; + callback = last.call ? last : undefined; if (!Array.isArray(ids)) { ids = [ids]; } - ids = ids.map(function(id) { return id.toString();}).join(','); + ids = ids + .map(function(id) { + return id.toString(); + }) + .join(','); var params = { collection_name: collectionName, - ids: ids + ids: ids, }; return this.client.delete( @@ -116,9 +125,10 @@ Collections.prototype = { url: 'meta/', serviceName: 'api', qs: params, - signature: this.client.getCollectionsToken() + signature: this.client.getCollectionsToken(), }, - callback); + callback + ); }, }; diff --git a/src/lib/errors.js b/src/lib/errors.js index af656bc5..bace9e86 100644 --- a/src/lib/errors.js +++ b/src/lib/errors.js @@ -1,7 +1,7 @@ var errors = module.exports; -var canCapture = (typeof Error.captureStackTrace === 'function'); -var canStack = !!(new Error()).stack; +var canCapture = typeof Error.captureStackTrace === 'function'; +var canStack = !!new Error().stack; /** * Abstract error object @@ -19,7 +19,7 @@ function ErrorAbstract(msg, constructor) { if (canCapture) { Error.captureStackTrace(this, constructor); } else if (canStack) { - this.stack = (new Error()).stack; + this.stack = new Error().stack; } else { this.stack = ''; } diff --git a/src/lib/feed.js b/src/lib/feed.js index 250a0422..adc6a118 100644 --- a/src/lib/feed.js +++ b/src/lib/feed.js @@ -24,11 +24,15 @@ StreamFeed.prototype = { */ if (!feedSlug || !userId) { - throw new errors.FeedError('Please provide a feed slug and user id, ie client.feed("user", "1")'); + throw new errors.FeedError( + 'Please provide a feed slug and user id, ie client.feed("user", "1")' + ); } if (feedSlug.indexOf(':') !== -1) { - throw new errors.FeedError('Please initialize the feed using client.feed("user", "1") not client.feed("user:1")'); + throw new errors.FeedError( + 'Please initialize the feed using client.feed("user", "1") not client.feed("user:1")' + ); } utils.validateFeedSlug(feedSlug); @@ -36,7 +40,9 @@ StreamFeed.prototype = { // raise an error if there is no token if (!this.apiSecret && !token) { - throw new errors.FeedError('Missing token, in client side mode please provide a feed secret'); + throw new errors.FeedError( + 'Missing token, in client side mode please provide a feed secret' + ); } this.client = client; @@ -50,7 +56,8 @@ StreamFeed.prototype = { this.signature = this.feedTogether + ' ' + this.token; // faye setup - this.notificationChannel = 'site-' + this.client.appId + '-feed-' + this.feedTogether; + this.notificationChannel = + 'site-' + this.client.appId + '-feed-' + this.feedTogether; }, addActivity: function(activity, callback) { @@ -65,11 +72,14 @@ StreamFeed.prototype = { */ activity = this.client.signActivity(activity); - return this.client.post({ - url: 'feed/' + this.feedUrl + '/', - body: activity, - signature: this.signature, - }, callback); + return this.client.post( + { + url: 'feed/' + this.feedUrl + '/', + body: activity, + signature: this.signature, + }, + callback + ); }, removeActivity: function(activityId, callback) { @@ -85,17 +95,20 @@ StreamFeed.prototype = { * @example * feed.removeActivity({'foreignId': foreignId}); */ - var identifier = (activityId.foreignId) ? activityId.foreignId : activityId; + var identifier = activityId.foreignId ? activityId.foreignId : activityId; var params = {}; if (activityId.foreignId) { params['foreign_id'] = '1'; } - return this.client['delete']({ - url: 'feed/' + this.feedUrl + '/' + identifier + '/', - qs: params, - signature: this.signature, - }, callback); + return this.client['delete']( + { + url: 'feed/' + this.feedUrl + '/' + identifier + '/', + qs: params, + signature: this.signature, + }, + callback + ); }, addActivities: function(activities, callback) { @@ -111,11 +124,14 @@ StreamFeed.prototype = { var data = { activities: activities, }; - var xhr = this.client.post({ - url: 'feed/' + this.feedUrl + '/', - body: data, - signature: this.signature, - }, callback); + var xhr = this.client.post( + { + url: 'feed/' + this.feedUrl + '/', + body: data, + signature: this.signature, + }, + callback + ); return xhr; }, @@ -140,12 +156,12 @@ StreamFeed.prototype = { var activityCopyLimit; var last = arguments[arguments.length - 1]; // callback is always the last argument - callback = (last.call) ? last : undefined; + callback = last.call ? last : undefined; var target = targetSlug + ':' + targetUserId; // check for additional options if (options && !options.call) { - if (typeof options.limit !== "undefined" && options.limit !== null) { + if (typeof options.limit !== 'undefined' && options.limit !== null) { activityCopyLimit = options.limit; } } @@ -154,15 +170,21 @@ StreamFeed.prototype = { target: target, }; - if (typeof activityCopyLimit !== "undefined" && activityCopyLimit !== null) { + if ( + typeof activityCopyLimit !== 'undefined' && + activityCopyLimit !== null + ) { body['activity_copy_limit'] = activityCopyLimit; } - return this.client.post({ - url: 'feed/' + this.feedUrl + '/following/', - body: body, - signature: this.signature, - }, callback); + return this.client.post( + { + url: 'feed/' + this.feedUrl + '/following/', + body: body, + signature: this.signature, + }, + callback + ); }, unfollow: function(targetSlug, targetUserId, optionsOrCallback, callback) { @@ -179,19 +201,24 @@ StreamFeed.prototype = { * @return {object} XHR request object * @example feed.unfollow('user', '2', callback); */ - var options = {}, qs = {}; + var options = {}, + qs = {}; if (typeof optionsOrCallback === 'function') callback = optionsOrCallback; if (typeof optionsOrCallback === 'object') options = optionsOrCallback; - if (typeof options.keepHistory === 'boolean' && options.keepHistory) qs['keep_history'] = '1'; + if (typeof options.keepHistory === 'boolean' && options.keepHistory) + qs['keep_history'] = '1'; utils.validateFeedSlug(targetSlug); utils.validateUserId(targetUserId); var targetFeedId = targetSlug + ':' + targetUserId; - var xhr = this.client['delete']({ - url: 'feed/' + this.feedUrl + '/following/' + targetFeedId + '/', - qs: qs, - signature: this.signature, - }, callback); + var xhr = this.client['delete']( + { + url: 'feed/' + this.feedUrl + '/following/' + targetFeedId + '/', + qs: qs, + signature: this.signature, + }, + callback + ); return xhr; }, @@ -210,11 +237,14 @@ StreamFeed.prototype = { options.filter = options.filter.join(','); } - return this.client.get({ - url: 'feed/' + this.feedUrl + '/following/', - qs: options, - signature: this.signature, - }, callback); + return this.client.get( + { + url: 'feed/' + this.feedUrl + '/following/', + qs: options, + signature: this.signature, + }, + callback + ); }, followers: function(options, callback) { @@ -233,11 +263,14 @@ StreamFeed.prototype = { options.filter = options.filter.join(','); } - return this.client.get({ - url: 'feed/' + this.feedUrl + '/followers/', - qs: options, - signature: this.signature, - }, callback); + return this.client.get( + { + url: 'feed/' + this.feedUrl + '/followers/', + qs: options, + signature: this.signature, + }, + callback + ); }, get: function(options, callback) { @@ -259,11 +292,14 @@ StreamFeed.prototype = { options['mark_seen'] = options['mark_seen'].join(','); } - return this.client.get({ - url: 'feed/' + this.feedUrl + '/', - qs: options, - signature: this.signature, - }, callback); + return this.client.get( + { + url: 'feed/' + this.feedUrl + '/', + qs: options, + signature: this.signature, + }, + callback + ); }, getFayeClient: function() { @@ -290,14 +326,19 @@ StreamFeed.prototype = { * }); */ if (!this.client.appId) { - throw new errors.SiteError('Missing app id, which is needed to subscribe, use var client = stream.connect(key, secret, appId);'); + throw new errors.SiteError( + 'Missing app id, which is needed to subscribe, use var client = stream.connect(key, secret, appId);' + ); } - var subscription = this.getFayeClient().subscribe('/' + this.notificationChannel, callback); + var subscription = this.getFayeClient().subscribe( + '/' + this.notificationChannel, + callback + ); this.client.subscriptions['/' + this.notificationChannel] = { token: this.token, userId: this.notificationChannel, - fayeSubscription: subscription + fayeSubscription: subscription, }; return subscription; @@ -308,7 +349,9 @@ StreamFeed.prototype = { * Cancel updates created via feed.subscribe() * @return void */ - var streamSubscription = this.client.subscriptions['/' + this.notificationChannel]; + var streamSubscription = this.client.subscriptions[ + '/' + this.notificationChannel + ]; if (streamSubscription) { delete this.client.subscriptions['/' + this.notificationChannel]; streamSubscription.fayeSubscription.cancel(); @@ -328,7 +371,10 @@ StreamFeed.prototype = { * client.getReadOnlyToken('user', '1'); */ var feedId = '' + this.slug + this.userId; - return signing.JWTScopeToken(this.client.apiSecret, '*', 'read', { feedId: feedId, expireTokens: this.client.expireTokens }); + return signing.JWTScopeToken(this.client.apiSecret, '*', 'read', { + feedId: feedId, + expireTokens: this.client.expireTokens, + }); }, getReadWriteToken: function() { @@ -344,69 +390,83 @@ StreamFeed.prototype = { * client.getReadWriteToken('user', '1'); */ var feedId = '' + this.slug + this.userId; - return signing.JWTScopeToken(this.client.apiSecret, '*', '*', { feedId: feedId, expireTokens: this.client.expireTokens }); + return signing.JWTScopeToken(this.client.apiSecret, '*', '*', { + feedId: feedId, + expireTokens: this.client.expireTokens, + }); }, - updateActivityToTargets: function (foreign_id, time, new_targets, added_targets, removed_targets) { - /** - * Updates an activity's "to" fields - * @since 3.10.0 - * @param {string} foreign_id The foreign_id of the activity to update - * @param {string} time The time of the activity to update - * @param {array} new_targets Set the new "to" targets for the activity - will remove old targets - * @param {array} added_targets Add these new targets to the activity - * @param {array} removed_targets Remove these targets from the activity - */ - - - if (!foreign_id) { - throw new Error('Missing `foreign_id` parameter!'); - } else if (!time) { - throw new Error('Missing `time` parameter!'); - } + updateActivityToTargets: function( + foreign_id, + time, + new_targets, + added_targets, + removed_targets + ) { + /** + * Updates an activity's "to" fields + * @since 3.10.0 + * @param {string} foreign_id The foreign_id of the activity to update + * @param {string} time The time of the activity to update + * @param {array} new_targets Set the new "to" targets for the activity - will remove old targets + * @param {array} added_targets Add these new targets to the activity + * @param {array} removed_targets Remove these targets from the activity + */ - if (!new_targets && !added_targets && !removed_targets) { - throw new Error('Requires you to provide at least one parameter for `new_targets`, `added_targets`, or `removed_targets` - example: `updateActivityToTargets("foreignID:1234", new Date(), [new_targets...], [added_targets...], [removed_targets...])`'); - } + if (!foreign_id) { + throw new Error('Missing `foreign_id` parameter!'); + } else if (!time) { + throw new Error('Missing `time` parameter!'); + } - if (new_targets) { - if (added_targets || removed_targets) { - throw new Error("Can't include add_targets or removed_targets if you're also including new_targets"); - } + if (!new_targets && !added_targets && !removed_targets) { + throw new Error( + 'Requires you to provide at least one parameter for `new_targets`, `added_targets`, or `removed_targets` - example: `updateActivityToTargets("foreignID:1234", new Date(), [new_targets...], [added_targets...], [removed_targets...])`' + ); + } + + if (new_targets) { + if (added_targets || removed_targets) { + throw new Error( + "Can't include add_targets or removed_targets if you're also including new_targets" + ); } + } - if (added_targets && removed_targets) { - // brute force - iterate through added, check to see if removed contains that element - for (var i = 0; i < added_targets.length; i++) { - // would normally use Array.prototype.includes here, but it's not supported in Node.js v4 :( - for (var j = 0; j < removed_targets.length; j++) { - if (removed_targets[j] == added_targets[i]) { - throw new Error("Can't have the same feed ID in added_targets and removed_targets."); - } - } + if (added_targets && removed_targets) { + // brute force - iterate through added, check to see if removed contains that element + for (var i = 0; i < added_targets.length; i++) { + // would normally use Array.prototype.includes here, but it's not supported in Node.js v4 :( + for (var j = 0; j < removed_targets.length; j++) { + if (removed_targets[j] == added_targets[i]) { + throw new Error( + "Can't have the same feed ID in added_targets and removed_targets." + ); } + } } + } - var body = { - foreign_id: foreign_id, - time: time, - }; - if (new_targets) { - body['new_targets'] = new_targets; - } - if (added_targets) { - body['added_targets'] = added_targets; - } - if (removed_targets) { - body['removed_targets'] = removed_targets; - } + var body = { + foreign_id: foreign_id, + time: time, + }; + if (new_targets) { + body['new_targets'] = new_targets; + } + if (added_targets) { + body['added_targets'] = added_targets; + } + if (removed_targets) { + body['removed_targets'] = removed_targets; + } - return this.client.post({ - url: 'feed_targets/' + this.feedUrl + '/activity_to_targets/', - signature: this.signature, - body: body, - }); - } + return this.client.post({ + url: 'feed_targets/' + this.feedUrl + '/activity_to_targets/', + signature: this.signature, + body: body, + }); + }, }; module.exports = StreamFeed; diff --git a/src/lib/files.js b/src/lib/files.js index 6f944085..3f6a0678 100644 --- a/src/lib/files.js +++ b/src/lib/files.js @@ -3,12 +3,12 @@ var Headers = require('cross-fetch').Headers; var utils = require('./utils'); var FormData = require('form-data'); -var StreamFileStore = function () { +var StreamFileStore = function() { this.initialize.apply(this, arguments); }; StreamFileStore.prototype = { - initialize: function (client, token) { + initialize: function(client, token) { this.client = client; this.token = token; }, @@ -22,28 +22,30 @@ StreamFileStore.prototype = { fileField = { uri: uri, type: 'application/octet-stream', - name: name || uri.split('/').reverse()[0] + name: name || uri.split('/').reverse()[0], }; } data.append('file', fileField); return fetch( - `${this.client.enrichUrl('files/')}?api_key=${this.client.apiKey}`, { - method: 'post', - body: data, - headers: new Headers({ - 'Authorization': this.token, - }) - }).then(r => { return r.json() }); - }, - delete: function(uri) { - return this.client.delete( + `${this.client.enrichUrl('files/')}?api_key=${this.client.apiKey}`, { - url: `files/${uri}`, - signature: this.token, + method: 'post', + body: data, + headers: new Headers({ + Authorization: this.token, + }), } - ); + ).then((r) => { + return r.json(); + }); + }, + delete: function(uri) { + return this.client.delete({ + url: `files/${uri}`, + signature: this.token, + }); }, }; diff --git a/src/lib/images.js b/src/lib/images.js index 7188ce10..e6d47c1c 100644 --- a/src/lib/images.js +++ b/src/lib/images.js @@ -3,12 +3,12 @@ var Headers = require('cross-fetch').Headers; var FormData = require('form-data'); var utils = require('./utils'); -var StreamImageStore = function () { +var StreamImageStore = function() { this.initialize.apply(this, arguments); }; StreamImageStore.prototype = { - initialize: function (client, token) { + initialize: function(client, token) { this.client = client; this.token = token; }, @@ -22,26 +22,28 @@ StreamImageStore.prototype = { fileField = { uri: uri, type: 'application/octet-stream', - name: name || uri.split('/').reverse()[0] + name: name || uri.split('/').reverse()[0], }; } data.append('file', fileField); return fetch( - `${this.client.enrichUrl('images/')}?api_key=${this.client.apiKey}`, { - method: 'post', - body: data, - headers: new Headers({ - 'Authorization': this.token, - }) - }).then(r => { return r.json() }); - }, - delete: function(uri) { - return this.client.delete( + `${this.client.enrichUrl('images/')}?api_key=${this.client.apiKey}`, { - url: `images/${uri}`, - signature: this.token, + method: 'post', + body: data, + headers: new Headers({ + Authorization: this.token, + }), } - ); + ).then((r) => { + return r.json(); + }); + }, + delete: function(uri) { + return this.client.delete({ + url: `images/${uri}`, + signature: this.token, + }); }, process: function(uri, options) { let params = Object.assign(options); @@ -49,16 +51,19 @@ StreamImageStore.prototype = { params.crop = params.crop.join(','); } - return this.client.get( - { - url: `images/${uri}`, - qs: params, - signature: this.token, - } - ); + return this.client.get({ + url: `images/${uri}`, + qs: params, + signature: this.token, + }); }, - thumbmail: function(uri, w, h, {crop, resize} = {crop: 'center', resize: 'clip'}) { - return this.process(uri, {w, h, crop, resize}); + thumbmail: function( + uri, + w, + h, + { crop, resize } = { crop: 'center', resize: 'clip' } + ) { + return this.process(uri, { w, h, crop, resize }); }, }; diff --git a/src/lib/personalization.js b/src/lib/personalization.js index 3d784bff..3bec3de8 100644 --- a/src/lib/personalization.js +++ b/src/lib/personalization.js @@ -22,20 +22,20 @@ Personalization.prototype = { }, get: function(resource, options, callback) { - /** - * Get personalized activities for this feed - * - * @method get - * @memberof Personalization.prototype - * @param {object} resource - personalized resource endpoint i.e "follow_recommendations" - * @param {object} options Additional options - * @param {requestCallback} callback - Callback to call on completion - * @return {Promise} Promise object. Personalized feed - * @example client.personalization.get('follow_recommendations', {foo: 'bar', baz: 'qux'}, cb) - */ + /** + * Get personalized activities for this feed + * + * @method get + * @memberof Personalization.prototype + * @param {object} resource - personalized resource endpoint i.e "follow_recommendations" + * @param {object} options Additional options + * @param {requestCallback} callback - Callback to call on completion + * @return {Promise} Promise object. Personalized feed + * @example client.personalization.get('follow_recommendations', {foo: 'bar', baz: 'qux'}, cb) + */ var last = arguments[arguments.length - 1]; // callback is always the last argument - callback = (last.call) ? last : undefined; + callback = last.call ? last : undefined; if (!options || options.call) { options = {}; } @@ -45,27 +45,28 @@ Personalization.prototype = { url: resource + '/', serviceName: 'personalization', qs: options, - signature: this.client.getPersonalizationToken() + signature: this.client.getPersonalizationToken(), }, - callback); + callback + ); }, post: function(resource, options, data, callback) { - /** - * Post data to personalization endpoint - * - * @method post - * @memberof Personalization.prototype - * @param {object} resource - personalized resource endpoint i.e "follow_recommendations" - * @param {object} options - Additional options - * @param {object} data - Data to send in the payload - * @param {requestCallback} callback - Callback to call on completion - * @return {Promise} Promise object. Data that was posted if successful, or an error. - * @example client.personalization.post('follow_recommendations', {foo: 'bar', baz: 'qux'}, cb) - */ + /** + * Post data to personalization endpoint + * + * @method post + * @memberof Personalization.prototype + * @param {object} resource - personalized resource endpoint i.e "follow_recommendations" + * @param {object} options - Additional options + * @param {object} data - Data to send in the payload + * @param {requestCallback} callback - Callback to call on completion + * @return {Promise} Promise object. Data that was posted if successful, or an error. + * @example client.personalization.post('follow_recommendations', {foo: 'bar', baz: 'qux'}, cb) + */ var last = arguments[arguments.length - 1]; // callback is always the last argument - callback = (last.call) ? last : undefined; + callback = last.call ? last : undefined; if (!options || options.call) { options = {}; } @@ -79,26 +80,27 @@ Personalization.prototype = { serviceName: 'personalization', qs: options, body: data, - signature: this.client.getPersonalizationToken() + signature: this.client.getPersonalizationToken(), }, - callback); + callback + ); }, delete: function(resource, options, callback) { - /** - * Delete metadata or activites - * - * @method delete - * @memberof Personalization.prototype - * @param {object} resource - personalized resource endpoint i.e "follow_recommendations" - * @param {object} options - Additional options - * @param {requestCallback} callback - Callback to call on completion - * @return {Promise} Promise object. Data that was deleted if successful, or an error. - * @example client.personalization.delete('follow_recommendations', {foo: 'bar', baz: 'qux'}, cb) - */ + /** + * Delete metadata or activites + * + * @method delete + * @memberof Personalization.prototype + * @param {object} resource - personalized resource endpoint i.e "follow_recommendations" + * @param {object} options - Additional options + * @param {requestCallback} callback - Callback to call on completion + * @return {Promise} Promise object. Data that was deleted if successful, or an error. + * @example client.personalization.delete('follow_recommendations', {foo: 'bar', baz: 'qux'}, cb) + */ var last = arguments[arguments.length - 1]; // callback is always the last argument - callback = (last.call) ? last : undefined; + callback = last.call ? last : undefined; if (!options || options.call) { options = {}; } @@ -108,11 +110,11 @@ Personalization.prototype = { url: resource + '/', serviceName: 'personalization', qs: options, - signature: this.client.getPersonalizationToken() + signature: this.client.getPersonalizationToken(), }, - callback); + callback + ); }, - }; module.exports = Personalization; diff --git a/src/lib/promise.js b/src/lib/promise.js index 077c776c..924c4bde 100644 --- a/src/lib/promise.js +++ b/src/lib/promise.js @@ -1,3 +1,3 @@ var Promise = require('faye/src/util/promise'); -module.exports = Promise; \ No newline at end of file +module.exports = Promise; diff --git a/src/lib/signing.js b/src/lib/signing.js index 05824e8a..b25b350e 100644 --- a/src/lib/signing.js +++ b/src/lib/signing.js @@ -25,7 +25,7 @@ function decodeBase64Url(base64UrlString) { } function safeJsonParse(thing) { - if (typeof (thing) === 'object') return thing; + if (typeof thing === 'object') return thing; try { return JSON.parse(thing); } catch (e) { @@ -36,12 +36,10 @@ function safeJsonParse(thing) { function padString(string) { var segmentLength = 4; var diff = string.length % segmentLength; - if (!diff) - return string; + if (!diff) return string; var padLength = segmentLength - diff; - while (padLength--) - string += '='; + while (padLength--) string += '='; return string; } @@ -97,7 +95,7 @@ exports.JWTScopeToken = function(apiSecret, resource, action, opts) { * @return {string} JWT Token */ var options = opts || {}, - noTimestamp = options.expireTokens ? !options.expireTokens : true; + noTimestamp = options.expireTokens ? !options.expireTokens : true; var payload = { resource: resource, action: action, @@ -111,11 +109,19 @@ exports.JWTScopeToken = function(apiSecret, resource, action, opts) { payload['user_id'] = options.userId; } - var token = jwt.sign(payload, apiSecret, { algorithm: 'HS256', noTimestamp: noTimestamp }); + var token = jwt.sign(payload, apiSecret, { + algorithm: 'HS256', + noTimestamp: noTimestamp, + }); return token; }; -exports.JWTUserSessionToken = function(apiSecret, userId, extraData={}, jwtOptions={}) { +exports.JWTUserSessionToken = function( + apiSecret, + userId, + extraData = {}, + jwtOptions = {} +) { /** * Creates the JWT token that can be used for a UserSession * @method JWTUserSessionToken @@ -136,12 +142,14 @@ exports.JWTUserSessionToken = function(apiSecret, userId, extraData={}, jwtOptio ...extraData, }; - var opts = Object.assign({ algorithm: 'HS256', noTimestamp: true }, jwtOptions); + var opts = Object.assign( + { algorithm: 'HS256', noTimestamp: true }, + jwtOptions + ); var token = jwt.sign(payload, apiSecret, opts); return token; }; - exports.isJWTSignature = function(signature) { /** * check if token is a valid JWT token diff --git a/src/lib/user.js b/src/lib/user.js index 68c55e6a..2f4b2111 100644 --- a/src/lib/user.js +++ b/src/lib/user.js @@ -22,22 +22,24 @@ StreamUser.prototype = { }, _streamRef: function() { - return `SU:${this.id}`; + return `SU:${this.id}`; }, get: function(options, callback) { - return this.client.get({ - url: this.url, - signature: this.token, - qs: options, - }).then((response) => { - this.full = response; - this.data = response.data; - if (callback) { - callback(response); - } - return response; - }); + return this.client + .get({ + url: this.url, + signature: this.token, + qs: options, + }) + .then((response) => { + this.full = response; + this.data = response.data; + if (callback) { + callback(response); + } + return response; + }); }, _chooseData: function(data) { @@ -51,39 +53,43 @@ StreamUser.prototype = { }, create: function(data, options, callback) { - return this.client.post({ - url: 'user/', - body: { - id: this.id, - data: this._chooseData(data), - }, - qs: options, - signature: this.token, - }).then((response) => { - this.full = response; - this.data = response.data; - if (callback) { - callback(response); - } - return response; - }); + return this.client + .post({ + url: 'user/', + body: { + id: this.id, + data: this._chooseData(data), + }, + qs: options, + signature: this.token, + }) + .then((response) => { + this.full = response; + this.data = response.data; + if (callback) { + callback(response); + } + return response; + }); }, update: function(data, callback) { - return this.client.put({ - url: this.url, - body: { - data: this._chooseData(data), - }, - signature: this.token, - }).then((response) => { - this.full = response; - this.data = response.data; - if (callback) { - callback(response); - } - return response; - }); + return this.client + .put({ + url: this.url, + body: { + data: this._chooseData(data), + }, + signature: this.token, + }) + .then((response) => { + this.full = response; + this.data = response.data; + if (callback) { + callback(response); + } + return response; + }); }, getOrCreate: function(data, callback) { return this.create(data, { get_or_create: true }, callback); diff --git a/src/lib/utils.js b/src/lib/utils.js index ace30f6d..dd9611f0 100644 --- a/src/lib/utils.js +++ b/src/lib/utils.js @@ -8,7 +8,9 @@ function validateFeedId(feedId) { */ var parts = feedId.split(':'); if (parts.length !== 2) { - throw new errors.FeedError('Invalid feedId, expected something like user:1 got ' + feedId); + throw new errors.FeedError( + 'Invalid feedId, expected something like user:1 got ' + feedId + ); } var feedSlug = parts[0]; @@ -26,7 +28,9 @@ function validateFeedSlug(feedSlug) { */ var valid = validFeedSlugRe.test(feedSlug); if (!valid) { - throw new errors.FeedError('Invalid feedSlug, please use letters, numbers or _: ' + feedSlug); + throw new errors.FeedError( + 'Invalid feedSlug, please use letters, numbers or _: ' + feedSlug + ); } return feedSlug; @@ -40,7 +44,9 @@ function validateUserId(userId) { */ var valid = validUserIdRe.test(userId); if (!valid) { - throw new errors.FeedError('Invalid userId, please use letters, numbers, - or _: ' + userId); + throw new errors.FeedError( + 'Invalid userId, please use letters, numbers, - or _: ' + userId + ); } return userId; @@ -50,16 +56,24 @@ exports.validateUserId = validateUserId; function rfc3986(str) { return str.replace(/[!'()*]/g, function(c) { - return '%' + c.charCodeAt(0).toString(16).toUpperCase(); + return ( + '%' + + c + .charCodeAt(0) + .toString(16) + .toUpperCase() + ); }); } exports.rfc3986 = rfc3986; function isReadableStream(obj) { - return typeof obj === 'object' && + return ( + typeof obj === 'object' && typeof (obj._read === 'function') && - typeof (obj._readableState === 'object'); + typeof (obj._readableState === 'object') + ); } exports.isReadableStream = isReadableStream; diff --git a/test/integration/browser/client_test.js b/test/integration/browser/client_test.js index 78bdbbfb..f58a1c5a 100644 --- a/test/integration/browser/client_test.js +++ b/test/integration/browser/client_test.js @@ -1,37 +1,39 @@ -var beforeEachFn = require('../utils/hooks').beforeEach - , expect = require('expect.js') - , signing = require('../../../src/lib/signing') - , init = require('../utils/hooks').init; +var beforeEachFn = require('../utils/hooks').beforeEach, + expect = require('expect.js'), + signing = require('../../../src/lib/signing'), + init = require('../utils/hooks').init; describe('[INTEGRATION] Stream client (Browser)', function() { + init.call(this); + beforeEach(beforeEachFn); - init.call(this); - beforeEach(beforeEachFn); - - it('add activity using to', function() { - var self = this; - var activityId = null; - var activity = { - 'actor': 1, - 'verb': 'add', - 'object': 1 - }; - activity['participants'] = ['Thierry', 'Tommaso']; - activity['route'] = { - 'name': 'Vondelpark', - 'distance': '20' - }; - var signature = signing.sign(process.env.STREAM_API_SECRET, this.flat3.slug + this.flat3.userId); - activity['to'] = [this.flat3.id + ' ' + signature]; - - return this.user1.addActivity(activity) - .then(function(body) { - activityId = body['id']; - return self.flat3.get({ 'limit': 1 }); - }) - .then(function(body) { - expect(body['results'][0]['id']).to.eql(activityId); - }); - }); + it('add activity using to', function() { + var self = this; + var activityId = null; + var activity = { + actor: 1, + verb: 'add', + object: 1, + }; + activity['participants'] = ['Thierry', 'Tommaso']; + activity['route'] = { + name: 'Vondelpark', + distance: '20', + }; + var signature = signing.sign( + process.env.STREAM_API_SECRET, + this.flat3.slug + this.flat3.userId + ); + activity['to'] = [this.flat3.id + ' ' + signature]; -}); \ No newline at end of file + return this.user1 + .addActivity(activity) + .then(function(body) { + activityId = body['id']; + return self.flat3.get({ limit: 1 }); + }) + .then(function(body) { + expect(body['results'][0]['id']).to.eql(activityId); + }); + }); +}); diff --git a/test/integration/cloud/activities.js b/test/integration/cloud/activities.js index e30e9257..7031ba22 100644 --- a/test/integration/cloud/activities.js +++ b/test/integration/cloud/activities.js @@ -1,34 +1,34 @@ var { CloudContext } = require('./utils'); describe('Get activities', () => { - let ctx = new CloudContext(); - ctx.createUsers(); - ctx.aliceAddsCheeseBurger(); + let ctx = new CloudContext(); + ctx.createUsers(); + ctx.aliceAddsCheeseBurger(); - describe('When alice eats the cheese burger', () => { - let at = new Date().toISOString(); + describe('When alice eats the cheese burger', () => { + let at = new Date().toISOString(); - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.feed('user').addActivity({ - actor: ctx.alice.user, - verb: 'eat', - object: ctx.cheeseBurger, - foreign_id: 'fid:123', - time: at, - }); - }); + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.feed('user').addActivity({ + actor: ctx.alice.user, + verb: 'eat', + object: ctx.cheeseBurger, + foreign_id: 'fid:123', + time: at, + }); + }); - it('Should be possible to read the same activity by ID', async () => { - let response = await ctx.alice - .feed('user') - .getActivityDetail([ctx.response.id]); - let activity = response.results[0]; - activity.should.have.property('foreign_id'); - activity.actor.should.eql(ctx.alice.user.full); - activity.verb.should.equal('eat'); - activity.object.should.eql(ctx.cheeseBurger.full); - // activity.object.collection.should.equal('food'); - // activity.object.data.name.should.equal('cheese burger'); - }); + it('Should be possible to read the same activity by ID', async () => { + let response = await ctx.alice + .feed('user') + .getActivityDetail([ctx.response.id]); + let activity = response.results[0]; + activity.should.have.property('foreign_id'); + activity.actor.should.eql(ctx.alice.user.full); + activity.verb.should.equal('eat'); + activity.object.should.eql(ctx.cheeseBurger.full); + // activity.object.collection.should.equal('food'); + // activity.object.data.name.should.equal('cheese burger'); }); + }); }); diff --git a/test/integration/cloud/enrich.js b/test/integration/cloud/enrich.js index 2bdda1ae..d9eb7851 100644 --- a/test/integration/cloud/enrich.js +++ b/test/integration/cloud/enrich.js @@ -1,325 +1,302 @@ var { CloudContext } = require('./utils'); describe('Enrich story', () => { - let ctx = new CloudContext(); - let eatCheeseBurgerActivity; - let like; - let like2; - let comment; - - ctx.createUsers(); - ctx.aliceAddsCheeseBurger(); - - describe('When alice reads her empty feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.feed('user').get(); - }); + let ctx = new CloudContext(); + let eatCheeseBurgerActivity; + let like; + let like2; + let comment; + + ctx.createUsers(); + ctx.aliceAddsCheeseBurger(); + + describe('When alice reads her empty feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.feed('user').get(); + }); + + ctx.responseShouldHaveNoActivities(); + }); - ctx.responseShouldHaveNoActivities(); + describe('When alice eats the cheese burger', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.feed('user').addActivity({ + actor: ctx.alice.user, + verb: 'eat', + object: ctx.cheeseBurger, + }); }); + describe('and then alice reads her feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.feed('user').get(); + }); + + ctx.responseShouldHaveActivityWithFields(); + + ctx.responseShould('have the activity containing enriched data', () => { + ctx.activity.actor.should.eql(ctx.alice.user.full); + ctx.activity.verb.should.eql('eat'); + ctx.activity.object.should.eql(ctx.cheeseBurger.full); + eatCheeseBurgerActivity = ctx.response.results[0]; + }); + }); + }); - describe('When alice eats the cheese burger', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.feed('user').addActivity({ - actor: ctx.alice.user, - verb: 'eat', - object: ctx.cheeseBurger, - }); - }); - describe('and then alice reads her feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.feed('user').get(); - }); - - ctx.responseShouldHaveActivityWithFields(); - - ctx.responseShould( - 'have the activity containing enriched data', - () => { - ctx.activity.actor.should.eql(ctx.alice.user.full); - ctx.activity.verb.should.eql('eat'); - ctx.activity.object.should.eql(ctx.cheeseBurger.full); - eatCheeseBurgerActivity = ctx.response.results[0]; - }, - ); - }); + describe('When bob reads his empty timeline', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.bob.feed('timeline').get(); }); - describe('When bob reads his empty timeline', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.bob.feed('timeline').get(); - }); + ctx.responseShouldHaveNoActivities(); + }); - ctx.responseShouldHaveNoActivities(); + describe('When bob follows alice', () => { + ctx.requestShouldNotError(async () => { + await ctx.bob.followUser(ctx.alice.user); }); + describe('and then bob reads his timeline with own reactions', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.bob.feed('timeline').get(); + }); - describe('When bob follows alice', () => { - ctx.requestShouldNotError(async () => { - await ctx.bob.followUser(ctx.alice.user); - }); - describe('and then bob reads his timeline with own reactions', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.bob.feed('timeline').get(); - }); + ctx.responseShouldHaveActivityWithFields(); - ctx.responseShouldHaveActivityWithFields(); + ctx.activityShould('contain enriched data', () => { + ctx.activity.object.should.eql(ctx.cheeseBurger.full); + }); + }); + }); - ctx.activityShould('contain enriched data', () => { - ctx.activity.object.should.eql(ctx.cheeseBurger.full); - }); - }); + describe('When bob likes that alice ate the cheese burger', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.bob.react('like', eatCheeseBurgerActivity.id); }); - describe('When bob likes that alice ate the cheese burger', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.bob.react( - 'like', - eatCheeseBurgerActivity.id, - ); - }); + ctx.responseShouldHaveFields(...ctx.fields.reaction); - ctx.responseShouldHaveFields(...ctx.fields.reaction); + ctx.responseShouldHaveUUID(); - ctx.responseShouldHaveUUID(); + ctx.responseShould('have data matching the request', () => { + ctx.response.should.deep.include({ + kind: 'like', + activity_id: eatCheeseBurgerActivity.id, + user_id: ctx.bob.userId, + }); + ctx.response.data.should.eql({}); + like = ctx.reactionToReactionInActivity(ctx.response, ctx.bob.user); + }); - ctx.responseShould('have data matching the request', () => { - ctx.response.should.deep.include({ - kind: 'like', - activity_id: eatCheeseBurgerActivity.id, - user_id: ctx.bob.userId, - }); - ctx.response.data.should.eql({}); - like = ctx.reactionToReactionInActivity(ctx.response, ctx.bob.user); - }); + describe('and then bob reads his timeline with own reactions', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.bob + .feed('timeline') + .get({ withOwnReactions: true }); + }); - describe('and then bob reads his timeline with own reactions', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.bob - .feed('timeline') - .get({ withOwnReactions: true }); - }); + ctx.responseShouldHaveActivityWithFields('own_reactions'); - ctx.responseShouldHaveActivityWithFields('own_reactions'); + ctx.activityShould('contain the enriched data', () => { + ctx.activity.object.should.eql(ctx.cheeseBurger.full); + }); - ctx.activityShould('contain the enriched data', () => { - ctx.activity.object.should.eql(ctx.cheeseBurger.full); - }); + ctx.activityShould('contain the reaction of bob', () => { + ctx.activity.own_reactions.like.should.eql([like]); + }); + }); - ctx.activityShould('contain the reaction of bob', () => { - ctx.activity.own_reactions.like.should.eql([like]); - }); - }); + describe('and then bob reads alice her feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.bob + .feed('user', ctx.alice.userId) + .get({ withOwnReactions: true }); + }); - describe('and then bob reads alice her feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.bob - .feed('user', ctx.alice.userId) - .get({ withOwnReactions: true }); - }); + ctx.responseShouldHaveActivityWithFields('own_reactions'); - ctx.responseShouldHaveActivityWithFields('own_reactions'); + ctx.activityShould('contain the enriched data', () => { + ctx.activity.object.should.eql(ctx.cheeseBurger.full); + }); - ctx.activityShould('contain the enriched data', () => { - ctx.activity.object.should.eql(ctx.cheeseBurger.full); - }); + ctx.activityShould('contain the reaction of bob', () => { + ctx.activity.own_reactions.like.should.eql([like]); + }); + }); - ctx.activityShould('contain the reaction of bob', () => { - ctx.activity.own_reactions.like.should.eql([like]); - }); - }); + describe('and then carl reads alice her feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.carl + .feed('user', ctx.alice.userId) + .get({ withRecentReactions: true, withOwnReactions: true }); + }); + + ctx.responseShouldHaveActivityWithFields( + 'own_reactions', + 'latest_reactions' + ); + + ctx.activityShould('contain the enriched data', () => { + ctx.activity.object.should.eql(ctx.cheeseBurger.full); + }); + + ctx.activityShould('not contain anything in own_reactions', () => { + ctx.activity.own_reactions.should.eql({}); + }); + + ctx.activityShould( + 'contain the reaction of bob in latest_reactions', + () => { + ctx.activity.latest_reactions.like.should.eql([like]); + } + ); + }); + }); - describe('and then carl reads alice her feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.carl - .feed('user', ctx.alice.userId) - .get({ withRecentReactions: true, withOwnReactions: true }); - }); - - ctx.responseShouldHaveActivityWithFields( - 'own_reactions', - 'latest_reactions', - ); - - ctx.activityShould('contain the enriched data', () => { - ctx.activity.object.should.eql(ctx.cheeseBurger.full); - }); - - ctx.activityShould('not contain anything in own_reactions', () => { - ctx.activity.own_reactions.should.eql({}); - }); - - ctx.activityShould( - 'contain the reaction of bob in latest_reactions', - () => { - ctx.activity.latest_reactions.like.should.eql([like]); - }, - ); - }); + describe('When dave also likes that alice ate the cheese burger', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.dave.react('like', eatCheeseBurgerActivity.id); }); - describe('When dave also likes that alice ate the cheese burger', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.dave.react( - 'like', - eatCheeseBurgerActivity.id, - ); - }); + ctx.responseShouldHaveFields(...ctx.fields.reaction); - ctx.responseShouldHaveFields(...ctx.fields.reaction); - - ctx.responseShouldHaveUUID(); - - ctx.responseShould('have data matching the request', () => { - ctx.response.should.deep.include({ - kind: 'like', - activity_id: eatCheeseBurgerActivity.id, - user_id: ctx.dave.userId, - }); - ctx.response.data.should.eql({}); - like2 = ctx.reactionToReactionInActivity( - ctx.response, - ctx.dave.user, - ); - }); + ctx.responseShouldHaveUUID(); + + ctx.responseShould('have data matching the request', () => { + ctx.response.should.deep.include({ + kind: 'like', + activity_id: eatCheeseBurgerActivity.id, + user_id: ctx.dave.userId, + }); + ctx.response.data.should.eql({}); + like2 = ctx.reactionToReactionInActivity(ctx.response, ctx.dave.user); + }); + }); + + describe('When dave comments on that alice ate a cheeseburger', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.dave.react('comment', eatCheeseBurgerActivity, { + data: { + text: 'Looks juicy!!!', + }, + }); }); - describe('When dave comments on that alice ate a cheeseburger', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.dave.react( - 'comment', - eatCheeseBurgerActivity, - { - data: { - text: 'Looks juicy!!!', - }, - }, - ); - }); + ctx.responseShouldHaveFields(...ctx.fields.reaction); - ctx.responseShouldHaveFields(...ctx.fields.reaction); - - ctx.responseShouldHaveUUID(); - - ctx.responseShould('have data matching the request', () => { - ctx.response.should.deep.include({ - kind: 'comment', - activity_id: eatCheeseBurgerActivity.id, - user_id: ctx.dave.userId, - }); - ctx.response.data.should.eql({ - text: 'Looks juicy!!!', - }); - comment = ctx.reactionToReactionInActivity( - ctx.response, - ctx.dave.user, - ); - }); + ctx.responseShouldHaveUUID(); - describe('and then dave reads alice her feed with all enrichment enabled', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.dave - .feed('user', ctx.alice.userId) - .get({ - withRecentReactions: true, - withOwnReactions: true, - withReactionCounts: true, - }); - }); - - ctx.responseShouldHaveActivityWithFields( - 'own_reactions', - 'latest_reactions', - 'reaction_counts', - ); - - ctx.activityShould('contain the enriched data', () => { - ctx.activity.object.should.eql(ctx.cheeseBurger.full); - }); - - ctx.activityShould( - 'contain dave his like and comment in own_reactions', - () => { - ctx.activity.own_reactions.should.eql({ - like: [like2], - comment: [comment], - }); - }, - ); - - ctx.activityShould( - 'contain his own reactions and of bob his like in latest_reactions', - () => { - ctx.activity.latest_reactions.should.eql({ - like: [like2, like], - comment: [comment], - }); - }, - ); - - ctx.activityShould('have the correct counts for reactions', () => { - ctx.activity.reaction_counts.should.eql({ - like: 2, - comment: 1, - }); - }); - }); + ctx.responseShould('have data matching the request', () => { + ctx.response.should.deep.include({ + kind: 'comment', + activity_id: eatCheeseBurgerActivity.id, + user_id: ctx.dave.userId, + }); + ctx.response.data.should.eql({ + text: 'Looks juicy!!!', + }); + comment = ctx.reactionToReactionInActivity(ctx.response, ctx.dave.user); }); - describe('When dave removes his likes that alice ate the cheese burger', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.dave.reactions.delete(like2.id); + describe('and then dave reads alice her feed with all enrichment enabled', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.dave.feed('user', ctx.alice.userId).get({ + withRecentReactions: true, + withOwnReactions: true, + withReactionCounts: true, }); - - ctx.responseShould('be empty JSON', () => { - ctx.response.should.eql({}); + }); + + ctx.responseShouldHaveActivityWithFields( + 'own_reactions', + 'latest_reactions', + 'reaction_counts' + ); + + ctx.activityShould('contain the enriched data', () => { + ctx.activity.object.should.eql(ctx.cheeseBurger.full); + }); + + ctx.activityShould( + 'contain dave his like and comment in own_reactions', + () => { + ctx.activity.own_reactions.should.eql({ + like: [like2], + comment: [comment], + }); + } + ); + + ctx.activityShould( + 'contain his own reactions and of bob his like in latest_reactions', + () => { + ctx.activity.latest_reactions.should.eql({ + like: [like2, like], + comment: [comment], + }); + } + ); + + ctx.activityShould('have the correct counts for reactions', () => { + ctx.activity.reaction_counts.should.eql({ + like: 2, + comment: 1, }); + }); + }); + }); + + describe('When dave removes his likes that alice ate the cheese burger', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.dave.reactions.delete(like2.id); + }); + + ctx.responseShould('be empty JSON', () => { + ctx.response.should.eql({}); + }); - describe('and then dave reads alice her feed with all enrichment enabled', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.dave - .feed('user', ctx.alice.user) - .get({ - withRecentReactions: true, - withOwnReactions: true, - withReactionCounts: true, - }); - }); - - ctx.responseShouldHaveActivityWithFields( - 'own_reactions', - 'latest_reactions', - 'reaction_counts', - ); - - ctx.activityShould('contain the enriched data', () => { - ctx.activity.object.should.eql(ctx.cheeseBurger.full); - }); - - ctx.activityShould( - 'contain dave his like and comment in own_reactions', - () => { - ctx.activity.own_reactions.should.eql({ - comment: [comment], - }); - }, - ); - - ctx.activityShould( - 'contain his own reactions and of bob his like in latest_reactions', - () => { - ctx.activity.latest_reactions.should.eql({ - like: [like], - comment: [comment], - }); - }, - ); - - ctx.activityShould('have the correct counts for reactions', () => { - ctx.activity.reaction_counts.should.eql({ - like: 1, - comment: 1, - }); - }); + describe('and then dave reads alice her feed with all enrichment enabled', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.dave.feed('user', ctx.alice.user).get({ + withRecentReactions: true, + withOwnReactions: true, + withReactionCounts: true, + }); + }); + + ctx.responseShouldHaveActivityWithFields( + 'own_reactions', + 'latest_reactions', + 'reaction_counts' + ); + + ctx.activityShould('contain the enriched data', () => { + ctx.activity.object.should.eql(ctx.cheeseBurger.full); + }); + + ctx.activityShould( + 'contain dave his like and comment in own_reactions', + () => { + ctx.activity.own_reactions.should.eql({ + comment: [comment], + }); + } + ); + + ctx.activityShould( + 'contain his own reactions and of bob his like in latest_reactions', + () => { + ctx.activity.latest_reactions.should.eql({ + like: [like], + comment: [comment], + }); + } + ); + + ctx.activityShould('have the correct counts for reactions', () => { + ctx.activity.reaction_counts.should.eql({ + like: 1, + comment: 1, }); + }); }); + }); }); diff --git a/test/integration/cloud/files.js b/test/integration/cloud/files.js index 716f29e9..448b3485 100644 --- a/test/integration/cloud/files.js +++ b/test/integration/cloud/files.js @@ -3,41 +3,39 @@ var fs = require('fs'); var request = require('request'); describe('Files', () => { - let ctx = new CloudContext(); - let fileURL; + let ctx = new CloudContext(); + let fileURL; - describe('When alice adds a new file', () => { - ctx.requestShouldNotError(async () => { - let file = fs.createReadStream( - './test/integration/cloud/helloworld.txt', - ); - ctx.response = await ctx.alice.files.upload(file, 'helloworld.txt'); - }); + describe('When alice adds a new file', () => { + ctx.requestShouldNotError(async () => { + let file = fs.createReadStream('./test/integration/cloud/helloworld.txt'); + ctx.response = await ctx.alice.files.upload(file, 'helloworld.txt'); + }); - ctx.responseShould('have the expected content', () => { - ctx.response.should.have.all.keys('file'); - fileURL = ctx.response.file; - }); + ctx.responseShould('have the expected content', () => { + ctx.response.should.have.all.keys('file'); + fileURL = ctx.response.file; }); + }); - describe('When the file is requested', () => { - ctx.test('should return 200', function(done) { - request.get(fileURL, function(err, res, body) { - res.statusCode.should.eql(200); - done(); - }); - }); + describe('When the file is requested', () => { + ctx.test('should return 200', function(done) { + request.get(fileURL, function(err, res, body) { + res.statusCode.should.eql(200); + done(); + }); }); + }); - describe('When alice deletes an existing file', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.files.delete(fileURL); - }); + describe('When alice deletes an existing file', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.files.delete(fileURL); }); + }); - describe('When alice deletes an already deleted file', () => { - ctx.requestShouldError(404, async () => { - ctx.response = await ctx.alice.files.delete(fileURL); - }); + describe('When alice deletes an already deleted file', () => { + ctx.requestShouldError(404, async () => { + ctx.response = await ctx.alice.files.delete(fileURL); }); + }); }); diff --git a/test/integration/cloud/follow_list.js b/test/integration/cloud/follow_list.js index 8c1e6c5d..5e81d577 100644 --- a/test/integration/cloud/follow_list.js +++ b/test/integration/cloud/follow_list.js @@ -2,86 +2,80 @@ var { CloudContext } = require('./utils'); var expect = require('chai').expect; describe('Read followers', () => { - let ctx = new CloudContext(); + let ctx = new CloudContext(); - let bobData = { - name: 'Robert', - }; + let bobData = { + name: 'Robert', + }; - let carlData = { - name: 'Carl', - }; + let carlData = { + name: 'Carl', + }; - describe('When initializing follow relationships', async function() { - ctx.noRequestsShouldError(async () => { - await Promise.all([ - ctx.bob.user.create(bobData), - ctx.carl.user.create(carlData), - ctx.bob.followUser(ctx.alice.user), - ctx.carl.followUser(ctx.alice.user), - ctx.dave.followUser(ctx.alice.user), - ]); - }); + describe('When initializing follow relationships', async function() { + ctx.noRequestsShouldError(async () => { + await Promise.all([ + ctx.bob.user.create(bobData), + ctx.carl.user.create(carlData), + ctx.bob.followUser(ctx.alice.user), + ctx.carl.followUser(ctx.alice.user), + ctx.dave.followUser(ctx.alice.user), + ]); }); + }); - describe('When alice reads the list of followers', async () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.feed('user').followers(); - }); + describe('When alice reads the list of followers', async () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.feed('user').followers(); + }); - ctx.responseShould('have 3', () => { - expect(ctx.response.results).to.have.lengthOf(3); - }); + ctx.responseShould('have 3', () => { + expect(ctx.response.results).to.have.lengthOf(3); + }); - ctx.responseShould( - 'should include a user key with bob and carl', - () => { - ctx.response.should.have.property('users'); - ctx.response.users[ctx.bob.user.id].data.should.eql(bobData); - ctx.response.users[ctx.carl.user.id].data.should.eql(carlData); - }, - ); + ctx.responseShould('should include a user key with bob and carl', () => { + ctx.response.should.have.property('users'); + ctx.response.users[ctx.bob.user.id].data.should.eql(bobData); + ctx.response.users[ctx.carl.user.id].data.should.eql(carlData); }); + }); }); describe('Read followings', () => { - let ctx = new CloudContext(); + let ctx = new CloudContext(); - let bobData = { - name: 'Robert', - }; + let bobData = { + name: 'Robert', + }; - let carlData = { - name: 'Carl', - }; + let carlData = { + name: 'Carl', + }; - describe('When initializing follow relationships', async function() { - ctx.noRequestsShouldError(async () => { - await Promise.all([ - ctx.bob.user.create(bobData), - ctx.carl.user.create(carlData), - ctx.alice.followUser(ctx.bob.user), - ctx.alice.followUser(ctx.carl.user), - ctx.alice.followUser(ctx.dave.user), - ]); - }); + describe('When initializing follow relationships', async function() { + ctx.noRequestsShouldError(async () => { + await Promise.all([ + ctx.bob.user.create(bobData), + ctx.carl.user.create(carlData), + ctx.alice.followUser(ctx.bob.user), + ctx.alice.followUser(ctx.carl.user), + ctx.alice.followUser(ctx.dave.user), + ]); }); + }); - describe('When alice reads the list of followings', async () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.feed('timeline').following(); - }); - ctx.responseShould('have 3', () => { - expect(ctx.response.results).to.have.lengthOf(3); - }); + describe('When alice reads the list of followings', async () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.feed('timeline').following(); + }); + ctx.responseShould('have 3', () => { + expect(ctx.response.results).to.have.lengthOf(3); + }); - ctx.responseShould( - 'should include a user key with bob and carl', - () => { - ctx.response.should.have.property('users'); - ctx.response.users[ctx.bob.user.id].data.should.eql(bobData); - ctx.response.users[ctx.carl.user.id].data.should.eql(carlData); - }, - ); + ctx.responseShould('should include a user key with bob and carl', () => { + ctx.response.should.have.property('users'); + ctx.response.users[ctx.bob.user.id].data.should.eql(bobData); + ctx.response.users[ctx.carl.user.id].data.should.eql(carlData); }); + }); }); diff --git a/test/integration/cloud/images.js b/test/integration/cloud/images.js index 439a8c4f..214bf108 100644 --- a/test/integration/cloud/images.js +++ b/test/integration/cloud/images.js @@ -3,67 +3,62 @@ var fs = require('fs'); var request = require('request'); describe('Images', () => { - let ctx = new CloudContext(); - let imageUrl; + let ctx = new CloudContext(); + let imageUrl; - describe('When alice adds a new image', () => { - ctx.requestShouldNotError(async () => { - let file = fs.createReadStream( - './test/integration/cloud/helloworld.jpg', - ); - ctx.response = await ctx.alice.images.upload( - file, - 'helloworld.txt', - ); - }); + describe('When alice adds a new image', () => { + ctx.requestShouldNotError(async () => { + let file = fs.createReadStream('./test/integration/cloud/helloworld.jpg'); + ctx.response = await ctx.alice.images.upload(file, 'helloworld.txt'); + }); - ctx.responseShould('have the expected content', () => { - ctx.response.should.have.all.keys('file'); - imageUrl = ctx.response.file; - }); + ctx.responseShould('have the expected content', () => { + ctx.response.should.have.all.keys('file'); + imageUrl = ctx.response.file; }); + }); - describe('When the image ${imageUrl} is requested', () => { - ctx.test('should return 200', function(done) { - request.get(imageUrl, function(err, res, body) { - res.statusCode.should.eql(200); - done(); - }); - }); + describe('When the image ${imageUrl} is requested', () => { + ctx.test('should return 200', function(done) { + request.get(imageUrl, function(err, res, body) { + res.statusCode.should.eql(200); + done(); + }); }); + }); - describe('When alice creates a thumbmail 50x50', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.images.thumbmail(imageUrl, { - w: 50, - h: 50, - }); - ctx.responseShould('have the expected content', () => { - ctx.response.should.have.all.keys('file'); - imageUrl = ctx.response.file; - }); - }); + describe('When alice creates a thumbmail 50x50', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.images.thumbmail(imageUrl, { + w: 50, + h: 50, + }); + ctx.responseShould('have the expected content', () => { + ctx.response.should.have.all.keys('file'); + imageUrl = ctx.response.file; + }); }); + }); - describe('When the thumbnail is requested', () => { - ctx.test('should return 200', function(done) { - request.get(imageUrl, function(err, res, body) { - res.statusCode.should.eql(200); - done(); - }); - }); + describe('When the thumbnail is requested', () => { + ctx.test('should return 200', function(done) { + request.get(imageUrl, function(err, res, body) { + res.statusCode.should.eql(200); + done(); + }); }); + }); - describe('When alice deletes an existing image', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.images.delete(imageUrl); - }); + describe('When alice deletes an existing image', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.images.delete(imageUrl); }); + }); - describe('When alice deletes an already deleted image', () => { - ctx.requestShouldError(404, async () => { - ctx.response = await ctx.alice.images.delete(imageUrl); - console.log(ctx.response); - }); + describe('When alice deletes an already deleted image', () => { + ctx.requestShouldError(404, async () => { + ctx.response = await ctx.alice.images.delete(imageUrl); + console.log(ctx.response); }); + }); }); diff --git a/test/integration/cloud/object_store.js b/test/integration/cloud/object_store.js index e854c8ed..84a040bc 100644 --- a/test/integration/cloud/object_store.js +++ b/test/integration/cloud/object_store.js @@ -2,181 +2,169 @@ var { CloudContext } = require('./utils'); var randUserId = require('../utils/hooks').randUserId; describe('Object Store CRUD behaviours', () => { - let ctx = new CloudContext(); - let improvedCheeseBurgerData = { - name: 'The improved cheese burger', - toppings: ['cheese', 'pickles', 'bacon'], - }; - ctx.aliceAddsCheeseBurger(); - - describe('When alice tries to get the cheeseburger', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice - .storage('food') - .get(ctx.cheeseBurger.id); - ctx.prevResponse = ctx.response; - }); - - ctx.responseShould( - 'be the same as when the cheeseburger was added', - async () => { - ctx.response.should.eql(ctx.cheeseBurger.full); - }, - ); - }); - - describe('When bob tries to get the cheeseburger', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.bob - .storage('food') - .get(ctx.cheeseBurger.id); - }); - - ctx.responseShouldEqualPreviousResponse(); - }); - - describe('When bob tries to add the improved cheeseburger with the same ID', () => { - ctx.requestShouldError(409, async () => { - ctx.response = await ctx.bob - .storage('food') - .add(ctx.cheeseBurger.id, improvedCheeseBurgerData); - }); - }); - - describe('When alice tries to add the improved cheeseburger with the same ID', () => { - ctx.requestShouldError(409, async () => { - ctx.response = await ctx.alice - .storage('food') - .add(ctx.cheeseBurger.id, improvedCheeseBurgerData); - }); - }); - - describe('When bob tries to update the cheeseburger', () => { - ctx.requestShouldError(403, async () => { - ctx.response = await ctx.bob - .storage('food') - .update(ctx.cheeseBurger.id, improvedCheeseBurgerData); - }); - }); - - describe('When alice tries to update the cheeseburger', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice - .storage('food') - .update(ctx.cheeseBurger.id, improvedCheeseBurgerData); - }); - ctx.responseShouldHaveNewUpdatedAt(); - }); - - describe('When alice then tries to get the cheeseburger', () => { - ctx.requestShouldNotError(async () => { - ctx.prevResponse = ctx.response; - ctx.response = await ctx.alice - .storage('food') - .get(ctx.cheeseBurger.id); - }); - - ctx.responseShouldEqualPreviousResponse(); - }); - - describe('When alice tries to change the ID of cheeseburger in an update call', () => { - ctx.requestShouldError(400, async () => { - let storage = ctx.alice.storage('food'); - var body = { - id: 1234, - data: improvedCheeseBurgerData, - }; - await storage.client.put({ - url: storage.buildURL(ctx.cheeseBurger.id), - body: body, - signature: storage.signature, - }); - }); - }); - - describe('When bob tries to delete the cheeseburger', () => { - ctx.requestShouldError(403, async () => { - ctx.response = await ctx.bob - .storage('food') - .delete(ctx.cheeseBurger.id); - }); - }); - - describe('When alice tries to delete the cheeseburger', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice - .storage('food') - .delete(ctx.cheeseBurger.id); - }); - - ctx.responseShould('be empty JSON', async () => { - ctx.response.should.eql({}); - }); - }); - - describe('When alice then tries to get the cheeseburger', () => { - ctx.requestShouldError(404, async () => { - await ctx.alice.storage('food').get(ctx.cheeseBurger.id); - }); - }); - - describe('When alice tries to create an object with an illegal character in the id', () => { - ctx.requestShouldError(400, async () => { - await ctx.alice.storage('food').add('!abcdee!', {}); - }); - }); - - let newCheeseBurger; - - describe('When alice tries to add a new cheeseburger with a provided ID', () => { - let newCheeseBurgerID = randUserId('cheeseburger'); - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice - .storage('food') - .add(newCheeseBurgerID, ctx.cheeseBurgerData); - }); - - ctx.responseShouldHaveFields(...ctx.fields.collection); - - ctx.responseShould( - 'have ID, collection and data matching the request', - () => { - ctx.response.id.should.equal(newCheeseBurgerID); - ctx.response.collection.should.equal('food'); - ctx.response.data.should.eql(ctx.cheeseBurgerData); - }, - ); - - ctx.afterTest(() => { - newCheeseBurger = ctx.response; - }); - }); - - describe('When alice tries to get the new cheeseburger', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice - .storage('food') - .get(newCheeseBurger.id); - }); - ctx.responseShould( - 'be the same as when the new cheeseburger was added', - async () => { - ctx.response.should.eql(newCheeseBurger); - }, - ); - }); - - describe('When alice tries to add an object with a string as data', () => { - ctx.requestShouldError(400, async () => { - ctx.response = await ctx.alice - .storage('food') - .add(null, 'some string'); - }); - }); - - describe('When alice tries to add an object with empty data', () => { - ctx.requestShouldError(400, async () => { - ctx.response = await ctx.alice.storage('food').add(null, {}); - }); + let ctx = new CloudContext(); + let improvedCheeseBurgerData = { + name: 'The improved cheese burger', + toppings: ['cheese', 'pickles', 'bacon'], + }; + ctx.aliceAddsCheeseBurger(); + + describe('When alice tries to get the cheeseburger', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.storage('food').get(ctx.cheeseBurger.id); + ctx.prevResponse = ctx.response; + }); + + ctx.responseShould( + 'be the same as when the cheeseburger was added', + async () => { + ctx.response.should.eql(ctx.cheeseBurger.full); + } + ); + }); + + describe('When bob tries to get the cheeseburger', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.bob.storage('food').get(ctx.cheeseBurger.id); + }); + + ctx.responseShouldEqualPreviousResponse(); + }); + + describe('When bob tries to add the improved cheeseburger with the same ID', () => { + ctx.requestShouldError(409, async () => { + ctx.response = await ctx.bob + .storage('food') + .add(ctx.cheeseBurger.id, improvedCheeseBurgerData); + }); + }); + + describe('When alice tries to add the improved cheeseburger with the same ID', () => { + ctx.requestShouldError(409, async () => { + ctx.response = await ctx.alice + .storage('food') + .add(ctx.cheeseBurger.id, improvedCheeseBurgerData); + }); + }); + + describe('When bob tries to update the cheeseburger', () => { + ctx.requestShouldError(403, async () => { + ctx.response = await ctx.bob + .storage('food') + .update(ctx.cheeseBurger.id, improvedCheeseBurgerData); + }); + }); + + describe('When alice tries to update the cheeseburger', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice + .storage('food') + .update(ctx.cheeseBurger.id, improvedCheeseBurgerData); + }); + ctx.responseShouldHaveNewUpdatedAt(); + }); + + describe('When alice then tries to get the cheeseburger', () => { + ctx.requestShouldNotError(async () => { + ctx.prevResponse = ctx.response; + ctx.response = await ctx.alice.storage('food').get(ctx.cheeseBurger.id); + }); + + ctx.responseShouldEqualPreviousResponse(); + }); + + describe('When alice tries to change the ID of cheeseburger in an update call', () => { + ctx.requestShouldError(400, async () => { + let storage = ctx.alice.storage('food'); + var body = { + id: 1234, + data: improvedCheeseBurgerData, + }; + await storage.client.put({ + url: storage.buildURL(ctx.cheeseBurger.id), + body: body, + signature: storage.signature, + }); + }); + }); + + describe('When bob tries to delete the cheeseburger', () => { + ctx.requestShouldError(403, async () => { + ctx.response = await ctx.bob.storage('food').delete(ctx.cheeseBurger.id); + }); + }); + + describe('When alice tries to delete the cheeseburger', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice + .storage('food') + .delete(ctx.cheeseBurger.id); + }); + + ctx.responseShould('be empty JSON', async () => { + ctx.response.should.eql({}); + }); + }); + + describe('When alice then tries to get the cheeseburger', () => { + ctx.requestShouldError(404, async () => { + await ctx.alice.storage('food').get(ctx.cheeseBurger.id); + }); + }); + + describe('When alice tries to create an object with an illegal character in the id', () => { + ctx.requestShouldError(400, async () => { + await ctx.alice.storage('food').add('!abcdee!', {}); + }); + }); + + let newCheeseBurger; + + describe('When alice tries to add a new cheeseburger with a provided ID', () => { + let newCheeseBurgerID = randUserId('cheeseburger'); + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice + .storage('food') + .add(newCheeseBurgerID, ctx.cheeseBurgerData); + }); + + ctx.responseShouldHaveFields(...ctx.fields.collection); + + ctx.responseShould( + 'have ID, collection and data matching the request', + () => { + ctx.response.id.should.equal(newCheeseBurgerID); + ctx.response.collection.should.equal('food'); + ctx.response.data.should.eql(ctx.cheeseBurgerData); + } + ); + + ctx.afterTest(() => { + newCheeseBurger = ctx.response; + }); + }); + + describe('When alice tries to get the new cheeseburger', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.storage('food').get(newCheeseBurger.id); + }); + ctx.responseShould( + 'be the same as when the new cheeseburger was added', + async () => { + ctx.response.should.eql(newCheeseBurger); + } + ); + }); + + describe('When alice tries to add an object with a string as data', () => { + ctx.requestShouldError(400, async () => { + ctx.response = await ctx.alice.storage('food').add(null, 'some string'); + }); + }); + + describe('When alice tries to add an object with empty data', () => { + ctx.requestShouldError(400, async () => { + ctx.response = await ctx.alice.storage('food').add(null, {}); }); + }); }); diff --git a/test/integration/cloud/open_graph.js b/test/integration/cloud/open_graph.js index cca03504..8d05797e 100644 --- a/test/integration/cloud/open_graph.js +++ b/test/integration/cloud/open_graph.js @@ -1,52 +1,51 @@ var { CloudContext } = require('./utils'); describe('OpenGraph story', () => { - let ctx = new CloudContext(); + let ctx = new CloudContext(); - describe('When alice requests opengraph info for our blog', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.og( - 'https://getstream.io/blog/try-out-the-stream-api-with-postman', - ); - }); + describe('When alice requests opengraph info for our blog', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.og( + 'https://getstream.io/blog/try-out-the-stream-api-with-postman' + ); + }); - ctx.responseShould('have the expected content', () => { - ctx.response.should.eql({ - locale: 'en_US', - type: 'article', - title: 'Try out the Stream API with Postman - The Stream Blog', - description: - "Many of us at Stream use Postman regularly as we build and test our services. We're also always looking for ways to make it quick and easy for other developers to try the service. One of our goals is to help people see first hand how simple it is to build powerful social apps with Stream.", - url: - 'https://getstream.io/blog/try-out-the-stream-api-with-postman/', - site_name: 'The Stream Blog', - images: [ - { - image: - 'https://getstream-blog.imgix.net/blog/wp-content/uploads/2018/04/stream_postman.png', - secure_url: - 'https://getstream-blog.imgix.net/blog/wp-content/uploads/2018/04/stream_postman.png', - width: '1600', - height: '835', - alt: 'Postman Collection for the Stream API', - }, - ], - }); - }); + ctx.responseShould('have the expected content', () => { + ctx.response.should.eql({ + locale: 'en_US', + type: 'article', + title: 'Try out the Stream API with Postman - The Stream Blog', + description: + "Many of us at Stream use Postman regularly as we build and test our services. We're also always looking for ways to make it quick and easy for other developers to try the service. One of our goals is to help people see first hand how simple it is to build powerful social apps with Stream.", + url: 'https://getstream.io/blog/try-out-the-stream-api-with-postman/', + site_name: 'The Stream Blog', + images: [ + { + image: + 'https://getstream-blog.imgix.net/blog/wp-content/uploads/2018/04/stream_postman.png', + secure_url: + 'https://getstream-blog.imgix.net/blog/wp-content/uploads/2018/04/stream_postman.png', + width: '1600', + height: '835', + alt: 'Postman Collection for the Stream API', + }, + ], + }); }); + }); - describe('When alice requests opengraph info for a binary blob', () => { - ctx.requestShouldError(400, async () => { - ctx.response = await ctx.alice.og( - 'https://github.com/buger/goreplay/releases/download/v0.16.1/gor_0.16.1_mac.tar.gz', - ); - }); + describe('When alice requests opengraph info for a binary blob', () => { + ctx.requestShouldError(400, async () => { + ctx.response = await ctx.alice.og( + 'https://github.com/buger/goreplay/releases/download/v0.16.1/gor_0.16.1_mac.tar.gz' + ); + }); - ctx.responseShould('have the expected content', () => { - ctx.response.should.eql({ - detail: 'document too large (>1MB)', - status_code: 400 - }); - }); + ctx.responseShould('have the expected content', () => { + ctx.response.should.eql({ + detail: 'document too large (>1MB)', + status_code: 400, + }); }); + }); }); diff --git a/test/integration/cloud/permissions.js b/test/integration/cloud/permissions.js index 34e04584..1835a661 100644 --- a/test/integration/cloud/permissions.js +++ b/test/integration/cloud/permissions.js @@ -3,160 +3,154 @@ var randUserId = require('../utils/hooks').randUserId; var util = require('util'); function log(...args) { - console.log( - util.inspect(...args, { showHidden: false, depth: null, colors: true }), - ); + console.log( + util.inspect(...args, { showHidden: false, depth: null, colors: true }) + ); } describe('Permission managament', () => { - let ctx = new CloudContext(); - let policies; - let fixedPolicies = []; - let newPolicy; - describe('When alice requests to see the policies', () => { - ctx.requestShouldError(403, async () => { - ctx.response = await ctx.alice.permissions.get(); - }); + let ctx = new CloudContext(); + let policies; + let fixedPolicies = []; + let newPolicy; + describe('When alice requests to see the policies', () => { + ctx.requestShouldError(403, async () => { + ctx.response = await ctx.alice.permissions.get(); }); + }); - describe('When root requests to see the policy', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.root.permissions.get(); - policies = ctx.response.policies; - // log(policies); - }); + describe('When root requests to see the policy', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.root.permissions.get(); + policies = ctx.response.policies; + // log(policies); }); + }); - describe('When root tries to clear the default policies', () => { - ctx.noRequestsShouldError(async () => { - let deleteRequests = []; - for (let p of policies) { - if (p.priority > 0 && p.priority < 1000) { - deleteRequests.push( - ctx.root.permissions.delete(p.priority), - ); - } else { - fixedPolicies.push(p); - } - } - await Promise.all(deleteRequests); - }); - describe('and then requests to see the policies', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.root.permissions.get(); - policies = ctx.response.policies; - }); - ctx.test('the policies should be there again', () => { - policies.should.have.lengthOf.above(fixedPolicies.length); - }); - }); + describe('When root tries to clear the default policies', () => { + ctx.noRequestsShouldError(async () => { + let deleteRequests = []; + for (let p of policies) { + if (p.priority > 0 && p.priority < 1000) { + deleteRequests.push(ctx.root.permissions.delete(p.priority)); + } else { + fixedPolicies.push(p); + } + } + await Promise.all(deleteRequests); }); - - describe('When root tries to overwrite a default policy', () => { - ctx.requestShouldError(409, async () => { - await ctx.root.permissions.add(policies[1]); - }); + describe('and then requests to see the policies', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.root.permissions.get(); + policies = ctx.response.policies; + }); + ctx.test('the policies should be there again', () => { + policies.should.have.lengthOf.above(fixedPolicies.length); + }); }); + }); - describe('When alice tries to delete a default policy', () => { - ctx.requestShouldError(403, async () => { - await ctx.alice.permissions.delete(policies[1].priority); - }); + describe('When root tries to overwrite a default policy', () => { + ctx.requestShouldError(409, async () => { + await ctx.root.permissions.add(policies[1]); }); + }); - describe('When root tries to delete a fixed policy', () => { - ctx.requestShouldError(400, async () => { - await ctx.root.permissions.delete(policies[0].priority); - }); + describe('When alice tries to delete a default policy', () => { + ctx.requestShouldError(403, async () => { + await ctx.alice.permissions.delete(policies[1].priority); }); + }); - describe('When root tries to delete a single default policy', () => { - ctx.requestShouldNotError(async () => { - await ctx.root.permissions.delete(policies[1].priority); - }); - describe('and then requests to see the policies', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.root.permissions.get(); - }); - ctx.test('the policy should be removed', () => { - ctx.response.policies.should.have.lengthOf(policies.length - 1); - ctx.response.policies[1].should.eql(policies[2]); - }); - }); + describe('When root tries to delete a fixed policy', () => { + ctx.requestShouldError(400, async () => { + await ctx.root.permissions.delete(policies[0].priority); + }); + }); - describe('and then alice tries to add the policy again', () => { - ctx.requestShouldError(403, async () => { - await ctx.alice.permissions.add(policies[1]); - }); - }); + describe('When root tries to delete a single default policy', () => { + ctx.requestShouldNotError(async () => { + await ctx.root.permissions.delete(policies[1].priority); + }); + describe('and then requests to see the policies', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.root.permissions.get(); + }); + ctx.test('the policy should be removed', () => { + ctx.response.policies.should.have.lengthOf(policies.length - 1); + ctx.response.policies[1].should.eql(policies[2]); + }); + }); - describe('and then root tries to add the policy again', () => { - ctx.requestShouldNotError(async () => { - await ctx.root.permissions.add(policies[1]); - }); - }); + describe('and then alice tries to add the policy again', () => { + ctx.requestShouldError(403, async () => { + await ctx.alice.permissions.add(policies[1]); + }); + }); - describe('and then requests to see the policies', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.root.permissions.get(); - }); - ctx.test('the policy should be there again', () => { - ctx.response.policies.should.have.lengthOf(policies.length); - ctx.response.policies[1].priority.should.eql( - policies[1].priority, - ); - }); - }); + describe('and then root tries to add the policy again', () => { + ctx.requestShouldNotError(async () => { + await ctx.root.permissions.add(policies[1]); + }); }); - // Clean up policies again - after(async () => { - let deleteRequests = []; - for (let p of policies) { - if (p.priority > 0 && p.priority < 1000) { - deleteRequests.push(ctx.root.permissions.delete(p.priority)); - } else { - fixedPolicies.push(p); - } - } - await Promise.all(deleteRequests); + describe('and then requests to see the policies', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.root.permissions.get(); + }); + ctx.test('the policy should be there again', () => { + ctx.response.policies.should.have.lengthOf(policies.length); + ctx.response.policies[1].priority.should.eql(policies[1].priority); + }); }); + }); + + // Clean up policies again + after(async () => { + let deleteRequests = []; + for (let p of policies) { + if (p.priority > 0 && p.priority < 1000) { + deleteRequests.push(ctx.root.permissions.delete(p.priority)); + } else { + fixedPolicies.push(p); + } + } + await Promise.all(deleteRequests); + }); }); describe('Permission checking', () => { - let ctx = new CloudContext(); - ctx.createUsers(); - describe('When alice tries to impersonate bob', () => { - let at = new Date().toISOString(); - ctx.requestShouldError(403, async () => { - ctx.response = await ctx.alice.feed('user').addActivity({ - actor: ctx.bob.user, - verb: 'eat', - object: ctx.cheeseBurger, - foreign_id: 'fid:123', - time: at, - }); - }); - }); - describe('When alice tries to create another user', () => { - ctx.requestShouldError(403, async () => { - ctx.response = await ctx.alice - .getUser(randUserId('someone')) - .create(); - }); - }); - describe('When alice tries to update bob', () => { - ctx.requestShouldError(403, async () => { - ctx.response = await ctx.alice - .getUser(ctx.bob.userId) - .update({ hacked: true }); - }); - }); - describe('When alice tries to delete bob', () => { - ctx.requestShouldError(403, async () => { - ctx.response = await ctx.alice - .getUser(ctx.bob.userId) - .update({ hacked: true }); - }); + let ctx = new CloudContext(); + ctx.createUsers(); + describe('When alice tries to impersonate bob', () => { + let at = new Date().toISOString(); + ctx.requestShouldError(403, async () => { + ctx.response = await ctx.alice.feed('user').addActivity({ + actor: ctx.bob.user, + verb: 'eat', + object: ctx.cheeseBurger, + foreign_id: 'fid:123', + time: at, + }); + }); + }); + describe('When alice tries to create another user', () => { + ctx.requestShouldError(403, async () => { + ctx.response = await ctx.alice.getUser(randUserId('someone')).create(); + }); + }); + describe('When alice tries to update bob', () => { + ctx.requestShouldError(403, async () => { + ctx.response = await ctx.alice + .getUser(ctx.bob.userId) + .update({ hacked: true }); + }); + }); + describe('When alice tries to delete bob', () => { + ctx.requestShouldError(403, async () => { + ctx.response = await ctx.alice + .getUser(ctx.bob.userId) + .update({ hacked: true }); }); + }); }); diff --git a/test/integration/cloud/personalized_feed.js b/test/integration/cloud/personalized_feed.js index 7edac2a5..d758d392 100644 --- a/test/integration/cloud/personalized_feed.js +++ b/test/integration/cloud/personalized_feed.js @@ -1,21 +1,20 @@ var { CloudContext } = require('./utils'); describe('Personalized enrichment story', () => { - let ctx = new CloudContext(); - let eatCheeseBurgerActivity; - let like; - let like2; - let comment; + let ctx = new CloudContext(); + let eatCheeseBurgerActivity; + let like; + let like2; + let comment; - describe('When alice reads her personalization feed', () => { - ctx.requestShouldError(404, async () => { - ctx.response = await ctx.alice.personalizedFeed({feed_slug: 'abc'}) - }); + describe('When alice reads her personalization feed', () => { + ctx.requestShouldError(404, async () => { + ctx.response = await ctx.alice.personalizedFeed({ feed_slug: 'abc' }); }); - describe('When alice reads her personalization feed without args', () => { - ctx.requestShouldError(404, async () => { - ctx.response = await ctx.alice.personalizedFeed() - }); + }); + describe('When alice reads her personalization feed without args', () => { + ctx.requestShouldError(404, async () => { + ctx.response = await ctx.alice.personalizedFeed(); }); -}) - + }); +}); diff --git a/test/integration/cloud/profile.js b/test/integration/cloud/profile.js index 49f4c2e3..0b213d7b 100644 --- a/test/integration/cloud/profile.js +++ b/test/integration/cloud/profile.js @@ -1,147 +1,147 @@ var { CloudContext } = require('./utils'); describe('User profile story', () => { - let ctx = new CloudContext(); - let aliceData = ctx.userData.alice; - let bobData = ctx.userData.bob; - let newBobData = { - name: bobData.name, - hates: bobData.likes, - }; - - describe('When alice gets her account without creating it', () => { - ctx.requestShouldError(404, async () => { - ctx.response = await ctx.alice.user.get(); - }); + let ctx = new CloudContext(); + let aliceData = ctx.userData.alice; + let bobData = ctx.userData.bob; + let newBobData = { + name: bobData.name, + hates: bobData.likes, + }; + + describe('When alice gets her account without creating it', () => { + ctx.requestShouldError(404, async () => { + ctx.response = await ctx.alice.user.get(); }); + }); - let checkUserResponse = (userFn, data) => { - ctx.responseShouldHaveFields('id', 'created_at', 'updated_at', 'data'); - - ctx.responseShould('have id and data matching the request', () => { - ctx.response.id.should.equal(userFn().id); - ctx.response.data.should.eql(data); - }); - - ctx.test('the local user data should be updated', () => { - userFn().data.should.eql(data); - }); - }; - - let checkProfileResponse = (userFn, data, following, followers) => { - ctx.responseShouldHaveFields( - 'id', - 'created_at', - 'updated_at', - 'data', - 'following_count', - 'followers_count', - ); - - ctx.responseShould( - 'have id and data matching the previously submitted data', - () => { - ctx.response.id.should.equal(userFn().id); - ctx.response.data.should.eql(data); - }, - ); - - ctx.test('the local user data should be updated', () => { - userFn().data.should.eql(data); - }); - - ctx.responseShould( - 'contain the counts for following and followers for timeline->user feedgroups', - () => { - ctx.response.following_count.should.equal(following); - ctx.response.followers_count.should.equal(followers); - }, - ); - }; - - describe('When alice creates her account', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.user.create(aliceData); - }); - checkUserResponse(() => ctx.alice.user, aliceData); + let checkUserResponse = (userFn, data) => { + ctx.responseShouldHaveFields('id', 'created_at', 'updated_at', 'data'); + + ctx.responseShould('have id and data matching the request', () => { + ctx.response.id.should.equal(userFn().id); + ctx.response.data.should.eql(data); }); - describe('When alice tries to create her account again', () => { - ctx.requestShouldError(409, async () => { - await ctx.alice.user.create(aliceData); - }); + ctx.test('the local user data should be updated', () => { + userFn().data.should.eql(data); + }); + }; + + let checkProfileResponse = (userFn, data, following, followers) => { + ctx.responseShouldHaveFields( + 'id', + 'created_at', + 'updated_at', + 'data', + 'following_count', + 'followers_count' + ); + + ctx.responseShould( + 'have id and data matching the previously submitted data', + () => { + ctx.response.id.should.equal(userFn().id); + ctx.response.data.should.eql(data); + } + ); + + ctx.test('the local user data should be updated', () => { + userFn().data.should.eql(data); }); - describe('When bob calls getOrCreate for his user that does not exist yet', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.bob.user.getOrCreate(bobData); - }); - checkUserResponse(() => ctx.bob.user, bobData); + ctx.responseShould( + 'contain the counts for following and followers for timeline->user feedgroups', + () => { + ctx.response.following_count.should.equal(following); + ctx.response.followers_count.should.equal(followers); + } + ); + }; + + describe('When alice creates her account', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.user.create(aliceData); }); + checkUserResponse(() => ctx.alice.user, aliceData); + }); - describe('When bob calls getOrCreate for his existing user with new data', () => { - ctx.requestShouldNotError(async () => { - ctx.prevResponse = ctx.response; - ctx.response = await ctx.bob.user.getOrCreate(newBobData); - }); + describe('When alice tries to create her account again', () => { + ctx.requestShouldError(409, async () => { + await ctx.alice.user.create(aliceData); + }); + }); - ctx.responseShould('be the same as the previous response', () => { - ctx.response.should.eql(ctx.prevResponse); - }); + describe('When bob calls getOrCreate for his user that does not exist yet', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.bob.user.getOrCreate(bobData); }); + checkUserResponse(() => ctx.bob.user, bobData); + }); - describe('When bob updates his existing user', () => { - ctx.requestShouldNotError(async () => { - ctx.prevResponse = ctx.response; - ctx.response = await ctx.bob.user.update(newBobData); - }); - checkUserResponse(() => ctx.bob.user, newBobData); - ctx.responseShouldHaveNewUpdatedAt(); + describe('When bob calls getOrCreate for his existing user with new data', () => { + ctx.requestShouldNotError(async () => { + ctx.prevResponse = ctx.response; + ctx.response = await ctx.bob.user.getOrCreate(newBobData); }); - describe('When creating follow relationships', () => { - ctx.requestShouldNotError(async () => { - let promises = []; - promises.push(ctx.alice.followUser(ctx.bob.userId)); - promises.push(ctx.alice.followUser(ctx.carl.userId)); - promises.push( - ctx.alice.feed('timeline').follow('timeline', ctx.dave.userId), - ); - promises.push(ctx.bob.followUser(ctx.alice.userId)); - promises.push( - ctx.bob.feed('notification').follow('user', ctx.alice.userId), - ); - promises.push( - ctx.carl.feed('notification').follow('user', ctx.alice.userId), - ); - promises.push( - ctx.dave.feed('notification').follow('user', ctx.alice.userId), - ); - await Promise.all(promises); - }); + ctx.responseShould('be the same as the previous response', () => { + ctx.response.should.eql(ctx.prevResponse); }); + }); - describe('When alice looks at her own profile', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.user.profile(); - }); + describe('When bob updates his existing user', () => { + ctx.requestShouldNotError(async () => { + ctx.prevResponse = ctx.response; + ctx.response = await ctx.bob.user.update(newBobData); + }); + checkUserResponse(() => ctx.bob.user, newBobData); + ctx.responseShouldHaveNewUpdatedAt(); + }); + + describe('When creating follow relationships', () => { + ctx.requestShouldNotError(async () => { + let promises = []; + promises.push(ctx.alice.followUser(ctx.bob.userId)); + promises.push(ctx.alice.followUser(ctx.carl.userId)); + promises.push( + ctx.alice.feed('timeline').follow('timeline', ctx.dave.userId) + ); + promises.push(ctx.bob.followUser(ctx.alice.userId)); + promises.push( + ctx.bob.feed('notification').follow('user', ctx.alice.userId) + ); + promises.push( + ctx.carl.feed('notification').follow('user', ctx.alice.userId) + ); + promises.push( + ctx.dave.feed('notification').follow('user', ctx.alice.userId) + ); + await Promise.all(promises); + }); + }); - checkProfileResponse(() => ctx.alice.user, aliceData, 2, 1); + describe('When alice looks at her own profile', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.user.profile(); }); - describe("When alice looks at bob's profile", () => { - let bobUser; - ctx.requestShouldNotError(async () => { - bobUser = ctx.alice.getUser(ctx.bob.userId); - ctx.response = await bobUser.profile(); - }); + checkProfileResponse(() => ctx.alice.user, aliceData, 2, 1); + }); - checkProfileResponse(() => bobUser, newBobData, 1, 1); + describe("When alice looks at bob's profile", () => { + let bobUser; + ctx.requestShouldNotError(async () => { + bobUser = ctx.alice.getUser(ctx.bob.userId); + ctx.response = await bobUser.profile(); }); - describe('When alice tries to set a string as user data', () => { - ctx.requestShouldError(400, async () => { - ctx.response = await ctx.alice.user.update('some string'); - }); + checkProfileResponse(() => bobUser, newBobData, 1, 1); + }); + + describe('When alice tries to set a string as user data', () => { + ctx.requestShouldError(400, async () => { + ctx.response = await ctx.alice.user.update('some string'); }); + }); }); diff --git a/test/integration/cloud/reaction.js b/test/integration/cloud/reaction.js index 0b4f5c53..d9e7cc04 100644 --- a/test/integration/cloud/reaction.js +++ b/test/integration/cloud/reaction.js @@ -1,230 +1,230 @@ var { CloudContext } = require('./utils'); describe('Reaction CRUD and posting reactions to feeds', () => { - let ctx = new CloudContext(); - - let eatActivity; - let commentActivity; - let comment; - let expectedCommentData; - let commentData = { - text: 'Looking yummy! @carl wanna get this on Tuesday?', - }; - - ctx.createUsers(); - describe('When alice eats a cheese burger', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.feed('user').addActivity({ - actor: ctx.alice.user, - verb: 'eat', - object: 'cheeseburger', - }); - eatActivity = ctx.response; - delete eatActivity.duration; - eatActivity.actor = ctx.alice.user.full; - }); - }); - - describe('When bob comments on that alice ate the cheese burger', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.bob.react('comment', eatActivity.id, { - data: commentData, - targetFeeds: [ - ctx.bob.feed('user').id, - ctx.bob.feed('notification', ctx.alice.userId), - ctx.bob.feed('notification', ctx.carl.userId), - ], - }); - comment = ctx.response; - }); - - ctx.responseShouldHaveFields(...ctx.fields.reaction); - - ctx.responseShouldHaveUUID(); - - ctx.responseShould('have data matching the request', () => { - ctx.response.should.deep.include({ - kind: 'comment', - activity_id: eatActivity.id, - user_id: ctx.bob.userId, - }); - ctx.response.data.should.eql(commentData); - }); - - describe('and then alice reads bob his feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.feed('user', ctx.bob.user).get(); - }); - ctx.responseShouldHaveActivityWithFields('reaction'); - ctx.activityShould('contain the expected data', () => { - expectedCommentData = { - verb: 'comment', - foreign_id: `reaction:${comment.id}`, - time: comment.created_at.slice(0, -1), // chop off the Z suffix - target: '', - origin: null, - }; - - ctx.activity.should.include(expectedCommentData); - ctx.activity.actor.should.eql(ctx.bob.user.full); - ctx.activity.object.should.eql(eatActivity); - ctx.activity.reaction.should.eql(comment); - commentActivity = ctx.activity; - }); - }); - - describe('and then alice reads her own notification feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.feed('notification').get(); - }); - ctx.responseShouldHaveActivityInGroupWithFields('reaction'); - ctx.activityShould('be the same as on bob his feed', () => { - ctx.activity.should.eql(commentActivity); - }); - }); - - describe('and then carl reads his notification feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.carl.feed('notification').get(); - }); - ctx.responseShouldHaveActivityInGroupWithFields('reaction'); - ctx.activityShould('be the same as on bob his feed', () => { - ctx.activity.should.eql(commentActivity); - }); - }); - }); - - describe('When alice tries to update bob his comment', () => { - ctx.requestShouldError(403, async () => { - commentData = { - text: 'Alice you are the best!!!!', - }; - ctx.response = await ctx.alice.reactions.update(comment.id, { - data: commentData, - }); - }); - }); - - describe('When bob updates his comment and tags dave instead of carl', () => { - ctx.requestShouldNotError(async () => { - commentData = { - text: 'Looking yummy! @dave wanna get this on Tuesday?', - }; - ctx.response = await ctx.bob.reactions.update(comment.id, { - data: commentData, - targetFeeds: [ - ctx.bob.feed('user').id, - ctx.bob.feed('notification', ctx.alice.userId), - ctx.bob.feed('notification', ctx.dave.userId), - ], - }); - }); - - ctx.responseShouldHaveFields(...ctx.fields.reaction); - - ctx.responseShouldHaveUUID(); - - ctx.responseShould('have data matching the request', () => { - ctx.response.should.deep.include({ - kind: 'comment', - activity_id: eatActivity.id, - user_id: ctx.bob.userId, - }); - ctx.response.data.should.eql(commentData); - comment = ctx.response; - }); - - describe('and then alice reads bob his feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.feed('user', ctx.bob.user).get(); - }); - ctx.responseShouldHaveActivityWithFields('reaction'); - ctx.activityShould('contain the expected data', () => { - ctx.activity.should.include(expectedCommentData); - commentActivity = ctx.activity; - }); - }); - - describe('and then alice reads her own notification feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.feed('notification').get(); - }); - ctx.responseShouldHaveActivityInGroupWithFields('reaction'); - ctx.activityShould('be the same as on bob his feed', () => { - ctx.activity.should.eql(commentActivity); - }); - }); - - describe('and then carl reads his notification feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.carl.feed('notification').get(); - }); - ctx.responseShouldHaveNoActivities(); - }); - - describe('and then dave reads his notification feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.dave.feed('notification').get(); - }); - ctx.responseShouldHaveActivityInGroupWithFields('reaction'); - ctx.activityShould('be the same as on bob his feed', () => { - ctx.activity.should.eql(commentActivity); - }); - }); - }); - - describe('When alice tries to delete bob his comment', () => { - ctx.requestShouldError(403, async () => { - commentData = { - text: 'Alice you are the best!!!!', - }; - ctx.response = await ctx.alice.reactions.delete(comment.id); - }); - }); - - describe('When bob deletes his comment', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.bob.reactions.delete(comment.id); - }); - - ctx.responseShould('be empty JSON', () => { - ctx.response.should.eql({}); - }); - - describe('and then alice reads bob his feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.feed('user', ctx.bob.user).get(); - }); - ctx.responseShouldHaveNoActivities(); - }); - - describe('and then alice reads her own notification feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.alice.feed('notification').get(); - }); - ctx.responseShouldHaveNoActivities(); - }); - - describe('and then carl reads his notification feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.carl.feed('notification').get(); - }); - ctx.responseShouldHaveNoActivities(); - }); - - describe('and then dave reads his notification feed', () => { - ctx.requestShouldNotError(async () => { - ctx.response = await ctx.dave.feed('notification').get(); - }); - ctx.responseShouldHaveNoActivities(); - }); - }); - - describe('When alice tries to set a string as the reaction data', () => { - ctx.requestShouldError(400, async () => { - ctx.response = await ctx.alice.react('comment', eatActivity.id, { - data: 'some string', - }); - }); + let ctx = new CloudContext(); + + let eatActivity; + let commentActivity; + let comment; + let expectedCommentData; + let commentData = { + text: 'Looking yummy! @carl wanna get this on Tuesday?', + }; + + ctx.createUsers(); + describe('When alice eats a cheese burger', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.feed('user').addActivity({ + actor: ctx.alice.user, + verb: 'eat', + object: 'cheeseburger', + }); + eatActivity = ctx.response; + delete eatActivity.duration; + eatActivity.actor = ctx.alice.user.full; }); + }); + + describe('When bob comments on that alice ate the cheese burger', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.bob.react('comment', eatActivity.id, { + data: commentData, + targetFeeds: [ + ctx.bob.feed('user').id, + ctx.bob.feed('notification', ctx.alice.userId), + ctx.bob.feed('notification', ctx.carl.userId), + ], + }); + comment = ctx.response; + }); + + ctx.responseShouldHaveFields(...ctx.fields.reaction); + + ctx.responseShouldHaveUUID(); + + ctx.responseShould('have data matching the request', () => { + ctx.response.should.deep.include({ + kind: 'comment', + activity_id: eatActivity.id, + user_id: ctx.bob.userId, + }); + ctx.response.data.should.eql(commentData); + }); + + describe('and then alice reads bob his feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.feed('user', ctx.bob.user).get(); + }); + ctx.responseShouldHaveActivityWithFields('reaction'); + ctx.activityShould('contain the expected data', () => { + expectedCommentData = { + verb: 'comment', + foreign_id: `reaction:${comment.id}`, + time: comment.created_at.slice(0, -1), // chop off the Z suffix + target: '', + origin: null, + }; + + ctx.activity.should.include(expectedCommentData); + ctx.activity.actor.should.eql(ctx.bob.user.full); + ctx.activity.object.should.eql(eatActivity); + ctx.activity.reaction.should.eql(comment); + commentActivity = ctx.activity; + }); + }); + + describe('and then alice reads her own notification feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.feed('notification').get(); + }); + ctx.responseShouldHaveActivityInGroupWithFields('reaction'); + ctx.activityShould('be the same as on bob his feed', () => { + ctx.activity.should.eql(commentActivity); + }); + }); + + describe('and then carl reads his notification feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.carl.feed('notification').get(); + }); + ctx.responseShouldHaveActivityInGroupWithFields('reaction'); + ctx.activityShould('be the same as on bob his feed', () => { + ctx.activity.should.eql(commentActivity); + }); + }); + }); + + describe('When alice tries to update bob his comment', () => { + ctx.requestShouldError(403, async () => { + commentData = { + text: 'Alice you are the best!!!!', + }; + ctx.response = await ctx.alice.reactions.update(comment.id, { + data: commentData, + }); + }); + }); + + describe('When bob updates his comment and tags dave instead of carl', () => { + ctx.requestShouldNotError(async () => { + commentData = { + text: 'Looking yummy! @dave wanna get this on Tuesday?', + }; + ctx.response = await ctx.bob.reactions.update(comment.id, { + data: commentData, + targetFeeds: [ + ctx.bob.feed('user').id, + ctx.bob.feed('notification', ctx.alice.userId), + ctx.bob.feed('notification', ctx.dave.userId), + ], + }); + }); + + ctx.responseShouldHaveFields(...ctx.fields.reaction); + + ctx.responseShouldHaveUUID(); + + ctx.responseShould('have data matching the request', () => { + ctx.response.should.deep.include({ + kind: 'comment', + activity_id: eatActivity.id, + user_id: ctx.bob.userId, + }); + ctx.response.data.should.eql(commentData); + comment = ctx.response; + }); + + describe('and then alice reads bob his feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.feed('user', ctx.bob.user).get(); + }); + ctx.responseShouldHaveActivityWithFields('reaction'); + ctx.activityShould('contain the expected data', () => { + ctx.activity.should.include(expectedCommentData); + commentActivity = ctx.activity; + }); + }); + + describe('and then alice reads her own notification feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.feed('notification').get(); + }); + ctx.responseShouldHaveActivityInGroupWithFields('reaction'); + ctx.activityShould('be the same as on bob his feed', () => { + ctx.activity.should.eql(commentActivity); + }); + }); + + describe('and then carl reads his notification feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.carl.feed('notification').get(); + }); + ctx.responseShouldHaveNoActivities(); + }); + + describe('and then dave reads his notification feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.dave.feed('notification').get(); + }); + ctx.responseShouldHaveActivityInGroupWithFields('reaction'); + ctx.activityShould('be the same as on bob his feed', () => { + ctx.activity.should.eql(commentActivity); + }); + }); + }); + + describe('When alice tries to delete bob his comment', () => { + ctx.requestShouldError(403, async () => { + commentData = { + text: 'Alice you are the best!!!!', + }; + ctx.response = await ctx.alice.reactions.delete(comment.id); + }); + }); + + describe('When bob deletes his comment', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.bob.reactions.delete(comment.id); + }); + + ctx.responseShould('be empty JSON', () => { + ctx.response.should.eql({}); + }); + + describe('and then alice reads bob his feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.feed('user', ctx.bob.user).get(); + }); + ctx.responseShouldHaveNoActivities(); + }); + + describe('and then alice reads her own notification feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.alice.feed('notification').get(); + }); + ctx.responseShouldHaveNoActivities(); + }); + + describe('and then carl reads his notification feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.carl.feed('notification').get(); + }); + ctx.responseShouldHaveNoActivities(); + }); + + describe('and then dave reads his notification feed', () => { + ctx.requestShouldNotError(async () => { + ctx.response = await ctx.dave.feed('notification').get(); + }); + ctx.responseShouldHaveNoActivities(); + }); + }); + + describe('When alice tries to set a string as the reaction data', () => { + ctx.requestShouldError(400, async () => { + ctx.response = await ctx.alice.react('comment', eatActivity.id, { + data: 'some string', + }); + }); + }); }); diff --git a/test/integration/cloud/utils.js b/test/integration/cloud/utils.js index 4e527e64..6060d1cf 100644 --- a/test/integration/cloud/utils.js +++ b/test/integration/cloud/utils.js @@ -6,291 +6,268 @@ var expect = require('chai').expect; var should = require('chai').should(); class CloudContext { - constructor() { - this.response = null; - this.prevResponse = null; - this.activity = null; - this.failed = false; - this.cheeseBurger = null; - this.cheeseBurgerData = { - name: 'cheese burger', - toppings: ['cheese'], - }; - this.client = stream.connectCloud(config.API_KEY, config.APP_ID, { - group: 'testCycle', - protocol: 'https', - keepAlive: false, - }); - this.alice = this.createUserSession('alice'); - this.bob = this.createUserSession('bob'); - this.carl = this.createUserSession('carl'); - this.dave = this.createUserSession('dave'); - this.root = this.createUserSession('root', { stream_admin: true }); - this.userData = { - alice: { - name: 'Alice Abbot', - likes: ['apples', 'ajax'], - }, - bob: { - name: 'Bob Baker', - likes: ['berries'], - }, - carl: { - name: 'Carl Church', - likes: ['cherries', 'curry'], - }, - dave: { - name: 'Dave Dawson', - likes: ['dark chocolate'], - }, - root: { - name: 'The ultimate user', - likes: ['power'], - }, - }; + constructor() { + this.response = null; + this.prevResponse = null; + this.activity = null; + this.failed = false; + this.cheeseBurger = null; + this.cheeseBurgerData = { + name: 'cheese burger', + toppings: ['cheese'], + }; + this.client = stream.connectCloud(config.API_KEY, config.APP_ID, { + group: 'testCycle', + protocol: 'https', + keepAlive: false, + }); + this.alice = this.createUserSession('alice'); + this.bob = this.createUserSession('bob'); + this.carl = this.createUserSession('carl'); + this.dave = this.createUserSession('dave'); + this.root = this.createUserSession('root', { stream_admin: true }); + this.userData = { + alice: { + name: 'Alice Abbot', + likes: ['apples', 'ajax'], + }, + bob: { + name: 'Bob Baker', + likes: ['berries'], + }, + carl: { + name: 'Carl Church', + likes: ['cherries', 'curry'], + }, + dave: { + name: 'Dave Dawson', + likes: ['dark chocolate'], + }, + root: { + name: 'The ultimate user', + likes: ['power'], + }, + }; - this.fields = { - collection: [ - 'id', - 'created_at', - 'updated_at', - 'collection', - 'data', - ], - reaction: [ - 'id', - 'kind', - 'activity_id', - 'user_id', - 'data', - 'created_at', - 'updated_at', - ], - activity: [ - 'id', - 'foreign_id', - 'time', - 'actor', - 'verb', - 'target', - 'object', - 'origin', - ], - reactionInActivity: [ - 'id', - 'kind', - 'user', - 'data', - 'created_at', - 'updated_at', - ], - }; - } + this.fields = { + collection: ['id', 'created_at', 'updated_at', 'collection', 'data'], + reaction: [ + 'id', + 'kind', + 'activity_id', + 'user_id', + 'data', + 'created_at', + 'updated_at', + ], + activity: [ + 'id', + 'foreign_id', + 'time', + 'actor', + 'verb', + 'target', + 'object', + 'origin', + ], + reactionInActivity: [ + 'id', + 'kind', + 'user', + 'data', + 'created_at', + 'updated_at', + ], + }; + } - createUserSession(userId, extraData) { - userId = randUserId(userId); - return this.client.createUserSession( - signing.JWTUserSessionToken(config.API_SECRET, userId, extraData), - ); - } + createUserSession(userId, extraData) { + userId = randUserId(userId); + return this.client.createUserSession( + signing.JWTUserSessionToken(config.API_SECRET, userId, extraData) + ); + } - wrapFn(fn) { - let ctx = this; - if (fn.length == 0) { - return async function() { - if (ctx.failed) { - this.skip(); - } - try { - await fn(); - } catch (ex) { - ctx.failed = true; - throw ex; - } - }; + wrapFn(fn) { + let ctx = this; + if (fn.length == 0) { + return async function() { + if (ctx.failed) { + this.skip(); + } + try { + await fn(); + } catch (ex) { + ctx.failed = true; + throw ex; } - return function(done) { - if (ctx.failed) { - this.skip(); - } - try { - fn(done); - } catch (ex) { - ctx.failed = true; - throw ex; - } - }; + }; } + return function(done) { + if (ctx.failed) { + this.skip(); + } + try { + fn(done); + } catch (ex) { + ctx.failed = true; + throw ex; + } + }; + } - // test is a wrapper around "it" that skips the test if a previous one in - // the same context failed already. - test(label, fn) { - it(label, this.wrapFn(fn)); - } + // test is a wrapper around "it" that skips the test if a previous one in + // the same context failed already. + test(label, fn) { + it(label, this.wrapFn(fn)); + } - // afterTest is a wrapper around "after" that skips the after if a previous - // test or afterTest in the same context failed already. - afterTest(fn) { - after(this.wrapFn(fn)); - } + // afterTest is a wrapper around "after" that skips the after if a previous + // test or afterTest in the same context failed already. + afterTest(fn) { + after(this.wrapFn(fn)); + } - requestShouldNotError(fn) { - this.test('the request should not error', fn); - } - noRequestsShouldError(fn) { - this.test('the request should not error', fn); - } - responseShould(label, fn) { - this.test('the response should ' + label, fn); - } - activityShould(label, fn) { - this.test('the activity should ' + label, fn); - } + requestShouldNotError(fn) { + this.test('the request should not error', fn); + } + noRequestsShouldError(fn) { + this.test('the request should not error', fn); + } + responseShould(label, fn) { + this.test('the response should ' + label, fn); + } + activityShould(label, fn) { + this.test('the activity should ' + label, fn); + } - requestShouldError(statusCode, fn) { - this.test( - 'the request should error with status ' + statusCode, - async () => { - try { - await fn(); - expect.fail(null, null, 'request should not succeed'); - } catch (e) { - if (!(e instanceof stream.errors.StreamApiError)) { - throw e; - } - e.response.statusCode.should.equal(statusCode); - this.response = e.error; - } - }, - ); - } + requestShouldError(statusCode, fn) { + this.test( + 'the request should error with status ' + statusCode, + async () => { + try { + await fn(); + expect.fail(null, null, 'request should not succeed'); + } catch (e) { + if (!(e instanceof stream.errors.StreamApiError)) { + throw e; + } + e.response.statusCode.should.equal(statusCode); + this.response = e.error; + } + } + ); + } - responseShouldHaveFields(...fields) { - this.responseShould('have all expected fields', () => { - this.response.should.have.all.keys(fields); - }); - } + responseShouldHaveFields(...fields) { + this.responseShould('have all expected fields', () => { + this.response.should.have.all.keys(fields); + }); + } - responseShouldHaveNoActivities() { - this.responseShould('have no activities', () => { - this.response.results.should.eql([]); - }); - } + responseShouldHaveNoActivities() { + this.responseShould('have no activities', () => { + this.response.results.should.eql([]); + }); + } - responseShouldHaveActivityInGroupWithFields(...fields) { - this.responseShould( - 'have a single group with a single activity', - () => { - this.response.should.include.keys( - 'results', - 'next', - 'duration', - ); - this.response.results.should.be.lengthOf(1); - this.response.results[0].activities.should.be.lengthOf(1); - this.activity = this.response.results[0].activities[0]; - }, - ); + responseShouldHaveActivityInGroupWithFields(...fields) { + this.responseShould('have a single group with a single activity', () => { + this.response.should.include.keys('results', 'next', 'duration'); + this.response.results.should.be.lengthOf(1); + this.response.results[0].activities.should.be.lengthOf(1); + this.activity = this.response.results[0].activities[0]; + }); - this.test('the activity should have all expected fields', () => { - this.activity.should.have.all.keys( - ...this.fields.activity, - ...fields, - ); - }); - } + this.test('the activity should have all expected fields', () => { + this.activity.should.have.all.keys(...this.fields.activity, ...fields); + }); + } - responseShouldHaveActivityWithFields(...fields) { - this.responseShould('have a single activity', () => { - this.response.should.have.all.keys('results', 'next', 'duration'); - this.response.results.should.be.lengthOf(1); - this.activity = this.response.results[0]; - }); + responseShouldHaveActivityWithFields(...fields) { + this.responseShould('have a single activity', () => { + this.response.should.have.all.keys('results', 'next', 'duration'); + this.response.results.should.be.lengthOf(1); + this.activity = this.response.results[0]; + }); - this.test('the activity should have all expected fields', () => { - this.activity.should.have.all.keys( - ...this.fields.activity, - ...fields, - ); - }); - } + this.test('the activity should have all expected fields', () => { + this.activity.should.have.all.keys(...this.fields.activity, ...fields); + }); + } - responseShouldHaveUUID() { - this.responseShould('have a generated UUID as ID', () => { - this.response.id.should.be.a('string').lengthOf(36); - }); - } + responseShouldHaveUUID() { + this.responseShould('have a generated UUID as ID', () => { + this.response.id.should.be.a('string').lengthOf(36); + }); + } - responseShouldHaveNewUpdatedAt() { - this.responseShould('have an updated updated_at', () => { - should.exist(this.prevResponse.updated_at); - should.exist(this.response.updated_at); - this.response.updated_at.should.not.equal( - this.prevResponse.updated_at, - ); - }); - } + responseShouldHaveNewUpdatedAt() { + this.responseShould('have an updated updated_at', () => { + should.exist(this.prevResponse.updated_at); + should.exist(this.response.updated_at); + this.response.updated_at.should.not.equal(this.prevResponse.updated_at); + }); + } - responseShouldEqualPreviousResponse() { - this.responseShould('be the same as the previous response', () => { - should.exist(this.prevResponse); - should.exist(this.response); - this.response.should.eql(this.prevResponse); - }); - } + responseShouldEqualPreviousResponse() { + this.responseShould('be the same as the previous response', () => { + should.exist(this.prevResponse); + should.exist(this.response); + this.response.should.eql(this.prevResponse); + }); + } - aliceAddsCheeseBurger() { - describe('When alice adds a cheese burger to the food collection', () => { - this.requestShouldNotError(async () => { - this.response = await this.alice - .storage('food') - .add(null, this.cheeseBurgerData); - }); + aliceAddsCheeseBurger() { + describe('When alice adds a cheese burger to the food collection', () => { + this.requestShouldNotError(async () => { + this.response = await this.alice + .storage('food') + .add(null, this.cheeseBurgerData); + }); - this.responseShouldHaveFields(...this.fields.collection); + this.responseShouldHaveFields(...this.fields.collection); - this.responseShouldHaveUUID(); + this.responseShouldHaveUUID(); - this.responseShould( - 'have collection and data matching the request', - () => { - this.response.collection.should.equal('food'); - this.response.data.should.eql(this.cheeseBurgerData); - }, - ); + this.responseShould( + 'have collection and data matching the request', + () => { + this.response.collection.should.equal('food'); + this.response.data.should.eql(this.cheeseBurgerData); + } + ); - this.afterTest(() => { - this.cheeseBurger = this.alice.objectFromResponse( - this.response, - ); - }); - }); - } + this.afterTest(() => { + this.cheeseBurger = this.alice.objectFromResponse(this.response); + }); + }); + } - createUsers() { - describe('When creating the users', () => { - this.noRequestsShouldError(async () => { - await Promise.all([ - this.alice.user.create(this.userData.alice), - this.bob.user.create(this.userData.bob), - this.carl.user.create(this.userData.carl), - this.dave.user.create(this.userData.dave), - ]); - }); - }); - } + createUsers() { + describe('When creating the users', () => { + this.noRequestsShouldError(async () => { + await Promise.all([ + this.alice.user.create(this.userData.alice), + this.bob.user.create(this.userData.bob), + this.carl.user.create(this.userData.carl), + this.dave.user.create(this.userData.dave), + ]); + }); + }); + } - reactionToReactionInActivity(reaction, user) { - reaction = Object.assign({}, reaction); + reactionToReactionInActivity(reaction, user) { + reaction = Object.assign({}, reaction); - delete reaction.activity_id; - delete reaction.user_id; - reaction.user = user.full; + delete reaction.activity_id; + delete reaction.user_id; + reaction.user = user.full; - return reaction; - } + return reaction; + } } module.exports = { - CloudContext: CloudContext, + CloudContext: CloudContext, }; diff --git a/test/integration/common/client_test.js b/test/integration/common/client_test.js index eab8f489..924496eb 100644 --- a/test/integration/common/client_test.js +++ b/test/integration/common/client_test.js @@ -1,482 +1,507 @@ -var init = require('../utils/hooks').init - , beforeEachFn = require('../utils/hooks').beforeEach - , expect = require('expect.js') - , errors = require('../../../src/getstream').errors - , utils = require('../utils') - , config = require('../utils/config'); +var init = require('../utils/hooks').init, + beforeEachFn = require('../utils/hooks').beforeEach, + expect = require('expect.js'), + errors = require('../../../src/getstream').errors, + utils = require('../utils'), + config = require('../utils/config'); describe('[INTEGRATION] Stream client (Common)', function() { - - init.call(this); - beforeEach(beforeEachFn); - - it.skip('handlers', function() { - var called = {}; - var self = this; - called.request = 0; - called.response = 0; - - function callback() { - called.request += 1; - } - - function responseCallback() { - called.response += 1; - } - - this.client.on('request', callback); - this.client.on('response', responseCallback); - - return this.user1.get({ - 'limit': 1 - }) - .then(function() { - self.client.off(); - return self.user1.get({ 'limit': 1 }); - }) - .then(function() { - expect(called.request).to.eql(1); - expect(called.response).to.eql(1); - }); - }); - - it.skip('err not null', function(done) { - this.user1.addActivity({ - actor: 'actorname', - actorName: 'abc', - verb: 'follow' - }, function(error, response, body) { - expect(error).to.be.an(Object); - done(); - }); - }); - - it('signing', function(done) { - expect(this.user1.token).to.be.an('string'); + init.call(this); + beforeEach(beforeEachFn); + + it.skip('handlers', function() { + var called = {}; + var self = this; + called.request = 0; + called.response = 0; + + function callback() { + called.request += 1; + } + + function responseCallback() { + called.response += 1; + } + + this.client.on('request', callback); + this.client.on('response', responseCallback); + + return this.user1 + .get({ + limit: 1, + }) + .then(function() { + self.client.off(); + return self.user1.get({ limit: 1 }); + }) + .then(function() { + expect(called.request).to.eql(1); + expect(called.response).to.eql(1); + }); + }); + + it.skip('err not null', function(done) { + this.user1.addActivity( + { + actor: 'actorname', + actorName: 'abc', + verb: 'follow', + }, + function(error, response, body) { + expect(error).to.be.an(Object); done(); + } + ); + }); + + it('signing', function(done) { + expect(this.user1.token).to.be.an('string'); + done(); + }); + + it('get wrong feed', function(done) { + var self = this; + + var getFeed = function() { + self.client.feed('flat1'); + }; + expect(getFeed).to.throwException(function(e) { + expect(e).to.be.a(errors.FeedError); }); + done(); + }); - it('get wrong feed', function(done) { - var self = this; + it('get wrong format', function(done) { + var self = this; - var getFeed = function() { - self.client.feed('flat1'); - }; - expect(getFeed).to.throwException(function(e) { - expect(e).to.be.a(errors.FeedError); - }); - done(); + var getFeed = function() { + self.client.feed('flat:1', '2'); + }; + expect(getFeed).to.throwException(function(e) { + expect(e).to.be.a(errors.FeedError); }); + done(); + }); - it('get wrong format', function(done) { - var self = this; + it('get invalid format', function() { + var self = this; - var getFeed = function() { - self.client.feed('flat:1', '2'); - }; - expect(getFeed).to.throwException(function(e) { - expect(e).to.be.a(errors.FeedError); - }); - done(); + var invalidFormats = []; + invalidFormats.push(function() { + self.client.feed('flat 1', '2'); }); - - it('get invalid format', function() { - var self = this; - - var invalidFormats = []; - invalidFormats.push(function() { - self.client.feed('flat 1', '2'); - }); - invalidFormats.push(function() { - self.client.feed('flat1', '2:3'); - }); - invalidFormats.push(function() { - self.user1.follow('flat 1', '3'); - }); - invalidFormats.push(function() { - self.user1.follow('flat', '3 3'); - }); - // verify all of the above throw an error - for (var i = 0; i < invalidFormats.length; i++) { - var callable = invalidFormats[i]; - expect(callable).to.throwException(function(e) { - expect(e).to.be.a(errors.FeedError); - }); - } - // a dash should be allowed - this.client.feed('flat1', '2-3', 'token'); + invalidFormats.push(function() { + self.client.feed('flat1', '2:3'); }); - - it('add activity', function() { - var self = this; - var activityId = null; - var activity = { - 'actor': 'test-various:characters', - 'verb': 'add', - 'object': 1, - 'tweet': 'hello world' - }; - - return this.user1.addActivity(activity) - .then(function(body) { - activityId = body['id']; - return self.user1.get({'limit': 1}); - }) - .then(function(body) { - expect(body['results'][0]['id']).to.eql(activityId); - }); + invalidFormats.push(function() { + self.user1.follow('flat 1', '3'); }); - - it('add complex activity', function() { - var self = this; - var activityId = null; - var activity = { - 'actor': 1, - 'verb': 'add', - 'object': 1 - }; - activity['participants'] = ['Thierry', 'Tommaso']; - activity['route'] = { - 'name': 'Vondelpark', - 'distance': '20' - }; - var currentDate = new Date(); - activity['date'] = currentDate; - var isoDate = currentDate.toISOString(); - - return this.user1.addActivity(activity) - .then(function(body) { - activityId = body['id']; - return self.user1.get({ 'limit': 1 }); - }) - .then(function(body) { - expect(body['results'][0]['id']).to.eql(activityId); - expect(body['results'][0]['participants']).to.eql(['Thierry', 'Tommaso']); - expect(body['results'][0]['route']).to.eql({ - 'name': 'Vondelpark', - 'distance': '20' - }); - expect(body['results'][0]['date']).to.eql(isoDate); - }); - }); - - it('add activity no callback', function() { - var activity = { - 'actor': 1, - 'verb': 'add', - 'object': 1 - }; - - return this.user1.addActivity(activity); + invalidFormats.push(function() { + self.user1.follow('flat', '3 3'); }); - - it('remove activity', function() { - var self = this; - var activity = { - 'actor': 1, - 'verb': 'add', - 'object': 1 - }; - - return this.user1.addActivity(activity) - .then(function(body) { - var activityId = body['id']; - return self.user1.removeActivity(activityId); - }); + // verify all of the above throw an error + for (var i = 0; i < invalidFormats.length; i++) { + var callable = invalidFormats[i]; + expect(callable).to.throwException(function(e) { + expect(e).to.be.a(errors.FeedError); + }); + } + // a dash should be allowed + this.client.feed('flat1', '2-3', 'token'); + }); + + it('add activity', function() { + var self = this; + var activityId = null; + var activity = { + actor: 'test-various:characters', + verb: 'add', + object: 1, + tweet: 'hello world', + }; + + return this.user1 + .addActivity(activity) + .then(function(body) { + activityId = body['id']; + return self.user1.get({ limit: 1 }); + }) + .then(function(body) { + expect(body['results'][0]['id']).to.eql(activityId); + }); + }); + + it('add complex activity', function() { + var self = this; + var activityId = null; + var activity = { + actor: 1, + verb: 'add', + object: 1, + }; + activity['participants'] = ['Thierry', 'Tommaso']; + activity['route'] = { + name: 'Vondelpark', + distance: '20', + }; + var currentDate = new Date(); + activity['date'] = currentDate; + var isoDate = currentDate.toISOString(); + + return this.user1 + .addActivity(activity) + .then(function(body) { + activityId = body['id']; + return self.user1.get({ limit: 1 }); + }) + .then(function(body) { + expect(body['results'][0]['id']).to.eql(activityId); + expect(body['results'][0]['participants']).to.eql([ + 'Thierry', + 'Tommaso', + ]); + expect(body['results'][0]['route']).to.eql({ + name: 'Vondelpark', + distance: '20', + }); + expect(body['results'][0]['date']).to.eql(isoDate); + }); + }); + + it('add activity no callback', function() { + var activity = { + actor: 1, + verb: 'add', + object: 1, + }; + + return this.user1.addActivity(activity); + }); + + it('remove activity', function() { + var self = this; + var activity = { + actor: 1, + verb: 'add', + object: 1, + }; + + return this.user1.addActivity(activity).then(function(body) { + var activityId = body['id']; + return self.user1.removeActivity(activityId); }); - - it('remove activity foreign id', function() { - var self = this; - var activity = { - 'actor': 1, - 'verb': 'add', - 'object': 1, - 'foreign_id': 'add:2' - }; - var now = new Date(); - activity.time = now.toISOString(); - - return self.user4.addActivity(activity) - .then(function(body) { - return self.user4.removeActivity({ - foreignId: 'add:2' - }); - }) - .then(function() { - return self.user4.get({ limit: 10 }); - }) - .then(function(body) { - expect(body['results'].length).to.be(0); - }); + }); + + it('remove activity foreign id', function() { + var self = this; + var activity = { + actor: 1, + verb: 'add', + object: 1, + foreign_id: 'add:2', + }; + var now = new Date(); + activity.time = now.toISOString(); + + return self.user4 + .addActivity(activity) + .then(function(body) { + return self.user4.removeActivity({ + foreignId: 'add:2', + }); + }) + .then(function() { + return self.user4.get({ limit: 10 }); + }) + .then(function(body) { + expect(body['results'].length).to.be(0); + }); + }); + + it('add activities', function() { + var self = this; + var activityIdFirst, activityIdLast; + var activities = [ + { + actor: 1, + verb: 'tweet', + object: 1, + }, + { + actor: 2, + verb: 'tweet', + object: 3, + }, + ]; + + return this.user1 + .addActivities(activities) + .then(function(body) { + activityIdFirst = body['activities'][0]['id']; + activityIdLast = body['activities'][1]['id']; + return self.user1.get({ limit: 2 }); + }) + .then(function(body) { + expect(body['results'][0]['id']).to.eql(activityIdLast); + expect(body['results'][1]['id']).to.eql(activityIdFirst); + }); + }); + + it('follow', function() { + var self = this; + var activityId = null; + + var activity = { + actor: 1, + verb: 'add', + object: 1, + }; + + return self.user1 + .addActivity(activity) + .then(function(body) { + activityId = body['id']; + return self.aggregated2.follow('user', self.user1.userId); + }) + .then(function() { + return utils.delay(config.READ_TIMEOUT); + }) + .then(function check() { + return self.aggregated2.get({ limit: 1 }); + }) + .then(function(body) { + expect(body['results'][0]['activities'][0]['id']).to.eql(activityId); + }); + }); + + it('follow without callback', function() { + return this.aggregated2.follow('user', '111'); + }); + + it('follow with copy limit', function() { + return this.aggregated2.follow('user', '999', { + limit: 500, }); - - it('add activities', function() { - var self = this; - var activityIdFirst, activityIdLast; - var activities = [{ - 'actor': 1, - 'verb': 'tweet', - 'object': 1 - }, { - 'actor': 2, - 'verb': 'tweet', - 'object': 3 - }, ]; - - return this.user1.addActivities(activities) - .then(function(body) { - activityIdFirst = body['activities'][0]['id']; - activityIdLast = body['activities'][1]['id']; - return self.user1.get({ 'limit': 2 }); - }) - .then(function(body) { - expect(body['results'][0]['id']).to.eql(activityIdLast); - expect(body['results'][1]['id']).to.eql(activityIdFirst); - }); + }); + + it('unfollow', function() { + var self = this; + var activityId = null; + + var activity = { + actor: 1, + verb: 'add', + object: 1, + }; + + return self.user1 + .addActivity(activity) + .then(function follow(body) { + activityId = body['id']; + return self.aggregated2.follow('user', self.user1.userId); + }) + .then(function() { + return self.aggregated2.unfollow('user', self.user1.userId); + }) + .then(function() { + return utils.delay(config.READ_TIMEOUT); + }) + .then(function() { + return self.aggregated2.get({ limit: 1 }); + }) + .then(function(body) { + var firstResult = body['results'][0]; + var activityFound = firstResult + ? firstResult['activities'][0]['id'] + : null; + expect(activityFound).to.not.eql(activityId); + }); + }); + + it('unfollow keep_history', function() { + var self = this; + + var activityId = null; + + var activity = { + actor: 1, + verb: 'add', + object: 1, + }; + return self.user1 + .addActivity(activity) + .then(function(body) { + activityId = body['id']; + return self.flat3.follow('user', self.user1.userId); + }) + .then(function() { + return self.flat3.unfollow('user', self.user1.userId, { + keepHistory: true, + }); + }) + .then(function() { + return utils.delay(config.READ_TIMEOUT); + }) + .then(function() { + return self.flat3.get({ limit: 1 }); + }) + .then(function(body) { + var firstResult = body['results'][0]; + var activityFound = firstResult ? firstResult['id'] : null; + expect(activityFound).to.eql(activityId); + }); + }); + + it('list followers', function() { + return this.user1.followers({ + limit: '10', + offset: '10', }); + }); - - it('follow', function() { - var self = this; - var activityId = null; - - var activity = { - 'actor': 1, - 'verb': 'add', - 'object': 1 - }; - - return self.user1.addActivity(activity) - .then(function (body) { - activityId = body['id']; - return self.aggregated2.follow('user', self.user1.userId); - }) - .then(function() { - return utils.delay(config.READ_TIMEOUT); - }) - .then(function check() { - return self.aggregated2.get({ 'limit': 1 }); - }) - .then(function(body) { - expect(body['results'][0]['activities'][0]['id']).to.eql(activityId); - }); + it('list following', function() { + return this.user1.following({ + limit: '10', + offset: '10', }); + }); - it('follow without callback', function() { - return this.aggregated2.follow('user', '111'); - }); + it('do i follow', function() { + var self = this; - it('follow with copy limit', function() { - return this.aggregated2.follow('user', '999', { - limit: 500 + return this.user1 + .follow('flat', '33') + .then(function doifollow() { + return self.user1.following({ + filter: ['flat:33', 'flat:44'], }); + }) + .then(function callback(body) { + var results = body.results; + expect(results.length).to.eql(1); + expect(results[0].target_id).to.eql('flat:33'); + }); + }); + + it('get read-only feed', function() { + return this.user1ReadOnly.get({ + limit: 2, }); - - it('unfollow', function() { - var self = this; - var activityId = null; - + }); + + it('get filtering', function() { + // first add three activities + //TODO find a library to make async testing easier on the eye + var self = this; + var activityIdOne = null; + var activityIdTwo = null; + var activityIdThree = null; + + var activity = { + actor: 1, + verb: 'add', + object: 1, + }; + + return self.user1 + .addActivity(activity) + .then(function add2(body) { + activityIdOne = body['id']; var activity = { - 'actor': 1, - 'verb': 'add', - 'object': 1 + actor: 2, + verb: 'watch', + object: 2, }; - - return self.user1.addActivity(activity) - .then(function follow(body) { - activityId = body['id']; - return self.aggregated2.follow('user', self.user1.userId); - }).then(function () { - return self.aggregated2.unfollow('user', self.user1.userId); - }).then(function () { - return utils.delay(config.READ_TIMEOUT); - }).then(function() { - return self.aggregated2.get({ 'limit': 1 }); - }).then(function(body) { - var firstResult = body['results'][0]; - var activityFound = (firstResult) ? firstResult['activities'][0]['id'] : null; - expect(activityFound).to.not.eql(activityId); - }); - }); - - it('unfollow keep_history', function() { - var self = this; - - var activityId = null; - + return self.user1.addActivity(activity); + }) + .then(function add3(body) { + activityIdTwo = body['id']; var activity = { - 'actor': 1, - 'verb': 'add', - 'object': 1 + actor: 3, + verb: 'run', + object: 2, }; - return self.user1.addActivity(activity) - .then(function (body) { - activityId = body['id']; - return self.flat3.follow('user', self.user1.userId); - }) - .then(function () { - return self.flat3.unfollow('user', self.user1.userId, { - keepHistory: true - }); - }) - .then(function() { - return utils.delay(config.READ_TIMEOUT); - }) - .then(function() { - return self.flat3.get({ 'limit': 1 }); - }) - .then(function(body) { - var firstResult = body['results'][0]; - var activityFound = (firstResult) ? firstResult['id'] : null; - expect(activityFound).to.eql(activityId); - }); - }); - - it('list followers', function() { - return this.user1.followers({ - limit: '10', - offset: '10' + return self.user1.addActivity(activity); + }) + .then(function(body) { + return utils.delay(200, body); + }) + .then(function get(body) { + activityIdThree = body['id']; + return self.user1.get({ + limit: 2, }); - }); - - it('list following', function() { - return this.user1.following({ - limit: '10', - offset: '10' + }) + .then(function check(body) { + expect(body['results'].length).to.eql(2); + expect(body['results'][0]['id']).to.eql(activityIdThree); + expect(body['results'][1]['id']).to.eql(activityIdTwo); + + return self.user1.get({ + limit: 2, + offset: 1, }); - }); - - it('do i follow', function() { - var self = this; - - return this.user1.follow('flat', '33') - .then(function doifollow() { - return self.user1.following({ - 'filter': ['flat:33', 'flat:44'] - }); - }) - .then(function callback(body) { - var results = body.results; - expect(results.length).to.eql(1); - expect(results[0].target_id).to.eql('flat:33'); - }); - }); - - it('get read-only feed', function() { - return this.user1ReadOnly.get({ - 'limit': 2 + }) + .then(function check2(body) { + expect(body['results'].length).to.eql(2); + expect(body['results'][0]['id']).to.eql(activityIdTwo); + expect(body['results'][1]['id']).to.eql(activityIdOne); + + return self.user1.get({ + limit: 1, + id_lt: activityIdTwo, }); - }); - - it('get filtering', function() { - // first add three activities - //TODO find a library to make async testing easier on the eye - var self = this; - var activityIdOne = null; - var activityIdTwo = null; - var activityIdThree = null; - - var activity = { - 'actor': 1, - 'verb': 'add', - 'object': 1 - }; - - return self.user1.addActivity(activity) - .then(function add2(body) { - activityIdOne = body['id']; - var activity = { - 'actor': 2, - 'verb': 'watch', - 'object': 2 - }; - return self.user1.addActivity(activity); - }) - .then(function add3(body) { - activityIdTwo = body['id']; - var activity = { - 'actor': 3, - 'verb': 'run', - 'object': 2 - }; - return self.user1.addActivity(activity); - }) - .then(function(body) { - return utils.delay(200, body); - }) - .then(function get(body) { - activityIdThree = body['id']; - return self.user1.get({ - 'limit': 2 - }); - }) - .then(function check(body) { - expect(body['results'].length).to.eql(2); - expect(body['results'][0]['id']).to.eql(activityIdThree); - expect(body['results'][1]['id']).to.eql(activityIdTwo); - - return self.user1.get({ - limit: 2, - offset: 1 - }); - }) - .then(function check2(body) { - expect(body['results'].length).to.eql(2); - expect(body['results'][0]['id']).to.eql(activityIdTwo); - expect(body['results'][1]['id']).to.eql(activityIdOne); - - return self.user1.get({ - limit: 1, - id_lt: activityIdTwo - }); - }) - .then(function check3(body) { - expect(body['results'].length).to.eql(1); - expect(body['results'][0]['id']).to.eql(activityIdOne); - }); - - }); - - it('mark read and seen', function() { - // add 2 activities to ensure we have new data - var self = this; + }) + .then(function check3(body) { + expect(body['results'].length).to.eql(1); + expect(body['results'][0]['id']).to.eql(activityIdOne); + }); + }); + + it('mark read and seen', function() { + // add 2 activities to ensure we have new data + var self = this; + var params = { + limit: 2, + }; + var activities = [ + { + actor: 1, + verb: 'add', + object: 1, + }, + { + actor: 2, + verb: 'test', + object: 2, + }, + ]; + + return this.notification3 + .addActivities(activities) + .then(function() { + return self.notification3.get(params); + }) + .then(function(body) { + var notificationId = body['results'][0]['id']; var params = { - limit: 2 + limit: 2, + mark_seen: true, + mark_read: notificationId, }; - var activities = [{ - 'actor': 1, - 'verb': 'add', - 'object': 1 - }, { - 'actor': 2, - 'verb': 'test', - 'object': 2 - }]; - - return this.notification3.addActivities(activities) - .then(function() { - return self.notification3.get(params); - }) - .then(function(body) { - var notificationId = body['results'][0]['id']; - var params = { - limit: 2, - mark_seen: true, - mark_read: notificationId - }; - - return self.notification3.get(params); - }) - .then(function() { - return self.notification3.get(params); - }) - .then(function(body) { - expect(body['results'][0]['is_seen']).to.eql(true); - expect(body['results'][1]['is_seen']).to.eql(true); - expect(body['results'][0]['is_read']).to.eql(true); - expect(body['results'][1]['is_read']).to.eql(false); - // expect(body['unread']).to.be.greaterThan(1); - expect(body['unseen']).to.eql(0); - }); - }); + + return self.notification3.get(params); + }) + .then(function() { + return self.notification3.get(params); + }) + .then(function(body) { + expect(body['results'][0]['is_seen']).to.eql(true); + expect(body['results'][1]['is_seen']).to.eql(true); + expect(body['results'][0]['is_read']).to.eql(true); + expect(body['results'][1]['is_read']).to.eql(false); + // expect(body['unread']).to.be.greaterThan(1); + expect(body['unseen']).to.eql(0); + }); + }); }); diff --git a/test/integration/common/faye_test.js b/test/integration/common/faye_test.js index 1be41db0..466f3928 100644 --- a/test/integration/common/faye_test.js +++ b/test/integration/common/faye_test.js @@ -1,142 +1,145 @@ -var stream = require('../../../src/getstream') - , errors = require('../../../src/getstream').errors - , expect = require('expect.js') - , init = require('../utils/hooks').init - , Promise = require('../../../src/lib/promise') - , utils = require('../utils/index') - , beforeEachFn = require('../utils/hooks').beforeEach; +var stream = require('../../../src/getstream'), + errors = require('../../../src/getstream').errors, + expect = require('expect.js'), + init = require('../utils/hooks').init, + Promise = require('../../../src/lib/promise'), + utils = require('../utils/index'), + beforeEachFn = require('../utils/hooks').beforeEach; describe('[INTEGRATION] Stream client (Faye)', function() { + init.call(this); + beforeEach(beforeEachFn); + + it('fayeGetClient', function() { + this.user1.getFayeClient(); + }); + + it('fayeSubscribe', function() { + return this.user1.subscribe(function callback() {}); + }); + + it('fayeSubscribeListening', function(done) { + this.timeout(60000); + + var testUser1 = this.user1, + testUser2 = this.user2, + testUser3 = this.user3; + + var subscribes = [], + messages = 0, + N_MESSAGES = 3, + activity = { + verb: 'test', + actor: 'User:1', + object: 1, + }; + + var msgCallback = function(message) { + if (message && message['new'] && message['new'].length > 0) { + messages += 1; + } + + if (messages == N_MESSAGES) { + done(); + } + }; + + var httpCallback = function(error, response, body) { + if (error) done(error); + if (response.statusCode !== 201) done(body); + }; + + Promise.all([ + testUser1.subscribe(msgCallback), + testUser2.subscribe(msgCallback), + testUser3.subscribe(msgCallback), + ]).then(function() { + testUser1.addActivity(activity, httpCallback); + testUser2.addActivity(activity, httpCallback); + testUser3.addActivity(activity, httpCallback); + }, done); + }); + + it('fayeSubscribeListeningWrongToken', function(done) { + // Invalid token: + var testUser1 = this.client.feed( + 'user', + '111', + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyZXNvdXJjZSI6IioiLCJhY3Rpb24iOiIqIiwiZmVlZF9pZCI6InVzZXIyMjIifQ.WXZTbUgxfitUVwJOhRKu9HRnpf-Je8AwA5BmiUG6vYY' + ); + // Valid token: + var testUser2 = this.user2; + + var messages = 0, + activity = { + verb: 'test', + actor: 'User:1', + object: 1, + }; + + var httpCallback = function(error, response, body) { + if (error) done(error); + if (response.statusCode !== 201) done(body); + }; + + var doneYet = function(obj) { + messages++; + + if (messages === 2) done(); + }; + + testUser1 + .subscribe(function(message) { + done('testUser1 should not receive any messages'); + }) + .then(function() { + done('testUser1 should not authenticate succefully'); + }, doneYet); + + testUser2.subscribe(doneYet).then(function() { + testUser2.addActivity(activity, httpCallback); + }, done); + }); + + it('fayeSubscribeScope', function(done) { + var client = this.user1ReadOnly.getFayeClient(); + var isDone = false; + + var doneYet = function() { + if (!isDone) { + done(); + isDone = true; + } + }; - init.call(this); - beforeEach(beforeEachFn); - - it('fayeGetClient', function() { - this.user1.getFayeClient(); - }); - - it('fayeSubscribe', function() { - return this.user1.subscribe(function callback() {}); - }); - - it('fayeSubscribeListening', function(done) { - this.timeout(60000); - - var testUser1 = this.user1, - testUser2 = this.user2, - testUser3 = this.user3; - - var subscribes = [], - messages = 0, - N_MESSAGES = 3, - activity = { - 'verb': 'test', - 'actor': 'User:1', - 'object': 1 - }; - - var msgCallback = function(message) { - if (message && message['new'] && message['new'].length > 0) { - messages += 1; - } - - if (messages == N_MESSAGES) { - done(); - } - }; - - var httpCallback = function(error, response, body) { - if (error) done(error); - if (response.statusCode !== 201) done(body); - }; - - Promise.all([ - testUser1.subscribe(msgCallback), - testUser2.subscribe(msgCallback), - testUser3.subscribe(msgCallback) - ]).then(function() { - testUser1.addActivity(activity, httpCallback); - testUser2.addActivity(activity, httpCallback); - testUser3.addActivity(activity, httpCallback); - }, done); - }); - - it('fayeSubscribeListeningWrongToken', function(done) { - // Invalid token: - var testUser1 = this.client.feed('user', '111', 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyZXNvdXJjZSI6IioiLCJhY3Rpb24iOiIqIiwiZmVlZF9pZCI6InVzZXIyMjIifQ.WXZTbUgxfitUVwJOhRKu9HRnpf-Je8AwA5BmiUG6vYY'); - // Valid token: - var testUser2 = this.user2; - - var messages = 0, - activity = { - 'verb': 'test', - 'actor': 'User:1', - 'object': 1 - }; - - var httpCallback = function(error, response, body) { - if (error) done(error); - if (response.statusCode !== 201) done(body); - }; - - var doneYet = function(obj) { - messages++; - - if (messages === 2) done(); - }; - - testUser1.subscribe(function(message) { - done('testUser1 should not receive any messages'); - }).then(function() { - done('testUser1 should not authenticate succefully'); - }, doneYet); - - testUser2.subscribe(doneYet).then(function() { - testUser2.addActivity(activity, httpCallback); - }, done); - - }); - - it('fayeSubscribeScope', function(done) { - var client = this.user1ReadOnly.getFayeClient(); - var isDone = false; - - var doneYet = function() { - if (!isDone) { - done(); - isDone = true; - } - }; - - var subscription = this.user1ReadOnly.subscribe(doneYet); - subscription.then(doneYet); - }); - - it('fayeSubscribeScopeTampered', function(done) { - var client = this.user1ReadOnly.getFayeClient(); - var isDone = false; - - var doneYet = function() { - if (!isDone) { - done(); - isDone = true; - } - }; - var subscription = this.user1ReadOnly.subscribe(doneYet); - subscription.then(doneYet); - }); + var subscription = this.user1ReadOnly.subscribe(doneYet); + subscription.then(doneYet); + }); - it('fayeSubscribeError', function(done) { - var client = stream.connect('5crf3bhfzesn'); + it('fayeSubscribeScopeTampered', function(done) { + var client = this.user1ReadOnly.getFayeClient(); + var isDone = false; - function sub() { - var user1 = client.feed('user', '11', 'secret'); - user1.subscribe(); - } - expect(sub).to.throwException(function(e) { - expect(e).to.be.a(errors.SiteError); - }); + var doneYet = function() { + if (!isDone) { done(); + isDone = true; + } + }; + var subscription = this.user1ReadOnly.subscribe(doneYet); + subscription.then(doneYet); + }); + + it('fayeSubscribeError', function(done) { + var client = stream.connect('5crf3bhfzesn'); + + function sub() { + var user1 = client.feed('user', '11', 'secret'); + user1.subscribe(); + } + expect(sub).to.throwException(function(e) { + expect(e).to.be.a(errors.SiteError); }); - -}); \ No newline at end of file + done(); + }); +}); diff --git a/test/integration/common/promise_test.js b/test/integration/common/promise_test.js index 1e720347..453990ff 100644 --- a/test/integration/common/promise_test.js +++ b/test/integration/common/promise_test.js @@ -1,42 +1,42 @@ -var init = require('../utils/hooks').init - , expect = require('expect.js') - , beforeEachFn = require('../utils/hooks').beforeEach; +var init = require('../utils/hooks').init, + expect = require('expect.js'), + beforeEachFn = require('../utils/hooks').beforeEach; describe('[INTEGRATION] Stream client (Promises)', function() { + init.call(this); + beforeEach(beforeEachFn); - init.call(this); - beforeEach(beforeEachFn); - - it('get promises', function() { - return this.user1.get({ - 'limit': 1 - }); + it('get promises', function() { + return this.user1.get({ + limit: 1, }); + }); - it('post promises', function() { - var activity = { - 'actor': 'test-various:characters', - 'verb': 'add', - 'object': 1, - 'tweet': 'hello world' - }; - return this.user1.addActivity(activity); - }); + it('post promises', function() { + var activity = { + actor: 'test-various:characters', + verb: 'add', + object: 1, + tweet: 'hello world', + }; + return this.user1.addActivity(activity); + }); - it('post promises fail', function(done) { - var activity = { - 'actor': 'test-various:characters', - 'verb': 'add', - 'object': '', - 'tweet': 'hello world' - }; - - this.user1.addActivity(activity) - .then(function() { - done('expected failure'); - }, function() { - done(); - }); - }); + it('post promises fail', function(done) { + var activity = { + actor: 'test-various:characters', + verb: 'add', + object: '', + tweet: 'hello world', + }; -}); \ No newline at end of file + this.user1.addActivity(activity).then( + function() { + done('expected failure'); + }, + function() { + done(); + } + ); + }); +}); diff --git a/test/integration/node/client_test.js b/test/integration/node/client_test.js index 61adade5..c7c72b27 100644 --- a/test/integration/node/client_test.js +++ b/test/integration/node/client_test.js @@ -1,653 +1,753 @@ -var stream = require('../../../src/getstream') - , errors = require('../../../src/getstream').errors - , init = require('../utils/hooks').init - , beforeEachFn = require('../utils/hooks').beforeEach - , expect = require('expect.js') - , wrapCB = require('../utils').wrapCB; +var stream = require('../../../src/getstream'), + errors = require('../../../src/getstream').errors, + init = require('../utils/hooks').init, + beforeEachFn = require('../utils/hooks').beforeEach, + expect = require('expect.js'), + wrapCB = require('../utils').wrapCB; describe('[INTEGRATION] Stream client (Node)', function() { + init.call(this); + beforeEach(beforeEachFn); + + it('get feed', function(done) { + this.user1.get( + { + limit: 1, + }, + function(error, response, body) { + if (error) done(error); + expect(response.statusCode).to.eql(200); + + var userAgent = response.req._headers['x-stream-client']; + expect(userAgent.indexOf('stream-javascript-client')).to.eql(0); + + done(); + } + ); + }); + + it('update activities', function() { + var self = this; + var activities = [ + { + actor: 1, + verb: 'tweet', + object: 1, + foreign_id: 'update_activity_1', + }, + { + actor: 2, + verb: 'tweet', + object: 3, + foreign_id: 'update_activity_1', + }, + ]; + + return this.user1 + .addActivities(activities) + .then(function(body) { + var activity = body['activities'][0]; + + activity['answer'] = 10; + delete activity.to; + delete activity.target; + delete activity.origin; + + var activities = [activity]; + + return self.client.updateActivities(activities); + }) + .then(function() { + return self.user1.get({ limit: 2 }); + }) + .then(function(body) { + var activity = body['results'][1]; + expect(activity.answer).to.be(10); + }); + }); + + it('update activity illegal foreign id', function() { + var self = this; + + var activity = { + actor: 1, + verb: 'tweet', + object: 2, + }; + + return this.user1 + .addActivity(activity) + .then(function(body) { + var activity = body; + + delete activity.id; + delete activity.duration; + delete activity.to; + delete activity.time; + + activity['foreign_id'] = 'aap'; + + return self.client.updateActivity(activity); + }) + .then(function() { + throw new Error('Expected InputException'); + }) + .catch(function(reason) { + expect(reason.error.code).to.be(4); + expect(reason.error.exception).to.be('InputException'); + }); + }); + + it('update activity illegal time', function() { + var self = this; + + var activity = { + actor: 1, + verb: 'tweet', + object: 2, + }; + + return this.user1 + .addActivity(activity) + .then(function(body) { + var activity = body; + + delete activity.duration; + delete activity.to; + + activity['time'] = 'aap'; + + return self.client.updateActivity(activity); + }) + .then(function() { + throw new Error('Expected InputException'); + }) + .catch(function(reason) { + expect(reason.error.code).to.be(4); + expect(reason.error.exception).to.be('InputException'); + }); + }); + + it('update activity illegal to field', function() { + var self = this; + + var activity = { + actor: 1, + verb: 'tweet', + object: 2, + }; + + return this.user1 + .addActivity(activity) + .then(function(body) { + var activity = body; + + delete activity.duration; + delete activity.time; + + activity['to'] = ['to:something']; + + return self.client.updateActivity(activity); + }) + .then(function() { + throw new Error('Expected InputException'); + }) + .catch(function(reason) { + expect(reason.error.code).to.be(4); + expect(reason.error.exception).to.be('InputException'); + }); + }); + + it('updating many activities', function() { + var self = this; + var activities = []; + for (var i = 0; i < 10; i++) { + activities.push({ + verb: 'do', + object: 'object:' + i, + actor: 'user:' + i, + foreign_id: 'update_activities_' + i, + }); + } + + return this.user1 + .addActivities(activities) + .then(function(body) { + var activitiesCreated = body['activities']; + + for (var j = 0; j < activitiesCreated.length; j++) { + activitiesCreated[j]['answer'] = 100; + } - init.call(this); - beforeEach(beforeEachFn); - - it('get feed', function(done) { - this.user1.get({ - 'limit': 1 - }, function(error, response, body) { - if (error) done(error); - expect(response.statusCode).to.eql(200); - - var userAgent = response.req._headers['x-stream-client']; - expect(userAgent.indexOf('stream-javascript-client')).to.eql(0); + return self.client.updateActivities(activitiesCreated); + }) + .then(function(body) { + return self.user1.get({ + limit: 10, + }); + }) + .then(function(body) { + var activitiesUpdated = body['results']; - done(); + for (var n = 0; n < activitiesUpdated.length; n++) { + expect(activitiesUpdated[n]['answer']).to.be(100); + } + }); + }); + + it('#updateActivity', function() { + var activity = { + verb: 'do', + actor: 'user:1', + object: 'object:1', + time: new Date().toISOString(), + foreign_id: 'update_activity_11', + }; + + return this.client.updateActivity(activity); + }); + + // it('supports application level authentication', function(done) { + // this.client.makeSignedRequest({ + // url: 'test/auth/digest/' + // }, wrapCB(200, done)); + // }); + + // it('fails application level authentication with wrong keys', function(done) { + // var client = stream.connect('aap', 'noot'); + + // client.makeSignedRequest({ + // url: 'test/auth/digest/' + // }, function(error, response, body) { + // if (error) return done(error); + // if (body.exception === 'ApiKeyException') return done(); + // }); + // }); + + it('supports adding activity to multiple feeds', function(done) { + var activity = { + actor: 'user:11', + verb: 'like', + object: '000', + }; + var feeds = ['flat:33', 'user:11']; + + this.client.addToMany(activity, feeds, wrapCB(201, done)); + }); + + it('supports batch following', function(done) { + var follows = [ + { + source: 'flat:1', + target: 'user:1', + }, + { + source: 'flat:1', + target: 'user:2', + }, + { + source: 'flat:1', + target: 'user:3', + }, + ]; + + this.client.followMany(follows, null, wrapCB(201, done)); + }); + + it('supports batch following with activity_copy_limit', function(done) { + var follows = [ + { + source: 'flat:1', + target: 'user:1', + }, + { + source: 'flat:1', + target: 'user:2', + }, + { + source: 'flat:1', + target: 'user:3', + }, + ]; + + this.client.followMany( + follows, + 20, + wrapCB(201, done, function(error, response, body) { + expect(response.req.path.indexOf('activity_copy_limit=20')).to.not.be( + 0 + ); + done(); + }) + ); + }); + + it('supports batch unfollowing', function(done) { + var unfollows = [ + { + source: 'flat:1', + target: 'user:1', + }, + { + source: 'flat:1', + target: 'user:2', + keep_history: true, + }, + { + source: 'flat:1', + target: 'user:3', + }, + ]; + + this.client.unfollowMany(unfollows, wrapCB(201, done)); + }); + + it('no secret application auth', function() { + var client = stream.connect('ahj2ndz7gsan'); + + expect(function() { + client.addToMany({}, []); + }).to.throwError(function(e) { + expect(e).to.be.a(errors.SiteError); + }); + }); + + it('batch promises', function() { + var activity = { + actor: 'user:11', + verb: 'like', + object: '000', + }; + var feeds = ['flat:33', 'user:11']; + + return this.client.addToMany(activity, feeds); + }); + + it('add activity using to', function() { + var self = this; + var activityId = null; + var activity = { + actor: 1, + verb: 'add', + object: 1, + }; + activity['participants'] = ['Thierry', 'Tommaso']; + activity['route'] = { + name: 'Vondelpark', + distance: '20', + }; + activity['to'] = [self.flat3.id, 'user:everyone']; + + return this.user1 + .addActivity(activity) + .then(function(body) { + activityId = body['id']; + return self.flat3.get({ limit: 1 }); + }) + .then(function(body) { + expect(body['results'][0]['id']).to.eql(activityId); + }); + }); + describe("updating activity's 'to' targets", function() { + it("replaces an activity's 'to' targets with `new_targets` (activity has existing targets)", function(done) { + var self = this; + var timestamp = new Date(); + + var activity = { + actor: 1, + verb: 'test', + object: 1, + foreign_id: 1234, + time: timestamp, + }; + this.user1 + .addActivity(activity) + .then(function() { + return self.user1.updateActivityToTargets(1234, timestamp, [ + 'user:5678', + ]); + }) + .then(function() { + return self.user1.get(); + }) + .then(function(response) { + expect(response.results[0].to).to.have.length(1); + expect(response.results[0].to).to.contain('user:5678'); + return done(); }); }); - - it('update activities', function() { - var self = this; - var activities = [{ - 'actor': 1, - 'verb': 'tweet', - 'object': 1, - 'foreign_id': 'update_activity_1' - }, { - 'actor': 2, - 'verb': 'tweet', - 'object': 3, - 'foreign_id': 'update_activity_1' - }, ]; - - return this.user1.addActivities(activities) - .then(function(body) { - var activity = body['activities'][0]; - - activity['answer'] = 10; - delete activity.to; - delete activity.target; - delete activity.origin; - - var activities = [activity]; - - return self.client.updateActivities(activities); - }) - .then(function() { - return self.user1.get({ limit: 2 }); - }) - .then(function(body) { - var activity = body['results'][1]; - expect(activity.answer).to.be(10); - }); + it("replaces an activity's 'to' targets with `new_targets` (activity has no existing targets)", function(done) { + var self = this; + var timestamp = new Date(); + + var activity = { + actor: 1, + verb: 'test', + object: 1, + foreign_id: 1234, + time: timestamp, + to: ['user:1234'], + }; + this.user1 + .addActivity(activity) + .then(function() { + return self.user1.updateActivityToTargets(1234, timestamp, [ + 'user:5678', + ]); + }) + .then(function() { + return self.user1.get(); + }) + .then(function(response) { + expect(response.results[0].to).to.have.length(1); + expect(response.results[0].to).to.contain('user:5678'); + return done(); + }); }); - it('update activity illegal foreign id', function() { - var self = this; - - var activity = { - 'actor': 1, - 'verb': 'tweet', - 'object': 2, - }; - - return this.user1.addActivity(activity) - .then(function(body) { - var activity = body; - - delete activity.id; - delete activity.duration; - delete activity.to; - delete activity.time; - - activity['foreign_id'] = 'aap'; - - return self.client.updateActivity(activity); - }) - .then(function() { - throw new Error('Expected InputException'); - }) - .catch(function(reason) { - expect(reason.error.code).to.be(4); - expect(reason.error.exception).to.be('InputException'); - }); + it("add new targets to an activity's 'to' targets with `add_targets` (activity has existing targets)", function(done) { + var self = this; + var timestamp = new Date(); + + var activity = { + actor: 1, + verb: 'test', + object: 1, + foreign_id: 1234, + time: timestamp, + to: ['user:1234'], + }; + this.user1 + .addActivity(activity) + .then(function() { + return self.user1.updateActivityToTargets(1234, timestamp, null, [ + 'user:5678', + ]); + }) + .then(function() { + return self.user1.get(); + }) + .then(function(response) { + expect(response.results[0].to).to.have.length(2); + expect(response.results[0].to).to.contain('user:1234'); + expect(response.results[0].to).to.contain('user:5678'); + done(); + }); }); - - it('update activity illegal time', function() { - var self = this; - - var activity = { - 'actor': 1, - 'verb': 'tweet', - 'object': 2, - }; - - return this.user1.addActivity(activity) - .then(function(body) { - var activity = body; - - delete activity.duration; - delete activity.to; - - activity['time'] = 'aap'; - - return self.client.updateActivity(activity); - }) - .then(function() { - throw new Error('Expected InputException'); - }) - .catch(function(reason) { - expect(reason.error.code).to.be(4); - expect(reason.error.exception).to.be('InputException'); - }); + it("add new targets to an activity's 'to' targets with `add_targets` (activity has no existing targets)", function(done) { + var self = this; + var timestamp = new Date(); + + var activity = { + actor: 1, + verb: 'test', + object: 1, + foreign_id: 1234, + time: timestamp, + }; + this.user1 + .addActivity(activity) + .then(function() { + return self.user1.updateActivityToTargets(1234, timestamp, null, [ + 'user:5678', + ]); + }) + .then(function() { + return self.user1.get(); + }) + .then(function(response) { + expect(response.results[0].to).to.have.length(1); + expect(response.results[0].to).to.contain('user:5678'); + done(); + }); }); - it('update activity illegal to field', function() { - var self = this; - - var activity = { - 'actor': 1, - 'verb': 'tweet', - 'object': 2, - }; - - return this.user1.addActivity(activity) - .then(function(body) { - var activity = body; - - delete activity.duration; - delete activity.time; - - activity['to'] = ['to:something']; - - return self.client.updateActivity(activity); - }) - .then(function() { - throw new Error('Expected InputException'); - }) - .catch(function(reason) { - expect(reason.error.code).to.be(4); - expect(reason.error.exception).to.be('InputException'); - }); + it("remove targets from an activity's 'to' targets with `remove_targets` (end result still has targets)", function(done) { + var self = this; + var timestamp = new Date(); + + var activity = { + actor: 1, + verb: 'test', + object: 1, + foreign_id: 1234, + time: timestamp, + to: ['user:1234', 'user:5678'], + }; + this.user1 + .addActivity(activity) + .then(function() { + return self.user1.updateActivityToTargets( + 1234, + timestamp, + null, + null, + ['user:5678'] + ); + }) + .then(function() { + return self.user1.get(); + }) + .then(function(response) { + expect(response.results[0].to).to.have.length(1); + expect(response.results[0].to).to.contain('user:1234'); + done(); + }); }); - - it('updating many activities', function() { - var self = this; - var activities = []; - for (var i = 0; i < 10; i++) { - activities.push({ - 'verb': 'do', - 'object': 'object:' + i, - 'actor': 'user:' + i, - 'foreign_id': 'update_activities_' + i - }); - } - - return this.user1.addActivities(activities) - .then(function(body) { - var activitiesCreated = body['activities']; - - for (var j = 0; j < activitiesCreated.length; j++) { - activitiesCreated[j]['answer'] = 100; - } - - return self.client.updateActivities(activitiesCreated); - }) - .then(function(body) { - return self.user1.get({ - limit: 10 - }); - }) - .then(function(body) { - var activitiesUpdated = body['results']; - - for (var n = 0; n < activitiesUpdated.length; n++) { - expect(activitiesUpdated[n]['answer']).to.be(100); - } - }); + it("remove targets from an activity's 'to' targets with `remove_targets` (end result has no targets)", function(done) { + var self = this; + var timestamp = new Date(); + + var activity = { + actor: 1, + verb: 'test', + object: 1, + foreign_id: 1234, + time: timestamp, + to: ['user:1234'], + }; + this.user1 + .addActivity(activity) + .then(function() { + return self.user1.updateActivityToTargets( + 1234, + timestamp, + null, + null, + ['user:1234'] + ); + }) + .then(function() { + return self.user1.get(); + }) + .then(function(response) { + expect(response.results[0].to).to.have.length(0); + done(); + }); }); - it('#updateActivity', function() { - var activity = { - 'verb': 'do', - 'actor': 'user:1', - 'object': 'object:1', - 'time': new Date().toISOString(), - 'foreign_id': 'update_activity_11' - }; - - return this.client.updateActivity(activity); + it("replaces an activity's 'to' targets with a combination of `add_targets` and `remove_targets` (activity has no other existing targets)", function(done) { + var self = this; + var timestamp = new Date(); + + var activity = { + actor: 1, + verb: 'test', + object: 1, + foreign_id: 1234, + time: timestamp, + to: ['user:1234'], + }; + this.user1 + .addActivity(activity) + .then(function() { + return self.user1.updateActivityToTargets( + 1234, + timestamp, + null, + ['user:5678'], + ['user:1234'] + ); + }) + .then(function() { + return self.user1.get(); + }) + .then(function(response) { + expect(response.results[0].to).to.have.length(1); + expect(response.results[0].to).to.have.contain('user:5678'); + done(); + }); }); -// it('supports application level authentication', function(done) { -// this.client.makeSignedRequest({ -// url: 'test/auth/digest/' -// }, wrapCB(200, done)); -// }); - -// it('fails application level authentication with wrong keys', function(done) { -// var client = stream.connect('aap', 'noot'); - -// client.makeSignedRequest({ -// url: 'test/auth/digest/' -// }, function(error, response, body) { -// if (error) return done(error); -// if (body.exception === 'ApiKeyException') return done(); -// }); -// }); - - it('supports adding activity to multiple feeds', function(done) { - var activity = { - 'actor': 'user:11', - 'verb': 'like', - 'object': '000' - }; - var feeds = ['flat:33', 'user:11']; - - this.client.addToMany(activity, feeds, wrapCB(201, done)); + it("replaces an activity's 'to' targets with a combination of `add_targets` and `remove_targets` (activity has other existing targets too, that don't get modified)", function(done) { + var self = this; + var timestamp = new Date(); + + var activity = { + actor: 1, + verb: 'test', + object: 1, + foreign_id: 1234, + time: timestamp, + to: ['user:0000', 'user:1234'], + }; + this.user1 + .addActivity(activity) + .then(function() { + return self.user1.updateActivityToTargets( + 1234, + timestamp, + null, + ['user:5678'], + ['user:1234'] + ); + }) + .then(function() { + return self.user1.get(); + }) + .then(function(response) { + expect(response.results[0].to).to.have.length(2); + expect(response.results[0].to).to.have.contain('user:0000'); + expect(response.results[0].to).to.have.contain('user:5678'); + done(); + }); }); - - it('supports batch following', function(done) { - var follows = [{ - 'source': 'flat:1', - 'target': 'user:1' - }, { - 'source': 'flat:1', - 'target': 'user:2' - }, { - 'source': 'flat:1', - 'target': 'user:3' - }]; - - this.client.followMany(follows, null, wrapCB(201, done)); + }); + + describe('get activities', function() { + var activity; + + beforeEach(function(done) { + var self = this; + this.user1 + .addActivity({ + actor: 1, + verb: 'test', + object: 1, + foreign_id: 1234, + time: new Date(), + }) + .then(function() { + return self.user1.get(); + }) + .then(function(resp) { + activity = resp.results[0]; + done(); + }); }); - it('supports batch following with activity_copy_limit', function(done) { - var follows = [{ - 'source': 'flat:1', - 'target': 'user:1' - }, { - 'source': 'flat:1', - 'target': 'user:2' - }, { - 'source': 'flat:1', - 'target': 'user:3' - }]; - - this.client.followMany(follows, 20, wrapCB(201, done, function(error, response, body) { - expect(response.req.path.indexOf('activity_copy_limit=20')).to.not.be(0); + describe('by ID', function() { + it('allows to retrieve activities directly by their ID', function(done) { + this.client + .getActivities({ ids: [activity['id']] }) + .then(function(resp) { + expect(resp.results[0]).to.eql(activity); done(); - })); + }); + }); }); - it('supports batch unfollowing', function (done) { - var unfollows = [{ - 'source': 'flat:1', - 'target': 'user:1' - }, { - 'source': 'flat:1', - 'target': 'user:2', - 'keep_history': true - }, { - 'source': 'flat:1', - 'target': 'user:3' - }]; - - this.client.unfollowMany(unfollows, wrapCB(201, done)); + describe('by foreign ID and time', function() { + it('allows to retrieve activities directly by their ID', function(done) { + this.client + .getActivities({ + foreignIDTimes: [ + { + foreignID: activity['foreign_id'], + time: activity['time'], + }, + ], + }) + .then(function(resp) { + expect(resp.results[0]).to.eql(activity); + done(); + }); + }); }); - - it('no secret application auth', function() { - var client = stream.connect('ahj2ndz7gsan'); - - expect(function() { - client.addToMany({}, []); - }).to.throwError(function(e) { - expect(e).to.be.a(errors.SiteError); + }); + + describe('update activity partial', function() { + var activity, expected; + + beforeEach(function(done) { + var self = this; + this.user1 + .addActivity({ + actor: 1, + verb: 'test', + object: 1, + foreign_id: 1234, + time: new Date(), + shares: { + facebook: 123, + twitter: 2000, + }, + popularity: 50, + color: 'blue', + }) + .then(function() { + return self.user1.get(); + }) + .then(function(resp) { + activity = resp.results[0]; + + expected = activity; + delete expected.color; + expected.popularity = 75; + expected.shares = { + facebook: 234, + twitter: 2000, + googleplus: 42, + }; + expected.foo = { + bar: { + baz: 999, + }, + }; + + done(); }); }); - it('batch promises', function() { - var activity = { - 'actor': 'user:11', - 'verb': 'like', - 'object': '000' - }; - var feeds = ['flat:33', 'user:11']; - - return this.client.addToMany(activity, feeds); - }); - - it('add activity using to', function() { + describe('by ID', function() { + it('allows to update the activity', function(done) { var self = this; - var activityId = null; - var activity = { - 'actor': 1, - 'verb': 'add', - 'object': 1 - }; - activity['participants'] = ['Thierry', 'Tommaso']; - activity['route'] = { - 'name': 'Vondelpark', - 'distance': '20' - }; - activity['to'] = [self.flat3.id, 'user:everyone']; - - return this.user1.addActivity(activity) - .then(function(body) { - activityId = body['id']; - return self.flat3.get({ 'limit': 1 }); - }) - .then(function(body) { - expect(body['results'][0]['id']).to.eql(activityId); - }); - }); - describe('updating activity\'s \'to\' targets', function() { - - it('replaces an activity\'s \'to\' targets with `new_targets` (activity has existing targets)', function(done) { - var self = this; - var timestamp = new Date(); - - var activity = { - 'actor': 1, - 'verb': 'test', - 'object': 1, - 'foreign_id': 1234, - 'time': timestamp - }; - this.user1.addActivity(activity).then(function() { - return self.user1.updateActivityToTargets(1234, timestamp, ["user:5678"]); - }).then(function() { - return self.user1.get(); - }).then(function(response) { - expect(response.results[0].to).to.have.length(1); - expect(response.results[0].to).to.contain("user:5678"); - return done(); - }); - }); - it('replaces an activity\'s \'to\' targets with `new_targets` (activity has no existing targets)', function(done) { - var self = this; - var timestamp = new Date(); - - var activity = { - 'actor': 1, - 'verb': 'test', - 'object': 1, - 'foreign_id': 1234, - 'time': timestamp, - 'to': ['user:1234'] - }; - this.user1.addActivity(activity).then(function() { - return self.user1.updateActivityToTargets(1234, timestamp, ["user:5678"]); - }).then(function() { - return self.user1.get(); - }).then(function(response) { - expect(response.results[0].to).to.have.length(1); - expect(response.results[0].to).to.contain("user:5678"); - return done(); - }); - }); - - it('add new targets to an activity\'s \'to\' targets with `add_targets` (activity has existing targets)', function(done) { - var self = this; - var timestamp = new Date(); - - var activity = { - 'actor': 1, - 'verb': 'test', - 'object': 1, - 'foreign_id': 1234, - 'time': timestamp, - 'to': ['user:1234'] - }; - this.user1.addActivity(activity).then(function() { - return self.user1.updateActivityToTargets(1234, timestamp, null, ['user:5678']); - }).then(function() { - return self.user1.get(); - }).then(function(response) { - expect(response.results[0].to).to.have.length(2); - expect(response.results[0].to).to.contain("user:1234"); - expect(response.results[0].to).to.contain("user:5678"); - done(); - }); - }); - it('add new targets to an activity\'s \'to\' targets with `add_targets` (activity has no existing targets)', function(done) { - var self = this; - var timestamp = new Date(); - - var activity = { - 'actor': 1, - 'verb': 'test', - 'object': 1, - 'foreign_id': 1234, - 'time': timestamp, - }; - this.user1.addActivity(activity).then(function() { - return self.user1.updateActivityToTargets(1234, timestamp, null, ['user:5678']); - }).then(function() { - return self.user1.get(); - }).then(function(response) { - expect(response.results[0].to).to.have.length(1); - expect(response.results[0].to).to.contain("user:5678"); - done(); - }); - }); - it('remove targets from an activity\'s \'to\' targets with `remove_targets` (end result still has targets)', function(done) { - var self = this; - var timestamp = new Date(); - - var activity = { - 'actor': 1, - 'verb': 'test', - 'object': 1, - 'foreign_id': 1234, - 'time': timestamp, - 'to': ['user:1234', 'user:5678'] - }; - this.user1.addActivity(activity).then(function() { - return self.user1.updateActivityToTargets(1234, timestamp, null, null, ['user:5678']); - }).then(function() { - return self.user1.get(); - }).then(function(response) { - expect(response.results[0].to).to.have.length(1); - expect(response.results[0].to).to.contain("user:1234"); - done(); - }); - }); - it('remove targets from an activity\'s \'to\' targets with `remove_targets` (end result has no targets)', function(done) { - var self = this; - var timestamp = new Date(); - - var activity = { - 'actor': 1, - 'verb': 'test', - 'object': 1, - 'foreign_id': 1234, - 'time': timestamp, - 'to': ['user:1234'] - }; - this.user1.addActivity(activity).then(function() { - return self.user1.updateActivityToTargets(1234, timestamp, null, null, ['user:1234']); - }).then(function() { - return self.user1.get(); - }).then(function(response) { - expect(response.results[0].to).to.have.length(0); - done(); - }); - }); - - it('replaces an activity\'s \'to\' targets with a combination of `add_targets` and `remove_targets` (activity has no other existing targets)', function (done) { - var self = this; - var timestamp = new Date(); - - var activity = { - 'actor': 1, - 'verb': 'test', - 'object': 1, - 'foreign_id': 1234, - 'time': timestamp, - 'to': ['user:1234'] - }; - this.user1.addActivity(activity).then(function() { - return self.user1.updateActivityToTargets(1234, timestamp, null, ["user:5678"], ['user:1234']); - }).then(function() { - return self.user1.get(); - }).then(function(response) { - expect(response.results[0].to).to.have.length(1); - expect(response.results[0].to).to.have.contain("user:5678"); - done(); - }); - }); - - it('replaces an activity\'s \'to\' targets with a combination of `add_targets` and `remove_targets` (activity has other existing targets too, that don\'t get modified)', function (done) { - var self = this; - var timestamp = new Date(); - - var activity = { - 'actor': 1, - 'verb': 'test', - 'object': 1, - 'foreign_id': 1234, - 'time': timestamp, - 'to': ['user:0000', 'user:1234'] - }; - this.user1.addActivity(activity).then(function() { - return self.user1.updateActivityToTargets(1234, timestamp, null, ["user:5678"], ['user:1234']); - }).then(function() { - return self.user1.get(); - }).then(function(response) { - expect(response.results[0].to).to.have.length(2); - expect(response.results[0].to).to.have.contain("user:0000"); - expect(response.results[0].to).to.have.contain("user:5678"); + this.client + .activityPartialUpdate({ + id: activity['id'], + set: { + popularity: 75, + 'shares.facebook': 234, + 'shares.googleplus': 42, + foo: { + bar: { + baz: 999, + }, + }, + }, + unset: ['color'], + }) + .then(function() { + self.client + .getActivities({ ids: [activity['id']] }) + .then(function(resp) { + expect(resp.results[0]).to.eql(expected); done(); - }); - - }); + }); + }); + }); }); - describe('get activities', function() { - var activity; - - beforeEach(function(done){ - var self = this; - this.user1.addActivity({ - 'actor': 1, - 'verb': 'test', - 'object': 1, - 'foreign_id': 1234, - 'time': new Date(), - }).then(function() { - return self.user1.get(); - }).then(function(resp) { - activity = resp.results[0]; - done(); - }); - }); - - describe('by ID', function() { - it('allows to retrieve activities directly by their ID', function(done) { - this.client.getActivities({ids: [activity['id']]}) - .then(function(resp){ - expect(resp.results[0]).to.eql(activity); - done(); - }); - }) - }); - - describe('by foreign ID and time', function () { - it('allows to retrieve activities directly by their ID', function (done) { - this.client.getActivities({ - foreignIDTimes: [ - { - foreignID: activity['foreign_id'], - time: activity['time'] - } - ] - }) - .then(function (resp) { - expect(resp.results[0]).to.eql(activity); - done(); - }); - }) - }); - }); + describe('by foreign ID and time', function() { + it('allows to update the activity', function(done) { + var self = this; - describe('update activity partial', function () { - var activity, expected; - - beforeEach(function (done) { - var self = this; - this.user1.addActivity({ - 'actor': 1, - 'verb': 'test', - 'object': 1, - 'foreign_id': 1234, - 'time': new Date(), - 'shares': { - 'facebook': 123, - 'twitter': 2000, + this.client + .activityPartialUpdate({ + foreignID: activity['foreign_id'], + time: activity['time'], + set: { + popularity: 75, + 'shares.facebook': 234, + 'shares.googleplus': 42, + foo: { + bar: { + baz: 999, }, - 'popularity': 50, - 'color': 'blue', - }).then(function () { - return self.user1.get(); - }).then(function (resp) { - activity = resp.results[0]; - - expected = activity; - delete expected.color; - expected.popularity = 75; - expected.shares = { - "facebook": 234, - "twitter": 2000, - "googleplus": 42 - }; - expected.foo = { - bar: { - baz: 999 - } - }; - + }, + }, + unset: ['color'], + }) + .then(function() { + self.client + .getActivities({ ids: [activity['id']] }) + .then(function(resp) { + expect(resp.results[0]).to.eql(expected); done(); - }); - }); - - describe('by ID', function () { - it("allows to update the activity", function (done) { - var self = this; - - this.client.activityPartialUpdate({ - id: activity['id'], - set: { - popularity: 75, - "shares.facebook": 234, - "shares.googleplus": 42, - foo: { - bar: { - baz: 999, - } - } - }, - unset: [ - "color", - ] - }).then(function() { - self.client.getActivities({ids: [activity['id']]}) - .then(function(resp) { - expect(resp.results[0]).to.eql(expected); - done(); - }) - }) - }) - }); - - describe('by foreign ID and time', function () { - it("allows to update the activity", function (done) { - var self = this; - - this.client.activityPartialUpdate({ - foreignID: activity['foreign_id'], - time: activity['time'], - set: { - popularity: 75, - "shares.facebook": 234, - "shares.googleplus": 42, - foo: { - bar: { - baz: 999, - } - } - }, - unset: [ - "color", - ] - }).then(function () { - self.client.getActivities({ ids: [activity['id']] }) - .then(function (resp) { - expect(resp.results[0]).to.eql(expected); - done(); - }) - }) - }) - }); + }); + }); + }); }); - + }); }); diff --git a/test/integration/utils/config.js b/test/integration/utils/config.js index 70543e08..19a4f745 100644 --- a/test/integration/utils/config.js +++ b/test/integration/utils/config.js @@ -1,14 +1,16 @@ var isNodeEnv = typeof window === 'undefined'; -var API_KEY = process.env.STREAM_API_KEY - , API_SECRET = process.env.STREAM_API_SECRET - , APP_ID = process.env.STREAM_APP_ID; +var API_KEY = process.env.STREAM_API_KEY, + API_SECRET = process.env.STREAM_API_SECRET, + APP_ID = process.env.STREAM_APP_ID; -if (! API_KEY || ! API_SECRET || ! APP_ID) { - throw new Error('Expected STREAM_API_KEY, STREAM_API_SECRET, and STREAM_APP_ID env vars'); +if (!API_KEY || !API_SECRET || !APP_ID) { + throw new Error( + 'Expected STREAM_API_KEY, STREAM_API_SECRET, and STREAM_APP_ID env vars' + ); } module.exports.API_KEY = API_KEY; module.exports.API_SECRET = API_SECRET; module.exports.APP_ID = APP_ID; -module.exports.IS_NODE_ENV = isNodeEnv; \ No newline at end of file +module.exports.IS_NODE_ENV = isNodeEnv; diff --git a/test/integration/utils/hooks.js b/test/integration/utils/hooks.js index d7db85c3..fc55e9b8 100644 --- a/test/integration/utils/hooks.js +++ b/test/integration/utils/hooks.js @@ -1,106 +1,128 @@ -var stream = require('../../../src/getstream') - , feed = require('../utils').feed - , config = require('./config'); +var stream = require('../../../src/getstream'), + feed = require('../utils').feed, + config = require('./config'); function jwt(resource, action, options) { - var KJUR = require('exports?KJUR!./kjur'); - - var header = { - alg: "HS256", - typ: "JWT", - }; - var payload = { - resource: resource, - action: action, - }; - - if (options.feedId) { - payload['feed_id'] = options.feedId; - } - - if (options.userId) { - payload['user_id'] = options.userId; - } - - header = JSON.stringify(header); - payload = JSON.stringify(payload); - - var res = KJUR.jws.JWS.sign("HS256", header, payload, process.env.STREAM_API_SECRET); - - return res; + var KJUR = require('exports?KJUR!./kjur'); + + var header = { + alg: 'HS256', + typ: 'JWT', + }; + var payload = { + resource: resource, + action: action, + }; + + if (options.feedId) { + payload['feed_id'] = options.feedId; + } + + if (options.userId) { + payload['user_id'] = options.userId; + } + + header = JSON.stringify(header); + payload = JSON.stringify(payload); + + var res = KJUR.jws.JWS.sign( + 'HS256', + header, + payload, + process.env.STREAM_API_SECRET + ); + + return res; } function randUserId(userId) { - return userId + '-' + Date.now() + '-' + Math.round(Math.random() * 1000); + return userId + '-' + Date.now() + '-' + Math.round(Math.random() * 1000); } function createFeedWithToken(client, feedGroup, userId, readOnly) { - userId = randUserId(userId); + userId = randUserId(userId); - var token = jwt('*', readOnly ? 'read' : '*', { feedId: feedGroup + userId }); - return client.feed(feedGroup, userId, token); + var token = jwt('*', readOnly ? 'read' : '*', { feedId: feedGroup + userId }); + return client.feed(feedGroup, userId, token); } function initNode() { - this.timeout(40000); + this.timeout(40000); } function initBrowser() { - this.timeout(40000); + this.timeout(40000); } function beforeEachNode() { - this.client = stream.connect(config.API_KEY, config.API_SECRET); - this.client = stream.connect(config.API_KEY, config.API_SECRET, config.APP_ID, { - 'group': 'testCycle', - 'location': 'qa', - 'protocol': 'https', - }); - this.user1 = this.client.feed('user', randUserId('11')); - this.user2 = this.client.feed('user', randUserId('22')); - this.user3 = this.client.feed('user', randUserId('33')); - this.user4 = this.client.feed('user', randUserId('44')); - this.aggregated2 = this.client.feed('aggregated', randUserId('22')); - this.aggregated3 = this.client.feed('aggregated', randUserId('33')); - this.flat3 = this.client.feed('flat', randUserId('33')); - this.secret3 = this.client.feed('secret', randUserId('33')); - this.notification3 = this.client.feed('notification', randUserId('33')); - this.user1ReadOnly = this.client.feed('user', randUserId('11'), null, null, {readOnly: true}); - this.user2ReadOnly = this.client.feed('user', randUserId('22'), null, null, {readOnly: true}); + this.client = stream.connect( + config.API_KEY, + config.API_SECRET + ); + this.client = stream.connect( + config.API_KEY, + config.API_SECRET, + config.APP_ID, + { + group: 'testCycle', + location: 'qa', + protocol: 'https', + } + ); + this.user1 = this.client.feed('user', randUserId('11')); + this.user2 = this.client.feed('user', randUserId('22')); + this.user3 = this.client.feed('user', randUserId('33')); + this.user4 = this.client.feed('user', randUserId('44')); + this.aggregated2 = this.client.feed('aggregated', randUserId('22')); + this.aggregated3 = this.client.feed('aggregated', randUserId('33')); + this.flat3 = this.client.feed('flat', randUserId('33')); + this.secret3 = this.client.feed('secret', randUserId('33')); + this.notification3 = this.client.feed('notification', randUserId('33')); + this.user1ReadOnly = this.client.feed('user', randUserId('11'), null, null, { + readOnly: true, + }); + this.user2ReadOnly = this.client.feed('user', randUserId('22'), null, null, { + readOnly: true, + }); } function beforeEachBrowser() { - this.client = stream.connect(config.API_KEY); - this.client = stream.connect(config.API_KEY, null, config.APP_ID, { - 'group': 'browserTestCycle', - 'location': 'qa', - 'protocol': 'https', - }); - - if (this.localRun){ - this.client.baseUrl = 'http://localhost:8000/api/'; - this.client.fayeUrl = 'http://localhost:9999/faye/'; + this.client = stream.connect(config.API_KEY); + this.client = stream.connect( + config.API_KEY, + null, + config.APP_ID, + { + group: 'browserTestCycle', + location: 'qa', + protocol: 'https', } - - this.user1 = createFeedWithToken(this.client, 'user', '11'); - this.user2 = createFeedWithToken(this.client, 'user', '22'); - this.user3 = createFeedWithToken(this.client, 'user', '33'); - this.user4 = createFeedWithToken(this.client, 'user', '44'); - this.aggregated2 = createFeedWithToken(this.client, 'aggregated', '22'); - this.aggregated3 = createFeedWithToken(this.client, 'aggregated', '33'); - this.flat3 = createFeedWithToken(this.client, 'flat', '33'); - this.secret3 = createFeedWithToken(this.client, 'secret', '33'); - this.notification3 = createFeedWithToken(this.client, 'notification', '33'); - this.user1ReadOnly = createFeedWithToken(this.client, 'user', '11', true); + ); + + if (this.localRun) { + this.client.baseUrl = 'http://localhost:8000/api/'; + this.client.fayeUrl = 'http://localhost:9999/faye/'; + } + + this.user1 = createFeedWithToken(this.client, 'user', '11'); + this.user2 = createFeedWithToken(this.client, 'user', '22'); + this.user3 = createFeedWithToken(this.client, 'user', '33'); + this.user4 = createFeedWithToken(this.client, 'user', '44'); + this.aggregated2 = createFeedWithToken(this.client, 'aggregated', '22'); + this.aggregated3 = createFeedWithToken(this.client, 'aggregated', '33'); + this.flat3 = createFeedWithToken(this.client, 'flat', '33'); + this.secret3 = createFeedWithToken(this.client, 'secret', '33'); + this.notification3 = createFeedWithToken(this.client, 'notification', '33'); + this.user1ReadOnly = createFeedWithToken(this.client, 'user', '11', true); } module.exports = { - jwt: jwt, - randUserId: randUserId, - initNode: initNode, - initBrowser: initBrowser, - beforeEachNode: beforeEachNode, - beforeEachBrowser: beforeEachBrowser, - beforeEach: config.IS_NODE_ENV ? beforeEachNode : beforeEachBrowser, - init: config.IS_NODE_ENV ? initNode : initBrowser, + jwt: jwt, + randUserId: randUserId, + initNode: initNode, + initBrowser: initBrowser, + beforeEachNode: beforeEachNode, + beforeEachBrowser: beforeEachBrowser, + beforeEach: config.IS_NODE_ENV ? beforeEachNode : beforeEachBrowser, + init: config.IS_NODE_ENV ? initNode : initBrowser, }; diff --git a/test/integration/utils/index.js b/test/integration/utils/index.js index 2ef84356..d26c5281 100644 --- a/test/integration/utils/index.js +++ b/test/integration/utils/index.js @@ -1,34 +1,34 @@ -var expect = require('expect.js') - , signing = require('../../../src/lib/signing') - , Promise = require('../../../src/lib/promise') - , config = require('./config'); +var expect = require('expect.js'), + signing = require('../../../src/lib/signing'), + Promise = require('../../../src/lib/promise'), + config = require('./config'); module.exports.wrapCB = function(expectedStatusCode, done, cb) { - return function(error, response, body) { - if (error) return done(error); - expect(response.statusCode).to.be(expectedStatusCode); + return function(error, response, body) { + if (error) return done(error); + expect(response.statusCode).to.be(expectedStatusCode); - if (typeof cb === 'function') { - cb.apply(cb, arguments); - } else { - done(); - } - }; + if (typeof cb === 'function') { + cb.apply(cb, arguments); + } else { + done(); + } + }; }; module.exports.feed = function(client, feedId, userId) { - var token = signing.JWTScopeToken(config.API_SECRET, '*', '*', { - feedId: feedId, - userId: userId, - }).token; + var token = signing.JWTScopeToken(config.API_SECRET, '*', '*', { + feedId: feedId, + userId: userId, + }).token; - return client.feed(feedId, userId, token); + return client.feed(feedId, userId, token); }; module.exports.delay = function(s, wth) { - return new Promise(function(resolve, reject) { - setTimeout(function() { - resolve(wth); - }, s); - }); -}; \ No newline at end of file + return new Promise(function(resolve, reject) { + setTimeout(function() { + resolve(wth); + }, s); + }); +}; diff --git a/test/unit/browser/client_test.js b/test/unit/browser/client_test.js index 045266d2..d70b8857 100644 --- a/test/unit/browser/client_test.js +++ b/test/unit/browser/client_test.js @@ -1,73 +1,86 @@ -var expect = require('expect.js') - , beforeEachFn = require('../utils/hooks').beforeEach - , init = require('../utils/hooks').init - , stream = require('../../../src/getstream') - , StreamFeed = require('../../../src/lib/feed') - , errors = stream.errors; +var expect = require('expect.js'), + beforeEachFn = require('../utils/hooks').beforeEach, + init = require('../utils/hooks').init, + stream = require('../../../src/getstream'), + StreamFeed = require('../../../src/lib/feed'), + errors = stream.errors; describe('[UNIT] Stream Client (browser)', function() { - - init.call(this); - beforeEach(beforeEachFn); - - it('shouldn\'t allow secret keys', function() { - // apiKey, apiSecret, appId, options - function createFn() { - stream.connect('abcdefgh', '123456789'); - } - - expect(createFn).to.throwException(function(e) { - expect(e).to.be.a(errors.FeedError); - }); - }); - - it('should store config on the client', function() { - var client = stream.connect('abcdefgh', null, 1000, { 'option': true }); - - expect(client.apiSecret).to.be(null); - expect(client.browser).to.be(true); - }); - - it('should store config on the client', function() { - var client = stream.connect('abcdefgh', null, 1000, { - 'version': 'v2.0', - 'fayeUrl': 'https://hello.world', - 'expireTokens': true, - 'location': 'nederland' - }); - - expect(client.version).to.be('v2.0'); - expect(client.expireTokens).to.be(true); - expect(client.baseUrl).to.be('https://nederland-api.stream-io-api.com/api/'); - expect(client.fayeUrl).to.be('https://hello.world'); + init.call(this); + beforeEach(beforeEachFn); + + it("shouldn't allow secret keys", function() { + // apiKey, apiSecret, appId, options + function createFn() { + stream.connect( + 'abcdefgh', + '123456789' + ); + } + + expect(createFn).to.throwException(function(e) { + expect(e).to.be.a(errors.FeedError); }); - - it('shouldn\'t support signed requests on the client', function() { - expect(this.client.makeSignedRequest).to.be(undefined); + }); + + it('should store config on the client', function() { + var client = stream.connect( + 'abcdefgh', + null, + 1000, + { option: true } + ); + + expect(client.apiSecret).to.be(null); + expect(client.browser).to.be(true); + }); + + it('should store config on the client', function() { + var client = stream.connect( + 'abcdefgh', + null, + 1000, + { + version: 'v2.0', + fayeUrl: 'https://hello.world', + expireTokens: true, + location: 'nederland', + } + ); + + expect(client.version).to.be('v2.0'); + expect(client.expireTokens).to.be(true); + expect(client.baseUrl).to.be( + 'https://nederland-api.stream-io-api.com/api/' + ); + expect(client.fayeUrl).to.be('https://hello.world'); + }); + + it("shouldn't support signed requests on the client", function() { + expect(this.client.makeSignedRequest).to.be(undefined); + }); + + it('#userAgent', function() { + var useragent = this.client.userAgent(); + + expect(useragent).to.be('stream-javascript-client-browser-unknown'); + }); + + it('#feed throw (1)', function() { + var self = this; + + function toThrow() { + self.client.feed('user', 'jaap'); + } + + expect(toThrow).to.throwException(function(e) { + expect(e).to.be.a(errors.FeedError); }); + }); - it('#userAgent', function() { - var useragent = this.client.userAgent(); - - expect(useragent).to.be('stream-javascript-client-browser-unknown'); - }); - - it('#feed throw (1)', function() { - var self = this; - - function toThrow() { - self.client.feed('user','jaap'); - } - - expect(toThrow).to.throwException(function(e) { - expect(e).to.be.a(errors.FeedError); - }); - }); - - it('#feed', function() { - var feed = this.client.feed('user','jaap', '123456789'); - - expect(feed).to.be.a(StreamFeed); - }); + it('#feed', function() { + var feed = this.client.feed('user', 'jaap', '123456789'); + expect(feed).to.be.a(StreamFeed); + }); }); diff --git a/test/unit/common/client_test.js b/test/unit/common/client_test.js index 87c5432e..b781742a 100644 --- a/test/unit/common/client_test.js +++ b/test/unit/common/client_test.js @@ -1,398 +1,389 @@ -var expect = require('expect.js') - , beforeEachFn = require('../utils/hooks').beforeEach - , init = require('../utils/hooks').init - , config = require('../utils/config') - , td = require('testdouble') - , stream = require('../../../src/getstream') - , errors = stream.errors; +var expect = require('expect.js'), + beforeEachFn = require('../utils/hooks').beforeEach, + init = require('../utils/hooks').init, + config = require('../utils/config'), + td = require('testdouble'), + stream = require('../../../src/getstream'), + errors = stream.errors; function enrichKwargs(kwargs) { - return kwargs; + return kwargs; } describe('[UNIT] Stream Client (Common)', function() { - - init.call(this); - beforeEach(beforeEachFn); - afterEach(function() { - td.reset(); - }); - - it('#connect', function() { - expect(this.client.apiKey).to.be(config.API_KEY); - expect(this.client.version).to.be('v1.0'); - expect(this.client.fayeUrl).to.be('https://faye.getstream.io/faye'); - expect(this.client.group).to.be('unspecified'); - expect(this.client.location).to.be(undefined); - expect(this.client.expireTokens).to.be(false); - expect(this.client.baseUrl).to.be('https://api.stream-io-api.com/api/'); + init.call(this); + beforeEach(beforeEachFn); + afterEach(function() { + td.reset(); + }); + + it('#connect', function() { + expect(this.client.apiKey).to.be(config.API_KEY); + expect(this.client.version).to.be('v1.0'); + expect(this.client.fayeUrl).to.be('https://faye.getstream.io/faye'); + expect(this.client.group).to.be('unspecified'); + expect(this.client.location).to.be(undefined); + expect(this.client.expireTokens).to.be(false); + expect(this.client.baseUrl).to.be('https://api.stream-io-api.com/api/'); + }); + + describe('#on', function() { + it('(1) without callback', function(done) { + expect(this.client.on).to.be.a(Function); + + td.replace(this.client, 'enrichKwargs', enrichKwargs); + + this.client.on('request', function() { + done(); + }); + + this.client.get({ uri: 'test' }); }); - describe('#on', function() { - - it('(1) without callback', function(done) { - expect(this.client.on).to.be.a(Function); - - td.replace(this.client, 'enrichKwargs', enrichKwargs); + it('(2) with callback', function(done) { + expect(this.client.on).to.be.a(Function); - this.client.on('request', function() { - done(); - }); + td.replace(this.client, 'enrichKwargs', enrichKwargs); - this.client.get({ uri: 'test' }); - }); - - it('(2) with callback', function(done) { - expect(this.client.on).to.be.a(Function); - - td.replace(this.client, 'enrichKwargs', enrichKwargs); - - this.client.on('request', function() { - done(); - }); - - this.client.get({ uri: 'test' }, function() {}); - }); + this.client.on('request', function() { + done(); + }); + this.client.get({ uri: 'test' }, function() {}); }); + }); - describe('#off', function() { - - it('(1) specific off', function(done) { - expect(this.client.off).to.be.a(Function); + describe('#off', function() { + it('(1) specific off', function(done) { + expect(this.client.off).to.be.a(Function); - td.replace(this.client, 'enrichKwargs', enrichKwargs); + td.replace(this.client, 'enrichKwargs', enrichKwargs); - this.client.on('request', function() { - done('Expected not to be called'); - }); - this.client.off('request'); + this.client.on('request', function() { + done('Expected not to be called'); + }); + this.client.off('request'); - this.client.get({ uri: 'test' }); + this.client.get({ uri: 'test' }); - done(); - }); - - it('(2) global off', function(done) { - expect(this.client.off).to.be.a(Function); + done(); + }); - td.replace(this.client, 'enrichKwargs', enrichKwargs); + it('(2) global off', function(done) { + expect(this.client.off).to.be.a(Function); - this.client.on('request', function() { - done('Expected not to be called'); - }); - this.client.off(); + td.replace(this.client, 'enrichKwargs', enrichKwargs); - this.client.get({ uri: 'test' }); + this.client.on('request', function() { + done('Expected not to be called'); + }); + this.client.off(); - done(); - }); + this.client.get({ uri: 'test' }); + done(); }); + }); - it('#send', function(done) { - expect(this.client.send).to.be.a(Function); - - this.client.on('test', function(a, b) { - expect(a).to.be(100); - expect(b).to.be(50); - done(); - }); + it('#send', function(done) { + expect(this.client.send).to.be.a(Function); - this.client.send('test', 100, 50); + this.client.on('test', function(a, b) { + expect(a).to.be(100); + expect(b).to.be(50); + done(); }); - describe('#feed', function() { + this.client.send('test', 100, 50); + }); - it('(1) throw', function() { - var self = this; + describe('#feed', function() { + it('(1) throw', function() { + var self = this; - function toThrow() { - self.client.feed(); - } + function toThrow() { + self.client.feed(); + } - expect(toThrow).to.throwException(function(e) { - expect(e).to.be.a(errors.FeedError); - }); - }); - - it('(2) throw', function() { - var self = this; + expect(toThrow).to.throwException(function(e) { + expect(e).to.be.a(errors.FeedError); + }); + }); - function toThrow() { - self.client.feed('user:jaap'); - } + it('(2) throw', function() { + var self = this; - expect(toThrow).to.throwException(function(e) { - expect(e).to.be.a(errors.FeedError); - }); - }); + function toThrow() { + self.client.feed('user:jaap'); + } - it('(3) throw', function() { - var self = this; + expect(toThrow).to.throwException(function(e) { + expect(e).to.be.a(errors.FeedError); + }); + }); - function toThrow() { - self.client.feed('user###','jaap'); - } + it('(3) throw', function() { + var self = this; - expect(toThrow).to.throwException(function(e) { - expect(e).to.be.a(errors.FeedError); - }); - }); + function toThrow() { + self.client.feed('user###', 'jaap'); + } - it('(4) throw', function() { - var self = this; + expect(toThrow).to.throwException(function(e) { + expect(e).to.be.a(errors.FeedError); + }); + }); - function toThrow() { - self.client.feed('user','###jaap'); - } + it('(4) throw', function() { + var self = this; - expect(toThrow).to.throwException(function(e) { - expect(e).to.be.a(errors.FeedError); - }); - }); + function toThrow() { + self.client.feed('user', '###jaap'); + } - it('(5) throw with colon', function() { - var self = this; + expect(toThrow).to.throwException(function(e) { + expect(e).to.be.a(errors.FeedError); + }); + }); - function toThrow() { - self.client.feed('user:jaap', 'jaap'); - } + it('(5) throw with colon', function() { + var self = this; - expect(toThrow).to.throwException(function(e) { - expect(e).to.be.a(errors.FeedError); - }); - }); + function toThrow() { + self.client.feed('user:jaap', 'jaap'); + } - it('(6) throw without secret and token', function() { - var self = this; + expect(toThrow).to.throwException(function(e) { + expect(e).to.be.a(errors.FeedError); + }); + }); - function toThrow() { - self.client.feed('user','jaap'); - } + it('(6) throw without secret and token', function() { + var self = this; - self.client.apiSecret = undefined; + function toThrow() { + self.client.feed('user', 'jaap'); + } - expect(toThrow).to.throwException(function(e) { - expect(e).to.be.a(errors.FeedError); - }); - }); + self.client.apiSecret = undefined; + expect(toThrow).to.throwException(function(e) { + expect(e).to.be.a(errors.FeedError); + }); }); + }); - describe('#wrapPromiseTask', function() { - - it('(1) success', function(done) { - function fulfill() { - done(); - } + describe('#wrapPromiseTask', function() { + it('(1) success', function(done) { + function fulfill() { + done(); + } - function reject(err) { - expect(err).to.be.a(errors.StreamApiError); - done(err); - } + function reject(err) { + expect(err).to.be.a(errors.StreamApiError); + done(err); + } - var task = this.client.wrapPromiseTask(undefined, fulfill, reject); + var task = this.client.wrapPromiseTask(undefined, fulfill, reject); - task(null, { statusCode: 200 }, {}); - }); - - it('(2) failure 500 status code', function(done) { - function fulfill() { - done('Expected to fail'); - } + task(null, { statusCode: 200 }, {}); + }); - function reject(err) { - expect(err).to.be.a(errors.StreamApiError); - done(); - } + it('(2) failure 500 status code', function(done) { + function fulfill() { + done('Expected to fail'); + } - var task = this.client.wrapPromiseTask(undefined, fulfill, reject); + function reject(err) { + expect(err).to.be.a(errors.StreamApiError); + done(); + } - task(null, { statusCode: 500 }, {}); - }); + var task = this.client.wrapPromiseTask(undefined, fulfill, reject); - it('(3) failure rejected', function(done) { - function fulfill() { - done('Expected to fail'); - } + task(null, { statusCode: 500 }, {}); + }); - function reject(err) { - expect(err).to.be.a(errors.StreamApiError); - done(); - } + it('(3) failure rejected', function(done) { + function fulfill() { + done('Expected to fail'); + } - var task = this.client.wrapPromiseTask(undefined, fulfill, reject); + function reject(err) { + expect(err).to.be.a(errors.StreamApiError); + done(); + } - task(new Error('oops'), { statusCode: 200 }, {}); - }); + var task = this.client.wrapPromiseTask(undefined, fulfill, reject); - it('(4) with callback', function(done) { - function fulfill() { - } + task(new Error('oops'), { statusCode: 200 }, {}); + }); - function reject(err) { - expect(err).to.be.a(errors.StreamApiError); - done(err); - } + it('(4) with callback', function(done) { + function fulfill() {} - var task = this.client.wrapPromiseTask(function() { - done(); - }, fulfill, reject); + function reject(err) { + expect(err).to.be.a(errors.StreamApiError); + done(err); + } - task(null, { statusCode: 200 }, {}); - }); + var task = this.client.wrapPromiseTask( + function() { + done(); + }, + fulfill, + reject + ); + task(null, { statusCode: 200 }, {}); }); - - describe('#enrichUrl', function() { - - it('(1) api service', function() { - var feedGroup = 'user' - var url = this.client.enrichUrl(feedGroup); - expect(url).to.be(this.client.baseUrl + this.client.version + '/' + feedGroup); - }); + }); + + describe('#enrichUrl', function() { + it('(1) api service', function() { + var feedGroup = 'user'; + var url = this.client.enrichUrl(feedGroup); + expect(url).to.be( + this.client.baseUrl + this.client.version + '/' + feedGroup + ); }); - - describe('#enrichKwargs', function() { - - it('(1) api service - simple auth type', function() { - var kwargs = this.client.enrichKwargs({ - url: 'feed', - signature: 'Basic encoded_password', - }); - - expect(kwargs.qs.api_key).to.be(this.client.apiKey); - expect(kwargs.qs.location).to.be(this.client.group); - expect(kwargs.json).to.be(true); - expect(kwargs.headers['stream-auth-type']).to.be('simple'); - expect(kwargs.headers['X-Stream-Client']).to.be(this.client.userAgent()); - expect(kwargs.headers['Authorization']).to.be('Basic encoded_password'); - expect(kwargs.url).to.contain('api.stream-io-api.com'); - }); - - it('(2) api service - jwt signature', function() { - var signature = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG5Eb2UiLCJhY3Rpb24iOiJyZWFkIn0.dfayorXXS1rAyd97BGCNgrCodPH9X3P80DPMH5b9D_A"; - - var kwargs = this.client.enrichKwargs({ - url: 'feed', - signature: "feedname " + signature, - }); - - expect(kwargs.qs.api_key).to.be(this.client.apiKey); - expect(kwargs.qs.location).to.be(this.client.group); - expect(kwargs.json).to.be(true); - expect(kwargs.headers['stream-auth-type']).to.be('jwt'); - expect(kwargs.headers['X-Stream-Client']).to.be(this.client.userAgent()); - expect(kwargs.headers['Authorization']).to.be(signature); - expect(kwargs.url).to.contain('api.stream-io-api.com'); - }); - - it('(3) personalization service - simple auth type', function() { - var kwargs = this.client.enrichKwargs({ - url: 'feed', - serviceName: 'personalization', - signature: 'Basic encoded_password', - }); - - expect(kwargs.qs.api_key).to.be(this.client.apiKey); - expect(kwargs.qs.location).to.be(this.client.group); - expect(kwargs.json).to.be(true); - expect(kwargs.headers['stream-auth-type']).to.be('simple'); - expect(kwargs.headers['X-Stream-Client']).to.be(this.client.userAgent()); - expect(kwargs.headers['Authorization']).to.be('Basic encoded_password'); - expect(kwargs.url).to.contain('personalization.stream-io-api.com'); - }); - - it('(4) personalization service - jwt signature', function() { - var signature = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZXNvdXJjZSI6IioiLCJhY3Rpb24iOiJwZXJzb25hbGl6YXRpb24iLCJmZWVkX2lkIjoiKiIsInVzZXJfaWQiOiIqIn0.JvX_IGajZSPD5zDOVpeZLkn0hhClMheN_ILnowyBUN"; - - var kwargs = this.client.enrichKwargs({ - url: 'feed', - serviceName: 'personalization', - signature: "feedname " + signature, - }); - - expect(kwargs.qs.api_key).to.be(this.client.apiKey); - expect(kwargs.qs.location).to.be(this.client.group); - expect(kwargs.json).to.be(true); - expect(kwargs.headers['stream-auth-type']).to.be('jwt'); - expect(kwargs.headers['X-Stream-Client']).to.be(this.client.userAgent()); - expect(kwargs.headers['Authorization']).to.be(signature); - expect(kwargs.url).to.contain('personalization.stream-io-api.com'); - }); - + }); + + describe('#enrichKwargs', function() { + it('(1) api service - simple auth type', function() { + var kwargs = this.client.enrichKwargs({ + url: 'feed', + signature: 'Basic encoded_password', + }); + + expect(kwargs.qs.api_key).to.be(this.client.apiKey); + expect(kwargs.qs.location).to.be(this.client.group); + expect(kwargs.json).to.be(true); + expect(kwargs.headers['stream-auth-type']).to.be('simple'); + expect(kwargs.headers['X-Stream-Client']).to.be(this.client.userAgent()); + expect(kwargs.headers['Authorization']).to.be('Basic encoded_password'); + expect(kwargs.url).to.contain('api.stream-io-api.com'); }); - describe('#signActivities', function() { + it('(2) api service - jwt signature', function() { + var signature = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG5Eb2UiLCJhY3Rpb24iOiJyZWFkIn0.dfayorXXS1rAyd97BGCNgrCodPH9X3P80DPMH5b9D_A'; + + var kwargs = this.client.enrichKwargs({ + url: 'feed', + signature: 'feedname ' + signature, + }); + + expect(kwargs.qs.api_key).to.be(this.client.apiKey); + expect(kwargs.qs.location).to.be(this.client.group); + expect(kwargs.json).to.be(true); + expect(kwargs.headers['stream-auth-type']).to.be('jwt'); + expect(kwargs.headers['X-Stream-Client']).to.be(this.client.userAgent()); + expect(kwargs.headers['Authorization']).to.be(signature); + expect(kwargs.url).to.contain('api.stream-io-api.com'); + }); - it('(1) without to', function() { - var activities = [{ object: 0, actor: 'matthisk', verb: 'tweet' }]; + it('(3) personalization service - simple auth type', function() { + var kwargs = this.client.enrichKwargs({ + url: 'feed', + serviceName: 'personalization', + signature: 'Basic encoded_password', + }); + + expect(kwargs.qs.api_key).to.be(this.client.apiKey); + expect(kwargs.qs.location).to.be(this.client.group); + expect(kwargs.json).to.be(true); + expect(kwargs.headers['stream-auth-type']).to.be('simple'); + expect(kwargs.headers['X-Stream-Client']).to.be(this.client.userAgent()); + expect(kwargs.headers['Authorization']).to.be('Basic encoded_password'); + expect(kwargs.url).to.contain('personalization.stream-io-api.com'); + }); - var output = this.client.signActivities(activities); + it('(4) personalization service - jwt signature', function() { + var signature = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZXNvdXJjZSI6IioiLCJhY3Rpb24iOiJwZXJzb25hbGl6YXRpb24iLCJmZWVkX2lkIjoiKiIsInVzZXJfaWQiOiIqIn0.JvX_IGajZSPD5zDOVpeZLkn0hhClMheN_ILnowyBUN'; + + var kwargs = this.client.enrichKwargs({ + url: 'feed', + serviceName: 'personalization', + signature: 'feedname ' + signature, + }); + + expect(kwargs.qs.api_key).to.be(this.client.apiKey); + expect(kwargs.qs.location).to.be(this.client.group); + expect(kwargs.json).to.be(true); + expect(kwargs.headers['stream-auth-type']).to.be('jwt'); + expect(kwargs.headers['X-Stream-Client']).to.be(this.client.userAgent()); + expect(kwargs.headers['Authorization']).to.be(signature); + expect(kwargs.url).to.contain('personalization.stream-io-api.com'); + }); + }); - expect(output).to.eql(activities); - }); + describe('#signActivities', function() { + it('(1) without to', function() { + var activities = [{ object: 0, actor: 'matthisk', verb: 'tweet' }]; - it('(2) with to', function() { - var activities = [{ object: 0, actor: 'matthisk', verb: 'tweet', to: ['global:feed'] }]; + var output = this.client.signActivities(activities); - var output = this.client.signActivities(activities); + expect(output).to.eql(activities); + }); - expect(activities[0].to).to.eql(['global:feed']) - expect(output[0].to[0].split(' ')[0]).to.be('global:feed'); + it('(2) with to', function() { + var activities = [ + { object: 0, actor: 'matthisk', verb: 'tweet', to: ['global:feed'] }, + ]; - if (this.client.apiSecret) { - var token = this.client.feed('global', 'feed').token; - expect(output[0].to[0].split(' ')[1]).to.be(token); - } + var output = this.client.signActivities(activities); - }); + expect(activities[0].to).to.eql(['global:feed']); + expect(output[0].to[0].split(' ')[0]).to.be('global:feed'); - it('(3) without secret', function() { - var activities = [{ object: 0, actor: 'matthisk', verb: 'tweet' }]; + if (this.client.apiSecret) { + var token = this.client.feed('global', 'feed').token; + expect(output[0].to[0].split(' ')[1]).to.be(token); + } + }); - this.client.apiSecret = undefined; - var output = this.client.signActivities(activities); + it('(3) without secret', function() { + var activities = [{ object: 0, actor: 'matthisk', verb: 'tweet' }]; - expect(output).to.equal(activities); - }); + this.client.apiSecret = undefined; + var output = this.client.signActivities(activities); + expect(output).to.equal(activities); }); + }); - describe('Requests', function() { - - var tdRequest = td.function(); - - function toExpect(method) { - var arg0 = { url: 'feed', method: method, gzip: true }; - var fun = td.matchers.isA(Function); - return tdRequest(arg0, fun); - } + describe('Requests', function() { + var tdRequest = td.function(); - beforeEach(function() { - this.client.request = tdRequest; - td.replace(this.client, 'enrichKwargs', enrichKwargs); - }); + function toExpect(method) { + var arg0 = { url: 'feed', method: method, gzip: true }; + var fun = td.matchers.isA(Function); + return tdRequest(arg0, fun); + } - it('#get', function() { - this.client.get({ url: 'feed' }); + beforeEach(function() { + this.client.request = tdRequest; + td.replace(this.client, 'enrichKwargs', enrichKwargs); + }); - td.verify(toExpect('GET')); - }); + it('#get', function() { + this.client.get({ url: 'feed' }); - it('#post', function() { - this.client.post({ url: 'feed' }); + td.verify(toExpect('GET')); + }); - td.verify(toExpect('POST')); - }); + it('#post', function() { + this.client.post({ url: 'feed' }); - it('#delete', function() { - this.client['delete']({ url: 'feed' }); + td.verify(toExpect('POST')); + }); - td.verify(toExpect('DELETE')); - }); + it('#delete', function() { + this.client['delete']({ url: 'feed' }); + td.verify(toExpect('DELETE')); }); - + }); }); diff --git a/test/unit/common/faye_test.js b/test/unit/common/faye_test.js index 8cff22e0..f2720c91 100644 --- a/test/unit/common/faye_test.js +++ b/test/unit/common/faye_test.js @@ -1,39 +1,38 @@ -var expect = require('expect.js') - , beforeEachFn = require('../utils/hooks').beforeEach - , init = require('../utils/hooks').init - , Faye = require('faye'); +var expect = require('expect.js'), + beforeEachFn = require('../utils/hooks').beforeEach, + init = require('../utils/hooks').init, + Faye = require('faye'); describe('[UNIT] Faye (browser)', function() { + init.call(this); + beforeEach(beforeEachFn); - init.call(this); - beforeEach(beforeEachFn); + it('#getFayeAuthorization', function() { + var self = this; + var auth = this.client.getFayeAuthorization(); - it('#getFayeAuthorization', function() { - var self = this; - var auth = this.client.getFayeAuthorization(); + expect(auth.incoming).to.be.a(Function); + expect(auth.outgoing).to.be.a(Function); - expect(auth.incoming).to.be.a(Function); - expect(auth.outgoing).to.be.a(Function); - - auth.incoming('matthisk', function(message) { - expect(message).to.be('matthisk'); - }); + auth.incoming('matthisk', function(message) { + expect(message).to.be('matthisk'); + }); - this.client.subscriptions['test'] = { - userId: 'matthisk', - token: 'token', - }; + this.client.subscriptions['test'] = { + userId: 'matthisk', + token: 'token', + }; - auth.outgoing({ subscription: 'test' }, function(message) { - expect(message.ext.user_id).to.be('matthisk'); - expect(message.ext.api_key).to.be(self.client.apiKey); - expect(message.ext.signature).to.be('token'); - }); + auth.outgoing({ subscription: 'test' }, function(message) { + expect(message.ext.user_id).to.be('matthisk'); + expect(message.ext.api_key).to.be(self.client.apiKey); + expect(message.ext.signature).to.be('token'); }); + }); - it('#getFayeClient', function() { - var client = this.client.getFayeClient(); + it('#getFayeClient', function() { + var client = this.client.getFayeClient(); - expect(client).to.be.a(Faye.Client); - }); -}); \ No newline at end of file + expect(client).to.be.a(Faye.Client); + }); +}); diff --git a/test/unit/common/feed_test.js b/test/unit/common/feed_test.js index 24425f34..bcc9e936 100644 --- a/test/unit/common/feed_test.js +++ b/test/unit/common/feed_test.js @@ -1,511 +1,646 @@ -var expect = require('expect.js') - , beforeEachFn = require('../utils/hooks').beforeEach - , init = require('../utils/hooks').init - , td = require('testdouble') - , errors = require('../../../src/getstream').errors - , StreamFeed = require('../../../src/lib/feed'); +var expect = require('expect.js'), + beforeEachFn = require('../utils/hooks').beforeEach, + init = require('../utils/hooks').init, + td = require('testdouble'), + errors = require('../../../src/getstream').errors, + StreamFeed = require('../../../src/lib/feed'); describe('[UNIT] Stream Feed (Common)', function() { - var get, post, del, feed; + var get, post, del, feed; + + init.call(this); + beforeEach(beforeEachFn); + beforeEach(function() { + feed = new StreamFeed(this.client, 'user', 'matthisk', 'token'); + post = td.function(); + del = td.function(); + get = td.function(); + td.replace(this.client, 'post', post); + td.replace(this.client, 'delete', del); + td.replace(this.client, 'get', get); + }); + + afterEach(function() { + td.reset(); + }); + + it('#intialize', function() { + expect(feed.client).to.be(this.client); + expect(feed.slug).to.be('user'); + expect(feed.userId).to.be('matthisk'); + expect(feed.id).to.be('user:matthisk'); + expect(feed.feedUrl).to.be('user/matthisk'); + expect(feed.feedTogether).to.be('usermatthisk'); + expect(feed.signature).to.be('usermatthisk token'); + expect(feed.notificationChannel).to.be( + 'site-' + this.client.appId + '-feed-usermatthisk' + ); + }); + + describe('#addActivity', function() { + var activity = { actor: 'matthisk', object: 0, verb: 'tweet' }; + + it('(1)', function() { + feed.addActivity(activity); + + td.verify( + post( + { + url: 'feed/user/matthisk/', + body: activity, + signature: 'usermatthisk token', + }, + undefined + ) + ); + }); - init.call(this); - beforeEach(beforeEachFn); - beforeEach(function() { - feed = new StreamFeed(this.client, 'user', 'matthisk', 'token'); - post = td.function(); - del = td.function(); - get = td.function(); - td.replace(this.client, 'post', post); - td.replace(this.client, 'delete', del); - td.replace(this.client, 'get', get); + it('(2)', function() { + var cb = function() {}; + feed.addActivity(activity, cb); + + td.verify( + post( + { + url: 'feed/user/matthisk/', + body: activity, + signature: 'usermatthisk token', + }, + cb + ) + ); + }); + }); + + describe('#addActivities', function() { + var activities = [{ actor: 'matthisk', object: 0, verb: 'tweet' }]; + + it('(1)', function() { + feed.addActivities(activities); + + td.verify( + post( + { + url: 'feed/user/matthisk/', + body: { activities: activities }, + signature: 'usermatthisk token', + }, + undefined + ) + ); }); - afterEach(function() { - td.reset(); + it('(2)', function() { + var cb = function() {}; + feed.addActivities(activities, cb); + + td.verify( + post( + { + url: 'feed/user/matthisk/', + body: { activities: activities }, + signature: 'usermatthisk token', + }, + cb + ) + ); }); + }); + + describe('#follow', function() { + it('(1) throws', function() { + function throws1() { + feed.follow('user###', 'henk'); + } - it('#intialize', function() { - expect(feed.client).to.be(this.client); - expect(feed.slug).to.be('user'); - expect(feed.userId).to.be('matthisk'); - expect(feed.id).to.be('user:matthisk'); - expect(feed.feedUrl).to.be('user/matthisk'); - expect(feed.feedTogether).to.be('usermatthisk'); - expect(feed.signature).to.be('usermatthisk token'); - expect(feed.notificationChannel).to.be('site-' + this.client.appId + '-feed-usermatthisk'); + function throws2() { + feed.follow('user', '###henk'); + } + + expect(throws1).to.throw; + expect(throws2).to.throw; }); - describe('#addActivity', function() { - var activity = { actor: 'matthisk', object: 0, verb: 'tweet' }; - - it('(1)', function() { - feed.addActivity(activity); + it('(2) default', function() { + feed.follow('user', 'henk'); + + var body = { + target: 'user:henk', + }; + + td.verify( + post( + { + url: 'feed/user/matthisk/following/', + body: body, + signature: 'usermatthisk token', + }, + undefined + ) + ); + }); - td.verify(post({ - url: 'feed/user/matthisk/', - body: activity, - signature: 'usermatthisk token', - }, undefined)); - }); - - it('(2)', function() { - var cb = function() {}; - feed.addActivity(activity, cb); - - td.verify(post({ - url: 'feed/user/matthisk/', - body: activity, - signature: 'usermatthisk token', - }, cb)); - }); - - }); - - describe('#addActivities', function() { - var activities = [{ actor: 'matthisk', object: 0, verb: 'tweet' }]; + it('(3) with cb', function() { + var cb = function() {}; + feed.follow('user', 'henk', cb); + + var body = { + target: 'user:henk', + }; + + td.verify( + post( + { + url: 'feed/user/matthisk/following/', + body: body, + signature: 'usermatthisk token', + }, + cb + ) + ); + }); - it('(1)', function() { - feed.addActivities(activities); + it('(4) activity copy limit', function() { + feed.follow('user', 'henk', { limit: 10 }); + + var body = { + target: 'user:henk', + activity_copy_limit: 10, + }; + + td.verify( + post( + { + url: 'feed/user/matthisk/following/', + body: body, + signature: 'usermatthisk token', + }, + undefined + ) + ); + }); - td.verify(post({ - url: 'feed/user/matthisk/', - body: { activities: activities }, - signature: 'usermatthisk token', - }, undefined)); - }); - - it('(2)', function() { - var cb = function() {}; - feed.addActivities(activities, cb); - - td.verify(post({ - url: 'feed/user/matthisk/', - body: { activities: activities }, - signature: 'usermatthisk token', - }, cb)); - }); + it('(5) with cb and activity copy limit', function() { + var cb = function() {}; + feed.follow('user', 'henk', { limit: 10 }, cb); + + var body = { + target: 'user:henk', + activity_copy_limit: 10, + }; + + td.verify( + post( + { + url: 'feed/user/matthisk/following/', + body: body, + signature: 'usermatthisk token', + }, + cb + ) + ); + }); + }); - }); - - describe('#follow', function() { + describe('#unfollow', function() { + it('(1) throws', function() { + function throws1() { + feed.unfollow('user###', 'henk'); + } - it('(1) throws', function() { - function throws1() { - feed.follow('user###', 'henk'); - } - - function throws2() { - feed.follow('user', '###henk'); - } - - expect(throws1).to.throw; - expect(throws2).to.throw; - }); - - it('(2) default', function() { - feed.follow('user', 'henk'); - - var body = { - target: 'user:henk', - }; - - td.verify(post({ - url: 'feed/user/matthisk/following/', - body: body, - signature: 'usermatthisk token', - }, undefined)); - }); - - it('(3) with cb', function() { - var cb = function() {}; - feed.follow('user', 'henk', cb); - - var body = { - target: 'user:henk', - }; - - td.verify(post({ - url: 'feed/user/matthisk/following/', - body: body, - signature: 'usermatthisk token', - }, cb)); - }); - - it('(4) activity copy limit', function() { - feed.follow('user', 'henk', { limit: 10 }); + function throws2() { + feed.unfollow('user', '###henk'); + } - var body = { - target: 'user:henk', - activity_copy_limit: 10, - }; - - td.verify(post({ - url: 'feed/user/matthisk/following/', - body: body, - signature: 'usermatthisk token', - }, undefined)); - }); - - it('(5) with cb and activity copy limit', function() { - var cb = function() {}; - feed.follow('user', 'henk', { limit: 10 }, cb); - - var body = { - target: 'user:henk', - activity_copy_limit: 10, - }; - - td.verify(post({ - url: 'feed/user/matthisk/following/', - body: body, - signature: 'usermatthisk token', - }, cb)); - }); - - }); - - describe('#unfollow', function() { - - it('(1) throws', function() { - function throws1() { - feed.unfollow('user###', 'henk'); - } - - function throws2() { - feed.unfollow('user', '###henk'); - } - - expect(throws1).to.throw; - expect(throws2).to.throw; - }); - - it('(2) default', function() { - feed.unfollow('user', 'henk'); - - td.verify(del({ - url: 'feed/user/matthisk/following/user:henk/', - qs: {}, - signature: 'usermatthisk token', - }, undefined)); - }); - - it('(3) default cb', function() { - var cb = function() {}; - feed.unfollow('user', 'henk', cb); - - td.verify(del({ - url: 'feed/user/matthisk/following/user:henk/', - qs: {}, - signature: 'usermatthisk token', - }, cb)); - }); - - it('(4) default keep_history', function() { - feed.unfollow('user', 'henk', { keepHistory: true }); - - td.verify(del({ - url: 'feed/user/matthisk/following/user:henk/', - qs: { - keep_history: '1', - }, - signature: 'usermatthisk token', - }, undefined)); - }); - - it('(5) default cb keep_history', function() { - var cb = function() {}; - feed.unfollow('user', 'henk', { keepHistory: true }, cb); - - td.verify(del({ - url: 'feed/user/matthisk/following/user:henk/', - qs: { - keep_history: '1', - }, - signature: 'usermatthisk token', - }, cb)); - }); - - }); - - describe('#following', function() { - - it('(1) default', function() { - feed.following({}); - - td.verify(get({ - url: 'feed/user/matthisk/following/', - qs: {}, - signature: 'usermatthisk token', - }, undefined)); - }); - - it('(2) cb', function() { - var cb = function() {}; - feed.following({}, cb); - - td.verify(get({ - url: 'feed/user/matthisk/following/', - qs: {}, - signature: 'usermatthisk token', - }, cb)); - }); - - it('(3) options', function() { - var cb = function() {}; - var filter = ['a', 'b', 'c']; - feed.following({ filter: filter }, cb); - - td.verify(get({ - url: 'feed/user/matthisk/following/', - qs: { - filter: 'a,b,c', - }, - signature: 'usermatthisk token', - }, cb)); - }); - - }); - - describe('#followers', function() { - - it('(1) default', function() { - feed.followers({}); - - td.verify(get({ - url: 'feed/user/matthisk/followers/', - qs: {}, - signature: 'usermatthisk token', - }, undefined)); - }); - - it('(2) cb', function() { - var cb = function() {}; - feed.followers({}, cb); - - td.verify(get({ - url: 'feed/user/matthisk/followers/', - qs: {}, - signature: 'usermatthisk token', - }, cb)); - }); - - it('(3) options', function() { - var cb = function() {}; - var filter = ['a', 'b', 'c']; - feed.followers({ filter: filter }, cb); - - td.verify(get({ - url: 'feed/user/matthisk/followers/', - qs: { - filter: 'a,b,c', - }, - signature: 'usermatthisk token', - }, cb)); - }); - - }); - - - describe('#get', function() { - - it('(1) default', function() { - feed.get({}); + expect(throws1).to.throw; + expect(throws2).to.throw; + }); - td.verify(get({ - url: 'feed/user/matthisk/', - qs: {}, - signature: 'usermatthisk token', - }, undefined)); - }); + it('(2) default', function() { + feed.unfollow('user', 'henk'); + + td.verify( + del( + { + url: 'feed/user/matthisk/following/user:henk/', + qs: {}, + signature: 'usermatthisk token', + }, + undefined + ) + ); + }); - it('(2) cb', function() { - var cb = function cb() {}; - feed.get({}, cb); + it('(3) default cb', function() { + var cb = function() {}; + feed.unfollow('user', 'henk', cb); + + td.verify( + del( + { + url: 'feed/user/matthisk/following/user:henk/', + qs: {}, + signature: 'usermatthisk token', + }, + cb + ) + ); + }); - td.verify(get({ - url: 'feed/user/matthisk/', - qs: {}, - signature: 'usermatthisk token', - }, cb)); - }); + it('(4) default keep_history', function() { + feed.unfollow('user', 'henk', { keepHistory: true }); + + td.verify( + del( + { + url: 'feed/user/matthisk/following/user:henk/', + qs: { + keep_history: '1', + }, + signature: 'usermatthisk token', + }, + undefined + ) + ); + }); - it('(3) default', function() { - feed.get({ - mark_read: ['a', 'b'], - mark_seen: ['c', 'd'], - }); + it('(5) default cb keep_history', function() { + var cb = function() {}; + feed.unfollow('user', 'henk', { keepHistory: true }, cb); + + td.verify( + del( + { + url: 'feed/user/matthisk/following/user:henk/', + qs: { + keep_history: '1', + }, + signature: 'usermatthisk token', + }, + cb + ) + ); + }); + }); + + describe('#following', function() { + it('(1) default', function() { + feed.following({}); + + td.verify( + get( + { + url: 'feed/user/matthisk/following/', + qs: {}, + signature: 'usermatthisk token', + }, + undefined + ) + ); + }); - td.verify(get({ - url: 'feed/user/matthisk/', - qs: { - mark_read: 'a,b', - mark_seen: 'c,d', - }, - signature: 'usermatthisk token', - }, undefined)); - }); + it('(2) cb', function() { + var cb = function() {}; + feed.following({}, cb); + + td.verify( + get( + { + url: 'feed/user/matthisk/following/', + qs: {}, + signature: 'usermatthisk token', + }, + cb + ) + ); + }); - it('(4) options plus cb', function() { - var cb = function() {}; - feed.get({ - mark_read: ['a', 'b'], - mark_seen: ['c', 'd'], - }, cb); + it('(3) options', function() { + var cb = function() {}; + var filter = ['a', 'b', 'c']; + feed.following({ filter: filter }, cb); + + td.verify( + get( + { + url: 'feed/user/matthisk/following/', + qs: { + filter: 'a,b,c', + }, + signature: 'usermatthisk token', + }, + cb + ) + ); + }); + }); + + describe('#followers', function() { + it('(1) default', function() { + feed.followers({}); + + td.verify( + get( + { + url: 'feed/user/matthisk/followers/', + qs: {}, + signature: 'usermatthisk token', + }, + undefined + ) + ); + }); - td.verify(get({ - url: 'feed/user/matthisk/', - qs: { - mark_read: 'a,b', - mark_seen: 'c,d', - }, - signature: 'usermatthisk token', - }, cb)); - }); + it('(2) cb', function() { + var cb = function() {}; + feed.followers({}, cb); + + td.verify( + get( + { + url: 'feed/user/matthisk/followers/', + qs: {}, + signature: 'usermatthisk token', + }, + cb + ) + ); + }); + it('(3) options', function() { + var cb = function() {}; + var filter = ['a', 'b', 'c']; + feed.followers({ filter: filter }, cb); + + td.verify( + get( + { + url: 'feed/user/matthisk/followers/', + qs: { + filter: 'a,b,c', + }, + signature: 'usermatthisk token', + }, + cb + ) + ); + }); + }); + + describe('#get', function() { + it('(1) default', function() { + feed.get({}); + + td.verify( + get( + { + url: 'feed/user/matthisk/', + qs: {}, + signature: 'usermatthisk token', + }, + undefined + ) + ); }); - describe('#subscribe', function() { + it('(2) cb', function() { + var cb = function cb() {}; + feed.get({}, cb); + + td.verify( + get( + { + url: 'feed/user/matthisk/', + qs: {}, + signature: 'usermatthisk token', + }, + cb + ) + ); + }); - it('(1) throws', function() { - td.replace(this.client, 'appId', 0); + it('(3) default', function() { + feed.get({ + mark_read: ['a', 'b'], + mark_seen: ['c', 'd'], + }); + + td.verify( + get( + { + url: 'feed/user/matthisk/', + qs: { + mark_read: 'a,b', + mark_seen: 'c,d', + }, + signature: 'usermatthisk token', + }, + undefined + ) + ); + }); - function throws() { - feed.subscribe(); - } + it('(4) options plus cb', function() { + var cb = function() {}; + feed.get( + { + mark_read: ['a', 'b'], + mark_seen: ['c', 'd'], + }, + cb + ); + + td.verify( + get( + { + url: 'feed/user/matthisk/', + qs: { + mark_read: 'a,b', + mark_seen: 'c,d', + }, + signature: 'usermatthisk token', + }, + cb + ) + ); + }); + }); - expect(throws).to.throwException(function(err) { - expect(err).to.be.a(errors.SiteError); - }); - }); + describe('#subscribe', function() { + it('(1) throws', function() { + td.replace(this.client, 'appId', 0); - it('(2) default', function() { - td.replace(this.client, 'appId', 1234); + function throws() { + feed.subscribe(); + } - var fn = td.function(); - var subscribeFn = td.function(); + expect(throws).to.throwException(function(err) { + expect(err).to.be.a(errors.SiteError); + }); + }); - td.when(fn()).thenReturn({ - subscribe: subscribeFn, - }); + it('(2) default', function() { + td.replace(this.client, 'appId', 1234); - td.replace(this.client, 'getFayeClient', fn); + var fn = td.function(); + var subscribeFn = td.function(); - feed.subscribe(); + td.when(fn()).thenReturn({ + subscribe: subscribeFn, + }); - td.verify(subscribeFn('/' + feed.notificationChannel, undefined)); - }); + td.replace(this.client, 'getFayeClient', fn); - it('(3) cb', function() { - var cb = function() {}; - td.replace(this.client, 'appId', 1234); + feed.subscribe(); - var fn = td.function(); - var subscribeFn = td.function(); + td.verify(subscribeFn('/' + feed.notificationChannel, undefined)); + }); - td.when(fn()).thenReturn({ - subscribe: subscribeFn, - }); - - td.replace(this.client, 'getFayeClient', fn); - - feed.subscribe(cb); - - td.verify(subscribeFn('/' + feed.notificationChannel, cb)); - }); - - }); - - describe('#unsubscribe', function() { - - it('(1) default', function() { - var subscriptionId = '/' + feed.notificationChannel; - var subscriptionDbl = td.object(['cancel']); - - feed.client.subscriptions[subscriptionId] = { - fayeSubscription: subscriptionDbl - }; - - feed.unsubscribe(); - expect(feed.client.subscriptions[subscriptionId]).to.be(undefined); - td.verify(subscriptionDbl.cancel()); - }); - }); - - describe('#removeActivity', function() { - - it('(1)', function() { - feed.removeActivity('aID'); - - td.verify(del({ - url: 'feed/user/matthisk/aID/', - qs: {}, - signature: 'usermatthisk token', - }, undefined)); - }); + it('(3) cb', function() { + var cb = function() {}; + td.replace(this.client, 'appId', 1234); - it('(2)', function() { - feed.removeActivity({ foreignId: 'fID' }); + var fn = td.function(); + var subscribeFn = td.function(); - td.verify(del({ - url: 'feed/user/matthisk/fID/', - qs: { 'foreign_id': '1' }, - signature: 'usermatthisk token', - }, undefined)); - }); + td.when(fn()).thenReturn({ + subscribe: subscribeFn, + }); - it('(3)', function() { - var cb = function() {}; - feed.removeActivity('aID', cb); + td.replace(this.client, 'getFayeClient', fn); - td.verify(del({ - url: 'feed/user/matthisk/aID/', - qs: {}, - signature: 'usermatthisk token', - }, cb)); - }); + feed.subscribe(cb); + td.verify(subscribeFn('/' + feed.notificationChannel, cb)); }); + }); + + describe('#unsubscribe', function() { + it('(1) default', function() { + var subscriptionId = '/' + feed.notificationChannel; + var subscriptionDbl = td.object(['cancel']); - describe('#updateActivityToTargets', function() { - it('throws an error if `foreign_id` or `time` isn\'t provided', function() { - function noTime() { - feed.updateActivityToTargets('foreign_id:1234'); - } + feed.client.subscriptions[subscriptionId] = { + fayeSubscription: subscriptionDbl, + }; - function noForeignID() { - feed.updateActivityToTargets(null, new Date()); - } - expect(noTime).to.throwException(); - expect(noForeignID).to.throwException(); - }); + feed.unsubscribe(); + expect(feed.client.subscriptions[subscriptionId]).to.be(undefined); + td.verify(subscriptionDbl.cancel()); + }); + }); + + describe('#removeActivity', function() { + it('(1)', function() { + feed.removeActivity('aID'); + + td.verify( + del( + { + url: 'feed/user/matthisk/aID/', + qs: {}, + signature: 'usermatthisk token', + }, + undefined + ) + ); + }); - it('throws an error if no `new_targets`, `add_targets`, or `remove_targets` isn\'t provided', function() { - var noTargets = function() { - feed.updateActivityToTargets('foreign_id:1234', new Date()); - }; - expect(noTargets).to.throwException(); - }); + it('(2)', function() { + feed.removeActivity({ foreignId: 'fID' }); + + td.verify( + del( + { + url: 'feed/user/matthisk/fID/', + qs: { foreign_id: '1' }, + signature: 'usermatthisk token', + }, + undefined + ) + ); + }); + + it('(3)', function() { + var cb = function() {}; + feed.removeActivity('aID', cb); + + td.verify( + del( + { + url: 'feed/user/matthisk/aID/', + qs: {}, + signature: 'usermatthisk token', + }, + cb + ) + ); + }); + }); + + describe('#updateActivityToTargets', function() { + it("throws an error if `foreign_id` or `time` isn't provided", function() { + function noTime() { + feed.updateActivityToTargets('foreign_id:1234'); + } + + function noForeignID() { + feed.updateActivityToTargets(null, new Date()); + } + expect(noTime).to.throwException(); + expect(noForeignID).to.throwException(); + }); + + it("throws an error if no `new_targets`, `add_targets`, or `remove_targets` isn't provided", function() { + var noTargets = function() { + feed.updateActivityToTargets('foreign_id:1234', new Date()); + }; + expect(noTargets).to.throwException(); + }); + + it('throws an error if `new_targets` is provided along with either `add_targets` or `remove_targets`', function() { + var newTargetsWithAdd = function() { + feed.updateActivityToTargets( + 'foreign_id:1234', + new Date(), + ['targetFeed:1234'], + ['anotherTargetFeed:1234'] + ); + }; + var newTargetsWithRemove = function() { + feed.updateActivityToTargets( + 'foreign_id:1234', + new Date(), + ['targetFeed:1234'], + null, + ['anotherTargetFeed:1234'] + ); + }; + expect(newTargetsWithAdd).to.throwException(); + expect(newTargetsWithRemove).to.throwException(); + }); - it('throws an error if `new_targets` is provided along with either `add_targets` or `remove_targets`', function() { - var newTargetsWithAdd = function() { - feed.updateActivityToTargets('foreign_id:1234', new Date(), ["targetFeed:1234"], ["anotherTargetFeed:1234"]); - }; - var newTargetsWithRemove = function() { - feed.updateActivityToTargets('foreign_id:1234', new Date(), ["targetFeed:1234"], null, ["anotherTargetFeed:1234"]); - }; - expect(newTargetsWithAdd).to.throwException(); - expect(newTargetsWithRemove).to.throwException(); - }); - - it('throws an error if `add_targets` and `remove_targets` both contain the same ID', function() { - var sameTargets1 = function() { - feed.updateActivityToTargets('foreign_id:1234', new Date(), null, ["targetFeed:1234"], ["targetFeed:1234"]); - }; - var sameTargets2 = function() { - feed.updateActivityToTargets('foreign_id:1234', new Date(), null, ["targetFeed:1234", "targetFeed:5678"], ["targetFeed:1234", "targetFeed:0000"]); - }; - expect(sameTargets1).to.throwException(); - expect(sameTargets2).to.throwException(); - }); + it('throws an error if `add_targets` and `remove_targets` both contain the same ID', function() { + var sameTargets1 = function() { + feed.updateActivityToTargets( + 'foreign_id:1234', + new Date(), + null, + ['targetFeed:1234'], + ['targetFeed:1234'] + ); + }; + var sameTargets2 = function() { + feed.updateActivityToTargets( + 'foreign_id:1234', + new Date(), + null, + ['targetFeed:1234', 'targetFeed:5678'], + ['targetFeed:1234', 'targetFeed:0000'] + ); + }; + expect(sameTargets1).to.throwException(); + expect(sameTargets2).to.throwException(); }); + }); }); diff --git a/test/unit/common/jwt_test.js b/test/unit/common/jwt_test.js index b363c544..ce8ae158 100644 --- a/test/unit/common/jwt_test.js +++ b/test/unit/common/jwt_test.js @@ -1,15 +1,17 @@ -var expect = require('expect.js') - , signing = signing || require('../../../src/lib/signing'); +var expect = require('expect.js'), + signing = signing || require('../../../src/lib/signing'); describe('[UNIT] Json web token validation', function() { - var validSignature = "feedname eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG5Eb2UiLCJhY3Rpb24iOiJyZWFkIn0.dfayorXXS1rAyd97BGCNgrCodPH9X3P80DPMH5b9D_A"; - var invalidSignature = "feedname eyJhbGiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZS.dfayorXXS1rAyd97BGCNgrCodH38PH5b9D_A"; + var validSignature = + 'feedname eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG5Eb2UiLCJhY3Rpb24iOiJyZWFkIn0.dfayorXXS1rAyd97BGCNgrCodPH9X3P80DPMH5b9D_A'; + var invalidSignature = + 'feedname eyJhbGiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZS.dfayorXXS1rAyd97BGCNgrCodH38PH5b9D_A'; it('should validate valid jwts', function() { - expect( signing.isJWTSignature(validSignature) ).to.be(true); + expect(signing.isJWTSignature(validSignature)).to.be(true); }); it('should validate unvalid jwts', function() { - expect( signing.isJWTSignature(invalidSignature) ).to.be(false); + expect(signing.isJWTSignature(invalidSignature)).to.be(false); }); -}); \ No newline at end of file +}); diff --git a/test/unit/common/utils_test.js b/test/unit/common/utils_test.js index 996108be..4c77252c 100644 --- a/test/unit/common/utils_test.js +++ b/test/unit/common/utils_test.js @@ -1,28 +1,26 @@ -var utils = require('../../../src/lib/utils') - , init = require('../utils/hooks').init - , expect = require('expect.js') - , errors = require('../../../src/lib/errors'); +var utils = require('../../../src/lib/utils'), + init = require('../utils/hooks').init, + expect = require('expect.js'), + errors = require('../../../src/lib/errors'); describe('[UNIT] Utility functions', function() { + init.call(this); - init.call(this); + it("should validate feed id's", function() { + expect(utils.validateFeedId('flat:0')).to.be.ok(); + }); - it('should validate feed id\'s', function() { - expect(utils.validateFeedId('flat:0')).to.be.ok(); + it('should throw exception while validating faulty feed id', function() { + expect(function() { + utils.validateFeedId('b134u92fval'); + }).to.throwError(function(e) { + expect(e).to.be.a(errors.FeedError); }); + }); - it('should throw exception while validating faulty feed id',function() { - expect(function() { - utils.validateFeedId('b134u92fval'); - }).to.throwError(function(e) { - expect(e).to.be.a(errors.FeedError); - }); - }); - - it('#rfc3986', function() { - var result = utils.rfc3986('hello!\'()*matthisk'); - - expect(result).to.be('hello%21%27%28%29%2Amatthisk'); - }); + it('#rfc3986', function() { + var result = utils.rfc3986("hello!'()*matthisk"); -}); \ No newline at end of file + expect(result).to.be('hello%21%27%28%29%2Amatthisk'); + }); +}); diff --git a/test/unit/node/batch_test.js b/test/unit/node/batch_test.js index 48c7e834..a0b5012b 100644 --- a/test/unit/node/batch_test.js +++ b/test/unit/node/batch_test.js @@ -1,132 +1,154 @@ var errors = require('../../../src/getstream').errors, - expect = require('expect.js'), - Promise = require('../../../src/lib/promise'), - td = require('testdouble'), - beforeEachFn = require('../utils/hooks').beforeEach, - signing = signing || require('../../../src/lib/signing'); - + expect = require('expect.js'), + Promise = require('../../../src/lib/promise'), + td = require('testdouble'), + beforeEachFn = require('../utils/hooks').beforeEach, + signing = signing || require('../../../src/lib/signing'); describe('[UNIT] Stream Client Batch (Node)', function() { - - beforeEach(beforeEachFn); - - afterEach(function() { - td.reset(); - }); - - function replaceMSR() { - var msr = td.function(); - td.replace(this.client, 'makeSignedRequest', msr); - return msr; + beforeEach(beforeEachFn); + + afterEach(function() { + td.reset(); + }); + + function replaceMSR() { + var msr = td.function(); + td.replace(this.client, 'makeSignedRequest', msr); + return msr; + } + + it('#addToMany', function() { + expect(this.client.addToMany).to.be.a(Function); + + var msr = replaceMSR.call(this); + + var activity = { actor: 'matthisk', object: 0, verb: 'tweet' }; + var feeds = ['global:feed', 'global:feed2']; + + this.client.addToMany(activity, feeds); + + td.verify( + msr( + { + url: 'feed/add_to_many/', + body: { + activity: activity, + feeds: feeds, + }, + }, + undefined + ) + ); + }); + + it('#followMany', function() { + expect(this.client.followMany).to.be.a(Function); + + var msr = replaceMSR.call(this); + + var follows = []; + var cb = function() {}; + + this.client.followMany(follows, 10, cb); + + td.verify( + msr( + { + url: 'follow_many/', + body: follows, + qs: { + activity_copy_limit: 10, + }, + }, + cb + ) + ); + }); + + it('#followMany', function() { + expect(this.client.followMany).to.be.a(Function); + + var msr = replaceMSR.call(this); + + var follows = []; + var cb = function() {}; + + this.client.followMany(follows, cb); + + td.verify( + msr( + { + url: 'follow_many/', + body: follows, + qs: {}, + }, + cb + ) + ); + }); + + it('#followMany', function() { + expect(this.client.followMany).to.be.a(Function); + + var msr = replaceMSR.call(this); + + var follows = []; + var cb = function() {}; + + this.client.followMany(follows, 0, cb); + + td.verify( + msr( + { + url: 'follow_many/', + body: follows, + qs: { + activity_copy_limit: 0, + }, + }, + cb + ) + ); + }); + + it('#makeSignedRequest', function() { + var self = this; + td.replace(this.client, 'apiSecret', ''); + + function throws() { + self.client.makeSignedRequest({}); } - it('#addToMany', function() { - expect(this.client.addToMany).to.be.a(Function); - - var msr = replaceMSR.call(this); - - var activity = { actor: 'matthisk', object: 0, verb: 'tweet' }; - var feeds = ['global:feed', 'global:feed2']; - - this.client.addToMany(activity, feeds); - - td.verify(msr({ - url: 'feed/add_to_many/', - body: { - activity: activity, - feeds: feeds - } - }, undefined)); + expect(throws).to.throwException(function(err) { + expect(err).to.be.a(errors.SiteError); }); + }); - it('#followMany', function() { - expect(this.client.followMany).to.be.a(Function); + it('#makeSignedRequest', function() { + var p = this.client.makeSignedRequest({}); - var msr = replaceMSR.call(this); + expect(p).to.be.a(Promise); + }); - var follows = []; - var cb = function() {}; + it('#unfollowMany', function() { + expect(this.client.unfollowMany).to.be.a(Function); - this.client.followMany(follows, 10, cb); - - td.verify(msr({ - url: 'follow_many/', - body: follows, - qs: { - 'activity_copy_limit': 10 - } - }, cb)); - }); - - it('#followMany', function() { - expect(this.client.followMany).to.be.a(Function); - - var msr = replaceMSR.call(this); - - var follows = []; - var cb = function() {}; - - this.client.followMany(follows, cb); - - td.verify(msr({ - url: 'follow_many/', - body: follows, - qs: { } - }, cb)); - }); + var msr = replaceMSR.call(this); - it('#followMany', function() { - expect(this.client.followMany).to.be.a(Function); + var unfollows = []; + var cb = function() {}; - var msr = replaceMSR.call(this); + this.client.unfollowMany(unfollows, cb); - var follows = []; - var cb = function() {}; - - this.client.followMany(follows, 0, cb); - - td.verify(msr({ - url: 'follow_many/', - body: follows, - qs: { - 'activity_copy_limit': 0 - } - }, cb)); - }); - - it('#makeSignedRequest', function() { - var self = this; - td.replace(this.client, 'apiSecret', ''); - - function throws() { - self.client.makeSignedRequest({}); - } - - expect(throws).to.throwException(function(err) { - expect(err).to.be.a(errors.SiteError); - }); - }); - - it('#makeSignedRequest', function() { - var p = this.client.makeSignedRequest({}); - - expect(p).to.be.a(Promise); - }); - - - it('#unfollowMany', function() { - expect(this.client.unfollowMany).to.be.a(Function); - - var msr = replaceMSR.call(this); - - var unfollows = [] - var cb = function() {}; - - this.client.unfollowMany(unfollows, cb); - - td.verify(msr({ - url: 'unfollow_many/', - body: unfollows - }, cb)); - }); + td.verify( + msr( + { + url: 'unfollow_many/', + body: unfollows, + }, + cb + ) + ); + }); }); diff --git a/test/unit/node/client_test.js b/test/unit/node/client_test.js index 02dc4105..4f2a23fe 100644 --- a/test/unit/node/client_test.js +++ b/test/unit/node/client_test.js @@ -1,423 +1,525 @@ var StreamFeed = require('../../../src/lib/feed'), - expect = require('expect.js'), - beforeEachFn = require('../utils/hooks').beforeEach, - td = require('testdouble'), - stream = require('../../../src/getstream'), - StreamClient = require('../../../src/lib/client'); - + expect = require('expect.js'), + beforeEachFn = require('../utils/hooks').beforeEach, + td = require('testdouble'), + stream = require('../../../src/getstream'), + StreamClient = require('../../../src/lib/client'); describe('[UNIT] Stream Client instantiation (Node)', function() { + it('with secret', function() { + new StreamClient('stub-key', 'stub-secret', 9498); + }); - it('with secret', function() { - new StreamClient('stub-key', 'stub-secret', 9498); - }); - - it('without secret', function() { - new StreamClient('stub-key', null, 9498); - }); + it('without secret', function() { + new StreamClient('stub-key', null, 9498); + }); }); describe('[UNIT] Stream Client (Node)', function() { + beforeEach(beforeEachFn); - beforeEach(beforeEachFn); + it('#updateActivities', function() { + var self = this; - it('#updateActivities', function() { - var self = this; - - expect(function() { - self.client.updateActivities('A-String-Thing'); - }).to.throwException(function(e) { - expect(e).to.be.a(TypeError); - }); + expect(function() { + self.client.updateActivities('A-String-Thing'); + }).to.throwException(function(e) { + expect(e).to.be.a(TypeError); }); - - it('#userAgent', function() { - var useragent = this.client.userAgent(); - - expect(useragent).to.be('stream-javascript-client-node-unknown'); + }); + + it('#userAgent', function() { + var useragent = this.client.userAgent(); + + expect(useragent).to.be('stream-javascript-client-node-unknown'); + }); + + it('#feed', function() { + var feed = this.client.feed('user', 'jaap', '123456789'); + + expect(feed).to.be.a(StreamFeed); + }); + + describe('#enrichUrl', function() { + it('(1) personalization service', function() { + var resource = 'influencers'; + var url = this.client.enrichUrl(resource, 'personalization'); + expect(url).to.be( + 'https://personalization.stream-io-api.com/personalization/' + + this.client.version + + '/' + + resource + ); }); - - it('#feed', function() { - var feed = this.client.feed('user', 'jaap', '123456789'); - - expect(feed).to.be.a(StreamFeed); + }); + + describe('#updateActivities', function() { + it('throws', function() { + function isGoingToThrow1() { + this.client.updateActivities({}); + } + + function isGoingToThrow2() { + this.client.updateActivities(0); + } + + function isGoingToThrow3() { + this.client.updateActivities(null); + } + + function isNotGoingToThrow() { + this.client.updateActivities([]); + } + + function isTypeError(err) { + expect(err).to.be.a(TypeError); + } + + expect(isGoingToThrow1).to.throwException(isTypeError); + expect(isGoingToThrow2).to.throwException(isTypeError); + expect(isGoingToThrow3).to.throwException(isTypeError); + expect(isNotGoingToThrow).to.not.throw; }); - describe('#enrichUrl', function() { - - it('(1) personalization service', function() { - var resource = 'influencers' - var url = this.client.enrichUrl(resource, 'personalization'); - expect(url).to.be('https://personalization.stream-io-api.com/personalization/' + this.client.version + '/' + resource); - }); - }); - - describe('#updateActivities', function() { - - it('throws', function() { - function isGoingToThrow1() { - this.client.updateActivities({}); - } - - function isGoingToThrow2() { - this.client.updateActivities(0); - } - - function isGoingToThrow3() { - this.client.updateActivities(null); - } - - function isNotGoingToThrow() { - this.client.updateActivities([]); - } - - function isTypeError(err) { - expect(err).to.be.a(TypeError); - } - - expect(isGoingToThrow1).to.throwException(isTypeError); - expect(isGoingToThrow2).to.throwException(isTypeError); - expect(isGoingToThrow3).to.throwException(isTypeError); - expect(isNotGoingToThrow).to.not.throw; - }); - - it('(1) works', function() { - var post = td.function(); - td.replace(this.client, 'post', post); - - var activities = [{ actor: 'matthisk', object: 0, verb: 'do' }]; - - this.client.updateActivities(activities); - - td.verify(post(td.matchers.contains({ - url: 'activities/', - }), undefined)); - }); - - it('(2) works - callback', function() { - var post = td.function(); - td.replace(this.client, 'post', post); - - var activities = [{ actor: 'matthisk', object: 0, verb: 'do' }]; - var fn = function() {}; - - this.client.updateActivities(activities, fn); - - td.verify(post(td.matchers.contains({ - url: 'activities/', - }), fn)); - }); - - it('(3) update single activity', function() { - var post = td.function(); - td.replace(this.client, 'post', post); + it('(1) works', function() { + var post = td.function(); + td.replace(this.client, 'post', post); - var activities = [{ actor: 'matthisk', object: 0, verb: 'do' }]; + var activities = [{ actor: 'matthisk', object: 0, verb: 'do' }]; - this.client.updateActivity(activities[0]); - - td.verify(post(td.matchers.contains({ - url: 'activities/', - }), undefined)); - }); - - it('(3) update single activity - callback', function() { - var fn = function() {}; - var post = td.function(); - td.replace(this.client, 'post', post); - - var activities = [{ actor: 'matthisk', object: 0, verb: 'do' }]; - - this.client.updateActivity(activities[0], fn); - - td.verify(post(td.matchers.contains({ - url: 'activities/', - }), fn)); - }); + this.client.updateActivities(activities); + td.verify( + post( + td.matchers.contains({ + url: 'activities/', + }), + undefined + ) + ); }); - describe('#getActivities', function() { - - it('throws', function() { - var self = this; - - function isGoingToThrow1() { - self.client.getActivities({}); - } - - function isGoingToThrow2() { - self.client.getActivities(0); - } - - function isGoingToThrow3() { - self.client.getActivities(null); - } - - function isGoingToThrow4() { - self.client.getActivities([]); - } - - function isNotGoingToThrow() { - self.client.getActivities({ ids: [] }); - self.client.getActivities({ foreignIDTimes: [] }); - } - - function isTypeError(err) { - expect(err).to.be.a(TypeError); - } - - expect(isGoingToThrow1).to.throwException(isTypeError); - expect(isGoingToThrow2).to.throwException(isTypeError); - expect(isGoingToThrow3).to.throwException(isTypeError); - expect(isGoingToThrow4).to.throwException(isTypeError); - expect(isNotGoingToThrow).to.not.throwException(isTypeError); - }); - - describe('by ID', function() { - - it('(1) works', function() { - var get = td.function(); - td.replace(this.client, 'get', get); + it('(2) works - callback', function() { + var post = td.function(); + td.replace(this.client, 'post', post); - var ids = ['one', 'two', 'three']; + var activities = [{ actor: 'matthisk', object: 0, verb: 'do' }]; + var fn = function() {}; - this.client.getActivities({ids: ids}); - - td.verify(get(td.matchers.contains({ - url: 'activities/', - }), undefined)); - }); - - it('(2) works - callback', function() { - var get = td.function(); - td.replace(this.client, 'get', get); - - var ids = ['one', 'two', 'three']; - var fn = function() {}; - - this.client.getActivities({ids: ids}, fn); - - td.verify(get(td.matchers.contains({ - url: 'activities/', - }), fn)); - }); - }); - - describe('by foreign ID and time', function () { - - it('(1) works', function () { - var get = td.function(); - td.replace(this.client, 'get', get); - - var foreignIDTimes = [ - { foreignID: "like:1", time: "2018-07-08T14:09:36.000000"}, - { foreignID: "post:2", time: "2018-07-09T20:30:40.000000"} - ]; - - this.client.getActivities({ foreignIDTimes: foreignIDTimes }); - - td.verify(get(td.matchers.contains({ - url: 'activities/', - }), undefined)); - }); - - it('(2) works - callback', function () { - var get = td.function(); - td.replace(this.client, 'get', get); - - var foreignIDTimes = [ - { foreignID: "like:1", time: "2018-07-08T14:09:36.000000" }, - { foreignID: "post:2", time: "2018-07-09T20:30:40.000000" } - ]; - var fn = function () { }; - - this.client.getActivities({ foreignIDTimes: foreignIDTimes }, fn); - - td.verify(get(td.matchers.contains({ - url: 'activities/', - }), fn)); - }); - }); + this.client.updateActivities(activities, fn); + td.verify( + post( + td.matchers.contains({ + url: 'activities/', + }), + fn + ) + ); }); - describe('#activityPartialUpdate', function () { - - it('throws', function () { - var self = this; - - function isGoingToThrow1() { - self.client.activityPartialUpdate({}); - } - - function isGoingToThrow2() { - self.client.activityPartialUpdate(0); - } + it('(3) update single activity', function() { + var post = td.function(); + td.replace(this.client, 'post', post); - function isGoingToThrow3() { - self.client.activityPartialUpdate(null); - } + var activities = [{ actor: 'matthisk', object: 0, verb: 'do' }]; - function isGoingToThrow4() { - self.client.activityPartialUpdate({ foreignID: "foo:bar" }); - } - - function isGoingToThrow5() { - self.client.activityPartialUpdate({ time: "2016-11-10T13:20:00.000000" }); - } - - function isGoingToThrow6() { - self.client.activityPartialUpdate({ id: "test", set: "wrong" }); - } - - function isGoingToThrow7() { - self.client.activityPartialUpdate({ id: "test", unset: "wrong" }); - } - - function isTypeError(err) { - expect(err).to.be.a(TypeError); - } - - expect(isGoingToThrow1).to.throwException(isTypeError); - expect(isGoingToThrow2).to.throwException(isTypeError); - expect(isGoingToThrow3).to.throwException(isTypeError); - expect(isGoingToThrow4).to.throwException(isTypeError); - expect(isGoingToThrow5).to.throwException(isTypeError); - expect(isGoingToThrow6).to.throwException(isTypeError); - expect(isGoingToThrow7).to.throwException(isTypeError); - }); + this.client.updateActivity(activities[0]); - describe('by ID', function () { - - it('(1) works', function () { - var post = td.function(); - td.replace(this.client, 'post', post); - - var data = {id: "54a60c1e-4ee3-494b-a1e3-50c06acb5ed4", set: {"foo.bar": 42}, unset: ["baz"]}; - - this.client.activityPartialUpdate(data); - - td.verify(post(td.matchers.contains({ - url: 'activity/', - }), undefined)); - }); - - it('(2) works - callback', function () { - var post = td.function(); - td.replace(this.client, 'post', post); + td.verify( + post( + td.matchers.contains({ + url: 'activities/', + }), + undefined + ) + ); + }); - var data = {id: "54a60c1e-4ee3-494b-a1e3-50c06acb5ed4", set: {"foo.bar": 42}, unset: ["baz"]}; - var fn = function () { }; + it('(3) update single activity - callback', function() { + var fn = function() {}; + var post = td.function(); + td.replace(this.client, 'post', post); - this.client.activityPartialUpdate(data, fn); + var activities = [{ actor: 'matthisk', object: 0, verb: 'do' }]; - td.verify(post(td.matchers.contains({ - url: 'activity/', - }), fn)); - }); - }); + this.client.updateActivity(activities[0], fn); - describe('by foreign ID and time', function () { + td.verify( + post( + td.matchers.contains({ + url: 'activities/', + }), + fn + ) + ); + }); + }); + + describe('#getActivities', function() { + it('throws', function() { + var self = this; + + function isGoingToThrow1() { + self.client.getActivities({}); + } + + function isGoingToThrow2() { + self.client.getActivities(0); + } + + function isGoingToThrow3() { + self.client.getActivities(null); + } + + function isGoingToThrow4() { + self.client.getActivities([]); + } + + function isNotGoingToThrow() { + self.client.getActivities({ ids: [] }); + self.client.getActivities({ foreignIDTimes: [] }); + } + + function isTypeError(err) { + expect(err).to.be.a(TypeError); + } + + expect(isGoingToThrow1).to.throwException(isTypeError); + expect(isGoingToThrow2).to.throwException(isTypeError); + expect(isGoingToThrow3).to.throwException(isTypeError); + expect(isGoingToThrow4).to.throwException(isTypeError); + expect(isNotGoingToThrow).to.not.throwException(isTypeError); + }); - it('(1) works', function () { - var post = td.function(); - td.replace(this.client, 'post', post); + describe('by ID', function() { + it('(1) works', function() { + var get = td.function(); + td.replace(this.client, 'get', get); + + var ids = ['one', 'two', 'three']; + + this.client.getActivities({ ids: ids }); + + td.verify( + get( + td.matchers.contains({ + url: 'activities/', + }), + undefined + ) + ); + }); + + it('(2) works - callback', function() { + var get = td.function(); + td.replace(this.client, 'get', get); + + var ids = ['one', 'two', 'three']; + var fn = function() {}; + + this.client.getActivities({ ids: ids }, fn); + + td.verify( + get( + td.matchers.contains({ + url: 'activities/', + }), + fn + ) + ); + }); + }); - var data = {foreignID: "product:123", time: "2016-11-10T13:20:00.000000", set: {"foo.bar": 42}, unset: ["baz"]}; + describe('by foreign ID and time', function() { + it('(1) works', function() { + var get = td.function(); + td.replace(this.client, 'get', get); + + var foreignIDTimes = [ + { foreignID: 'like:1', time: '2018-07-08T14:09:36.000000' }, + { foreignID: 'post:2', time: '2018-07-09T20:30:40.000000' }, + ]; + + this.client.getActivities({ foreignIDTimes: foreignIDTimes }); + + td.verify( + get( + td.matchers.contains({ + url: 'activities/', + }), + undefined + ) + ); + }); + + it('(2) works - callback', function() { + var get = td.function(); + td.replace(this.client, 'get', get); + + var foreignIDTimes = [ + { foreignID: 'like:1', time: '2018-07-08T14:09:36.000000' }, + { foreignID: 'post:2', time: '2018-07-09T20:30:40.000000' }, + ]; + var fn = function() {}; + + this.client.getActivities({ foreignIDTimes: foreignIDTimes }, fn); + + td.verify( + get( + td.matchers.contains({ + url: 'activities/', + }), + fn + ) + ); + }); + }); + }); - this.client.activityPartialUpdate(data); + describe('#activityPartialUpdate', function() { + it('throws', function() { + var self = this; - td.verify(post(td.matchers.contains({ - url: 'activity/', - }), undefined)); - }); + function isGoingToThrow1() { + self.client.activityPartialUpdate({}); + } - it('(2) works - callback', function () { - var post = td.function(); - td.replace(this.client, 'post', post); + function isGoingToThrow2() { + self.client.activityPartialUpdate(0); + } - var data = {foreignID: "product:123", time: "2016-11-10T13:20:00.000000", set: {"foo.bar": 42}, unset: ["baz"]}; - var fn = function () { }; + function isGoingToThrow3() { + self.client.activityPartialUpdate(null); + } - this.client.activityPartialUpdate(data, fn) + function isGoingToThrow4() { + self.client.activityPartialUpdate({ foreignID: 'foo:bar' }); + } - td.verify(post(td.matchers.contains({ - url: 'activity/', - }), fn)); - }); + function isGoingToThrow5() { + self.client.activityPartialUpdate({ + time: '2016-11-10T13:20:00.000000', }); - + } + + function isGoingToThrow6() { + self.client.activityPartialUpdate({ id: 'test', set: 'wrong' }); + } + + function isGoingToThrow7() { + self.client.activityPartialUpdate({ id: 'test', unset: 'wrong' }); + } + + function isTypeError(err) { + expect(err).to.be.a(TypeError); + } + + expect(isGoingToThrow1).to.throwException(isTypeError); + expect(isGoingToThrow2).to.throwException(isTypeError); + expect(isGoingToThrow3).to.throwException(isTypeError); + expect(isGoingToThrow4).to.throwException(isTypeError); + expect(isGoingToThrow5).to.throwException(isTypeError); + expect(isGoingToThrow6).to.throwException(isTypeError); + expect(isGoingToThrow7).to.throwException(isTypeError); }); - describe('getAnalyticsToken', function(){ - it('generate correct token', function() { - var client = stream.connect('12345', 'abcdefghijklmnop'); - var token = client.getAnalyticsToken(); - expect(token).to.be('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZXNvdXJjZSI6ImFuYWx5dGljcyIsImFjdGlvbiI6IioiLCJ1c2VyX2lkIjoiKiJ9.f7KFu7U2Uw_yq__9hV4-wr9S0KXo7w3wxTELOAY4qdc'); - }); - }); - - describe('createUserSessionToken', function(){ - it('with userId only', function() { - var client = stream.connect('12345', 'abcdefghijklmnop'); - var token = client.createUserSessionToken("42"); - expect(token).to.be('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNDIifQ.fJP44ZlP7bly-2HvbPxBO7WUGJhc1i2hpj4TnXmtYLE'); - }); - - it('with extra data', function() { - var client = stream.connect('12345', 'abcdefghijklmnop'); - var token = client.createUserSessionToken("42", {'a':'b'}); - expect(token).to.be('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNDIiLCJhIjoiYiJ9.tnHcqgTi__BExVZ3Tl0awZQe_p3A7wJ3y_uNlsxg4DM'); - }); + describe('by ID', function() { + it('(1) works', function() { + var post = td.function(); + td.replace(this.client, 'post', post); + + var data = { + id: '54a60c1e-4ee3-494b-a1e3-50c06acb5ed4', + set: { 'foo.bar': 42 }, + unset: ['baz'], + }; + + this.client.activityPartialUpdate(data); + + td.verify( + post( + td.matchers.contains({ + url: 'activity/', + }), + undefined + ) + ); + }); + + it('(2) works - callback', function() { + var post = td.function(); + td.replace(this.client, 'post', post); + + var data = { + id: '54a60c1e-4ee3-494b-a1e3-50c06acb5ed4', + set: { 'foo.bar': 42 }, + unset: ['baz'], + }; + var fn = function() {}; + + this.client.activityPartialUpdate(data, fn); + + td.verify( + post( + td.matchers.contains({ + url: 'activity/', + }), + fn + ) + ); + }); }); - describe('createUserSession', function(){ - it('should return a user session', function() { - var client = stream.connect('12345', 'abcdefghijklmnop'); - var token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNDIiLCJhIjoiYiJ9.tnHcqgTi__BExVZ3Tl0awZQe_p3A7wJ3y_uNlsxg4DM"; - var userSession= client.createUserSession(token); - expect(userSession.userId).to.be("42"); - expect(userSession.token).to.be(token); - expect(userSession.client).to.not.be(null); - }); + describe('by foreign ID and time', function() { + it('(1) works', function() { + var post = td.function(); + td.replace(this.client, 'post', post); + + var data = { + foreignID: 'product:123', + time: '2016-11-10T13:20:00.000000', + set: { 'foo.bar': 42 }, + unset: ['baz'], + }; + + this.client.activityPartialUpdate(data); + + td.verify( + post( + td.matchers.contains({ + url: 'activity/', + }), + undefined + ) + ); + }); + + it('(2) works - callback', function() { + var post = td.function(); + td.replace(this.client, 'post', post); + + var data = { + foreignID: 'product:123', + time: '2016-11-10T13:20:00.000000', + set: { 'foo.bar': 42 }, + unset: ['baz'], + }; + var fn = function() {}; + + this.client.activityPartialUpdate(data, fn); + + td.verify( + post( + td.matchers.contains({ + url: 'activity/', + }), + fn + ) + ); + }); + }); + }); + + describe('getAnalyticsToken', function() { + it('generate correct token', function() { + var client = stream.connect( + '12345', + 'abcdefghijklmnop' + ); + var token = client.getAnalyticsToken(); + expect(token).to.be( + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyZXNvdXJjZSI6ImFuYWx5dGljcyIsImFjdGlvbiI6IioiLCJ1c2VyX2lkIjoiKiJ9.f7KFu7U2Uw_yq__9hV4-wr9S0KXo7w3wxTELOAY4qdc' + ); + }); + }); + + describe('createUserSessionToken', function() { + it('with userId only', function() { + var client = stream.connect( + '12345', + 'abcdefghijklmnop' + ); + var token = client.createUserSessionToken('42'); + expect(token).to.be( + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNDIifQ.fJP44ZlP7bly-2HvbPxBO7WUGJhc1i2hpj4TnXmtYLE' + ); }); - describe('connect', function() { - - it('#LOCAL', function() { - process.env['LOCAL'] = 1; + it('with extra data', function() { + var client = stream.connect( + '12345', + 'abcdefghijklmnop' + ); + var token = client.createUserSessionToken('42', { a: 'b' }); + expect(token).to.be( + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNDIiLCJhIjoiYiJ9.tnHcqgTi__BExVZ3Tl0awZQe_p3A7wJ3y_uNlsxg4DM' + ); + }); + }); + + describe('createUserSession', function() { + it('should return a user session', function() { + var client = stream.connect( + '12345', + 'abcdefghijklmnop' + ); + var token = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNDIiLCJhIjoiYiJ9.tnHcqgTi__BExVZ3Tl0awZQe_p3A7wJ3y_uNlsxg4DM'; + var userSession = client.createUserSession(token); + expect(userSession.userId).to.be('42'); + expect(userSession.token).to.be(token); + expect(userSession.client).to.not.be(null); + }); + }); - var client = stream.connect('12345', 'abcdefghijklmnop'); - expect(client.baseUrl).to.be('http://localhost:8000/api/'); + describe('connect', function() { + it('#LOCAL', function() { + process.env['LOCAL'] = 1; - delete process.env['LOCAL']; - }); + var client = stream.connect( + '12345', + 'abcdefghijklmnop' + ); + expect(client.baseUrl).to.be('http://localhost:8000/api/'); - it('#LOCAL', function() { - var client = stream.connect('12345', 'abcdefghijklmnop', null, { - location: 'nl-NL' - }); - expect(client.baseUrl).to.be('https://nl-NL-api.stream-io-api.com/api/'); - }); + delete process.env['LOCAL']; + }); - it('#LOCAL_FAYE', function() { - process.env['LOCAL_FAYE'] = 1; + it('#LOCAL', function() { + var client = stream.connect( + '12345', + 'abcdefghijklmnop', + null, + { + location: 'nl-NL', + } + ); + expect(client.baseUrl).to.be('https://nl-NL-api.stream-io-api.com/api/'); + }); - var client = stream.connect('12345', 'abcdefghijklmnop'); - expect(client.fayeUrl).to.be('http://localhost:9999/faye/'); + it('#LOCAL_FAYE', function() { + process.env['LOCAL_FAYE'] = 1; - delete process.env['LOCAL_FAYE']; - }); + var client = stream.connect( + '12345', + 'abcdefghijklmnop' + ); + expect(client.fayeUrl).to.be('http://localhost:9999/faye/'); - it('#STREAM_BASE_URL', function() { - process.env['STREAM_BASE_URL'] = 'https://local.stream-io-api.com/api/'; + delete process.env['LOCAL_FAYE']; + }); - var client = stream.connect('12345', 'abcdefghijklmnop'); - expect(client.baseUrl).to.be('https://local.stream-io-api.com/api/'); + it('#STREAM_BASE_URL', function() { + process.env['STREAM_BASE_URL'] = 'https://local.stream-io-api.com/api/'; - delete process.env['STREAM_BASE_URL']; - }); + var client = stream.connect( + '12345', + 'abcdefghijklmnop' + ); + expect(client.baseUrl).to.be('https://local.stream-io-api.com/api/'); + delete process.env['STREAM_BASE_URL']; }); + }); }); diff --git a/test/unit/node/collections_test.js b/test/unit/node/collections_test.js index 87cf522c..39d5afbf 100644 --- a/test/unit/node/collections_test.js +++ b/test/unit/node/collections_test.js @@ -1,235 +1,261 @@ var expect = require('expect.js'), - beforeEachFn = require('../utils/hooks').beforeEach, - errors = require('../../../src/getstream').errors, - td = require('testdouble'), - stream = require('../../../src/getstream'), - signing = require('../../../src/lib/signing'), - Collections = require('../../../src/lib/collections'), - StreamClient = require('../../../src/lib/client'); - + beforeEachFn = require('../utils/hooks').beforeEach, + errors = require('../../../src/getstream').errors, + td = require('testdouble'), + stream = require('../../../src/getstream'), + signing = require('../../../src/lib/signing'), + Collections = require('../../../src/lib/collections'), + StreamClient = require('../../../src/lib/client'); describe('[UNIT] Stream Collections (node)', function() { - let get; - let post; - let del; - - beforeEach(beforeEachFn); - beforeEach(function() { - get = td.function(); - post = td.function(); - del = td.function(); - td.replace(this.client, 'get', get); - td.replace(this.client, 'post', post); - td.replace(this.client, 'delete', del); + let get; + let post; + let del; + + beforeEach(beforeEachFn); + beforeEach(function() { + get = td.function(); + post = td.function(); + del = td.function(); + td.replace(this.client, 'get', get); + td.replace(this.client, 'post', post); + td.replace(this.client, 'delete', del); + }); + + afterEach(function() { + td.reset(); + }); + + describe('#upsert', function() { + it('should send post request correctly with single object (promise)', function() { + var fakedJWT = 'Faked JWT'; + var collectionName = 'user'; + var data = { id: 'john', username: 'johndoe', favorite_color: 'gray' }; + + this.client._collectionsToken = fakedJWT; + this.client.collections.upsert(collectionName, data); + + var expected_body = { data: {} }; + expected_body.data[collectionName] = [data]; + td.verify( + post( + { + url: 'meta/', + serviceName: 'api', + body: expected_body, + signature: fakedJWT, + }, + undefined + ) + ); }); - afterEach(function() { - td.reset(); + it('should send post request correctly with single object (cb)', function() { + var fakedJWT = 'Faked JWT'; + var collectionName = 'user'; + var data = { id: 'john', username: 'johndoe', favorite_color: 'gray' }; + var cb = function() {}; + + this.client._collectionsToken = fakedJWT; + this.client.collections.upsert(collectionName, data, cb); + + var expected_body = { data: {} }; + expected_body.data[collectionName] = [data]; + td.verify( + post( + { + url: 'meta/', + serviceName: 'api', + body: expected_body, + signature: fakedJWT, + }, + cb + ) + ); }); - describe('#upsert', function() { - - it('should send post request correctly with single object (promise)', function() { - var fakedJWT = 'Faked JWT'; - var collectionName = 'user'; - var data = {'id': 'john', 'username': 'johndoe', 'favorite_color': 'gray'}; - - this.client._collectionsToken = fakedJWT; - this.client.collections.upsert(collectionName, data); - - var expected_body = {data: {}}; - expected_body.data[collectionName] = [data]; - td.verify(post( - { - url: 'meta/', - serviceName: 'api', - body: expected_body, - signature: fakedJWT - }, - undefined)); - }); - - it('should send post request correctly with single object (cb)', function() { - var fakedJWT = 'Faked JWT'; - var collectionName = 'user'; - var data = {'id': 'john', 'username': 'johndoe', 'favorite_color': 'gray'}; - var cb = function() {}; - - this.client._collectionsToken = fakedJWT; - this.client.collections.upsert(collectionName, data, cb); - - var expected_body = {data: {}}; - expected_body.data[collectionName] = [data]; - td.verify(post( - { - url: 'meta/', - serviceName: 'api', - body: expected_body, - signature: fakedJWT - }, - cb)); - }); - - it('should send post request correctly with multiple objects (promise)', function() { - var fakedJWT = 'Faked JWT'; - var collectionName = 'user'; - var data = [ - {'id': 'john', 'username': 'johndoe', 'favorite_color': 'gray'}, - {'id': 'dave', 'username': 'daveo', 'favorite_color': 'green'} - ]; - - this.client._collectionsToken = fakedJWT; - this.client.collections.upsert(collectionName, data); - - var expected_body = {data: {}}; - expected_body.data[collectionName] = data; - td.verify(post( - { - url: 'meta/', - serviceName: 'api', - body: expected_body, - signature: fakedJWT - }, - undefined)); - }); - - it('should send post request correctly with multiple objects (cb)', function() { - var fakedJWT = 'Faked JWT'; - var collectionName = 'user'; - var data = [ - {'id': 'john', 'username': 'johndoe', 'favorite_color': 'gray'}, - {'id': 'dave', 'username': 'daveo', 'favorite_color': 'green'} - ]; - var cb = function() {}; - - this.client._collectionsToken = fakedJWT; - this.client.collections.upsert(collectionName, data, cb); - - var expected_body = {data: {}}; - expected_body.data[collectionName] = data; - td.verify(post( - { - url: 'meta/', - serviceName: 'api', - body: expected_body, - signature: fakedJWT - }, - cb)); - }); + it('should send post request correctly with multiple objects (promise)', function() { + var fakedJWT = 'Faked JWT'; + var collectionName = 'user'; + var data = [ + { id: 'john', username: 'johndoe', favorite_color: 'gray' }, + { id: 'dave', username: 'daveo', favorite_color: 'green' }, + ]; + + this.client._collectionsToken = fakedJWT; + this.client.collections.upsert(collectionName, data); + + var expected_body = { data: {} }; + expected_body.data[collectionName] = data; + td.verify( + post( + { + url: 'meta/', + serviceName: 'api', + body: expected_body, + signature: fakedJWT, + }, + undefined + ) + ); }); - describe('#select', function() { - - it('should send get request correctly with single id (promise)', function() { - var fakedJWT = 'Faked JWT'; - var collectionName = 'user'; - var id = 'john'; + it('should send post request correctly with multiple objects (cb)', function() { + var fakedJWT = 'Faked JWT'; + var collectionName = 'user'; + var data = [ + { id: 'john', username: 'johndoe', favorite_color: 'gray' }, + { id: 'dave', username: 'daveo', favorite_color: 'green' }, + ]; + var cb = function() {}; + + this.client._collectionsToken = fakedJWT; + this.client.collections.upsert(collectionName, data, cb); + + var expected_body = { data: {} }; + expected_body.data[collectionName] = data; + td.verify( + post( + { + url: 'meta/', + serviceName: 'api', + body: expected_body, + signature: fakedJWT, + }, + cb + ) + ); + }); + }); + + describe('#select', function() { + it('should send get request correctly with single id (promise)', function() { + var fakedJWT = 'Faked JWT'; + var collectionName = 'user'; + var id = 'john'; + + this.client._collectionsToken = fakedJWT; + this.client.collections.select(collectionName, id); + + td.verify( + get( + { + url: 'meta/', + serviceName: 'api', + qs: { foreign_ids: collectionName + ':' + id }, + signature: fakedJWT, + }, + undefined + ) + ); + }); - this.client._collectionsToken = fakedJWT; - this.client.collections.select(collectionName, id); + it('should send get request correctly with single id (callback)', function() { + var fakedJWT = 'Faked JWT'; + var collectionName = 'user'; + var id = 'john'; + var cb = function() {}; + + this.client._collectionsToken = fakedJWT; + this.client.collections.select(collectionName, id, cb); + + td.verify( + get( + { + url: 'meta/', + serviceName: 'api', + qs: { foreign_ids: collectionName + ':' + id }, + signature: fakedJWT, + }, + cb + ) + ); + }); - td.verify(get( - { - url: 'meta/', - serviceName: 'api', - qs: {'foreign_ids': collectionName + ':' + id}, - signature: fakedJWT - }, - undefined)); - }); + it('should send get request correctly with multiple ids (promise)', function() { + var fakedJWT = 'Faked JWT'; + var collectionName = 'user'; + var ids = ['john', 'dave']; + + this.client._collectionsToken = fakedJWT; + this.client.collections.select(collectionName, ids); + + td.verify( + get( + { + url: 'meta/', + serviceName: 'api', + qs: { + foreign_ids: ids + .map(function(id) { + return collectionName + ':' + id; + }) + .join(','), + }, + signature: fakedJWT, + }, + undefined + ) + ); + }); - it('should send get request correctly with single id (callback)', function() { - var fakedJWT = 'Faked JWT'; - var collectionName = 'user'; - var id = 'john'; - var cb = function() {}; - - this.client._collectionsToken = fakedJWT; - this.client.collections.select(collectionName, id, cb); - - td.verify(get( - { - url: 'meta/', - serviceName: 'api', - qs: {'foreign_ids': collectionName + ':' + id}, - signature: fakedJWT - }, - cb)); - }); + it('should send get request correctly with multiple ids (callback)', function() { + var fakedJWT = 'Faked JWT'; + var collectionName = 'user'; + var ids = ['john', 'dave']; + var cb = function() {}; + + this.client._collectionsToken = fakedJWT; + this.client.collections.select(collectionName, ids, cb); + + td.verify( + get( + { + url: 'meta/', + serviceName: 'api', + qs: { + foreign_ids: ids + .map(function(id) { + return collectionName + ':' + id; + }) + .join(','), + }, + signature: fakedJWT, + }, + cb + ) + ); + }); - it('should send get request correctly with multiple ids (promise)', function() { - var fakedJWT = 'Faked JWT'; - var collectionName = 'user'; - var ids = ['john', 'dave']; - - this.client._collectionsToken = fakedJWT; - this.client.collections.select(collectionName, ids); - - td.verify(get( - { - url: 'meta/', - serviceName: 'api', - qs: {'foreign_ids': ids.map(function (id) { return collectionName + ':' + id;}).join(',')}, - signature: fakedJWT - }, - undefined)); + describe('No secret provided', function() { + it('should raise SiteErrors', function() { + var client = new StreamClient('stub-key', null, 9498); + var collectionName = 'user'; + var ids = ['john', 'dave']; + var data = { id: 'john', username: 'johndoe', favorite_color: 'gray' }; + var cb = function() {}; + + // upsert + expect(function() { + client.collections.upsert(collectionName, data, cb); + }).to.throwException(function(e) { + expect(e).to.be.a(errors.SiteError); }); - it('should send get request correctly with multiple ids (callback)', function() { - var fakedJWT = 'Faked JWT'; - var collectionName = 'user'; - var ids = ['john', 'dave']; - var cb = function() {}; - - this.client._collectionsToken = fakedJWT; - this.client.collections.select(collectionName, ids, cb); - - td.verify(get( - { - url: 'meta/', - serviceName: 'api', - qs: {'foreign_ids': ids.map(function (id) { return collectionName + ':' + id;}).join(',')}, - signature: fakedJWT - }, - cb)); + // select + expect(function() { + client.collections.select(collectionName, ids, cb); + }).to.throwException(function(e) { + expect(e).to.be.a(errors.SiteError); }); - - - describe('No secret provided', function() { - - it('should raise SiteErrors', function() { - - var client = new StreamClient('stub-key', null, 9498); - var collectionName = 'user'; - var ids = ['john', 'dave']; - var data = {'id': 'john', 'username': 'johndoe', 'favorite_color': 'gray'}; - var cb = function() {}; - - // upsert - expect(function() { - client.collections.upsert(collectionName, data, cb); - }).to.throwException(function(e) { - expect(e).to.be.a(errors.SiteError); - }); - - // select - expect(function() { - client.collections.select(collectionName, ids, cb); - }).to.throwException(function(e) { - expect(e).to.be.a(errors.SiteError); - }); - - // delete - expect(function() { - client.collections.delete(collectionName, cb); - }).to.throwException(function(e) { - expect(e).to.be.a(errors.SiteError); - }); - - }); + // delete + expect(function() { + client.collections.delete(collectionName, cb); + }).to.throwException(function(e) { + expect(e).to.be.a(errors.SiteError); }); - + }); }); - + }); }); diff --git a/test/unit/node/heroku_test.js b/test/unit/node/heroku_test.js index 50188e28..eb8acfdd 100644 --- a/test/unit/node/heroku_test.js +++ b/test/unit/node/heroku_test.js @@ -1,113 +1,135 @@ -var beforeEachFn = require('../utils/hooks').beforeEach - , init = require('../utils/hooks').init - , stream = require('../../../src/getstream') - , expect = require('expect.js'); +var beforeEachFn = require('../utils/hooks').beforeEach, + init = require('../utils/hooks').init, + stream = require('../../../src/getstream'), + expect = require('expect.js'); describe('[UNIT] Stream client (Heroku)', function() { + init.call(this); + beforeEach(beforeEachFn); - init.call(this); - beforeEach(beforeEachFn); - - describe('#Heroku', function() { - - it('heroku (stream-io-api.com)', function(done) { - var url = 'https://thierry:pass@stream-io-api.com/?app_id=1'; - process.env.STREAM_URL = url; - this.client = stream.connect(); - expect(this.client.apiKey).to.eql('thierry'); - expect(this.client.apiSecret).to.eql('pass'); - expect(this.client.appId).to.eql('1'); - expect(this.client.baseUrl).to.eql('https://api.stream-io-api.com/api/'); - delete process.env['STREAM_URL']; - done(); - }); + describe('#Heroku', function() { + it('heroku (stream-io-api.com)', function(done) { + var url = 'https://thierry:pass@stream-io-api.com/?app_id=1'; + process.env.STREAM_URL = url; + this.client = stream.connect(); + expect(this.client.apiKey).to.eql('thierry'); + expect(this.client.apiSecret).to.eql('pass'); + expect(this.client.appId).to.eql('1'); + expect(this.client.baseUrl).to.eql('https://api.stream-io-api.com/api/'); + delete process.env['STREAM_URL']; + done(); + }); - it('heroku (getstream.io)', function(done) { - var url = 'https://thierry:pass@getstream.io/?app_id=1'; - process.env.STREAM_URL = url; - process.env.STREAM_BASE_URL = 'https://api.getstream.io/api/'; - this.client = stream.connect(); - expect(this.client.apiKey).to.eql('thierry'); - expect(this.client.apiSecret).to.eql('pass'); - expect(this.client.appId).to.eql('1'); - expect(this.client.baseUrl).to.eql('https://api.getstream.io/api/'); - delete process.env['STREAM_URL']; - delete process.env['STREAM_BASE_URL']; - done(); - }); + it('heroku (getstream.io)', function(done) { + var url = 'https://thierry:pass@getstream.io/?app_id=1'; + process.env.STREAM_URL = url; + process.env.STREAM_BASE_URL = 'https://api.getstream.io/api/'; + this.client = stream.connect(); + expect(this.client.apiKey).to.eql('thierry'); + expect(this.client.apiSecret).to.eql('pass'); + expect(this.client.appId).to.eql('1'); + expect(this.client.baseUrl).to.eql('https://api.getstream.io/api/'); + delete process.env['STREAM_URL']; + delete process.env['STREAM_BASE_URL']; + done(); + }); - it('heroku legacy (stream-io-api.com)', function(done) { - var url = 'https://bvt88g4kvc63:twc5ywfste5bm2ngqkzs7ukxk3pn96yweghjrxcmcrarnt3j4dqj3tucbhym5wfd@stream-io-api.com/?app_id=669'; - process.env.STREAM_URL = url; - this.client = stream.connect(); - expect(this.client.apiKey).to.eql('bvt88g4kvc63'); - expect(this.client.apiSecret).to.eql('twc5ywfste5bm2ngqkzs7ukxk3pn96yweghjrxcmcrarnt3j4dqj3tucbhym5wfd'); - expect(this.client.appId).to.eql('669'); - expect(this.client.baseUrl).to.eql('https://api.stream-io-api.com/api/'); - delete process.env['STREAM_URL']; - done(); - }); + it('heroku legacy (stream-io-api.com)', function(done) { + var url = + 'https://bvt88g4kvc63:twc5ywfste5bm2ngqkzs7ukxk3pn96yweghjrxcmcrarnt3j4dqj3tucbhym5wfd@stream-io-api.com/?app_id=669'; + process.env.STREAM_URL = url; + this.client = stream.connect(); + expect(this.client.apiKey).to.eql('bvt88g4kvc63'); + expect(this.client.apiSecret).to.eql( + 'twc5ywfste5bm2ngqkzs7ukxk3pn96yweghjrxcmcrarnt3j4dqj3tucbhym5wfd' + ); + expect(this.client.appId).to.eql('669'); + expect(this.client.baseUrl).to.eql('https://api.stream-io-api.com/api/'); + delete process.env['STREAM_URL']; + done(); + }); - it('heroku legacy (getstream.io)', function(done) { - var url = 'https://bvt88g4kvc63:twc5ywfste5bm2ngqkzs7ukxk3pn96yweghjrxcmcrarnt3j4dqj3tucbhym5wfd@getstream.io/?app_id=669'; - process.env.STREAM_URL = url; - process.env.STREAM_BASE_URL = 'https://api.getstream.io/api/'; - this.client = stream.connect(); - expect(this.client.apiKey).to.eql('bvt88g4kvc63'); - expect(this.client.apiSecret).to.eql('twc5ywfste5bm2ngqkzs7ukxk3pn96yweghjrxcmcrarnt3j4dqj3tucbhym5wfd'); - expect(this.client.appId).to.eql('669'); - expect(this.client.baseUrl).to.eql('https://api.getstream.io/api/'); - delete process.env['STREAM_URL']; - delete process.env['STREAM_BASE_URL']; - done(); - }); + it('heroku legacy (getstream.io)', function(done) { + var url = + 'https://bvt88g4kvc63:twc5ywfste5bm2ngqkzs7ukxk3pn96yweghjrxcmcrarnt3j4dqj3tucbhym5wfd@getstream.io/?app_id=669'; + process.env.STREAM_URL = url; + process.env.STREAM_BASE_URL = 'https://api.getstream.io/api/'; + this.client = stream.connect(); + expect(this.client.apiKey).to.eql('bvt88g4kvc63'); + expect(this.client.apiSecret).to.eql( + 'twc5ywfste5bm2ngqkzs7ukxk3pn96yweghjrxcmcrarnt3j4dqj3tucbhym5wfd' + ); + expect(this.client.appId).to.eql('669'); + expect(this.client.baseUrl).to.eql('https://api.getstream.io/api/'); + delete process.env['STREAM_URL']; + delete process.env['STREAM_BASE_URL']; + done(); + }); - it('heroku with location (stream-io-api.com)', function(done) { - var url = 'https://ahj2ndz7gsan:gthc2t9gh7pzq52f6cky8w4r4up9dr6rju9w3fjgmkv6cdvvav2ufe5fv7e2r9qy@us-east.stream-io-api.com/?app_id=1'; - process.env.STREAM_URL = url; - this.client = stream.connect(); - expect(this.client.apiKey).to.eql('ahj2ndz7gsan'); - expect(this.client.apiSecret).to.eql('gthc2t9gh7pzq52f6cky8w4r4up9dr6rju9w3fjgmkv6cdvvav2ufe5fv7e2r9qy'); - expect(this.client.appId).to.eql('1'); - expect(this.client.baseUrl).to.eql('https://us-east-api.stream-io-api.com/api/'); - delete process.env['STREAM_URL']; - done(); - }); + it('heroku with location (stream-io-api.com)', function(done) { + var url = + 'https://ahj2ndz7gsan:gthc2t9gh7pzq52f6cky8w4r4up9dr6rju9w3fjgmkv6cdvvav2ufe5fv7e2r9qy@us-east.stream-io-api.com/?app_id=1'; + process.env.STREAM_URL = url; + this.client = stream.connect(); + expect(this.client.apiKey).to.eql('ahj2ndz7gsan'); + expect(this.client.apiSecret).to.eql( + 'gthc2t9gh7pzq52f6cky8w4r4up9dr6rju9w3fjgmkv6cdvvav2ufe5fv7e2r9qy' + ); + expect(this.client.appId).to.eql('1'); + expect(this.client.baseUrl).to.eql( + 'https://us-east-api.stream-io-api.com/api/' + ); + delete process.env['STREAM_URL']; + done(); + }); - it('heroku with location (getstream.io)', function(done) { - var url = 'https://ahj2ndz7gsan:gthc2t9gh7pzq52f6cky8w4r4up9dr6rju9w3fjgmkv6cdvvav2ufe5fv7e2r9qy@us-east.getstream.io/?app_id=1'; - process.env.STREAM_URL = url; - process.env.STREAM_BASE_URL = 'https://us-east-api.getstream.io/api/'; - this.client = stream.connect(); - expect(this.client.apiKey).to.eql('ahj2ndz7gsan'); - expect(this.client.apiSecret).to.eql('gthc2t9gh7pzq52f6cky8w4r4up9dr6rju9w3fjgmkv6cdvvav2ufe5fv7e2r9qy'); - expect(this.client.appId).to.eql('1'); - expect(this.client.baseUrl).to.eql('https://us-east-api.getstream.io/api/'); - delete process.env['STREAM_URL']; - delete process.env['STREAM_BASE_URL']; - done(); - }); + it('heroku with location (getstream.io)', function(done) { + var url = + 'https://ahj2ndz7gsan:gthc2t9gh7pzq52f6cky8w4r4up9dr6rju9w3fjgmkv6cdvvav2ufe5fv7e2r9qy@us-east.getstream.io/?app_id=1'; + process.env.STREAM_URL = url; + process.env.STREAM_BASE_URL = 'https://us-east-api.getstream.io/api/'; + this.client = stream.connect(); + expect(this.client.apiKey).to.eql('ahj2ndz7gsan'); + expect(this.client.apiSecret).to.eql( + 'gthc2t9gh7pzq52f6cky8w4r4up9dr6rju9w3fjgmkv6cdvvav2ufe5fv7e2r9qy' + ); + expect(this.client.appId).to.eql('1'); + expect(this.client.baseUrl).to.eql( + 'https://us-east-api.getstream.io/api/' + ); + delete process.env['STREAM_URL']; + delete process.env['STREAM_BASE_URL']; + done(); + }); - it('heroku_overwrite (stream-io-api.com)', function(done) { - var url = 'https://thierry:pass@stream-io-api.com/?app_id=1'; - process.env.STREAM_URL = url; - this.client = stream.connect('a', 'b', 'c'); - expect(this.client.apiKey).to.eql('a'); - expect(this.client.apiSecret).to.eql('b'); - expect(this.client.appId).to.eql('c'); - delete process.env['STREAM_URL']; - done(); - }); + it('heroku_overwrite (stream-io-api.com)', function(done) { + var url = 'https://thierry:pass@stream-io-api.com/?app_id=1'; + process.env.STREAM_URL = url; + this.client = stream.connect( + 'a', + 'b', + 'c' + ); + expect(this.client.apiKey).to.eql('a'); + expect(this.client.apiSecret).to.eql('b'); + expect(this.client.appId).to.eql('c'); + delete process.env['STREAM_URL']; + done(); + }); - it('heroku_overwrite (getstream.io)', function(done) { - var url = 'https://thierry:pass@getstream.io/?app_id=1'; - process.env.STREAM_URL = url; - this.client = stream.connect('a', 'b', 'c'); - expect(this.client.apiKey).to.eql('a'); - expect(this.client.apiSecret).to.eql('b'); - expect(this.client.appId).to.eql('c'); - delete process.env['STREAM_URL']; - done(); - }); + it('heroku_overwrite (getstream.io)', function(done) { + var url = 'https://thierry:pass@getstream.io/?app_id=1'; + process.env.STREAM_URL = url; + this.client = stream.connect( + 'a', + 'b', + 'c' + ); + expect(this.client.apiKey).to.eql('a'); + expect(this.client.apiSecret).to.eql('b'); + expect(this.client.appId).to.eql('c'); + delete process.env['STREAM_URL']; + done(); }); + }); }); diff --git a/test/unit/node/jwt_test.js b/test/unit/node/jwt_test.js index c92deca2..1c988c89 100644 --- a/test/unit/node/jwt_test.js +++ b/test/unit/node/jwt_test.js @@ -1,14 +1,12 @@ -var expect = require('expect.js') - , qc = require('quickcheck') - , qcJWT = require('../utils/jwt') - , signing = signing || require('../../../src/lib/signing'); +var expect = require('expect.js'), + qc = require('quickcheck'), + qcJWT = require('../utils/jwt'), + signing = signing || require('../../../src/lib/signing'); describe('[UNIT] Json web token validation', function() { + this.timeout(10000); - this.timeout(10000); - - it('should decode valid jwts headers', function() { - qc.forAll( qcJWT.propertyHeaderJSON, qcJWT.arbJWT ); - }); - -}); \ No newline at end of file + it('should decode valid jwts headers', function() { + qc.forAll(qcJWT.propertyHeaderJSON, qcJWT.arbJWT); + }); +}); diff --git a/test/unit/node/personalization_test.js b/test/unit/node/personalization_test.js index 2ef970f5..88f1b48d 100644 --- a/test/unit/node/personalization_test.js +++ b/test/unit/node/personalization_test.js @@ -1,315 +1,368 @@ var expect = require('expect.js'), - beforeEachFn = require('../utils/hooks').beforeEach, - errors = require('../../../src/getstream').errors, - td = require('testdouble'), - stream = require('../../../src/getstream'), - signing = require('../../../src/lib/signing'), - StreamClient = require('../../../src/lib/client'); - + beforeEachFn = require('../utils/hooks').beforeEach, + errors = require('../../../src/getstream').errors, + td = require('testdouble'), + stream = require('../../../src/getstream'), + signing = require('../../../src/lib/signing'), + StreamClient = require('../../../src/lib/client'); describe('[UNIT] Stream Personalization (node)', function() { - let get; - let post; - let del; - let callback; - - beforeEach(beforeEachFn); - beforeEach(function() { - get = td.function(); - post = td.function(); - del = td.function(); - td.replace(this.client, 'get', get); - td.replace(this.client, 'post', post); - td.replace(this.client, 'delete', del); + let get; + let post; + let del; + let callback; + + beforeEach(beforeEachFn); + beforeEach(function() { + get = td.function(); + post = td.function(); + del = td.function(); + td.replace(this.client, 'get', get); + td.replace(this.client, 'post', post); + td.replace(this.client, 'delete', del); + }); + + afterEach(function() { + td.reset(); + }); + + describe('#get', function() { + it('should send get request correctly with options (promise)', function() { + var fakedJWT = 'Faked JWT'; + var resource = 'example'; + var options = { foo: 'bar', baz: 'qux' }; + + this.client._personalizationToken = fakedJWT; + this.client.personalization.get(resource, options); + + td.verify( + get( + { + url: resource + '/', + serviceName: 'personalization', + qs: options, + signature: fakedJWT, + }, + undefined + ) + ); }); - afterEach(function() { - td.reset(); + it('should send get request correctly with options (cb)', function() { + var fakedJWT = 'Faked JWT'; + var resource = 'example'; + var options = { foo: 'bar', baz: 'qux' }; + var cb = function() {}; + + this.client._personalizationToken = fakedJWT; + this.client.personalization.get(resource, options, cb); + + td.verify( + get( + { + url: resource + '/', + serviceName: 'personalization', + qs: options, + signature: fakedJWT, + }, + (callback = cb) + ) + ); }); - describe('#get', function() { - - it('should send get request correctly with options (promise)', function() { - var fakedJWT = "Faked JWT"; - var resource = 'example'; - var options = {foo: 'bar', baz: 'qux'}; - - this.client._personalizationToken = fakedJWT; - this.client.personalization.get(resource, options); - - td.verify(get({ - url: resource + '/', - serviceName: 'personalization', - qs: options, - signature: fakedJWT - }, undefined)); - }); - - it('should send get request correctly with options (cb)', function() { - var fakedJWT = "Faked JWT"; - var resource = 'example'; - var options = {foo: 'bar', baz: 'qux'}; - var cb = function() {}; - - this.client._personalizationToken = fakedJWT; - this.client.personalization.get(resource, options, cb); - - td.verify(get({ - url: resource + '/', - serviceName: 'personalization', - qs: options, - signature: fakedJWT - }, - callback=cb)); - }); - - it('should send get request correctly without options (promise)', function() { - var fakedJWT = "Faked JWT"; - var resource = 'example'; - - this.client._personalizationToken = fakedJWT; - this.client.personalization.get(resource); - - td.verify(get({ - url: resource + '/', - serviceName: 'personalization', - qs: {}, - signature: fakedJWT - }, undefined)); - }); - - it('should send get request correctly without options (cb)', function() { - var fakedJWT = "Faked JWT"; - var resource = 'example'; - var cb = function() {}; - - this.client._personalizationToken = fakedJWT; - this.client.personalization.get(resource, cb); - - td.verify(get({ - url: resource + '/', - serviceName: 'personalization', - qs: {}, - signature: fakedJWT - }, - callback=cb)); - }); + it('should send get request correctly without options (promise)', function() { + var fakedJWT = 'Faked JWT'; + var resource = 'example'; + + this.client._personalizationToken = fakedJWT; + this.client.personalization.get(resource); + + td.verify( + get( + { + url: resource + '/', + serviceName: 'personalization', + qs: {}, + signature: fakedJWT, + }, + undefined + ) + ); }); - describe('#post', function() { - - it('should send post request correctly with options and data (promise)', function() { - var fakedJWT = "Faked JWT"; - var resource = 'example'; - var data = {k: 'v'}; - var options = {foo: 'bar', baz: 'qux'}; - - this.client._personalizationToken = fakedJWT; - this.client.personalization.post(resource, options, data); - - td.verify(post({ - url: resource + '/', - serviceName: 'personalization', - qs: options, - body: data, - signature: fakedJWT - }, undefined)); - }); - - it('should send post request correctly with options and data (cb)', function() { - var fakedJWT = "Faked JWT"; - var resource = 'example'; - var options = {foo: 'bar', baz: 'qux'}; - var data = {k: 'v'}; - var cb = function() {}; - - this.client._personalizationToken = fakedJWT; - this.client.personalization.post(resource, options, data, cb); - - td.verify(post({ - url: resource + '/', - serviceName: 'personalization', - qs: options, - body: data, - signature: fakedJWT - }, - callback=cb)); - }); - - it('should send post request correctly with options (promise)', function() { - var fakedJWT = "Faked JWT"; - var resource = 'example'; - var options = {foo: 'bar', baz: 'qux'}; - - this.client._personalizationToken = fakedJWT; - this.client.personalization.post(resource, options); - - td.verify(post({ - url: resource + '/', - serviceName: 'personalization', - qs: options, - body: {}, - signature: fakedJWT - }, undefined)); - }); - - it('should send post request correctly with options (cb)', function() { - var fakedJWT = "Faked JWT"; - var resource = 'example'; - var options = {foo: 'bar', baz: 'qux'}; - var cb = function() {}; - - this.client._personalizationToken = fakedJWT; - this.client.personalization.post(resource, options, cb); - - td.verify(post({ - url: resource + '/', - serviceName: 'personalization', - qs: options, - body: {}, - signature: fakedJWT - }, - callback=cb)); - }); - - - it('should send post request correctly without options or data (promise)', function() { - var fakedJWT = "Faked JWT"; - var resource = 'example'; - - this.client._personalizationToken = fakedJWT; - this.client.personalization.post(resource); - - td.verify(post({ - url: resource + '/', - serviceName: 'personalization', - qs: {}, - body: {}, - signature: fakedJWT - }, undefined)); - }); - - it('should send post request correctly without options or data (cb)', function() { - var fakedJWT = "Faked JWT"; - var resource = 'example'; - var cb = function() {}; - - this.client._personalizationToken = fakedJWT; - this.client.personalization.post(resource, cb); - - td.verify(post({ - url: resource + '/', - serviceName: 'personalization', - qs: {}, - body: {}, - signature: fakedJWT - }, - callback=cb)); - }); + it('should send get request correctly without options (cb)', function() { + var fakedJWT = 'Faked JWT'; + var resource = 'example'; + var cb = function() {}; + + this.client._personalizationToken = fakedJWT; + this.client.personalization.get(resource, cb); + + td.verify( + get( + { + url: resource + '/', + serviceName: 'personalization', + qs: {}, + signature: fakedJWT, + }, + (callback = cb) + ) + ); }); - - describe('#delete', function() { - - it('should send delete request correctly with options (promise)', function() { - var fakedJWT = "Faked JWT"; - var resource = 'example'; - var options = {foo: 'bar', baz: 'qux'}; - - this.client._personalizationToken = fakedJWT; - this.client.personalization.delete(resource, options); - - td.verify(del({ - url: resource + '/', - serviceName: 'personalization', - qs: options, - signature: fakedJWT - }, undefined)); - }); - - it('should send delete request correctly with options (cb)', function() { - var fakedJWT = "Faked JWT"; - var resource = 'example'; - var options = {foo: 'bar', baz: 'qux'}; - var cb = function() {}; - - this.client._personalizationToken = fakedJWT; - this.client.personalization.delete(resource, options, cb); - - td.verify(del({ - url: resource + '/', - serviceName: 'personalization', - qs: options, - signature: fakedJWT - }, - callback=cb)); - }); - - it('should send delete request correctly without options (promise)', function() { - var fakedJWT = "Faked JWT"; - var resource = 'example'; - - this.client._personalizationToken = fakedJWT; - this.client.personalization.delete(resource); - - td.verify(del({ - url: resource + '/', - serviceName: 'personalization', - qs: {}, - signature: fakedJWT - }, undefined)); - }); - - it('should send delete request correctly without options (cb)', function() { - var fakedJWT = "Faked JWT"; - var resource = 'example'; - var cb = function() {}; - - this.client._personalizationToken = fakedJWT; - this.client.personalization.delete(resource, cb); - - td.verify(del({ - url: resource + '/', - serviceName: 'personalization', - qs: {}, - signature: fakedJWT - }, - callback=cb)); - }); + }); + + describe('#post', function() { + it('should send post request correctly with options and data (promise)', function() { + var fakedJWT = 'Faked JWT'; + var resource = 'example'; + var data = { k: 'v' }; + var options = { foo: 'bar', baz: 'qux' }; + + this.client._personalizationToken = fakedJWT; + this.client.personalization.post(resource, options, data); + + td.verify( + post( + { + url: resource + '/', + serviceName: 'personalization', + qs: options, + body: data, + signature: fakedJWT, + }, + undefined + ) + ); }); + it('should send post request correctly with options and data (cb)', function() { + var fakedJWT = 'Faked JWT'; + var resource = 'example'; + var options = { foo: 'bar', baz: 'qux' }; + var data = { k: 'v' }; + var cb = function() {}; + + this.client._personalizationToken = fakedJWT; + this.client.personalization.post(resource, options, data, cb); + + td.verify( + post( + { + url: resource + '/', + serviceName: 'personalization', + qs: options, + body: data, + signature: fakedJWT, + }, + (callback = cb) + ) + ); + }); - describe('No secret provided', function() { - - it('should raise SiteErrors', function() { + it('should send post request correctly with options (promise)', function() { + var fakedJWT = 'Faked JWT'; + var resource = 'example'; + var options = { foo: 'bar', baz: 'qux' }; + + this.client._personalizationToken = fakedJWT; + this.client.personalization.post(resource, options); + + td.verify( + post( + { + url: resource + '/', + serviceName: 'personalization', + qs: options, + body: {}, + signature: fakedJWT, + }, + undefined + ) + ); + }); - var client = new StreamClient('stub-key', null, 9498); - var resource = 'example'; - var options = {foo: 'bar', baz: 'qux'}; - var data = {k: 'v'}; - var cb = function() {}; + it('should send post request correctly with options (cb)', function() { + var fakedJWT = 'Faked JWT'; + var resource = 'example'; + var options = { foo: 'bar', baz: 'qux' }; + var cb = function() {}; + + this.client._personalizationToken = fakedJWT; + this.client.personalization.post(resource, options, cb); + + td.verify( + post( + { + url: resource + '/', + serviceName: 'personalization', + qs: options, + body: {}, + signature: fakedJWT, + }, + (callback = cb) + ) + ); + }); - // get - expect(function() { - client.personalization.get(resource, options); - }).to.throwException(function(e) { - expect(e).to.be.a(errors.SiteError); - }); + it('should send post request correctly without options or data (promise)', function() { + var fakedJWT = 'Faked JWT'; + var resource = 'example'; + + this.client._personalizationToken = fakedJWT; + this.client.personalization.post(resource); + + td.verify( + post( + { + url: resource + '/', + serviceName: 'personalization', + qs: {}, + body: {}, + signature: fakedJWT, + }, + undefined + ) + ); + }); - // post - expect(function() { - client.personalization.post(resource, options, data, cb); - }).to.throwException(function(e) { - expect(e).to.be.a(errors.SiteError); - }); + it('should send post request correctly without options or data (cb)', function() { + var fakedJWT = 'Faked JWT'; + var resource = 'example'; + var cb = function() {}; + + this.client._personalizationToken = fakedJWT; + this.client.personalization.post(resource, cb); + + td.verify( + post( + { + url: resource + '/', + serviceName: 'personalization', + qs: {}, + body: {}, + signature: fakedJWT, + }, + (callback = cb) + ) + ); + }); + }); + + describe('#delete', function() { + it('should send delete request correctly with options (promise)', function() { + var fakedJWT = 'Faked JWT'; + var resource = 'example'; + var options = { foo: 'bar', baz: 'qux' }; + + this.client._personalizationToken = fakedJWT; + this.client.personalization.delete(resource, options); + + td.verify( + del( + { + url: resource + '/', + serviceName: 'personalization', + qs: options, + signature: fakedJWT, + }, + undefined + ) + ); + }); - // delete - expect(function() { - client.personalization.delete(resource); - }).to.throwException(function(e) { - expect(e).to.be.a(errors.SiteError); - }); + it('should send delete request correctly with options (cb)', function() { + var fakedJWT = 'Faked JWT'; + var resource = 'example'; + var options = { foo: 'bar', baz: 'qux' }; + var cb = function() {}; + + this.client._personalizationToken = fakedJWT; + this.client.personalization.delete(resource, options, cb); + + td.verify( + del( + { + url: resource + '/', + serviceName: 'personalization', + qs: options, + signature: fakedJWT, + }, + (callback = cb) + ) + ); + }); - }); + it('should send delete request correctly without options (promise)', function() { + var fakedJWT = 'Faked JWT'; + var resource = 'example'; + + this.client._personalizationToken = fakedJWT; + this.client.personalization.delete(resource); + + td.verify( + del( + { + url: resource + '/', + serviceName: 'personalization', + qs: {}, + signature: fakedJWT, + }, + undefined + ) + ); }); + it('should send delete request correctly without options (cb)', function() { + var fakedJWT = 'Faked JWT'; + var resource = 'example'; + var cb = function() {}; + + this.client._personalizationToken = fakedJWT; + this.client.personalization.delete(resource, cb); + + td.verify( + del( + { + url: resource + '/', + serviceName: 'personalization', + qs: {}, + signature: fakedJWT, + }, + (callback = cb) + ) + ); + }); + }); + + describe('No secret provided', function() { + it('should raise SiteErrors', function() { + var client = new StreamClient('stub-key', null, 9498); + var resource = 'example'; + var options = { foo: 'bar', baz: 'qux' }; + var data = { k: 'v' }; + var cb = function() {}; + + // get + expect(function() { + client.personalization.get(resource, options); + }).to.throwException(function(e) { + expect(e).to.be.a(errors.SiteError); + }); + + // post + expect(function() { + client.personalization.post(resource, options, data, cb); + }).to.throwException(function(e) { + expect(e).to.be.a(errors.SiteError); + }); + + // delete + expect(function() { + client.personalization.delete(resource); + }).to.throwException(function(e) { + expect(e).to.be.a(errors.SiteError); + }); + }); + }); }); diff --git a/test/unit/node/redirect_test.js b/test/unit/node/redirect_test.js index 457f1db6..a88a0d97 100644 --- a/test/unit/node/redirect_test.js +++ b/test/unit/node/redirect_test.js @@ -1,141 +1,144 @@ -var config = require('../utils/config') - , StreamClient = require('../../../src/lib/client') - , jwt = require('jsonwebtoken') - , url = require('url') - , request = require('request') - , expect = require('expect.js') - , afterEachFn = require('../utils/hooks').afterEach - , beforeEachFn = require('../utils/hooks').beforeEach - , errors = require('../../../src/lib/errors') - , qs = require('qs'); - -describe('[UNIT] Redirect URL\'s', function() { - - // beforeEach(beforeEachFn); - - it('should create email redirects (analytics.stream-io-api.com)', function() { - var expectedParts = ['https://analytics.stream-io-api.com/analytics/redirect/', - 'auth_type=jwt', - 'url=http%3A%2F%2Fgoogle.com%2F%3Fa%3Db%26c%3Dd', - 'events=%5B%7B%22foreign_ids%22%3A%5B%22tweet%3A1%22%2C%22tweet%3A2%22%2C%22tweet%3A3%22%2C%22tweet%3A4%22%2C%22tweet%3A5%22%5D%2C%22user_id%22%3A%22tommaso%22%2C%22location%22%3A%22email%22%2C%22feed_id%22%3A%22user%3Aglobal%22%7D%2C%7B%22foreign_id%22%3A%22tweet%3A1%22%2C%22label%22%3A%22click%22%2C%22position%22%3A3%2C%22user_id%22%3A%22tommaso%22%2C%22location%22%3A%22email%22%2C%22feed_id%22%3A%22user%3Aglobal%22%7D%5D', - 'api_key=' + config.API_KEY, - ]; - var engagement = { - 'foreign_id': 'tweet:1', - 'label': 'click', - 'position': 3, - 'user_id': 'tommaso', - 'location': 'email', - 'feed_id': 'user:global' - }, - impression = { - 'foreign_ids': ['tweet:1', 'tweet:2', 'tweet:3', 'tweet:4', 'tweet:5'], - 'user_id': 'tommaso', - 'location': 'email', - 'feed_id': 'user:global' - }, - events = [impression, engagement], - userId = 'tommaso', - targetUrl = 'http://google.com/?a=b&c=d'; - - this.client = new StreamClient(config.API_KEY, config.API_SECRET); - var redirectUrl = this.client.createRedirectUrl(targetUrl, userId, events); - - var queryString = qs.parse(url.parse(redirectUrl).query); - var decoded = jwt.verify(queryString.authorization, config.API_SECRET); - - expect(decoded).to.eql({ - 'resource': 'redirect_and_track', - 'action': '*', - 'user_id': '*', - }); - - for (var i = 0; i < expectedParts.length; i++) { - expect(redirectUrl).to.contain(expectedParts[i]); - } - }); - - it('should create email redirects (analytics.getstream.io)', function() { - var expectedParts = ['https://analytics.getstream.io/analytics/redirect/', - 'auth_type=jwt', - 'url=http%3A%2F%2Fgoogle.com%2F%3Fa%3Db%26c%3Dd', - 'events=%5B%7B%22foreign_ids%22%3A%5B%22tweet%3A1%22%2C%22tweet%3A2%22%2C%22tweet%3A3%22%2C%22tweet%3A4%22%2C%22tweet%3A5%22%5D%2C%22user_id%22%3A%22tommaso%22%2C%22location%22%3A%22email%22%2C%22feed_id%22%3A%22user%3Aglobal%22%7D%2C%7B%22foreign_id%22%3A%22tweet%3A1%22%2C%22label%22%3A%22click%22%2C%22position%22%3A3%2C%22user_id%22%3A%22tommaso%22%2C%22location%22%3A%22email%22%2C%22feed_id%22%3A%22user%3Aglobal%22%7D%5D', - 'api_key=' + config.API_KEY, - ]; - var engagement = { - 'foreign_id': 'tweet:1', - 'label': 'click', - 'position': 3, - 'user_id': 'tommaso', - 'location': 'email', - 'feed_id': 'user:global' - }, - impression = { - 'foreign_ids': ['tweet:1', 'tweet:2', 'tweet:3', 'tweet:4', 'tweet:5'], - 'user_id': 'tommaso', - 'location': 'email', - 'feed_id': 'user:global' - }, - events = [impression, engagement], - userId = 'tommaso', - targetUrl = 'http://google.com/?a=b&c=d'; - process.env.STREAM_ANALYTICS_BASE_URL = 'https://analytics.getstream.io/analytics/' - this.client = new StreamClient(config.API_KEY, config.API_SECRET); - var redirectUrl = this.client.createRedirectUrl(targetUrl, userId, events); - - var queryString = qs.parse(url.parse(redirectUrl).query); - var decoded = jwt.verify(queryString.authorization, config.API_SECRET); - - expect(decoded).to.eql({ - 'resource': 'redirect_and_track', - 'action': '*', - 'user_id': '*', - }); - - for (var i = 0; i < expectedParts.length; i++) { - expect(redirectUrl).to.contain(expectedParts[i]); - } - delete process.env['STREAM_ANALYTICS_BASE_URL'] +var config = require('../utils/config'), + StreamClient = require('../../../src/lib/client'), + jwt = require('jsonwebtoken'), + url = require('url'), + request = require('request'), + expect = require('expect.js'), + afterEachFn = require('../utils/hooks').afterEach, + beforeEachFn = require('../utils/hooks').beforeEach, + errors = require('../../../src/lib/errors'), + qs = require('qs'); + +describe("[UNIT] Redirect URL's", function() { + // beforeEach(beforeEachFn); + + it('should create email redirects (analytics.stream-io-api.com)', function() { + var expectedParts = [ + 'https://analytics.stream-io-api.com/analytics/redirect/', + 'auth_type=jwt', + 'url=http%3A%2F%2Fgoogle.com%2F%3Fa%3Db%26c%3Dd', + 'events=%5B%7B%22foreign_ids%22%3A%5B%22tweet%3A1%22%2C%22tweet%3A2%22%2C%22tweet%3A3%22%2C%22tweet%3A4%22%2C%22tweet%3A5%22%5D%2C%22user_id%22%3A%22tommaso%22%2C%22location%22%3A%22email%22%2C%22feed_id%22%3A%22user%3Aglobal%22%7D%2C%7B%22foreign_id%22%3A%22tweet%3A1%22%2C%22label%22%3A%22click%22%2C%22position%22%3A3%2C%22user_id%22%3A%22tommaso%22%2C%22location%22%3A%22email%22%2C%22feed_id%22%3A%22user%3Aglobal%22%7D%5D', + 'api_key=' + config.API_KEY, + ]; + var engagement = { + foreign_id: 'tweet:1', + label: 'click', + position: 3, + user_id: 'tommaso', + location: 'email', + feed_id: 'user:global', + }, + impression = { + foreign_ids: ['tweet:1', 'tweet:2', 'tweet:3', 'tweet:4', 'tweet:5'], + user_id: 'tommaso', + location: 'email', + feed_id: 'user:global', + }, + events = [impression, engagement], + userId = 'tommaso', + targetUrl = 'http://google.com/?a=b&c=d'; + + this.client = new StreamClient(config.API_KEY, config.API_SECRET); + var redirectUrl = this.client.createRedirectUrl(targetUrl, userId, events); + + var queryString = qs.parse(url.parse(redirectUrl).query); + var decoded = jwt.verify(queryString.authorization, config.API_SECRET); + + expect(decoded).to.eql({ + resource: 'redirect_and_track', + action: '*', + user_id: '*', }); - - it('should follow redirect urls', function(done) { - var events = [{ - 'content_list': ['tweet:1', 'tweet:2', 'tweet:3'], - 'user_data':'tommaso', - 'location':'email', - 'feed_id':'user:global' - },{ - 'content':'tweet:2', - 'label':'click', - 'position':1, - 'user_data':'tommaso', - 'location':'email', - 'feed_id':'user:global' - }], - userId = 'tommaso', - targetUrl = 'http://google.com/?a=b&c=d'; - - var redirectUrl = this.client.createRedirectUrl(targetUrl, userId, events); - - request(redirectUrl, function(err, response) { - if (err) { - done(err); - } else if (response.statusCode !== 200) { - done('Expecting a status code of 200 but got ' + response.statusCode); - } else if (response.request.uri.hostname.indexOf('google') === -1) { - done('Did not follow redirect to google'); - } else { - done(); - } - }); + for (var i = 0; i < expectedParts.length; i++) { + expect(redirectUrl).to.contain(expectedParts[i]); + } + }); + + it('should create email redirects (analytics.getstream.io)', function() { + var expectedParts = [ + 'https://analytics.getstream.io/analytics/redirect/', + 'auth_type=jwt', + 'url=http%3A%2F%2Fgoogle.com%2F%3Fa%3Db%26c%3Dd', + 'events=%5B%7B%22foreign_ids%22%3A%5B%22tweet%3A1%22%2C%22tweet%3A2%22%2C%22tweet%3A3%22%2C%22tweet%3A4%22%2C%22tweet%3A5%22%5D%2C%22user_id%22%3A%22tommaso%22%2C%22location%22%3A%22email%22%2C%22feed_id%22%3A%22user%3Aglobal%22%7D%2C%7B%22foreign_id%22%3A%22tweet%3A1%22%2C%22label%22%3A%22click%22%2C%22position%22%3A3%2C%22user_id%22%3A%22tommaso%22%2C%22location%22%3A%22email%22%2C%22feed_id%22%3A%22user%3Aglobal%22%7D%5D', + 'api_key=' + config.API_KEY, + ]; + var engagement = { + foreign_id: 'tweet:1', + label: 'click', + position: 3, + user_id: 'tommaso', + location: 'email', + feed_id: 'user:global', + }, + impression = { + foreign_ids: ['tweet:1', 'tweet:2', 'tweet:3', 'tweet:4', 'tweet:5'], + user_id: 'tommaso', + location: 'email', + feed_id: 'user:global', + }, + events = [impression, engagement], + userId = 'tommaso', + targetUrl = 'http://google.com/?a=b&c=d'; + process.env.STREAM_ANALYTICS_BASE_URL = + 'https://analytics.getstream.io/analytics/'; + this.client = new StreamClient(config.API_KEY, config.API_SECRET); + var redirectUrl = this.client.createRedirectUrl(targetUrl, userId, events); + + var queryString = qs.parse(url.parse(redirectUrl).query); + var decoded = jwt.verify(queryString.authorization, config.API_SECRET); + + expect(decoded).to.eql({ + resource: 'redirect_and_track', + action: '*', + user_id: '*', }); - it('should fail creating email redirects on invalid targets', function() { - var self = this; - expect(function() { - self.client.createRedirectUrl('google.com', 'tommaso', []); - }).to.throwException(new errors.MissingSchemaError()); + for (var i = 0; i < expectedParts.length; i++) { + expect(redirectUrl).to.contain(expectedParts[i]); + } + delete process.env['STREAM_ANALYTICS_BASE_URL']; + }); + + it('should follow redirect urls', function(done) { + var events = [ + { + content_list: ['tweet:1', 'tweet:2', 'tweet:3'], + user_data: 'tommaso', + location: 'email', + feed_id: 'user:global', + }, + { + content: 'tweet:2', + label: 'click', + position: 1, + user_data: 'tommaso', + location: 'email', + feed_id: 'user:global', + }, + ], + userId = 'tommaso', + targetUrl = 'http://google.com/?a=b&c=d'; + + var redirectUrl = this.client.createRedirectUrl(targetUrl, userId, events); + + request(redirectUrl, function(err, response) { + if (err) { + done(err); + } else if (response.statusCode !== 200) { + done('Expecting a status code of 200 but got ' + response.statusCode); + } else if (response.request.uri.hostname.indexOf('google') === -1) { + done('Did not follow redirect to google'); + } else { + done(); + } }); - + }); + + it('should fail creating email redirects on invalid targets', function() { + var self = this; + expect(function() { + self.client.createRedirectUrl('google.com', 'tommaso', []); + }).to.throwException(new errors.MissingSchemaError()); + }); }); diff --git a/test/unit/node/token_test.js b/test/unit/node/token_test.js index 6f2d49a3..bc30b9d7 100644 --- a/test/unit/node/token_test.js +++ b/test/unit/node/token_test.js @@ -1,65 +1,63 @@ -var signing = require('../../../src/lib/signing') - , expect = require('expect.js') - , beforeEachFn = require('../utils/hooks').beforeEach; +var signing = require('../../../src/lib/signing'), + expect = require('expect.js'), + beforeEachFn = require('../utils/hooks').beforeEach; describe('[UNIT] Creating tokens', function() { + beforeEach(beforeEachFn); - beforeEach(beforeEachFn); + it('#getReadOnlyToken', function() { + var token = this.client.getReadOnlyToken('user', 'test'); - it('#getReadOnlyToken', function() { - var token = this.client.getReadOnlyToken('user', 'test'); + expect(token).not.to.be(undefined); - expect(token).not.to.be(undefined); - - var feedId = 'usertest'; - var expected = signing.JWTScopeToken(this.client.apiSecret, '*', 'read', { - feedId: feedId, - expireTokens: this.client.expireTokens - }); - - expect(token).to.be(expected); + var feedId = 'usertest'; + var expected = signing.JWTScopeToken(this.client.apiSecret, '*', 'read', { + feedId: feedId, + expireTokens: this.client.expireTokens, }); - it('#getReadWriteToken', function() { - var token = this.client.getReadWriteToken('user', 'test'); + expect(token).to.be(expected); + }); - expect(token).not.to.be(undefined); + it('#getReadWriteToken', function() { + var token = this.client.getReadWriteToken('user', 'test'); - var feedId = 'usertest'; - var expected = signing.JWTScopeToken(this.client.apiSecret, '*', '*', { - feedId: feedId, - expireTokens: this.client.expireTokens - }); + expect(token).not.to.be(undefined); - expect(token).to.be(expected); + var feedId = 'usertest'; + var expected = signing.JWTScopeToken(this.client.apiSecret, '*', '*', { + feedId: feedId, + expireTokens: this.client.expireTokens, }); - it('feed #getReadOnlyToken', function() { - var token = this.client.feed('user', 'test').getReadOnlyToken(); + expect(token).to.be(expected); + }); - expect(token).not.to.be(undefined); + it('feed #getReadOnlyToken', function() { + var token = this.client.feed('user', 'test').getReadOnlyToken(); - var feedId = 'usertest'; - var expected = signing.JWTScopeToken(this.client.apiSecret, '*', 'read', { - feedId: feedId, - expireTokens: this.client.expireTokens - }); + expect(token).not.to.be(undefined); - expect(token).to.be(expected); + var feedId = 'usertest'; + var expected = signing.JWTScopeToken(this.client.apiSecret, '*', 'read', { + feedId: feedId, + expireTokens: this.client.expireTokens, }); - it('feed #getReadWriteToken', function() { - var token = this.client.feed('user', 'test').getReadWriteToken(); + expect(token).to.be(expected); + }); - expect(token).not.to.be(undefined); + it('feed #getReadWriteToken', function() { + var token = this.client.feed('user', 'test').getReadWriteToken(); - var feedId = 'usertest'; - var expected = signing.JWTScopeToken(this.client.apiSecret, '*', '*', { - feedId: feedId, - expireTokens: this.client.expireTokens - }); + expect(token).not.to.be(undefined); - expect(token).to.be(expected); + var feedId = 'usertest'; + var expected = signing.JWTScopeToken(this.client.apiSecret, '*', '*', { + feedId: feedId, + expireTokens: this.client.expireTokens, }); -}); \ No newline at end of file + expect(token).to.be(expected); + }); +}); diff --git a/test/unit/utils/config.js b/test/unit/utils/config.js index b405164b..d3fddce5 100644 --- a/test/unit/utils/config.js +++ b/test/unit/utils/config.js @@ -2,15 +2,16 @@ var isNodeEnv = typeof window === 'undefined'; var LOCAL_RUN = false; -var API_KEY = 'q56mdvdzreye' - , API_SECRET = 'spmf6x2b2v2tqg93sfp5t393wfcxru58zm7jr3ynf7dmmndw5y8chux25hs63znf'; +var API_KEY = 'q56mdvdzreye', + API_SECRET = + 'spmf6x2b2v2tqg93sfp5t393wfcxru58zm7jr3ynf7dmmndw5y8chux25hs63znf'; if (LOCAL_RUN && isNodeEnv) { module.exports.API_KEY = process.env.STREAM_API_KEY || API_KEY; module.exports.API_SECRET = process.env.STREAM_API_SECRET || API_SECRET; } else { - module.exports.API_KEY = API_KEY; - module.exports.API_SECRET = API_SECRET; + module.exports.API_KEY = API_KEY; + module.exports.API_SECRET = API_SECRET; } -module.exports.IS_NODE_ENV = isNodeEnv; \ No newline at end of file +module.exports.IS_NODE_ENV = isNodeEnv; diff --git a/test/unit/utils/hooks.js b/test/unit/utils/hooks.js index 5ddda22d..e708023c 100644 --- a/test/unit/utils/hooks.js +++ b/test/unit/utils/hooks.js @@ -1,9 +1,9 @@ -var config = require('./config') - , td = require('testdouble') - , StreamClient = require('../../../src/lib/client'); +var config = require('./config'), + td = require('testdouble'), + StreamClient = require('../../../src/lib/client'); function init() { - this.timeout(500); + this.timeout(500); } function beforeEachBrowser() { @@ -18,7 +18,7 @@ function beforeEachNode() { module.exports = { init: init, - beforeEachNode : beforeEachNode, - beforeEachBrowser : beforeEachBrowser, + beforeEachNode: beforeEachNode, + beforeEachBrowser: beforeEachBrowser, beforeEach: config.IS_NODE_ENV ? beforeEachNode : beforeEachBrowser, }; diff --git a/test/unit/utils/jwt.js b/test/unit/utils/jwt.js index 23c578b5..d0068062 100644 --- a/test/unit/utils/jwt.js +++ b/test/unit/utils/jwt.js @@ -1,6 +1,6 @@ -var signing = require('../../../src/lib/signing') - , jwt = require('jsonwebtoken') - , qc = require('quickcheck'); +var signing = require('../../../src/lib/signing'), + jwt = require('jsonwebtoken'), + qc = require('quickcheck'); function propertyHeaderJSON(jwt) { var json = signing.isJWTSignature(jwt); @@ -12,17 +12,17 @@ function arbJSON(depth) { var result = {}; - while(width--) { + while (width--) { var value = qc.arbString(), - maxDepth = Math.floor(Math.random() * (3 - 1) + 1); + maxDepth = Math.floor(Math.random() * (3 - 1) + 1); - if(depth) { - value = arbJSON(depth-1); - } else if(depth === undefined) { + if (depth) { + value = arbJSON(depth - 1); + } else if (depth === undefined) { value = arbJSON(maxDepth); } - result[ qc.arbString() ] = value; + result[qc.arbString()] = value; } return result; @@ -35,12 +35,15 @@ function arbNonEmptyString() { } function arbJWT() { - return jwt.sign( arbJSON(), arbNonEmptyString(), { algorithm: 'HS256', noTimestamp: true }); + return jwt.sign(arbJSON(), arbNonEmptyString(), { + algorithm: 'HS256', + noTimestamp: true, + }); } module.exports = { - propertyHeaderJSON: propertyHeaderJSON, - arbJSON: arbJSON, - arbNonEmptyString: arbNonEmptyString, - arbJWT: arbJWT, -}; \ No newline at end of file + propertyHeaderJSON: propertyHeaderJSON, + arbJSON: arbJSON, + arbNonEmptyString: arbNonEmptyString, + arbJWT: arbJWT, +}; diff --git a/types/getstream/index.d.ts b/types/getstream/index.d.ts index 5c5e08a0..30c05255 100644 --- a/types/getstream/index.d.ts +++ b/types/getstream/index.d.ts @@ -7,89 +7,85 @@ export as namespace stream; */ export function connect( apiKey: string, - apiSecret: string|null, + apiSecret: string | null, appId: string, - options?: object + options?: object, ): stream.Client; export class Collections { /** Construct Collections. */ - constructor( - client: StreamClient, - ); + constructor(client: StreamClient); // Upsert one or more items within a collection. upsert( collectionName: string, - data:object|object[], - callback: (err: object, httpResponse: object, body: object) => void + data: object | object[], + callback: (err: object, httpResponse: object, body: object) => void, ): void; - upsert(collectionName: string, data: object|object[]): Promise; + upsert(collectionName: string, data: object | object[]): Promise; // Select all objects with ids from the collection. select( collectionName: string, - ids: object|object[], - callback: (err: object, httpResponse: object, body: object) => void + ids: object | object[], + callback: (err: object, httpResponse: object, body: object) => void, ): void; - select(collectionName: string, ids: object|object[]): Promise; + select(collectionName: string, ids: object | object[]): Promise; // Remove all objects by id from the collection. delete( collectionName: string, - ids: object|object[], - callback: (err: object, httpResponse: object, body: object) => void + ids: object | object[], + callback: (err: object, httpResponse: object, body: object) => void, ): void; - delete(collectionName: string, ids: object|object[]): Promise; + delete(collectionName: string, ids: object | object[]): Promise; } export class Personalization { /** Construct Personalization. */ - constructor( - client: StreamClient, - ); + constructor(client: StreamClient); // Get personalized activities for this feed. get( resource: string, options: object, - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; get( resource: string, - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; - get(resource: string, options?:object): Promise; + get(resource: string, options?: object): Promise; // Post data to personalization endpoint. post( resource: string, - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; post( resource: string, - options:object, - callback: (err: object, httpResponse: object, body: object) => void + options: object, + callback: (err: object, httpResponse: object, body: object) => void, ): void; post( resource: string, - options:object, + options: object, data: object, - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; - post(resource: string, options?:object, data?: object): Promise; + post(resource: string, options?: object, data?: object): Promise; // Delete metadata or activites delete( resource: string, - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; delete( resource: string, - options:object, - callback: (err: object, httpResponse: object, body: object) => void + options: object, + callback: (err: object, httpResponse: object, body: object) => void, ): void; - delete(resource: string, options?:object): Promise; + delete(resource: string, options?: object): Promise; } export class Feed { @@ -98,41 +94,41 @@ export class Feed { client: StreamClient, feedSlug: string, userId: string, - token: string + token: string, ); // Add activity addActivity(activity: object): Promise; addActivity( activity: object, - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; // Remove activity - removeActivity(activityId: string|object): Promise; + removeActivity(activityId: string | object): Promise; removeActivity( - activityId: string|object, - callback: (err: object, httpResponse: object, body: object) => void + activityId: string | object, + callback: (err: object, httpResponse: object, body: object) => void, ): void; // Add activities addActivities(activities: object[]): Promise; addActivities( activities: object[], - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; // Follow feed follow( targetSlug: string, targetUserId: string, - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; follow( targetSlug: string, targetUserId: string, options: object, - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; follow( targetSlug: string, @@ -144,39 +140,39 @@ export class Feed { unfollow( targetSlug: string, targetUserId: string, - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; unfollow( targetSlug: string, targetUserId: string, options: object, - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; unfollow( targetSlug: string, targetUserId: string, - options?: object + options?: object, ): Promise; // List followed feeds following(options: object): Promise; following( options: object, - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; // List followers followers(options: object): Promise; followers( options: object, - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; // Get feed get(options?: object): Promise; get( options: object, - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; // Subscribe to realtime @@ -194,7 +190,7 @@ export class StreamClient { apiKey: string, apiSecret?: string, appId?: string, - options?: object + options?: object, ); // Event subscriptions @@ -214,13 +210,13 @@ export class StreamClient { userId: string, token?: string, siteId?: string, - options?: object + options?: object, ): Feed; // Update activities updateActivities( activities: object[], - callback: (args: object[]) => void + callback: (args: object[]) => void, ): void; // Add activity to many feeds @@ -236,7 +232,7 @@ export class StreamClient { addToMany( activity: object, feeds: string[], - callback: (err: object, httpResponse: object, body: object) => void + callback: (err: object, httpResponse: object, body: object) => void, ): void; // Collections sub-component @@ -248,8 +244,7 @@ export class StreamClient { * followMany. * Available in node environments with batchOperations enabled */ - followMany(follows: object[], activityCopyLimit?: number - ): Promise; + followMany(follows: object[], activityCopyLimit?: number): Promise; /** * followMany. * Available in node environments with batchOperations enabled @@ -257,7 +252,7 @@ export class StreamClient { followMany( follows: object[], activityCopyLimit?: number, - callback?: (err: object, httpResponse: object, body: object) => void + callback?: (err: object, httpResponse: object, body: object) => void, ): void; // Unfollow many feeds @@ -272,7 +267,7 @@ export class StreamClient { */ unfollowMany( unfollows: object[], - callback?: (err: object, httpResponse: object, body: object) => void + callback?: (err: object, httpResponse: object, body: object) => void, ): void; } @@ -282,22 +277,22 @@ export { StreamClient as Client }; // Export the Stream errors export namespace errors { class MissingSchemaError { - /** - * Construct MissingSchemaError. - * Not typically instantiated by app developers. - */ + /** + * Construct MissingSchemaError. + * Not typically instantiated by app developers. + */ } class FeedError { - /** - * Construct FeedError. - * Not typically instantiated by app developers. - */ + /** + * Construct FeedError. + * Not typically instantiated by app developers. + */ } class SiteError { - /** - * Construct SiteError. - * Not typically instantiated by app developers. - */ + /** + * Construct SiteError. + * Not typically instantiated by app developers. + */ } } diff --git a/types/getstream/tests-getstream.ts b/types/getstream/tests-getstream.ts index 2130bbd5..52b50e9a 100644 --- a/types/getstream/tests-getstream.ts +++ b/types/getstream/tests-getstream.ts @@ -1,20 +1,46 @@ -new stream.Client("key", undefined, "apiSecret"); +new stream.Client('key', undefined, 'apiSecret'); -stream.connect("abc", "def", "ghi"); // $ExpectType StreamClient +stream.connect( + 'abc', + 'def', + 'ghi', +); // $ExpectType StreamClient -const client = stream.connect('abc', 'def', 'ghi'); +const client = stream.connect( + 'abc', + 'def', + 'ghi', +); client.feed('feedSlug', 'user'); // $ExpectType Feed let feed = client.feed('feedSlug', 'user'); feed.follow('feedSlug', 'user'); // $ExpectType Promise -feed.follow('feedSlug', 'user', {activity_copy_limit: 10}); // $ExpectType Promise -feed.follow('feedSlug', 'user', {activity_copy_limit: 10}, (err: object, httpResponse: object, body: object) => {}); // $ExpectType void -feed.follow('feedSlug', 'user', (err: object, httpResponse: object, body: object) => {}); // $ExpectType void +feed.follow('feedSlug', 'user', { activity_copy_limit: 10 }); // $ExpectType Promise +feed.follow( + 'feedSlug', + 'user', + { activity_copy_limit: 10 }, + (err: object, httpResponse: object, body: object) => {}, +); // $ExpectType void +feed.follow( + 'feedSlug', + 'user', + (err: object, httpResponse: object, body: object) => {}, +); // $ExpectType void feed.unfollow('feedSlug', 'user'); // $ExpectType Promise -feed.unfollow('feedSlug', 'user', {keep_history: true}); // $ExpectType Promise -feed.unfollow('feedSlug', 'user', {keep_history: true}, (err: object, httpResponse: object, body: object) => {}); // $ExpectType void -feed.unfollow('feedSlug', 'user', (err: object, httpResponse: object, body: object) => {}); // $ExpectType void +feed.unfollow('feedSlug', 'user', { keep_history: true }); // $ExpectType Promise +feed.unfollow( + 'feedSlug', + 'user', + { keep_history: true }, + (err: object, httpResponse: object, body: object) => {}, +); // $ExpectType void +feed.unfollow( + 'feedSlug', + 'user', + (err: object, httpResponse: object, body: object) => {}, +); // $ExpectType void new stream.errors.MissingSchemaError(); // $ExpectType MissingSchemaError new stream.errors.FeedError(); // $ExpectType FeedError diff --git a/webpack.config.js b/webpack.config.js index 88b03fd0..6b5837a6 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -2,55 +2,61 @@ const path = require('path'); const webpack = require('webpack'); const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); -module.exports = (env=[], argv=[]) => ({ +module.exports = (env = [], argv = []) => ({ entry: ['whatwg-fetch', './src/getstream.js'], - mode: "production", + mode: 'production', module: { rules: [ { test: /(jsonwebtoken|http-signature|batch_operations|qs)/, - use: 'null-loader' + use: 'null-loader', }, { test: /\.js$/, exclude: /(node_modules|bower_components)/, - use: 'babel-loader' - } - ] + use: 'babel-loader', + }, + ], }, node: { - console: false, - Buffer: false, - crypto: 'empty', - fs: 'empty', - net: 'empty', - tls: 'empty', - url: 'empty' + console: false, + Buffer: false, + crypto: 'empty', + fs: 'empty', + net: 'empty', + tls: 'empty', + url: 'empty', }, optimization: { - minimizer: argv.minify !== undefined ? - [new UglifyJsPlugin({uglifyOptions: {compress: {warnings: false}}})] : - [] + minimizer: + argv.minify !== undefined + ? [ + new UglifyJsPlugin({ + uglifyOptions: { compress: { warnings: false } }, + }), + ] + : [], }, output: { - path: argv.minify !== undefined ? - path.join(__dirname, 'dist', 'js_min') : - path.join(__dirname, "dist", "js"), - publicPath: "dist/", - filename: "getstream.js", - chunkFilename: "[chunkhash].js", - library: "stream", - libraryTarget: "umd" + path: + argv.minify !== undefined + ? path.join(__dirname, 'dist', 'js_min') + : path.join(__dirname, 'dist', 'js'), + publicPath: 'dist/', + filename: 'getstream.js', + chunkFilename: '[chunkhash].js', + library: 'stream', + libraryTarget: 'umd', }, resolve: { alias: { - 'request': 'xmlhttp-request' - } + request: 'xmlhttp-request', + }, }, });