issueAlertOptions.spec.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import selectEvent from 'react-select-event';
  2. import {
  3. MOCK_RESP_INCONSISTENT_INTERVALS,
  4. MOCK_RESP_INCONSISTENT_PLACEHOLDERS,
  5. MOCK_RESP_ONLY_IGNORED_CONDITIONS_INVALID,
  6. MOCK_RESP_VERBOSE,
  7. } from 'sentry-fixture/ruleConditions';
  8. import {initializeOrg} from 'sentry-test/initializeOrg';
  9. import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
  10. import IssueAlertOptions from 'sentry/views/projectInstall/issueAlertOptions';
  11. describe('IssueAlertOptions', function () {
  12. const {organization} = initializeOrg();
  13. const URL = `/projects/${organization.slug}/rule-conditions/`;
  14. const props = {
  15. onChange: jest.fn(),
  16. };
  17. beforeEach(() => {
  18. MockApiClient.addMockResponse({
  19. url: `/projects/${organization.slug}/rule-conditions/`,
  20. body: MOCK_RESP_VERBOSE,
  21. });
  22. });
  23. afterEach(() => {
  24. MockApiClient.clearMockResponses();
  25. jest.clearAllMocks();
  26. });
  27. it('should render only the `Default Rule` and `Create Later` option on empty response:[]', () => {
  28. MockApiClient.addMockResponse({
  29. url: URL,
  30. body: [],
  31. });
  32. render(<IssueAlertOptions {...props} />, {organization});
  33. expect(screen.getAllByRole('radio')).toHaveLength(2);
  34. });
  35. it('should render only the `Default Rule` and `Create Later` option on empty response:{}', () => {
  36. MockApiClient.addMockResponse({
  37. url: URL,
  38. body: {},
  39. });
  40. render(<IssueAlertOptions {...props} />, {organization});
  41. expect(screen.getAllByRole('radio')).toHaveLength(2);
  42. });
  43. it('should render only the `Default Rule` and `Create Later` option on responses with different allowable intervals', () => {
  44. MockApiClient.addMockResponse({
  45. url: URL,
  46. body: MOCK_RESP_INCONSISTENT_INTERVALS,
  47. });
  48. render(<IssueAlertOptions {...props} />, {organization});
  49. expect(screen.getAllByRole('radio')).toHaveLength(2);
  50. });
  51. it('should render all(three) options on responses with different placeholder values', () => {
  52. MockApiClient.addMockResponse({
  53. url: URL,
  54. body: MOCK_RESP_INCONSISTENT_PLACEHOLDERS,
  55. });
  56. render(<IssueAlertOptions {...props} />, {organization});
  57. expect(screen.getAllByRole('radio')).toHaveLength(3);
  58. });
  59. it('should ignore conditions that are not `sentry.rules.conditions.event_frequency.EventFrequencyCondition` and `sentry.rules.conditions.event_frequency.EventUniqueUserFrequencyCondition`', async () => {
  60. MockApiClient.addMockResponse({
  61. url: URL,
  62. body: MOCK_RESP_ONLY_IGNORED_CONDITIONS_INVALID,
  63. });
  64. render(<IssueAlertOptions {...props} />, {organization});
  65. expect(screen.getAllByRole('radio')).toHaveLength(3);
  66. await selectEvent.select(screen.getByText('Select...'), 'users affected by');
  67. expect(props.onChange).toHaveBeenCalledWith(
  68. expect.objectContaining({
  69. defaultRules: false,
  70. shouldCreateCustomRule: true,
  71. })
  72. );
  73. });
  74. it('should render all(three) options on a valid response', () => {
  75. MockApiClient.addMockResponse({
  76. url: URL,
  77. body: MOCK_RESP_VERBOSE,
  78. });
  79. render(<IssueAlertOptions {...props} />);
  80. expect(screen.getAllByRole('radio')).toHaveLength(3);
  81. });
  82. it('should pre-populate fields from server response', async () => {
  83. MockApiClient.addMockResponse({
  84. url: URL,
  85. body: MOCK_RESP_VERBOSE,
  86. });
  87. render(<IssueAlertOptions {...props} />);
  88. await selectEvent.select(screen.getByText('occurrences of'), 'users affected by');
  89. await selectEvent.select(screen.getByText('one minute'), '30 days');
  90. expect(props.onChange).toHaveBeenCalledWith(
  91. expect.objectContaining({
  92. defaultRules: false,
  93. shouldCreateCustomRule: true,
  94. })
  95. );
  96. });
  97. it('should pre-fill threshold value after a valid server response', () => {
  98. MockApiClient.addMockResponse({
  99. url: URL,
  100. body: MOCK_RESP_VERBOSE,
  101. });
  102. render(<IssueAlertOptions {...props} />);
  103. expect(screen.getByTestId('range-input')).toHaveValue(10);
  104. });
  105. it('should provide fallthroughType with issue action for issue-alert-fallback-targeting', async () => {
  106. MockApiClient.addMockResponse({
  107. url: URL,
  108. body: MOCK_RESP_VERBOSE,
  109. });
  110. const org = {...organization, features: ['issue-alert-fallback-targeting']};
  111. render(<IssueAlertOptions {...props} organization={org} />);
  112. await userEvent.click(screen.getByLabelText(/When there are more than/i));
  113. expect(props.onChange).toHaveBeenCalledWith(
  114. expect.objectContaining({
  115. actions: [
  116. {
  117. id: 'sentry.mail.actions.NotifyEmailAction',
  118. targetType: 'IssueOwners',
  119. fallthroughType: 'ActiveMembers',
  120. },
  121. ],
  122. })
  123. );
  124. });
  125. });