@unito/integration-cli
Version:
Integration CLI
364 lines (363 loc) • 21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const test_1 = require("@oclif/test");
const sinon_1 = tslib_1.__importDefault(require("sinon"));
const ngrok_1 = tslib_1.__importDefault(require("@ngrok/ngrok"));
const child_process_1 = tslib_1.__importDefault(require("child_process"));
const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
const GlobalConfiguration = tslib_1.__importStar(require("../../src/resources/globalConfiguration"));
const IntegrationsPlatform = tslib_1.__importStar(require("../../src/services/integrationsPlatform"));
const IntegrationResource = tslib_1.__importStar(require("../../src/resources/integrations"));
const IntegrationConfiguration = tslib_1.__importStar(require("../../src/resources/configuration"));
const errors_1 = require("../../src/errors");
const FileSystem = tslib_1.__importStar(require("../../src/resources/fileSystem"));
const integrations_1 = require("../helpers/integrations");
const styles_1 = require("../helpers/styles");
describe('Publish', () => {
const integration = (0, integrations_1.generateIntegration)();
beforeEach(() => {
sinon_1.default.stub(IntegrationResource, 'validateIsIntegrationDirectory');
sinon_1.default.stub(IntegrationsPlatform, 'setEnvironment');
sinon_1.default.stub(IntegrationsPlatform, 'setApiKey');
sinon_1.default.stub(IntegrationsPlatform, 'publishIntegration');
sinon_1.default.stub(IntegrationsPlatform, 'reencryptData').resolves({ encryptedData: 'newEncryptedSecret' });
sinon_1.default.stub(ngrok_1.default, 'forward');
sinon_1.default.stub(child_process_1.default, 'spawn');
sinon_1.default.stub(IntegrationsPlatform, 'getProfile').resolves({
id: 1,
createdAt: '',
updatedAt: '',
archivedAt: null,
email: 'foo@bar.com',
defaultUnitoOrganizationId: null,
role: 'developer',
apiKey: 'foo',
termsAcceptedAt: null,
});
});
afterEach(() => {
sinon_1.default.restore();
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'a' }))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish'])
.it('publish the integration - default', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('published');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'a' }))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish', '--config-path', '/custom-config.json'])
.it('publish the integration with custom config - default', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('published');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKeyLocal: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'a' }))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish', '--environment', 'local'])
.it('publish the integration - local', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('published');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKeyLocal: 'foo' }))
.stub(IntegrationConfiguration, 'getConfigurationPath', stub => stub.returns('/.unito.local.json'))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'a' }))
.stub(IntegrationConfiguration, 'writeConfiguration', stub => stub.resolves())
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish', '--environment', 'local'])
.it('publish the integration using .unito.local.json - local', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('published');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKeyStaging: 'foo' }))
.stub(IntegrationConfiguration, 'getConfigurationPath', stub => stub.returns('/.unito.json'))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'a' }))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish', '--environment', 'staging'])
.it('publish the integration - staging', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('published');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKeyStaging: 'foo' }))
.stub(IntegrationConfiguration, 'getConfigurationPath', stub => stub.returns('/.unito.staging.json'))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({}))
.stub(IntegrationConfiguration, 'writeConfiguration', stub => stub.resolves())
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish', '--environment', 'staging'])
.it('publish the integration using .unito.staging.json - staging', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('published');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfigurationPath', stub => stub.returns('/.unito.json'))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'a' }))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish', '--config-path', '/my-awesome-config.json'])
.it('publish the integration using custom configuration', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('published');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({}))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.stub(inquirer_1.default, 'prompt', stub => stub.resolves({ proceed: false }))
.command(['publish', '--registry-only'])
.it('aborts on user negative input', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('🙊 Abort! You are safe now 🍸 relax');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({}))
.stub(IntegrationsPlatform, 'getIntegration', stub => stub.returns(undefined))
.stub(IntegrationsPlatform, 'createIntegration', stub => stub.resolves(integration))
.stub(IntegrationsPlatform, 'updateIntegration', stub => stub.resolves(integration))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.stub(inquirer_1.default, 'prompt', stub => stub.resolves({ proceed: false }))
.command(['publish', '--registry-only', '--force'])
.it('bypass user confirmation with --force is active', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('created');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({}))
.stub(IntegrationsPlatform, 'getIntegration', stub => stub.returns(undefined))
.stub(IntegrationsPlatform, 'createIntegration', stub => stub.resolves(integration))
.stub(IntegrationsPlatform, 'updateIntegration', stub => stub.resolves(integration))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.stub(inquirer_1.default, 'prompt', stub => stub.resolves({ proceed: true }))
.command(['publish', '--registry-only'])
.it('creates the integration in the registry', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('created');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'a' }))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns({ name: 'a' }))
.stub(IntegrationsPlatform, 'createIntegration', stub => stub.resolves(integration))
.stub(IntegrationsPlatform, 'updateIntegration', stub => stub.resolves(integration))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.stub(inquirer_1.default, 'prompt', stub => stub.resolves({ proceed: true }))
.command(['publish', '--registry-only'])
.it('updates the integration in the registry', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('updated');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({
authorizations: [{ type: 'custom', development: true }, { type: 'oauth2' }],
}))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(IntegrationsPlatform, 'createIntegration', stub => stub.resolves(integration))
.stub(IntegrationsPlatform, 'updateIntegration', stub => stub.resolves(integration))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.stub(inquirer_1.default, 'prompt', stub => stub.resolves({ proceed: true }))
.command(['publish', '--registry-only'])
.it('filters out "development" authorizations', ctx => {
ctx.sandbox.assert.calledOnceWithMatch(
// @ts-expect-error syntax accepted by sinon.
IntegrationsPlatform.createIntegration, {
authorizations: [
{
type: 'oauth2',
instructionsImage: 'data:image/png;base64,',
instructionsMarkdown: '',
},
],
});
// @ts-expect-error syntax accepted by sinon.
ctx.sandbox.assert.notCalled(IntegrationsPlatform.updateIntegration);
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'foo' }))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(IntegrationsPlatform, 'createIntegration', stub => stub.resolves(integration))
.stub(IntegrationsPlatform, 'updateIntegration', stub => stub.resolves(integration))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish', '--preview'])
.it('preview the integration', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('published');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ name: 'foo', ui: { displayName: 'Foo' } }))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(IntegrationConfiguration, 'writeConfiguration', stub => stub.returns(integration))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish', '--preview'])
.it('preview the integration - override the display name', ctx => {
(0, test_1.expect)((0, styles_1.uncolorize)(ctx.stdout)).to.contain('foo-preview-9c88 is being published');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({}))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(IntegrationsPlatform, 'createIntegration', stub => stub.resolves(integration))
.stub(IntegrationsPlatform, 'updateIntegration', stub => stub.resolves(integration))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish', '--live-preview'])
.it('live-preview the integration', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('created');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({ ui: { displayName: 'Foo' } }))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(IntegrationsPlatform, 'createIntegration', stub => stub.resolves(integration))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish', '--live-preview'])
.it('live-preview the integration - override the display name', ctx => {
ctx.sandbox.assert.calledOnceWithMatch(
// @ts-expect-error syntax accepted by sinon.
IntegrationsPlatform.createIntegration, {
ui: { displayName: 'Foo - Live Preview - 9c88' },
name: 'undefined-live-preview-9c88',
baseUrl: undefined,
});
});
test_1.test
.stdout()
.stderr()
.stub(GlobalConfiguration, 'read', stub => stub.returns({}))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({}))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish'])
.exit(-1)
.it('missing api key', ctx => {
(0, test_1.expect)(ctx.stderr).to.contain('Your API key is not set!\nMake sure to run the login command first');
});
test_1.test
.stdout()
.stderr()
.stub(GlobalConfiguration, 'read', stub => stub.throws(new errors_1.NoConfigurationFileError()))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish'])
.exit(-1)
.it('handles exception');
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({
name: 'myIntegration',
authorizations: [{ name: 'oauth2', oauth2: { clientSecret: 'unito-secret-' } }],
secrets: { secret1: 'unito-secret-', invalidSecret: 'Should never happen anyway' },
}))
.stub(IntegrationConfiguration, 'writeConfiguration', stub => stub.returns({
name: 'myIntegration',
authorizations: [{ name: 'oauth2', oauth2: { clientSecret: 'unito-secret-' } }],
secrets: { secret1: 'unito-secret-', invalidSecret: 'Should never happen anyway' },
}))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish', '--preview'])
.it('reencrypts the clientSecret on preview', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('Reencrypting oauth2:clientSecret');
(0, test_1.expect)(ctx.stdout).to.contain('Reencrypting secrets:secret1');
(0, test_1.expect)(ctx.stdout).to.contain('Skipping secrets:invalidSecret');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({
name: 'myIntegration',
authorizations: [{ name: 'oauth2', oauth2: { clientSecret: 'unito-secret-' } }],
secrets: { secret1: 'unito-secret-', invalidSecret: 'Should never happen anyway' },
}))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(IntegrationsPlatform, 'createIntegration', stub => stub.resolves(integration))
.stub(IntegrationsPlatform, 'updateIntegration', stub => stub.resolves(integration))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish', '--live-preview'])
.it('reencrypts the clientSecret on live-preview', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('Reencrypting oauth2:clientSecret');
(0, test_1.expect)(ctx.stdout).to.contain('Reencrypting secrets:secret1');
(0, test_1.expect)(ctx.stdout).to.contain('Skipping secrets:invalidSecret');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({
name: 'myIntegration',
authorizations: [{ name: 'oauth2', oauth2: { clientSecret: 'toto' } }],
}))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(IntegrationsPlatform, 'createIntegration', stub => stub.resolves(integration))
.stub(IntegrationsPlatform, 'updateIntegration', stub => stub.resolves(integration))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('')))
.command(['publish', '--live-preview'])
.it('skips reencryption', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('Skipping oauth2:clientSecret');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({
authorizations: [
{
name: 'foo',
method: 'custom',
},
],
}))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(IntegrationsPlatform, 'createIntegration', stub => stub.resolves(integration))
.stub(IntegrationsPlatform, 'updateIntegration', stub => stub.resolves(integration))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(Buffer.from('foo')))
.stub(inquirer_1.default, 'prompt', stub => stub.resolves({ proceed: true }))
.command(['publish', '--registry-only'])
.it('update assets', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('image: <set>');
(0, test_1.expect)(ctx.stdout).to.contain('markdown: <set>');
});
test_1.test
.stdout()
.stub(GlobalConfiguration, 'read', stub => stub.returns({ apiKey: 'foo' }))
.stub(IntegrationConfiguration, 'getConfiguration', stub => stub.returns({
authorizations: [
{
name: 'foo',
method: 'custom',
},
],
}))
.stub(IntegrationsPlatform, 'getIntegrationByName', stub => stub.returns(undefined))
.stub(FileSystem, 'getFileBuffer', stub => stub.resolves(null))
.stub(inquirer_1.default, 'prompt', stub => stub.resolves({ proceed: true }))
.stub(IntegrationsPlatform, 'createIntegration', stub => stub.resolves(integration))
.stub(IntegrationsPlatform, 'updateIntegration', stub => stub.resolves(integration))
.command(['publish', '--registry-only'])
.it('it defaults instructions to null if no file in assets folder', ctx => {
(0, test_1.expect)(ctx.stdout).to.contain('image: <unset>');
(0, test_1.expect)(ctx.stdout).to.contain('markdown: <unset>');
});
});