import {act, render, screen, userEvent} from 'sentry-test/reactTestingLibrary'; import IntegrationExternalMappingForm from 'sentry/components/integrationExternalMappingForm'; describe('IntegrationExternalMappingForm', function () { const dataEndpoint = '/test/dataEndpoint/'; const baseProps = { integration: TestStubs.GitHubIntegration(), dataEndpoint, getBaseFormEndpoint: jest.fn(_mapping => dataEndpoint), sentryNamesMapper: mappings => mappings, }; const MOCK_USER_MAPPING = { id: '1', userId: '1', externalName: '@gwen', sentryName: 'gwen@mcu.org', }; const MOCK_TEAM_MAPPING = { id: '1', teamId: '1', externalName: '@getsentry/animals', sentryName: '#zoo', }; const DEFAULT_OPTIONS = [ {id: '1', name: 'option1'}, {id: '2', name: 'option2'}, {id: '3', name: 'option3'}, ]; let getResponse, postResponse, putResponse; beforeEach(() => { jest.clearAllMocks(); MockApiClient.clearMockResponses(); getResponse = MockApiClient.addMockResponse({ url: dataEndpoint, method: 'GET', body: DEFAULT_OPTIONS, }); postResponse = MockApiClient.addMockResponse({ url: dataEndpoint, method: 'POST', body: {}, }); putResponse = MockApiClient.addMockResponse({ url: `${dataEndpoint}1/`, method: 'PUT', body: {}, }); }); // No mapping provided (e.g. Create a new mapping) it('renders with no mapping provided as a form', function () { render(); expect(screen.getByPlaceholderText('@username')).toBeInTheDocument(); expect(screen.getByText('Select Sentry User')).toBeInTheDocument(); expect(screen.getByTestId('form-submit')).toBeInTheDocument(); }); it('renders with no mapping as an inline field', async function () { render(); await act(tick); expect(screen.queryByPlaceholderText('@username')).not.toBeInTheDocument(); expect(screen.getByText('Select Sentry User')).toBeInTheDocument(); expect(screen.queryByTestId('form-submit')).not.toBeInTheDocument(); }); // Full mapping provided (e.g. Update an existing mapping) it('renders with a full mapping provided as a form', async function () { render( ); await act(tick); expect(screen.getByDisplayValue(MOCK_USER_MAPPING.externalName)).toBeInTheDocument(); expect(screen.getByText(`option${MOCK_USER_MAPPING.userId}`)).toBeInTheDocument(); expect(screen.getByTestId('form-submit')).toBeInTheDocument(); }); it('renders with a full mapping provided as an inline field', async function () { render( ); await act(tick); expect( screen.queryByDisplayValue(MOCK_USER_MAPPING.externalName) ).not.toBeInTheDocument(); expect(screen.getByText(`option${MOCK_USER_MAPPING.userId}`)).toBeInTheDocument(); expect(screen.queryByTestId('form-submit')).not.toBeInTheDocument(); }); // Suggested mapping provided (e.g. Create new mapping from suggested external name) it('renders with a suggested mapping provided as a form', function () { render( ); expect(screen.getByDisplayValue(MOCK_TEAM_MAPPING.externalName)).toBeInTheDocument(); expect(screen.getByText('Select Sentry Team')).toBeInTheDocument(); expect(screen.getByTestId('form-submit')).toBeInTheDocument(); }); it('renders with a suggested mapping provided as an inline field', function () { render( ); expect( screen.queryByDisplayValue(MOCK_TEAM_MAPPING.externalName) ).not.toBeInTheDocument(); expect(screen.getByText('Select Sentry Team')).toBeInTheDocument(); expect(screen.queryByTestId('form-submit')).not.toBeInTheDocument(); }); it('updates the model when submitting', async function () { render( ); expect(baseProps.getBaseFormEndpoint).not.toHaveBeenCalled(); expect(postResponse).not.toHaveBeenCalled(); userEvent.type(screen.getByText('Select Sentry User'), 'option2'); await act(tick); userEvent.click(screen.getAllByText('option2')[1]); userEvent.click(screen.getByTestId('form-submit')); expect(baseProps.getBaseFormEndpoint).toHaveBeenCalledWith({ externalName: MOCK_USER_MAPPING.externalName, integrationId: baseProps.integration.id, provider: baseProps.integration.provider.name.toLowerCase(), // From option2 selection userId: '2', }); expect(postResponse).toHaveBeenCalled(); expect(putResponse).not.toHaveBeenCalled(); }); it('submits on blur when used as an inline field', async function () { render( ); await act(tick); expect(baseProps.getBaseFormEndpoint).not.toHaveBeenCalled(); expect(putResponse).not.toHaveBeenCalled(); userEvent.type(screen.getByRole('textbox'), 'option3'); await act(tick); userEvent.click(screen.getAllByText('option3')[1]); expect(baseProps.getBaseFormEndpoint).toHaveBeenCalledWith({ ...MOCK_TEAM_MAPPING, integrationId: baseProps.integration.id, provider: baseProps.integration.provider.name.toLowerCase(), // From option3 selection teamId: '3', }); await act(tick); expect(putResponse).toHaveBeenCalled(); expect(postResponse).not.toHaveBeenCalled(); }); it('allows defaultOptions to be provided', async function () { render( ({value: id, label: name}))} {...baseProps} /> ); const sentryNameField = screen.getByText(`option${MOCK_USER_MAPPING.userId}`); // Don't query for results on load expect(sentryNameField).toBeInTheDocument(); await act(tick); expect(getResponse).not.toHaveBeenCalled(); // Now that the user types, query for results userEvent.type(sentryNameField, 'option2'); await act(tick); userEvent.click(screen.getAllByText('option2')[1]); expect(getResponse).toHaveBeenCalled(); }); });