transactionThresholdModal.spec.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import {OrganizationFixture} from 'sentry-fixture/organization';
  2. import {ProjectFixture} from 'sentry-fixture/project';
  3. import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  4. import selectEvent from 'sentry-test/selectEvent';
  5. import {
  6. makeClosableHeader,
  7. makeCloseButton,
  8. ModalBody,
  9. ModalFooter,
  10. } from 'sentry/components/globalModal/components';
  11. import ProjectsStore from 'sentry/stores/projectsStore';
  12. import type {Organization as TOrganization} from 'sentry/types';
  13. import EventView from 'sentry/utils/discover/eventView';
  14. import TransactionThresholdModal, {
  15. TransactionThresholdMetric,
  16. } from 'sentry/views/performance/transactionSummary/transactionThresholdModal';
  17. function mountModal(
  18. eventView: EventView,
  19. organization: TOrganization,
  20. onApply: React.ComponentProps<typeof TransactionThresholdModal>['onApply']
  21. ) {
  22. render(
  23. <TransactionThresholdModal
  24. Body={ModalBody}
  25. closeModal={jest.fn()}
  26. CloseButton={makeCloseButton(jest.fn())}
  27. Header={makeClosableHeader(jest.fn())}
  28. Footer={ModalFooter}
  29. eventView={eventView}
  30. organization={organization}
  31. transactionName="transaction/threshold"
  32. transactionThreshold={400}
  33. transactionThresholdMetric={TransactionThresholdMetric.LARGEST_CONTENTFUL_PAINT}
  34. onApply={onApply}
  35. />
  36. );
  37. }
  38. describe('TransactionThresholdModal', function () {
  39. const organization = OrganizationFixture({features: ['performance-view']});
  40. const project = ProjectFixture();
  41. const eventView = EventView.fromSavedQuery({
  42. id: '1',
  43. version: 2,
  44. name: 'my query',
  45. fields: ['count()'],
  46. orderby: '-count',
  47. query: '',
  48. projects: [parseInt(project.id, 10)],
  49. start: '2019-10-01T00:00:00',
  50. end: '2019-10-02T00:00:00',
  51. environment: [],
  52. });
  53. const onApply = jest.fn();
  54. let postTransactionThresholdMock;
  55. beforeEach(function () {
  56. MockApiClient.clearMockResponses();
  57. ProjectsStore.loadInitialData([project]);
  58. postTransactionThresholdMock = MockApiClient.addMockResponse({
  59. url: '/organizations/org-slug/project-transaction-threshold-override/',
  60. method: 'POST',
  61. body: {
  62. data: [],
  63. },
  64. });
  65. });
  66. it('can update threshold', async function () {
  67. mountModal(eventView, organization, onApply);
  68. await userEvent.clear(await screen.findByRole('spinbutton'));
  69. await userEvent.type(screen.getByRole('spinbutton'), '1000{enter}');
  70. await userEvent.click(screen.getByTestId('apply-threshold'));
  71. await waitFor(() => {
  72. expect(postTransactionThresholdMock).toHaveBeenCalledWith(
  73. '/organizations/org-slug/project-transaction-threshold-override/',
  74. expect.objectContaining({
  75. data: {metric: 'lcp', threshold: '1000', transaction: 'transaction/threshold'},
  76. })
  77. );
  78. });
  79. });
  80. it('can update metric', async function () {
  81. mountModal(eventView, organization, onApply);
  82. await selectEvent.select(
  83. await screen.findByText('Largest Contentful Paint'),
  84. 'Transaction Duration'
  85. );
  86. await userEvent.click(screen.getByTestId('apply-threshold'));
  87. await waitFor(() => {
  88. expect(postTransactionThresholdMock).toHaveBeenCalledWith(
  89. '/organizations/org-slug/project-transaction-threshold-override/',
  90. expect.objectContaining({
  91. data: {
  92. metric: 'duration',
  93. threshold: 400,
  94. transaction: 'transaction/threshold',
  95. },
  96. })
  97. );
  98. });
  99. });
  100. it('can clear metrics', async function () {
  101. mountModal(eventView, organization, onApply);
  102. const deleteTransactionThresholdMock = MockApiClient.addMockResponse({
  103. url: '/organizations/org-slug/project-transaction-threshold-override/',
  104. method: 'DELETE',
  105. });
  106. const getProjectThresholdMock = MockApiClient.addMockResponse({
  107. url: '/projects/org-slug/project-slug/transaction-threshold/configure/',
  108. method: 'GET',
  109. body: {
  110. threshold: '200',
  111. metric: 'duration',
  112. },
  113. });
  114. await userEvent.click(await screen.findByTestId('reset-all'));
  115. expect(deleteTransactionThresholdMock).toHaveBeenCalledTimes(1);
  116. // Replace with project fallback
  117. await waitFor(() => {
  118. expect(getProjectThresholdMock).toHaveBeenCalledTimes(1);
  119. });
  120. });
  121. });