import {GitHubIntegrationFixture} from 'sentry-fixture/githubIntegration';
import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
import IntegrationExternalMappingForm from './integrationExternalMappingForm';
describe('IntegrationExternalMappingForm', function () {
const dataEndpoint = '/test/dataEndpoint/';
const baseProps = {
integration: GitHubIntegrationFixture(),
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', async function () {
render();
expect(await screen.findByPlaceholderText('@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();
expect(await screen.findByText('Select Sentry User')).toBeInTheDocument();
expect(screen.queryByPlaceholderText('@username')).not.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(
);
expect(
await screen.findByDisplayValue(MOCK_USER_MAPPING.externalName)
).toBeInTheDocument();
expect(
await screen.findByText(`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(
);
expect(
await screen.findByText(`option${MOCK_USER_MAPPING.userId}`)
).toBeInTheDocument();
expect(
screen.queryByDisplayValue(MOCK_USER_MAPPING.externalName)
).not.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', async function () {
render(
);
expect(
await screen.findByDisplayValue(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', async function () {
render(
);
expect(await screen.findByText('Select Sentry Team')).toBeInTheDocument();
expect(
screen.queryByDisplayValue(MOCK_TEAM_MAPPING.externalName)
).not.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();
await userEvent.type(screen.getByText('Select Sentry User'), 'option2');
await userEvent.click(screen.getAllByText('option2')[1]);
await userEvent.click(screen.getByTestId('form-submit'));
await waitFor(() => {
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(
);
expect(await screen.findByText('option1')).toBeInTheDocument();
expect(baseProps.getBaseFormEndpoint).not.toHaveBeenCalled();
expect(putResponse).not.toHaveBeenCalled();
await userEvent.type(screen.getByRole('textbox'), 'option3');
expect(await screen.findAllByText('option3')).toHaveLength(2);
await userEvent.click(screen.getAllByText('option3')[1]);
await waitFor(() => {
expect(baseProps.getBaseFormEndpoint).toHaveBeenCalledWith({
...MOCK_TEAM_MAPPING,
integrationId: baseProps.integration.id,
provider: baseProps.integration.provider.name.toLowerCase(),
// From option3 selection
teamId: '3',
});
});
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(await screen.findByText('option1')).toBeInTheDocument();
expect(sentryNameField).toBeInTheDocument();
expect(getResponse).not.toHaveBeenCalled();
// Now that the user types, query for results
await userEvent.type(sentryNameField, 'option2');
await userEvent.click(screen.getAllByText('option2')[1]);
await waitFor(() => expect(getResponse).toHaveBeenCalled());
});
});