dataExport.spec.tsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import {render, screen, userEvent, waitFor} from 'sentry-test/reactTestingLibrary';
  2. import {addErrorMessage} from 'sentry/actionCreators/indicator';
  3. import WrappedDataExport, {ExportQueryType} from 'sentry/components/dataExport';
  4. import {Organization} from 'sentry/types';
  5. jest.mock('sentry/actionCreators/indicator');
  6. const mockUnauthorizedOrg = TestStubs.Organization({
  7. features: [],
  8. });
  9. const mockAuthorizedOrg = TestStubs.Organization({
  10. features: ['discover-query'],
  11. });
  12. const mockPayload = {
  13. queryType: ExportQueryType.ISSUES_BY_TAG,
  14. queryInfo: {project_id: '1', group_id: '1027', key: 'user'},
  15. };
  16. const mockRouterContext = (mockOrganization: Organization) =>
  17. TestStubs.routerContext([
  18. {
  19. organization: mockOrganization,
  20. },
  21. ]);
  22. describe('DataExport', function () {
  23. it('should not render anything for an unauthorized organization', function () {
  24. render(<WrappedDataExport payload={mockPayload} />, {
  25. context: mockRouterContext(mockUnauthorizedOrg),
  26. });
  27. expect(screen.queryByRole('button')).not.toBeInTheDocument();
  28. });
  29. it('should render the button for an authorized organization', function () {
  30. render(<WrappedDataExport payload={mockPayload} />, {
  31. context: mockRouterContext(mockAuthorizedOrg),
  32. });
  33. expect(screen.getByText(/Export All to CSV/)).toBeInTheDocument();
  34. });
  35. it('should render custom children if provided', function () {
  36. render(
  37. <WrappedDataExport payload={mockPayload}>
  38. This is an example string
  39. </WrappedDataExport>,
  40. {context: mockRouterContext(mockAuthorizedOrg)}
  41. );
  42. expect(screen.getByText(/This is an example string/)).toBeInTheDocument();
  43. });
  44. it('should respect the disabled prop and not be clickable', async function () {
  45. const postDataExport = MockApiClient.addMockResponse({
  46. url: `/organizations/${mockAuthorizedOrg.slug}/data-export/`,
  47. method: 'POST',
  48. body: {id: 721},
  49. });
  50. render(<WrappedDataExport payload={mockPayload} disabled />, {
  51. context: mockRouterContext(mockAuthorizedOrg),
  52. });
  53. await userEvent.click(screen.getByRole('button'));
  54. expect(postDataExport).not.toHaveBeenCalled();
  55. expect(screen.getByRole('button')).toBeDisabled();
  56. });
  57. it('should send a request and disable itself when clicked', async function () {
  58. const postDataExport = MockApiClient.addMockResponse({
  59. url: `/organizations/${mockAuthorizedOrg.slug}/data-export/`,
  60. method: 'POST',
  61. body: {id: 721},
  62. });
  63. render(<WrappedDataExport payload={mockPayload} />, {
  64. context: mockRouterContext(mockAuthorizedOrg),
  65. });
  66. await userEvent.click(screen.getByRole('button'));
  67. expect(postDataExport).toHaveBeenCalledWith(
  68. `/organizations/${mockAuthorizedOrg.slug}/data-export/`,
  69. {
  70. data: {
  71. query_type: mockPayload.queryType,
  72. query_info: mockPayload.queryInfo,
  73. },
  74. method: 'POST',
  75. error: expect.anything(),
  76. success: expect.anything(),
  77. }
  78. );
  79. await waitFor(() => {
  80. expect(screen.getByRole('button')).toBeDisabled();
  81. });
  82. });
  83. it('should reset the state when receiving a new payload', async function () {
  84. MockApiClient.addMockResponse({
  85. url: `/organizations/${mockAuthorizedOrg.slug}/data-export/`,
  86. method: 'POST',
  87. body: {id: 721},
  88. });
  89. const {rerender} = render(<WrappedDataExport payload={mockPayload} />, {
  90. context: mockRouterContext(mockAuthorizedOrg),
  91. });
  92. await userEvent.click(screen.getByText(/Export All to CSV/));
  93. await waitFor(() => {
  94. expect(screen.getByRole('button')).toBeDisabled();
  95. });
  96. rerender(
  97. <WrappedDataExport
  98. payload={{...mockPayload, queryType: ExportQueryType.DISCOVER}}
  99. />
  100. );
  101. await waitFor(() => {
  102. expect(screen.getByRole('button')).toBeEnabled();
  103. });
  104. });
  105. it('should display default error message if non provided', async function () {
  106. MockApiClient.addMockResponse({
  107. url: `/organizations/${mockAuthorizedOrg.slug}/data-export/`,
  108. method: 'POST',
  109. statusCode: 400,
  110. });
  111. render(<WrappedDataExport payload={mockPayload} />, {
  112. context: mockRouterContext(mockAuthorizedOrg),
  113. });
  114. await userEvent.click(screen.getByRole('button'));
  115. await waitFor(() => {
  116. expect(addErrorMessage).toHaveBeenCalledWith(
  117. "We tried our hardest, but we couldn't export your data. Give it another go."
  118. );
  119. });
  120. await waitFor(() => {
  121. expect(screen.getByRole('button')).toBeEnabled();
  122. });
  123. });
  124. it('should display provided error message', async function () {
  125. MockApiClient.addMockResponse({
  126. url: `/organizations/${mockAuthorizedOrg.slug}/data-export/`,
  127. method: 'POST',
  128. statusCode: 400,
  129. body: {detail: 'uh oh'},
  130. });
  131. render(<WrappedDataExport payload={mockPayload} />, {
  132. context: mockRouterContext(mockAuthorizedOrg),
  133. });
  134. await userEvent.click(screen.getByRole('button'));
  135. await waitFor(() => {
  136. expect(addErrorMessage).toHaveBeenCalledWith('uh oh');
  137. });
  138. });
  139. });