dataExport.spec.tsx 5.1 KB

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