import { COMPOUND_MUTATION_NAME, FORGE_GRAPHQL_SDK_ERROR_SOURCE, INTERNAL_SERVER_ERROR_TYPE, } from '../../helpers'; import { TIER_MISSING_VALUE } from '../../helpers/constants'; import api from '../../index'; import { MOCK_BASE_COMPONENT, MOCK_BASE_COMPONENT_WITHOUT_FIELDS, MOCK_BASE_COMPONENT_WITH_CUSTOM_FIELDS, MOCK_BASE_COMPONENT_WITH_ID, MOCK_BASE_GET_COMPONENT_WITH_CUSTOM_FIELDS_WITH_ID, MOCK_CLOUD_ID, MOCK_COMPLEX_COMPONENT, MOCK_COMPONENT_ID, MOCK_COMPONENT_TYPE_ID, MOCK_COMPONENT_WITH_DATA_MANAGER, MOCK_EXTERNAL_ALIAS, MOCK_GET_BASE_COMPONENT_WITH_EXTERNAL_ALIAS, MOCK_GET_COMPONENT_WITH_DATA_MANAGER, MOCK_GQL_ERROR, MOCK_MUTATION_ERROR, } from '../fixtures/mocks'; import { findCall } from './helpers/matchGql'; import './helpers/mockRequestAtlassian'; import { mockCreateBaseComponent, mockCreateExternalAlias, mockDeleteComponent, mockGetComponent, mockRequestGraph, mockUpdateDataManager, } from './helpers/requestMocks'; const compassApp = api.compass.asApp(); const getComponentSpy = jest.spyOn(compassApp, 'getComponent'); const createBaseComponentSpy = jest.spyOn(compassApp, 'createBaseComponent'); const createExternalAliasSpy = jest.spyOn(compassApp, 'createExternalAlias'); const deleteComponentSpy = jest.spyOn(compassApp, 'deleteComponent'); const updateDataManagerSpy = jest.spyOn(compassApp, 'updateDataManager'); // @ts-ignore const requestGraphSpy = jest.spyOn(compassApp.api, 'requestGraph'); describe('createComponent', () => { beforeEach(() => { jest.resetAllMocks(); jest.spyOn(global.Math, 'random').mockReturnValue(0.0000000001); }); describe('Creation of base component', () => { test('successfully creates a pending component', async () => { mockCreateBaseComponent(createBaseComponentSpy); mockGetComponent(getComponentSpy); const createComponentResp = await compassApp.createComponent({ cloudId: MOCK_CLOUD_ID, ...MOCK_BASE_COMPONENT, }); expect(createBaseComponentSpy).toMatchSnapshot(); expect(createExternalAliasSpy).not.toHaveBeenCalled(); expect(deleteComponentSpy).not.toHaveBeenCalled(); expect(requestGraphSpy).not.toBeCalled(); expect(updateDataManagerSpy).not.toHaveBeenCalled(); expect(getComponentSpy).toHaveBeenCalledWith({ componentId: MOCK_COMPONENT_ID, }); console.log(createComponentResp); expect(createComponentResp).toEqual({ errors: [], success: true, data: { component: MOCK_BASE_COMPONENT_WITH_ID }, }); }); test('successfully creates component from yaml and includes analytic header', async () => { mockCreateBaseComponent(createBaseComponentSpy); mockGetComponent(getComponentSpy); const createComponentResp = await compassApp.createComponent({ cloudId: MOCK_CLOUD_ID, ...MOCK_BASE_COMPONENT, options: { createdFromFile: true, }, }); expect(createBaseComponentSpy.mock.calls[0]).toMatchSnapshot(); expect(createComponentResp).toEqual({ errors: [], success: true, data: { component: MOCK_BASE_COMPONENT_WITH_ID }, }); }); test('successfully creates component with custom fields', async () => { mockCreateBaseComponent(createBaseComponentSpy); mockGetComponent( getComponentSpy, MOCK_BASE_GET_COMPONENT_WITH_CUSTOM_FIELDS_WITH_ID, ); const createComponentResp = await compassApp.createComponent({ cloudId: MOCK_CLOUD_ID, ...MOCK_BASE_COMPONENT_WITH_CUSTOM_FIELDS, }); expect(createBaseComponentSpy).toMatchSnapshot(); expect(createExternalAliasSpy).not.toHaveBeenCalled(); expect(deleteComponentSpy).not.toHaveBeenCalled(); expect(requestGraphSpy).not.toBeCalled(); expect(updateDataManagerSpy).not.toHaveBeenCalled(); expect(getComponentSpy).toHaveBeenCalledWith({ componentId: MOCK_COMPONENT_ID, }); expect(createComponentResp).toEqual({ errors: [], success: true, data: { component: MOCK_BASE_GET_COMPONENT_WITH_CUSTOM_FIELDS_WITH_ID, }, }); }); test('successfully creates component with external alias specified', async () => { mockCreateBaseComponent(createBaseComponentSpy); mockCreateExternalAlias(createExternalAliasSpy); mockGetComponent( getComponentSpy, MOCK_GET_BASE_COMPONENT_WITH_EXTERNAL_ALIAS, ); const createComponentResp = await compassApp.createComponent({ cloudId: MOCK_CLOUD_ID, externalAlias: { ...MOCK_EXTERNAL_ALIAS, }, ...MOCK_BASE_COMPONENT, }); expect(createBaseComponentSpy).toMatchSnapshot(); expect(createExternalAliasSpy).toMatchSnapshot(); expect(deleteComponentSpy).not.toHaveBeenCalled(); expect(createComponentResp).toEqual({ errors: [], success: true, data: { component: MOCK_GET_BASE_COMPONENT_WITH_EXTERNAL_ALIAS }, }); }); test('does not add fields to createBaseComponent input if none specified', async () => { mockCreateBaseComponent(createBaseComponentSpy); mockCreateExternalAlias(createExternalAliasSpy); mockGetComponent(getComponentSpy, { id: MOCK_COMPONENT_ID, typeId: MOCK_COMPONENT_TYPE_ID, ...MOCK_BASE_COMPONENT_WITHOUT_FIELDS, }); const createComponentResp = await compassApp.createComponent({ cloudId: MOCK_CLOUD_ID, ...MOCK_BASE_COMPONENT_WITHOUT_FIELDS, }); expect(createBaseComponentSpy).toMatchSnapshot(); expect(createExternalAliasSpy).not.toHaveBeenCalled(); expect(deleteComponentSpy).not.toHaveBeenCalled(); expect(createComponentResp).toEqual({ errors: [], success: true, data: { component: { id: MOCK_COMPONENT_ID, typeId: MOCK_COMPONENT_TYPE_ID, ...MOCK_BASE_COMPONENT_WITHOUT_FIELDS, }, }, }); }); test('rolls back creation of component if external alias could not be created', async () => { const createExternalAliasErrorMsg = 'Could not create external alias for component'; mockCreateBaseComponent(createBaseComponentSpy); mockCreateExternalAlias(createExternalAliasSpy, [ { message: createExternalAliasErrorMsg }, ]); mockDeleteComponent(deleteComponentSpy); mockGetComponent(getComponentSpy); const createComponentResp = await compassApp.createComponent({ cloudId: MOCK_CLOUD_ID, ...MOCK_BASE_COMPONENT, externalAlias: { ...MOCK_EXTERNAL_ALIAS, }, }); expect(createBaseComponentSpy).toMatchSnapshot(); expect(createExternalAliasSpy).toMatchSnapshot(); expect(deleteComponentSpy).toMatchSnapshot(); expect(createComponentResp).toEqual({ errors: [{ message: createExternalAliasErrorMsg }], success: false, data: { component: MOCK_BASE_COMPONENT_WITH_ID }, }); }); test('fails to create base component', async () => { const createBaseComponentErrorMsg = 'Could not create component'; mockCreateBaseComponent(createBaseComponentSpy, [ { message: createBaseComponentErrorMsg }, ]); const createComponentResp = await compassApp.createComponent({ cloudId: MOCK_CLOUD_ID, ...MOCK_COMPLEX_COMPONENT, }); expect(createExternalAliasSpy).not.toBeCalled(); expect(deleteComponentSpy).not.toBeCalled(); expect(requestGraphSpy).not.toBeCalled(); expect(getComponentSpy).not.toBeCalled(); expect(createComponentResp).toEqual({ errors: [{ message: createBaseComponentErrorMsg }], success: false, data: { component: {} }, }); }); }); describe('Generates segments to add properties to base component', () => { test('Adds data manager, links, relationships, and labels', async () => { mockCreateBaseComponent(createBaseComponentSpy); mockRequestGraph(requestGraphSpy); mockUpdateDataManager(updateDataManagerSpy); mockGetComponent(getComponentSpy); const createComponentResp = await compassApp.createComponent({ cloudId: MOCK_CLOUD_ID, ...MOCK_COMPONENT_WITH_DATA_MANAGER, }); expect(createBaseComponentSpy).toMatchSnapshot(); expect(createExternalAliasSpy).toMatchSnapshot(); expect(deleteComponentSpy).not.toHaveBeenCalled(); expect( findCall(requestGraphSpy, COMPOUND_MUTATION_NAME), ).toMatchSnapshot(); expect(updateDataManagerSpy).toMatchSnapshot(); expect(createComponentResp).toEqual({ errors: [], success: true, data: { component: MOCK_BASE_COMPONENT_WITH_ID }, }); }); test('Fails when making AGG request', async () => { mockCreateBaseComponent(createBaseComponentSpy); mockRequestGraph(requestGraphSpy, [MOCK_GQL_ERROR]); mockGetComponent(getComponentSpy); const createComponentResp = await compassApp.createComponent({ cloudId: MOCK_CLOUD_ID, ...MOCK_COMPLEX_COMPONENT, }); expect(createComponentResp).toMatchSnapshot(); }); test('Fails on one segment', async () => { mockCreateBaseComponent(createBaseComponentSpy); mockRequestGraph(requestGraphSpy, [], { compass: { createComponentLink_1: { errors: [MOCK_MUTATION_ERROR], }, }, } as any); mockGetComponent(getComponentSpy); const createComponentResp = await compassApp.createComponent({ cloudId: MOCK_CLOUD_ID, ...MOCK_COMPLEX_COMPONENT, }); expect(createComponentResp).toMatchSnapshot(); }); }); test('Fails in multiple requests', async () => { mockCreateBaseComponent(createBaseComponentSpy); mockRequestGraph(requestGraphSpy, [MOCK_GQL_ERROR]); mockUpdateDataManager(updateDataManagerSpy, [MOCK_GQL_ERROR]); mockGetComponent(getComponentSpy); const createComponentResp = await compassApp.createComponent({ cloudId: MOCK_CLOUD_ID, ...MOCK_COMPONENT_WITH_DATA_MANAGER, }); expect(createComponentResp).toMatchSnapshot(); }); test('Returns error when trying to make a component with empty tier', async () => { mockCreateBaseComponent(createBaseComponentSpy); mockRequestGraph(requestGraphSpy); mockGetComponent(getComponentSpy, MOCK_BASE_COMPONENT_WITH_ID); const createComponentResp = await compassApp.createComponent({ cloudId: MOCK_CLOUD_ID, ...MOCK_BASE_COMPONENT_WITH_ID, fields: { tier: [] }, }); expect(createComponentResp).toEqual({ errors: [TIER_MISSING_VALUE], success: false, data: { component: {} }, }); }); test('Returns error when trying to make a component with undefined tier', async () => { mockCreateBaseComponent(createBaseComponentSpy); mockRequestGraph(requestGraphSpy); mockGetComponent(getComponentSpy, MOCK_BASE_COMPONENT_WITH_ID); const createComponentResp = await compassApp.createComponent({ cloudId: MOCK_CLOUD_ID, ...MOCK_BASE_COMPONENT_WITH_ID, fields: { tier: undefined }, }); expect(createComponentResp).toEqual({ errors: [TIER_MISSING_VALUE], success: false, data: { component: {} }, }); }); test('Updates data manager with errors if it exists', async () => { const requestGraphErrorMessage = 'id is not a valid ARI'; mockCreateBaseComponent(createBaseComponentSpy); mockUpdateDataManager(updateDataManagerSpy); mockRequestGraph(requestGraphSpy, [ { message: requestGraphErrorMessage, }, ]); mockGetComponent(getComponentSpy, MOCK_GET_COMPONENT_WITH_DATA_MANAGER); const createComponentResp = await compassApp.createComponent({ cloudId: MOCK_CLOUD_ID, ...MOCK_COMPONENT_WITH_DATA_MANAGER, }); expect(updateDataManagerSpy).toMatchSnapshot(); expect(createComponentResp).toEqual({ errors: [ { message: requestGraphErrorMessage, errorType: INTERNAL_SERVER_ERROR_TYPE, errorSource: FORGE_GRAPHQL_SDK_ERROR_SOURCE, }, ], success: false, data: { component: MOCK_GET_COMPONENT_WITH_DATA_MANAGER }, }); }); });