setupMessagingIntegrationButton.spec.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import {GitHubIntegrationProviderFixture} from 'sentry-fixture/githubIntegrationProvider';
  2. import {OrganizationFixture} from 'sentry-fixture/organization';
  3. import {ProjectFixture} from 'sentry-fixture/project';
  4. import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  5. import {openModal} from 'sentry/actionCreators/modal';
  6. import HookStore from 'sentry/stores/hookStore';
  7. import SetupMessagingIntegrationButton, {
  8. MessagingIntegrationAnalyticsView,
  9. } from 'sentry/views/alerts/rules/issue/setupMessagingIntegrationButton';
  10. jest.mock('sentry/actionCreators/modal');
  11. describe('SetupAlertIntegrationButton', function () {
  12. const organization = OrganizationFixture();
  13. const project = ProjectFixture();
  14. const providers = (providerKey: string) => [
  15. GitHubIntegrationProviderFixture({key: providerKey}),
  16. ];
  17. const providerKeys = ['slack', 'discord', 'msteams'];
  18. let mockResponses: jest.Mock<any>[] = [];
  19. const getComponent = () => (
  20. <SetupMessagingIntegrationButton
  21. projectId={project.id}
  22. refetchConfigs={jest.fn()}
  23. analyticsParams={{view: MessagingIntegrationAnalyticsView.ALERT_RULE_CREATION}}
  24. />
  25. );
  26. beforeEach(function () {
  27. MockApiClient.clearMockResponses();
  28. mockResponses = [];
  29. providerKeys.forEach(providerKey => {
  30. mockResponses.push(
  31. MockApiClient.addMockResponse({
  32. url: `/organizations/${organization.slug}/config/integrations/?provider_key=${providerKey}`,
  33. body: {providers: providers(providerKey)},
  34. })
  35. );
  36. });
  37. });
  38. it('renders when no integration is installed', async function () {
  39. mockResponses.push(
  40. MockApiClient.addMockResponse({
  41. url: `/organizations/${organization.slug}/integrations/?integrationType=messaging`,
  42. body: [{status: 'disabled'}, {status: 'disabled'}, {status: 'disabled'}],
  43. })
  44. );
  45. render(getComponent(), {organization: organization});
  46. mockResponses.forEach(mock => {
  47. expect(mock).toHaveBeenCalled();
  48. });
  49. await screen.findByRole('button', {name: /connect to messaging/i});
  50. });
  51. it('does not render button if alert integration installed', function () {
  52. mockResponses.push(
  53. MockApiClient.addMockResponse({
  54. url: `/organizations/${organization.slug}/integrations/?integrationType=messaging`,
  55. body: [{status: 'active'}, {status: 'disabled'}, {status: 'disabled'}],
  56. })
  57. );
  58. render(getComponent(), {organization: organization});
  59. mockResponses.forEach(mock => {
  60. expect(mock).toHaveBeenCalled();
  61. });
  62. expect(screen.queryByRole('button')).not.toBeInTheDocument();
  63. });
  64. it('opens modal when clicked', async function () {
  65. mockResponses.push(
  66. MockApiClient.addMockResponse({
  67. url: `/organizations/${organization.slug}/integrations/?integrationType=messaging`,
  68. body: [{status: 'disabled'}, {status: 'disabled'}, {status: 'disabled'}],
  69. })
  70. );
  71. render(getComponent(), {organization: organization});
  72. mockResponses.forEach(mock => {
  73. expect(mock).toHaveBeenCalled();
  74. });
  75. const button = await screen.findByRole('button', {name: /connect to messaging/i});
  76. await userEvent.click(button);
  77. expect(openModal).toHaveBeenCalled();
  78. });
  79. it('does not render button if API errors', function () {
  80. mockResponses.push(
  81. MockApiClient.addMockResponse({
  82. url: `/organizations/${organization.slug}/integrations/?integrationType=messaging`,
  83. statusCode: 400,
  84. body: {error: 'internal error'},
  85. })
  86. );
  87. render(getComponent(), {organization: organization});
  88. expect(screen.queryByRole('button')).not.toBeInTheDocument();
  89. });
  90. it('disables button if user does not have integration feature', async function () {
  91. mockResponses.push(
  92. MockApiClient.addMockResponse({
  93. url: `/organizations/${organization.slug}/integrations/?integrationType=messaging`,
  94. body: [{status: 'disabled'}, {status: 'disabled'}, {status: 'disabled'}],
  95. })
  96. );
  97. HookStore.add('integrations:feature-gates', () => {
  98. return {
  99. IntegrationFeatures: p =>
  100. p.children({
  101. disabled: true,
  102. disabledReason: 'some reason',
  103. ungatedFeatures: p.features,
  104. gatedFeatureGroups: [],
  105. }),
  106. FeatureList: p => (p.provider = providers[0]),
  107. };
  108. });
  109. render(getComponent(), {organization: organization});
  110. mockResponses.forEach(mock => {
  111. expect(mock).toHaveBeenCalled();
  112. });
  113. await screen.findByRole('button', {name: /connect to messaging/i});
  114. expect(screen.getByRole('button')).toBeDisabled();
  115. });
  116. });