UNPKG

@unito/integration-cli

Version:

Integration CLI

617 lines (616 loc) 31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const strict_1 = tslib_1.__importDefault(require("node:assert/strict")); const tmp_1 = tslib_1.__importDefault(require("tmp")); const fs_1 = tslib_1.__importDefault(require("fs")); const sinon = tslib_1.__importStar(require("sinon")); const errors_1 = require("../../src/errors"); const Configuration = tslib_1.__importStar(require("../../src/resources/configuration")); const configurationTypes_1 = require("../../src/configurationTypes"); const errors_2 = require("../../src/errors"); const globalConfiguration_1 = require("../../src/resources/globalConfiguration"); describe('configuration', () => { let originalConfiguration; let tempDir; beforeEach(async () => { originalConfiguration = { name: 'my-integration', testAccounts: { development: { accessToken: 'foo', }, }, }; // Create a temporary directory tempDir = tmp_1.default.dirSync({ unsafeCleanup: true }); sinon.stub(process, 'cwd').returns(tempDir.name); // Create the configuration file. await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify(originalConfiguration, null, 2)); }); afterEach(() => { // Remove the temporary file tempDir.removeCallback(); sinon.restore(); }); describe('getConfiguration', () => { it('handles an error', async () => { sinon.stub(fs_1.default.promises, 'readFile').throws(); try { await Configuration.getConfiguration(globalConfiguration_1.Environment.Production); throw Error('Should have thrown NoConfigurationFileError'); } catch (error) { (0, strict_1.default)(error instanceof errors_2.NoConfigurationFileError); } }); it('handles missing specific environment file', async () => { const configuration = await Configuration.getConfiguration(globalConfiguration_1.Environment.Staging); strict_1.default.equal(configuration.name, originalConfiguration.name); }); it('returns existing specific environment file', async () => { await fs_1.default.promises.writeFile(`${process.cwd()}/.unito.${globalConfiguration_1.Environment.Staging}.json`, JSON.stringify({ name: 'foo', }, null, 2)); const configuration = await Configuration.getConfiguration(globalConfiguration_1.Environment.Staging); strict_1.default.equal(configuration.name, 'foo'); }); it('throws on missing custom configuration file', async () => { try { await Configuration.getConfiguration(globalConfiguration_1.Environment.Staging, '/mising-config.json'); throw Error('Should have thrown NoConfigurationFileError'); } catch (error) { (0, strict_1.default)(error instanceof errors_2.NoConfigurationFileError); } }); it('returns existing specific environment file', async () => { await fs_1.default.promises.writeFile(`${process.cwd()}/custom-config.json`, JSON.stringify({ name: 'foo', }, null, 2)); const configuration = await Configuration.getConfiguration(globalConfiguration_1.Environment.Staging, '/custom-config.json'); strict_1.default.equal(configuration.name, 'foo'); }); it('sets default values for "oauth2"', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', authorizations: [ { name: 'bar', method: 'oauth2', oauth2: { clientSecret: 'a', clientId: 'b', authorizationUrl: 'http://c.com', tokenUrl: 'http://d.com', scopes: [], }, }, ], }, null, 2)); const configuration = await Configuration.getConfiguration(globalConfiguration_1.Environment.Production); const oauth2 = configuration.authorizations?.at(0)?.oauth2; strict_1.default.equal(oauth2?.requestContentType, configurationTypes_1.RequestContentType.URL_ENCODED); strict_1.default.equal(oauth2?.responseContentType, configurationTypes_1.RequestContentType.JSON); strict_1.default.equal(oauth2?.grantType, configurationTypes_1.GrantType.AUTHORIZATION_CODE); }); it('accepts password grant for "oauth2"', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', authorizations: [ { name: 'bar', method: 'oauth2', oauth2: { clientSecret: 'a', clientId: 'b', authorizationUrl: 'http://c.com', tokenUrl: 'http://d.com', scopes: [], grantType: configurationTypes_1.GrantType.PASSWORD, }, }, ], }, null, 2)); const configuration = await Configuration.getConfiguration(globalConfiguration_1.Environment.Production); const oauth2 = configuration.authorizations?.at(0)?.oauth2; strict_1.default.equal(oauth2?.grantType, configurationTypes_1.GrantType.PASSWORD); }); it('accepts request parameters for "oauth2"', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', authorizations: [ { name: 'bar', method: 'oauth2', oauth2: { clientSecret: 'a', clientId: 'b', authorizationUrl: 'http://c.com', tokenUrl: 'http://d.com', scopes: [], grantType: configurationTypes_1.GrantType.PASSWORD, tokenRequestParameters: { header: { a: 'yo', }, body: { b: false, }, }, refreshRequestParameters: { body: { c: 1, }, }, }, }, ], }, null, 2)); const configuration = await Configuration.getConfiguration(globalConfiguration_1.Environment.Production); const oauth2 = configuration.authorizations?.at(0)?.oauth2; strict_1.default.deepEqual(oauth2?.tokenRequestParameters, { header: { a: 'yo', }, body: { b: false, }, }); strict_1.default.deepEqual(oauth2?.refreshRequestParameters, { body: { c: 1, }, }); }); describe('validates secrets', () => { it('valid secret', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', secrets: { foo: 'unito-secret-v1://bar', }, }, null, 2)); const configuration = await Configuration.getConfiguration(globalConfiguration_1.Environment.Production); strict_1.default.deepEqual(configuration.secrets, { foo: 'unito-secret-v1://bar' }); }); it('invalid secret - type', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', secrets: { foo: 123, }, }, null, 2)); await strict_1.default.rejects(Configuration.getConfiguration(globalConfiguration_1.Environment.Production), errors_1.ConfigurationInvalid); }); it('invalid secret - pattern', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', secrets: { foo: 'nope', }, }, null, 2)); await strict_1.default.rejects(Configuration.getConfiguration(globalConfiguration_1.Environment.Production), errors_1.ConfigurationInvalid); }); }); describe('validates environment variables', () => { it('valid', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', environmentVariables: { FOO: 'unito-secret-v1://bar', }, }, null, 2)); const configuration = await Configuration.getConfiguration(globalConfiguration_1.Environment.Production); strict_1.default.deepEqual(configuration.environmentVariables, { FOO: 'unito-secret-v1://bar' }); }); it('invalid - type', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', environmentVariables: { FOO: 123, }, }, null, 2)); await strict_1.default.rejects(Configuration.getConfiguration(globalConfiguration_1.Environment.Production), errors_1.ConfigurationInvalid); }); it('invalid - key pattern', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', environmentVariables: { foo: 'nope', }, }, null, 2)); await strict_1.default.rejects(Configuration.getConfiguration(globalConfiguration_1.Environment.Production), errors_1.ConfigurationInvalid); }); }); describe('validates test accounts - custom', () => { it('valid test accounts', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', authorizations: [ { name: 'apiKey', method: 'custom', variables: { apiKey: { type: 'password', required: true, label: 'Insert your Secret Key here', }, displayName: { type: 'string', required: false, label: 'Display Name (optional)', }, email: { type: 'string', required: true, label: 'Your Atlassian/Confluence email address', placeholder: 'myemail@company.com', }, domain: { type: 'string', required: true, label: 'Your Confluence URL', format: 'uri', placeholder: 'https://mycompany.atlassian.net', }, }, }, ], testAccounts: { development: { apiKey: 'xyz', email: 'manualtester+staging@unito.io', domain: 'https://unitomanualtests.atlassian.net', }, compliance: { apiKey: 'xyzw', displayName: 'My Awesome Nickname from first grade', email: 'manualtester+staging@unito.io', domain: 'ftp://unitomanualtests.atlassian.net', }, }, }, null, 2)); const configuration = await Configuration.getConfiguration(globalConfiguration_1.Environment.Production); const developmentKey = configuration.testAccounts?.development?.apiKey; const complianceKey = configuration.testAccounts?.compliance?.apiKey; strict_1.default.equal(developmentKey, 'xyz'); strict_1.default.equal(complianceKey, 'xyzw'); }); it('invalid test accounts', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', authorizations: [ { name: 'apiKey', method: 'custom', variables: { apiKey: { type: 'password', required: true, label: 'Insert your Secret Key here', }, displayName: { type: 'string', required: false, label: 'Display Name (optional)', }, }, }, ], testAccounts: { development: { apiKey: 'xyz', displayName: 'My Awesome Nickname from first grade', email: 'manualtester+staging@unito.io', domain: 'ftp://unitomanualtests.atlassian.net', }, compliance: { APIKEY: 'xyzw', displayName: 'My Awesome Nickname from first grade', email: 'manualtester+staging@unito.io', domain: 'ftp://unitomanualtests.atlassian.net', }, }, }, null, 2)); await strict_1.default.rejects(Configuration.getConfiguration(globalConfiguration_1.Environment.Production), errors_1.ConfigurationInvalid); }); }); describe('validates test accounts - oauth', () => { it('valid test accounts', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', authorizations: [ { name: 'oauth2', method: 'oauth2', development: false, oauth2: { clientSecret: 'xxxxx', clientId: 'xxxxx', authorizationUrl: 'https://api.surveymonkey.com/oauth/authorize', tokenUrl: 'https://api.surveymonkey.com/oauth/token', grantType: 'authorization_code', scopes: [ { name: 'users_read', }, { name: 'surveys_read', }, { name: 'collectors_read', }, { name: 'responses_read', }, { name: 'contacts_read', }, { name: 'responses_read_detail', }, ], requestContentType: 'application/x-www-form-urlencoded', responseContentType: 'application/json', }, variables: { displayName: { type: 'string', required: false, label: 'Display Name (optional)', }, email: { type: 'string', required: true, label: 'Your Atlassian/Confluence email address', placeholder: 'myemail@company.com', }, domain: { type: 'string', required: true, label: 'Your Confluence URL', format: 'uri', placeholder: 'https://mycompany.atlassian.net', }, }, }, ], testAccounts: { development: { accessToken: 'Super_Secret_token', displayName: 'My Awesome Nickname from first grade', email: 'manualtester+staging@unito.io', domain: 'ftp://unitomanualtests.atlassian.net', }, compliance: { accessToken: 'Super_Secret_token_2', email: 'manualtester+staging@unito.io', domain: 'ftp://unitomanualtests.atlassian.net', }, }, }, null, 2)); const configuration = await Configuration.getConfiguration(globalConfiguration_1.Environment.Production); const developmentKey = configuration.testAccounts?.development?.accessToken; const complianceKey = configuration.testAccounts?.compliance?.accessToken; strict_1.default.equal(developmentKey, 'Super_Secret_token'); strict_1.default.equal(complianceKey, 'Super_Secret_token_2'); }); it('invalid test accounts', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', authorizations: [ { name: 'oauth2', method: 'oauth2', development: false, oauth2: { clientSecret: 'xxxxx', clientId: 'xxxxx', authorizationUrl: 'https://api.surveymonkey.com/oauth/authorize', tokenUrl: 'https://api.surveymonkey.com/oauth/token', grantType: 'authorization_code', scopes: [ { name: 'users_read', }, { name: 'surveys_read', }, { name: 'collectors_read', }, { name: 'responses_read', }, { name: 'contacts_read', }, { name: 'responses_read_detail', }, ], requestContentType: 'application/x-www-form-urlencoded', responseContentType: 'application/json', }, }, ], testAccounts: { development: { apiKey: 'xyz', }, compliance: { apiKey: 'xyzw', }, }, }, null, 2)); await strict_1.default.rejects(Configuration.getConfiguration(globalConfiguration_1.Environment.Production), errors_1.ConfigurationInvalid); }); }); describe('validates test accounts - multiple authorization methods', () => { it('valid test accounts', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', authorizations: [ { name: 'apiKey', method: 'custom', variables: { apiKey: { type: 'password', required: true, label: 'Insert your Secret Key here', }, displayName: { type: 'string', required: false, label: 'Display Name (optional)', }, }, }, { name: 'oauth2', method: 'oauth2', development: false, oauth2: { clientSecret: 'xxxxx', clientId: 'xxxxx', authorizationUrl: 'https://api.surveymonkey.com/oauth/authorize', tokenUrl: 'https://api.surveymonkey.com/oauth/token', grantType: 'authorization_code', scopes: [ { name: 'users_read', }, { name: 'surveys_read', }, { name: 'collectors_read', }, { name: 'responses_read', }, { name: 'contacts_read', }, { name: 'responses_read_detail', }, ], requestContentType: 'application/x-www-form-urlencoded', responseContentType: 'application/json', }, variables: { displayName: { type: 'string', required: false, label: 'Display Name (optional)', }, email: { type: 'string', required: true, label: 'Your Atlassian/Confluence email address', placeholder: 'myemail@company.com', }, domain: { type: 'string', required: true, label: 'Your Confluence URL', format: 'uri', placeholder: 'https://mycompany.atlassian.net', }, }, }, ], testAccounts: { development: { accessToken: 'Super_Secret_token', displayName: 'My Awesome Nickname from first grade', email: 'manualtester+staging@unito.io', domain: 'ftp://unitomanualtests.atlassian.net', }, compliance: { apiKey: 'Super_Secret_api_key_2', }, }, }, null, 2)); const configuration = await Configuration.getConfiguration(globalConfiguration_1.Environment.Production); const developmentKey = configuration.testAccounts?.development?.accessToken; const complianceKey = configuration.testAccounts?.compliance?.apiKey; strict_1.default.equal(developmentKey, 'Super_Secret_token'); strict_1.default.equal(complianceKey, 'Super_Secret_api_key_2'); }); it('invalid test accounts', async () => { await fs_1.default.promises.writeFile(Configuration.getConfigurationPath(), JSON.stringify({ name: 'foo', authorizations: [ { name: 'apiKey', method: 'custom', variables: { apiKey: { type: 'password', required: true, label: 'Insert your Secret Key here', }, displayName: { type: 'string', required: false, label: 'Display Name (optional)', }, }, }, { name: 'oauth2', method: 'oauth2', development: false, oauth2: { clientSecret: 'xxxxx', clientId: 'xxxxx', authorizationUrl: 'https://api.surveymonkey.com/oauth/authorize', tokenUrl: 'https://api.surveymonkey.com/oauth/token', grantType: 'authorization_code', scopes: [ { name: 'users_read', }, { name: 'surveys_read', }, { name: 'collectors_read', }, { name: 'responses_read', }, { name: 'contacts_read', }, { name: 'responses_read_detail', }, ], requestContentType: 'application/x-www-form-urlencoded', responseContentType: 'application/json', }, }, ], testAccounts: { development: { accessTokens: 'Super_Secret_token', displayName: 'My Awesome Nickname from first grade', email: 'manualtester+staging@unito.io', domain: 'ftp://unitomanualtests.atlassian.net', }, compliance: { apiKeys: 'Super_Secret_api_key_2', }, }, }, null, 2)); await strict_1.default.rejects(Configuration.getConfiguration(globalConfiguration_1.Environment.Production), errors_1.ConfigurationInvalid); }); }); }); });