From 8713a179d103c51fbd297f58d02a779a0fe47ac1 Mon Sep 17 00:00:00 2001 From: Shu Shen Date: Tue, 11 May 2021 13:44:51 -0700 Subject: [PATCH] [actionsManager] Adding new Actions Managment APIs (#570) * add actionsManagers * change triggerId for get actions * change ActionBindingsManager name * rename ActionBindings * fix ActionBindingsManager names * fix ActionBindingsManager names * draft, deploy, tests and axecutions * adding and fixing tests * revert README * fix test trigger * add actionsManagers * change triggerId for get actions * change ActionBindingsManager name * rename ActionBindings * fix ActionBindingsManager names * draft, deploy, tests and axecutions * adding and fixing tests * fix test trigger * add update action binding list * feat: align actions managers with refreshed API * merging all actions stuff into a single manager * tests * Add create/get action version. * change some methods names * fix tests * Add link to actions docs. Co-authored-by: Luis Britos Manriquez Co-authored-by: Chris Geihsler --- src/management/ActionsManager.js | 632 ++++++++++++++++ src/management/index.js | 45 +- test/management/actions.tests.js | 1191 ++++++++++++++++++++++++++++++ 3 files changed, 1850 insertions(+), 18 deletions(-) create mode 100644 src/management/ActionsManager.js create mode 100644 test/management/actions.tests.js diff --git a/src/management/ActionsManager.js b/src/management/ActionsManager.js new file mode 100644 index 000000000..78d6e2d7c --- /dev/null +++ b/src/management/ActionsManager.js @@ -0,0 +1,632 @@ +var ArgumentError = require('rest-facade').ArgumentError; +var utils = require('../utils'); +var Auth0RestClient = require('../Auth0RestClient'); +var RetryRestClient = require('../RetryRestClient'); + +/** + * Simple facade for consuming a REST API endpoint. + * @external RestClient + * @see https://github.com/ngonzalvez/rest-facade + */ + +/** + * @class ActionsManager + * {@link https://auth0.com/docs/api/v2#!/Actions/get_actions Actions} provide a way to extend + * Auth0 flows with custom logic. + * See the {@link https://auth0.com/docs/actions Actions documentation} for more information. + * @constructor + * @memberOf module:management + * + * @param {Object} options The client options. + * @param {String} options.baseUrl The URL of the API. + * @param {Object} [options.headers] Headers to be included in all requests. + * @param {Object} [options.retry] Retry Policy Config + */ +var ActionsManager = function(options) { + if (options === null || typeof options !== 'object') { + throw new ArgumentError('Must provide client options'); + } + + if (options.baseUrl === null || options.baseUrl === undefined) { + throw new ArgumentError('Must provide a base URL for the API'); + } + + if ('string' !== typeof options.baseUrl || options.baseUrl.length === 0) { + throw new ArgumentError('The provided base URL is invalid'); + } + + /** + * Options object for the Rest Client instance. + * + * @type {Object} + */ + var clientOptions = { + errorFormatter: { message: 'message', name: 'error' }, + headers: options.headers, + query: { repeatParams: false } + }; + + /** + * Provides an abstraction layer for consuming the + * [Auth0 Actions endpoint]{@link https://auth0.com/docs/api/v2#!/actions}. + * + * @type {external:RestClient} + */ + var auth0RestClient = new Auth0RestClient( + options.baseUrl + '/actions/actions/:action_id', + clientOptions, + options.tokenProvider + ); + this.resource = new RetryRestClient(auth0RestClient, options.retry); + + var actionsDeployRestClient = new Auth0RestClient( + options.baseUrl + '/actions/actions/:action_id/deploy', + clientOptions, + options.tokenProvider + ); + this.actionsDeploy = new RetryRestClient(actionsDeployRestClient, options.retry); + + var actionsTestRestClient = new Auth0RestClient( + options.baseUrl + '/actions/actions/:action_id/test', + clientOptions, + options.tokenProvider + ); + this.actionsTest = new RetryRestClient(actionsTestRestClient, options.retry); + + var triggersRestClient = new Auth0RestClient( + options.baseUrl + '/actions/triggers/:trigger_id', + clientOptions, + options.tokenProvider + ); + this.triggers = new RetryRestClient(triggersRestClient, options.retry); + + var triggerBindingsRestClient = new Auth0RestClient( + options.baseUrl + '/actions/triggers/:trigger_id/bindings', + clientOptions, + options.tokenProvider + ); + this.triggerBindings = new RetryRestClient(triggerBindingsRestClient, options.retry); + + var triggersTestRestClient = new Auth0RestClient( + options.baseUrl + '/actions/triggers/:trigger_id/test', + clientOptions, + options.tokenProvider + ); + this.triggersTest = new RetryRestClient(triggersTestRestClient, options.retry); + + var executionsRestClient = new Auth0RestClient( + options.baseUrl + '/actions/executions/:execution_id', + clientOptions, + options.tokenProvider + ); + this.executions = new RetryRestClient(executionsRestClient, options.retry); + + var actionVersionRestClient = new Auth0RestClient( + options.baseUrl + '/actions/actions/:action_id/versions/:version_id', + clientOptions, + options.tokenProvider + ); + this.actionVersions = new RetryRestClient(actionVersionRestClient, options.retry); + + var deployActionVersionRestClient = new Auth0RestClient( + options.baseUrl + '/actions/actions/:action_id/versions/:version_id/deploy', + clientOptions, + options.tokenProvider + ); + this.actionVersionDeploy = new RetryRestClient(deployActionVersionRestClient, options.retry); +}; + +/** + * Get all Triggers. + * + * @method getAllTriggers + * @memberOf module:management.ActionsManager.prototype + * + * @example + * This method takes an optional object as first argument that may be used to + * specify pagination settings. If pagination options are not present, + * the first page of a limited number of results will be returned. + * + * // Pagination settings. + * var params = { + * per_page: 10, + * page: 0 + * }; + * + * management.actions.getAllTriggers(params, function (err, actions) { + * console.log(actions.length); + * }); + * + * @param {Object} [params] Actions parameters. + * @param {Number} [params.per_page] Number of results per page. + * @param {Number} [params.page] Page number, zero indexed. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +ActionsManager.prototype.getAllTriggers = function(params, cb) { + params = params || {}; + + if (cb && cb instanceof Function) { + return this.triggers.getAll(params, cb); + } + + return this.triggers.getAll(params); +}; + +/** + * Update the actions bound to a trigger . + * + * @method updateTriggerBindings + * @memberOf module:management.ActionsManager.prototype + * + * @example + * var data = { bindings: [{ id_type: "action_id", id_value: ACTION_ID1},{id_type: "action_name", id_value: ACTION_NAME2}]; + * var params = { trigger_id: TRIGGER_ID }; + * + * // Using auth0 instance. + * management.actions.updateTriggerBindings(params, data, function (err, bindings) { + * if (err) { + * // Handle error. + * } + * + * console.log(bindings.length); // 2 + * }); + * + * @param {Object} params Actions Binding parameters. + * @param {String} params.trigger_id Actions Trigger ID. + * @param {Object} data bindings array + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +ActionsManager.prototype.updateTriggerBindings = function(params, data, cb) { + params = params || {}; + + if (cb && cb instanceof Function) { + return this.triggerBindings.patch(params, data, cb); + } + + return this.triggerBindings.patch(params, data); +}; + +/** + * test an Trigger. + * + * @method testTrigger + * @memberOf module:management.ActionsManager.prototype + * + * @example + * var params = { trigger_id: TRIGGER_ID}; + * auth0.actions.testTrigger(params, payload, function (err) { + * if (err) { + * // Handle error. + * } + + * }); + * + * @param {Object} params Action parameters. + * @param {String} params.trigger_id Trigger ID. + * @param {Object} payload Payload represents the entire structure necessary to test a particular trigger + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +ActionsManager.prototype.testTrigger = function(params, payload, cb) { + params = params || {}; + payload = payload || {}; + + if (cb && cb instanceof Function) { + return this.triggersTest.create(params, payload, cb); + } + + return this.triggersTest.create(params, payload); +}; + +/** + * Get the actions bound to a trigger . + * + * @method getTriggerBindings + * @memberOf module:management.ActionsManager.prototype + * + * @example + * var params = { trigger_id: TRIGGER_ID }; + * + * // Using auth0 instance. + * management.actions.getTriggerBindings(params, function (err, bindings) { + * if (err) { + * // Handle error. + * } + * + * console.log(bindings.length); // 2 + * }); + * + * @param {Object} params Actions Binding parameters. + * @param {String} params.trigger_id Actions Trigger ID. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +ActionsManager.prototype.getTriggerBindings = function(params, cb) { + params = params || {}; + + if (cb && cb instanceof Function) { + return this.triggerBindings.getAll(params, cb); + } + + return this.triggerBindings.getAll(params); +}; + +/** + * Create a new Action. + * + * @method create + * @memberOf module:management.ActionsManager.prototype + * + * @example + * management.actions.create(data, function (err) { + * if (err) { + * // Handle error. + * } + * + * // Action created. + * }); + * + * @param {Object} data Action data object. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ActionsManager, 'create', 'resource.create'); + +/** + * Get all actions. + * + * @method getAll + * @memberOf module:management.ActionsManager.prototype + * + * @example + * This method takes an optional object as first argument that may be used to + * specify pagination settings. If pagination options are not present, + * the first page of a limited number of results will be returned. + * + * // Pagination settings. + * var params = { + * per_page: 10, + * page: 0, + * triggerId:'TRIGGER_ID', + * actionName: 'ACTION_NAME' + * }; + * + * management.actions.getAll(params, function (err, actions) { + * console.log(actions.length); + * }); + * + * @param {Object} [params] Actions parameters. + * @param {Number} [params.per_page] Number of results per page. + * @param {Number} [params.page] Page number, zero indexed. + * @param {String} [params.triggerId] The trigger ID of the actions to retrieve. + * @param {String} [params.actionName] The name of the actions to retrieve. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ActionsManager, 'getAll', 'resource.getAll'); + +/** + * Get an Auth0 action. + * + * @method get + * @memberOf module:management.ActionsManager.prototype + * + * @example + * management.actions.get({ action_id: ACTION_ID }, function (err, action) { + * if (err) { + * // Handle error. + * } + * + * console.log(action); + * }); + * + * @param {Object} params Action parameters. + * @param {String} params.action_id Action ID. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ActionsManager, 'get', 'resource.get'); + +/** + * Update an existing action. + * + * @method update + * @memberOf module:management.ActionsManager.prototype + * + * @example + * var data = { name: 'new-name' }; + * var params = { action_id: ACTION_ID }; + * + * // Using auth0 instance. + * management.updateAction(params, data, function (err, action) { + * if (err) { + * // Handle error. + * } + * + * console.log(action.name); // 'new-name' + * }); + * + * // Using the Actions manager directly. + * management.actions.update(params, data, function (err, action) { + * if (err) { + * // Handle error. + * } + * + * console.log(action.name); // 'new-name' + * }); + * + * @param {Object} params Action parameters. + * @param {String} params.action_id Action ID. + * @param {Object} data Updated action data. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ActionsManager, 'update', 'resource.patch'); + +/** + * Delete an existing action. Deleting an Action deletes all the action's versions + * + * @method delete + * @memberOf module:management.ActionsManager.prototype + * + * @example + * management.actions.delete({ action_id: ACTION_ID }, function (err) { + * if (err) { + * // Handle error. + * } + * + * // Action deleted. + * }); + * + * @param {Object} params Action parameters. + * @param {String} params.action_id Action ID. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +utils.wrapPropertyMethod(ActionsManager, 'delete', 'resource.delete'); + +/** + * test an Action. + * + * @method test + * @memberOf module:management.ActionsManager.prototype + * + * @example + * var params = { action_id: ACTION_ID}; + * management.actions.testAction(params, payload, function (err) { + * if (err) { + * // Handle error. + * } + + * }); + * + * @param {Object} params Action parameters. + * @param {String} params.action_id Action ID. + * @param {Object} payload Payload represents the entire structure necessary to test a particular trigger + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +ActionsManager.prototype.test = function(params, payload, cb) { + params = params || {}; + payload = payload || {}; + + if (cb && cb instanceof Function) { + return this.actionsTest.create(params, payload, cb); + } + + return this.actionsTest.create(params, payload); +}; + +/** + * deploy an Action. + * The action must be in a state of 'built' before it can be deployed. + * + * @method deploy + * @memberOf module:management.ActionsManager.prototype + * + * @example + * var params = { action_id: ACTION_ID}; + * mangement.actions.deploy(params, function (err, actionVersion) { + * if (err) { + * // Handle error. + * } + + * }); + * + * @param {Object} params Action parameters. + * @param {String} params.action_id Action ID. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +ActionsManager.prototype.deploy = function(params, cb) { + params = params || {}; + + if (cb && cb instanceof Function) { + return this.actionsDeploy.create(params, {}, cb); + } + + return this.actionsDeploy.create(params, {}); +}; + +/** + * Get all action versions + * + * @method getVersions + * @memberOf module:management.ActionsManager.prototype + * + * @example + * This method takes an optional object as first argument that may be used to + * specify pagination settings. If pagination options are not present, + * the first page of a limited number of results will be returned. + * + * // Pagination settings. + * var params = { + * per_page: 10, + * page: 0 + * }; + * + * management.actions.getVersions({ action_id: ACTION_ID }, function (err, actionVersions) { + * console.log(actionVersions.length); + * }); + * + * @param {Object} [params] ActionVersions parameters. + * @param {Number} [params.per_page] Number of results per page. + * @param {Number} [params.page] Page number, zero indexed. + * @param {String} [params.action_id] Action ID. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +ActionsManager.prototype.getVersions = function(params, cb) { + params = params || {}; + + if (cb && cb instanceof Function) { + return this.actionVersions.getAll(params, cb); + } + + return this.actionVersions.getAll(params); +}; + +/** + * Get an Action Version. + * + * @method getVersion + * @memberOf module:management.ActionsManager.prototype + * + * @example + * var params = { action_id: ACTION_ID, version_id: VERSION_ID }; + * management.actions.getVersion(params, function (err, actionVersion) { + * if (err) { + * // Handle error. + * } + + * }); + * + * @param {Object} params Action parameters. + * @param {String} params.action_id Action ID. + * @param {String} params.version_id ActionVersion ID. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +ActionsManager.prototype.getVersion = function(params, cb) { + params = params || {}; + + if (cb && cb instanceof Function) { + return this.actionVersions.get(params, cb); + } + + return this.actionVersions.get(params); +}; + +/** + * Create an Action Version. In general, updating an action and then + * deploying it is the preferred way of creating an action version, but + * this operation is supported as a way of creating versions without + * updating the action's code (which can be useful in some CI/CD scenarios). + * + * @method createVersion + * @memberOf module:management.ActionsManager.prototype + * + * @example + * var params = { action_id: ACTION_ID }; + * management.actions.createActionVersion(params, data, function (err, actionVersion) { + * if (err) { + * // Handle error. + * } + * }); + * + * @param {Object} params Action parameters. + * @param {String} params.action_id Action ID. + * @param {Object} data ActionVersion parameters. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +ActionsManager.prototype.createVersion = function(params, data, cb) { + params = params || {}; + + if (cb && cb instanceof Function) { + return this.actionVersions.create(params, data, cb); + } + + return this.actionVersions.create(params, data); +}; + +/** + * deploy an Action Version to roll back to a previous version. + * + * @method deployVersion + * @memberOf module:management.ActionsManager.prototype + * + * @example + * var params = { action_id: ACTION_ID, version_id: VERSION_ID }; + * management.actions.deployVersion(params, function (err, actionVersion) { + * if (err) { + * // Handle error. + * } + + * }); + * + * @param {Object} params Action parameters. + * @param {String} params.action_id Action ID. + * @param {String} params.version_id Action ID. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +ActionsManager.prototype.deployVersion = function(params, cb) { + params = params || {}; + + if (cb && cb instanceof Function) { + return this.actionVersionDeploy.create(params, {}, cb); + } + + return this.actionVersionDeploy.create(params, {}); +}; + +/** + * Get an execution by ID. + * + * @method getExecution + * @memberOf module:management.ActionExecutionsManager.prototype + * + * @example + * management.actions.getExecution({ execution_id: EXECUTION_ID }, function (err, action) { + * if (err) { + * // Handle error. + * } + * + * console.log(ActionExecution); + * }); + * + * @param {Object} params Action Execution parameters. + * @param {String} params.execution_id Action Execution ID. + * @param {Function} [cb] Callback function. + * + * @return {Promise|undefined} + */ +ActionsManager.prototype.getExecution = function(params, cb) { + params = params || {}; + + if (cb && cb instanceof Function) { + return this.executions.get(params, cb); + } + + return this.executions.get(params); +}; + +module.exports = ActionsManager; diff --git a/src/management/index.js b/src/management/index.js index e71bc054b..670937b47 100644 --- a/src/management/index.js +++ b/src/management/index.js @@ -34,6 +34,7 @@ var HooksManager = require('./HooksManager'); var BrandingManager = require('./BrandingManager'); var MigrationsManager = require('./MigrationsManager'); var PromptsManager = require('./PromptsManager'); +var ActionsManager = require('./ActionsManager'); var OrganizationsManager = require('./OrganizationsManager'); var BASE_URL_FORMAT = 'https://%s/api/v2'; @@ -352,6 +353,14 @@ var ManagementClient = function(options) { */ this.prompts = new PromptsManager(managerOptions); + /** + * Simple abstraction for performing CRUD operations on the + * actions endpoint. + * + * @type {ActionsManager} + */ + this.actions = new ActionsManager(managerOptions); + /** * Organizations Manager * @@ -3683,7 +3692,11 @@ utils.wrapPropertyMethod(ManagementClient, 'getBrandingSettings', 'branding.getS * * @return {Promise|undefined} */ -utils.wrapPropertyMethod(ManagementClient, 'getBrandingUniversalLoginTemplate', 'branding.getUniversalLoginTemplate'); +utils.wrapPropertyMethod( + ManagementClient, + 'getBrandingUniversalLoginTemplate', + 'branding.getUniversalLoginTemplate' +); /** * Get the new universal login template. @@ -3704,7 +3717,11 @@ utils.wrapPropertyMethod(ManagementClient, 'getBrandingUniversalLoginTemplate', * * @return {Promise|undefined} */ -utils.wrapPropertyMethod(ManagementClient, 'setBrandingUniversalLoginTemplate', 'branding.setUniversalLoginTemplate'); +utils.wrapPropertyMethod( + ManagementClient, + 'setBrandingUniversalLoginTemplate', + 'branding.setUniversalLoginTemplate' +); /** * Delete the new universal login template. @@ -3725,7 +3742,11 @@ utils.wrapPropertyMethod(ManagementClient, 'setBrandingUniversalLoginTemplate', * * @return {Promise|undefined} */ -utils.wrapPropertyMethod(ManagementClient, 'deleteBrandingUniversalLoginTemplate', 'branding.deleteUniversalLoginTemplate'); +utils.wrapPropertyMethod( + ManagementClient, + 'deleteBrandingUniversalLoginTemplate', + 'branding.deleteUniversalLoginTemplate' +); /** * Update the tenant migrations. @@ -3781,11 +3802,7 @@ utils.wrapPropertyMethod(ManagementClient, 'getMigrations', 'migrations.getMigra * * @example * management.getPromptsSettings(function (err, settings) { - * if (err) { - * // Handle error. - * } - * - * console.log(settings); + * * console.log(settings); * }); * * @param {Function} [cb] Callback function. @@ -3826,11 +3843,7 @@ utils.wrapPropertyMethod(ManagementClient, 'updatePromptsSettings', 'prompts.upd * var params = { prompt: PROMPT_NAME, language: LANGUAGE }; * * management.prompts.getCustomTextByLanguage(params, function (err, customText) { - * if (err) { - * // Handle error. - * } - * - * console.log('CustomText', customText); + * * console.log('CustomText', customText); * }); * * @param {Object} params Data object. @@ -3857,11 +3870,7 @@ utils.wrapPropertyMethod( * var params = { prompt: PROMPT_NAME, language: LANGUAGE, body: BODY_OBJECT }; * * management.prompts.updateCustomTextByLanguage(params, function (err, customText) { - * if (err) { - * // Handle error. - * } - * - * console.log('CustomText', customText); + * * console.log('CustomText', customText); * }); * * @param {Object} params Data object. diff --git a/test/management/actions.tests.js b/test/management/actions.tests.js new file mode 100644 index 000000000..c43d1367f --- /dev/null +++ b/test/management/actions.tests.js @@ -0,0 +1,1191 @@ +var expect = require('chai').expect; +var nock = require('nock'); + +var SRC_DIR = '../../src'; +var API_URL = 'https://tenant.auth0.com'; + +var ActionsManager = require(SRC_DIR + '/management/ActionsManager'); +var ArgumentError = require('rest-facade').ArgumentError; + +describe('ActionsManager', function() { + before(function() { + this.token = 'TOKEN'; + this.actions = new ActionsManager({ + headers: { authorization: 'Bearer ' + this.token }, + baseUrl: API_URL + }); + }); + + describe('instance', function() { + var methods = [ + 'get', + 'getAll', + 'create', + 'update', + 'delete', + 'deploy', + 'test', + 'getVersions', + 'getVersion', + 'createVersion', + 'deployVersion', + 'getAllTriggers', + 'testTrigger', + 'getTriggerBindings', + 'updateTriggerBindings' + ]; + + methods.forEach(function(method) { + it('should have a ' + method + ' method', function() { + expect(this.actions[method]).to.exist.to.be.an.instanceOf(Function); + }); + }); + }); + + describe('#constructor', function() { + it('should error when no options are provided', function() { + expect(ActionsManager).to.throw(ArgumentError, 'Must provide client options'); + }); + + it('should throw an error when no base URL is provided', function() { + var client = ActionsManager.bind(null, {}); + + expect(client).to.throw(ArgumentError, 'Must provide a base URL for the API'); + }); + + it('should throw an error when the base URL is invalid', function() { + var client = ActionsManager.bind(null, { baseUrl: '' }); + + expect(client).to.throw(ArgumentError, 'The provided base URL is invalid'); + }); + }); + + describe('#actions', () => { + describe('#getAll', function() { + beforeEach(function() { + this.request = nock(API_URL) + .get('/actions/actions') + .reply(200); + }); + + it('should accept a callback', function(done) { + this.actions.getAll(function() { + done(); + }); + }); + + it('should return a promise if no callback is given', function(done) { + this.actions + .getAll() + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/actions/actions') + .reply(500); + + this.actions.getAll().catch(function(err) { + expect(err).to.exist; + done(); + }); + }); + + it('should pass the body of the response to the "then" handler', function(done) { + nock.cleanAll(); + + var data = [{ test: true }]; + var request = nock(API_URL) + .get('/actions/actions') + .reply(200, data); + + this.actions.getAll().then(function(credentials) { + expect(credentials).to.be.an.instanceOf(Array); + + expect(credentials.length).to.equal(data.length); + + expect(credentials[0].test).to.equal(data[0].test); + + done(); + }); + }); + + it('should perform a GET request', function(done) { + var request = this.request; + + this.actions.getAll().then(function() { + expect(request.isDone()).to.be.true; + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/actions/actions') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.actions.getAll().then(function() { + expect(request.isDone()).to.be.true; + done(); + }); + }); + + it('should pass the parameters in the query-string', function(done) { + nock.cleanAll(); + + var params = { + include_fields: true, + fields: 'test' + }; + var request = nock(API_URL) + .get('/actions/actions') + .query(params) + .reply(200); + + this.actions.getAll(params).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#get', function() { + beforeEach(function() { + this.data = { + id: '0d565aa1-d8ce-4802-83e7-82e3d2040222', + name: 'Test Action', + supported_triggers: [ + { + id: 'post-login', + version: 'v1' + } + ], + required_configuration: [], + required_secrets: [], + created_at: '2020-07-29T19:45:15.725999098Z', + updated_at: '2020-07-29T19:45:15.725999098Z' + }; + + this.request = nock(API_URL) + .get('/actions/actions/' + this.data.id) + .reply(200, this.data); + }); + + it('should accept a callback', function(done) { + var params = { action_id: this.data.id }; + + this.actions.get(params, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.actions + .get({ action_id: this.data.id }) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a GET request', function(done) { + var request = this.request; + + this.actions.get({ action_id: this.data.id }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/actions/actions' + this.data.id) + .reply(500); + + this.actions.get({ action_id: this.data.id }).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/actions/actions/' + this.data.id) + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.actions.get({ action_id: this.data.id }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#create', function() { + var data = { + name: 'my-action-13', + supported_triggers: [ + { + id: 'post-login', + version: 'v1' + } + ] + }; + + beforeEach(function() { + this.request = nock(API_URL) + .post('/actions/actions') + .reply(201); + }); + + it('should accept a callback', function(done) { + this.actions.create(data, function() { + done(); + }); + }); + + it('should return a promise if no callback is given', function(done) { + this.actions + .create(data) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .post('/actions/actions/') + .reply(500); + + this.actions.create(data).catch(function(err) { + expect(err).to.exist; + done(); + }); + }); + + it('should perform a POST request', function(done) { + var request = this.request; + + this.actions.create(data).then(function() { + expect(request.isDone()).to.be.true; + done(); + }); + }); + + it('should pass the data in the body of the request', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .post('/actions/actions', data) + .reply(200); + + this.actions.create(data).then(function() { + expect(request.isDone()).to.be.true; + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .post('/actions/actions') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.actions.create(data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#update', function() { + beforeEach(function() { + this.data = { action_id: 'ACTION_ID' }; + + this.request = nock(API_URL) + .patch('/actions/actions/' + this.data.action_id, { name: 'my-new-action-name' }) + .reply(200, this.data); + }); + + it('should accept a callback', function(done) { + this.actions.update( + { action_id: 'ACTION_ID' }, + { name: 'my-new-action-name' }, + done.bind(null, null) + ); + }); + + it('should return a promise if no callback is given', function(done) { + this.actions + .update({ action_id: 'ACTION_ID' }, { name: 'my-new-action-name' }) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a PATCH request', function(done) { + var request = this.request; + + this.actions + .update({ action_id: 'ACTION_ID' }, { name: 'my-new-action-name' }) + .then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should include the new data in the body of the request', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .patch('/actions/actions/' + this.data.action_id, { name: 'my-new-action-name' }) + .reply(200); + + this.actions + .update({ action_id: 'ACTION_ID' }, { name: 'my-new-action-name' }) + .then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .patch('/actions/actions/' + this.data.id) + .reply(500); + + this.actions + .update({ action_id: this.data.id }, { name: 'my-new-action-name' }) + .catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + }); + + describe('#deploy', function() { + var action_id = 'action-id-1'; + + beforeEach(function() { + this.request = nock(API_URL) + .post('/actions/actions/' + action_id + '/deploy') + .reply(200); + }); + + it('should accept a callback', function(done) { + this.actions.deploy({ action_id }, done.bind(null, null)); + }); + + it('should return a promise when no callback is given', function(done) { + this.actions.deploy({ action_id }).then(done.bind(null, null)); + }); + + it('should perform a post request' + action_id, function(done) { + var request = this.request; + + this.actions.deploy({ action_id }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .post('/actions/actions/' + action_id + '/deploy') + .reply(500); + + this.actions.deploy({ action_id }).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .post('/actions/actions/' + action_id + '/deploy') + .matchHeader('authorization', 'Bearer ' + this.token) + .reply(200); + + this.actions.deploy({ action_id }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#test', function() { + var action_id = 'action-id-1'; + const payload = { event: {} }; + + beforeEach(function() { + this.request = nock(API_URL) + .post('/actions/actions/' + action_id + '/test') + .reply(200); + }); + + it('should accept a callback', function(done) { + this.actions.test({ action_id }, { payload }, done.bind(null, null)); + }); + + it('should return a promise when no callback is given', function(done) { + this.actions.test({ action_id }, { payload }).then(done.bind(null, null)); + }); + + it('should perform a post request' + action_id, function(done) { + var request = this.request; + + this.actions.test({ action_id }, { payload }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .post('/actions/actions/' + action_id + '/test') + .reply(500); + + this.actions.test({ action_id }, { payload }).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .post('/actions/actions/' + action_id + '/test') + .matchHeader('authorization', 'Bearer ' + this.token) + .reply(200); + + this.actions.test({ action_id }, { payload }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#delete', function() { + var action_id = 'action-id-1'; + + beforeEach(function() { + this.request = nock(API_URL) + .delete('/actions/actions/' + action_id) + .reply(200); + }); + + it('should accept a callback', function(done) { + this.actions.delete({ action_id }, done.bind(null, null)); + }); + + it('should return a promise when no callback is given', function(done) { + this.actions.delete({ action_id }).then(done.bind(null, null)); + }); + + it('should perform a delete request' + action_id, function(done) { + var request = this.request; + + this.actions.delete({ action_id }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .delete('/actions/actions/' + action_id) + .reply(500); + + this.actions.delete({ action_id }).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .delete('/actions/actions/' + action_id) + .matchHeader('authorization', 'Bearer ' + this.token) + .reply(200); + + this.actions.delete({ action_id }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + }); + + describe('action versions', function() { + describe('#getVersions', function() { + beforeEach(function() { + nock.cleanAll(); + + this.data = { + id: '0d565aa1-d8ce-4802-83e7-82e3d2040222' + }; + + this.request = nock(API_URL) + .get('/actions/actions/' + this.data.id + '/versions') + .reply(200, this.data); + }); + + it('should accept a callback', function(done) { + var params = { action_id: this.data.id }; + + this.actions.getVersions(params, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.actions + .get({ action_id: this.data.id }) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a GET request', function(done) { + var request = this.request; + + this.actions.getVersions({ action_id: this.data.id }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/actions/actions/' + this.data.id + '/versions') + .reply(500); + + this.actions.getVersions({ action_id: this.data.id }).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/actions/actions/' + this.data.id + '/versions') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.actions.getVersions({ action_id: this.data.id }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#getVersion', function() { + beforeEach(function() { + nock.cleanAll(); + + this.data = { + id: '0d565aa1-d8ce-4802-83e7-82e3d2040222', + versionId: '7asd8sd9-d8ce-4802-83e7-82e3d2040222' + }; + + this.request = nock(API_URL) + .get('/actions/actions/' + this.data.id + '/versions/' + this.data.versionId) + .reply(200, this.data); + }); + + it('should accept a callback', function(done) { + var params = { action_id: this.data.id, version_id: this.data.versionId }; + + this.actions.getVersion(params, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.actions + .get({ action_id: this.data.id, version_id: this.data.versionId }) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a GET request', function(done) { + var request = this.request; + + this.actions + .getVersion({ action_id: this.data.id, version_id: this.data.versionId }) + .then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/actions/actions/' + this.data.id + '/versions/' + this.data.versionId) + .reply(500); + + this.actions + .getVersion({ action_id: this.data.id, version_id: this.data.versionId }) + .catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/actions/actions/' + this.data.id + '/versions/' + this.data.versionId) + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.actions + .getVersion({ action_id: this.data.id, version_id: this.data.versionId }) + .then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#createVersion', function() { + beforeEach(function() { + nock.cleanAll(); + + this.data = { + id: '0d565aa1-d8ce-4802-83e7-82e3d2040222' + }; + + this.request = nock(API_URL) + .post('/actions/actions/' + this.data.id + '/versions') + .reply(200, this.data); + }); + + it('should accept a callback', function(done) { + var params = { action_id: this.data.id }; + + this.actions.createVersion(params, this.data, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.actions + .createVersion({ action_id: this.data.id }, {}) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a POST request', function(done) { + var request = this.request; + + this.actions.createVersion({ action_id: this.data.id }, {}).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .post('/actions/actions/' + this.data.id + '/versions') + .reply(500); + + this.actions.createVersion({ action_id: this.data.id }, {}).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .post('/actions/actions/' + this.data.id + '/versions') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.actions.createVersion({ action_id: this.data.id }, {}).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#deployVersion', function() { + var action_id = 'action-id-1'; + var version_id = 'action-version-id-1'; + + beforeEach(function() { + this.request = nock(API_URL) + .post('/actions/actions/' + action_id + '/versions/' + version_id + '/deploy') + .reply(200); + }); + + it('should accept a callback', function(done) { + this.actions.deployVersion({ action_id, version_id }, done.bind(null, null)); + }); + + it('should return a promise when no callback is given', function(done) { + this.actions.deployVersion({ action_id, version_id }).then(done.bind(null, null)); + }); + + it('should perform a post request', function(done) { + var request = this.request; + + this.actions.deployVersion({ action_id, version_id }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .post('/actions/actions/' + action_id + '/versions/' + version_id + '/deploy') + .reply(500); + + this.actions.deployVersion({ action_id, version_id }).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .post('/actions/actions/' + action_id + '/deploy') + .matchHeader('authorization', 'Bearer ' + this.token) + .reply(200); + + this.actions.deploy({ action_id }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + }); + + describe('executions', function() { + describe('#getExecution', function() { + beforeEach(function() { + this.data = { + id: '0d565aa1-d8ce-4802-83e7', + name: 'Execution' + }; + + this.request = nock(API_URL) + .get('/actions/executions/' + this.data.id) + .reply(200); + }); + + it('should accept a callback', function(done) { + var params = { execution_id: this.data.id }; + + this.actions.getExecution(params, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.actions + .getExecution({ execution_id: this.data.id }) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a GET request', function(done) { + var request = this.request; + + this.actions + .getExecution({ execution_id: this.data.id }) + .then(function() { + expect(request.isDone()).to.be.true; + + done(); + }) + .catch(function(err) { + console.log(err); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/actions/executions/' + this.data.id) + .reply(500); + + this.actions.getExecution({ execution_id: this.data.id }).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/actions/executions/' + this.data.id) + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.actions.getExecution({ execution_id: this.data.id }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + }); + + describe('triggers', () => { + const params = { per_page: 2 }; + describe('#getAllTriggers', function() { + beforeEach(function() { + this.request = nock(API_URL) + .get('/actions/triggers') + .reply(200); + }); + + it('should accept a callback', function(done) { + this.actions.getAllTriggers(params, function() { + done(); + }); + }); + + it('should return a promise if no callback is given', function(done) { + this.actions + .getAllTriggers() + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/actions/triggers') + .reply(500); + + this.actions.getAllTriggers().catch(function(err) { + expect(err).to.exist; + done(); + }); + }); + + it('should pass the body of the response to the "then" handler', function(done) { + nock.cleanAll(); + + var data = [{ trigger1: 'rigger1' }]; + var request = nock(API_URL) + .get('/actions/triggers') + .reply(200, data); + + this.actions.getAllTriggers().then(function(triggers) { + expect(triggers).to.be.an.instanceOf(Array); + + expect(triggers.length).to.equal(data.length); + + expect(triggers[0].trigger1).to.equal(data[0].trigger1); + + done(); + }); + }); + + it('should perform a GET request', function(done) { + var request = this.request; + + this.actions.getAllTriggers().then(function() { + expect(request.isDone()).to.be.true; + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/actions/triggers') + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.actions.getAllTriggers().then(function() { + expect(request.isDone()).to.be.true; + done(); + }); + }); + + it('should pass the parameters in the query-string', function(done) { + nock.cleanAll(); + + var params = { + include_fields: true, + fields: 'test' + }; + var request = nock(API_URL) + .get('/actions/triggers') + .query(params) + .reply(200); + + this.actions.getAllTriggers(params).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#testTrigger', function() { + const params = { trigger_id: 'post-login' }; + const data = { + payload: { + user_info: 'userInfo' + } + }; + + beforeEach(function() { + this.request = nock(API_URL) + .post('/actions/triggers/' + params.trigger_id + '/test', data) + .reply(200); + }); + + it('should accept a callback', function(done) { + this.actions.testTrigger(params, data, function() { + done(); + }); + }); + + it('should return a promise if no callback is given', function(done) { + this.actions + .testTrigger(params, data) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .post('/actions/triggers/' + params.trigger_id + '/test', data) + .reply(500); + + this.actions.testTrigger(params, data).catch(function(err) { + expect(err).to.exist; + done(); + }); + }); + + it('should perform a POST request', function(done) { + var request = this.request; + + this.actions.testTrigger(params, data).then(function() { + expect(request.isDone()).to.be.true; + done(); + }); + }); + + it('should pass the data in the body of the request', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .post('/actions/triggers/' + params.trigger_id + '/test', data) + .reply(200); + + this.actions.testTrigger(params, data).then(function() { + expect(request.isDone()).to.be.true; + done(); + }); + }); + + it('should include the token in the Authorization header', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .post('/actions/triggers/' + params.trigger_id + '/test', data) + .matchHeader('Authorization', 'Bearer ' + this.token) + .reply(200); + + this.actions.testTrigger(params, data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + }); + + describe('#updateTriggerBindings', function() { + const trigger_id = 'post-login'; + + beforeEach(function() { + this.data = { bindings: [] }; + + this.request = nock(API_URL) + .patch('/actions/triggers/' + trigger_id + '/bindings') + .reply(200, this.data); + }); + + it('should accept a callback', function(done) { + this.actions.updateTriggerBindings({ trigger_id }, this.data, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.actions + .updateTriggerBindings({ trigger_id }, this.data) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a PATCH request', function(done) { + var request = this.request; + + this.actions.updateTriggerBindings({ trigger_id }, this.data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should include the new data in the body of the request', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .patch('/actions/triggers/' + trigger_id + '/bindings') + .reply(200); + + this.actions.updateTriggerBindings({ trigger_id }, this.data).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .patch('/actions/triggers/' + trigger_id + '/bindings') + .reply(500); + + this.actions.updateTriggerBindings({ trigger_id }, this.data).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + }); + + describe('#getTriggerBindings', function() { + const trigger_id = 'post-login'; + + beforeEach(function() { + this.data = { bindings: {} }; + + this.request = nock(API_URL) + .get('/actions/triggers/' + trigger_id + '/bindings') + .reply(200, this.data); + }); + + it('should accept a callback', function(done) { + this.actions.getTriggerBindings({ trigger_id }, done.bind(null, null)); + }); + + it('should return a promise if no callback is given', function(done) { + this.actions + .getTriggerBindings({ trigger_id }) + .then(done.bind(null, null)) + .catch(done.bind(null, null)); + }); + + it('should perform a GET request', function(done) { + var request = this.request; + + this.actions.getTriggerBindings({ trigger_id }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should include the new data in the body of the request', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .get('/actions/triggers/' + trigger_id + '/bindings') + .reply(200); + + this.actions.getTriggerBindings({ trigger_id }).then(function() { + expect(request.isDone()).to.be.true; + + done(); + }); + }); + + it('should pass any errors to the promise catch handler', function(done) { + nock.cleanAll(); + + var request = nock(API_URL) + .patch('/actions/triggers/' + trigger_id + '/bindings') + .reply(500); + + this.actions.getTriggerBindings({ trigger_id }).catch(function(err) { + expect(err).to.exist; + + done(); + }); + }); + }); + }); +});