dataExport.spec.jsx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import {act, fireEvent, render, screen, waitFor} from 'sentry-test/reactTestingLibrary';
  2. import {addErrorMessage} from 'sentry/actionCreators/indicator';
  3. import WrappedDataExport from 'sentry/components/dataExport';
  4. jest.mock('sentry/actionCreators/indicator');
  5. const mockUnauthorizedOrg = TestStubs.Organization({
  6. features: [],
  7. });
  8. const mockAuthorizedOrg = TestStubs.Organization({
  9. features: ['discover-query'],
  10. });
  11. const mockPayload = {
  12. queryType: 'Issues-by-Tag',
  13. queryInfo: {project_id: '1', group_id: '1027', key: 'user'},
  14. };
  15. const mockRouterContext = mockOrganization =>
  16. TestStubs.routerContext([
  17. {
  18. organization: mockOrganization,
  19. },
  20. ]);
  21. describe('DataExport', function () {
  22. it('should not render anything for an unauthorized organization', function () {
  23. render(<WrappedDataExport payload={mockPayload} />, {
  24. context: mockRouterContext(mockUnauthorizedOrg),
  25. });
  26. expect(screen.queryByRole('button')).not.toBeInTheDocument();
  27. });
  28. it('should render the button for an authorized organization', function () {
  29. render(<WrappedDataExport payload={mockPayload} />, {
  30. context: mockRouterContext(mockAuthorizedOrg),
  31. });
  32. expect(screen.getByText(/Export All to CSV/)).toBeInTheDocument();
  33. });
  34. it('should render custom children if provided', function () {
  35. render(
  36. <WrappedDataExport payload={mockPayload}>
  37. This is an example string
  38. </WrappedDataExport>,
  39. {context: mockRouterContext(mockAuthorizedOrg)}
  40. );
  41. expect(screen.getByText(/This is an example string/)).toBeInTheDocument();
  42. });
  43. it('should respect the disabled prop and not be clickable', function () {
  44. const postDataExport = MockApiClient.addMockResponse({
  45. url: `/organizations/${mockAuthorizedOrg.slug}/data-export/`,
  46. method: 'POST',
  47. body: {id: 721},
  48. });
  49. render(<WrappedDataExport payload={mockPayload} disabled />, {
  50. context: mockRouterContext(mockAuthorizedOrg),
  51. });
  52. fireEvent.click(screen.getByRole('button'));
  53. expect(postDataExport).not.toHaveBeenCalled();
  54. expect(screen.getByRole('button')).toBeDisabled();
  55. });
  56. it('should send a request and disable itself when clicked', async function () {
  57. const postDataExport = MockApiClient.addMockResponse({
  58. url: `/organizations/${mockAuthorizedOrg.slug}/data-export/`,
  59. method: 'POST',
  60. body: {id: 721},
  61. });
  62. render(<WrappedDataExport payload={mockPayload} />, {
  63. context: mockRouterContext(mockAuthorizedOrg),
  64. });
  65. act(() => {
  66. fireEvent.click(screen.getByRole('button'));
  67. });
  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. act(() => {
  94. fireEvent.click(screen.getByText(/Export All to CSV/));
  95. });
  96. await waitFor(() => {
  97. expect(screen.getByRole('button')).toBeDisabled();
  98. });
  99. rerender(<WrappedDataExport payload={{...mockPayload, queryType: 'Discover'}} />);
  100. await waitFor(() => {
  101. expect(screen.getByRole('button')).toBeEnabled();
  102. });
  103. });
  104. it('should display default error message if non provided', async function () {
  105. MockApiClient.addMockResponse({
  106. url: `/organizations/${mockAuthorizedOrg.slug}/data-export/`,
  107. method: 'POST',
  108. statusCode: 400,
  109. });
  110. render(<WrappedDataExport payload={mockPayload} />, {
  111. context: mockRouterContext(mockAuthorizedOrg),
  112. });
  113. act(() => {
  114. fireEvent.click(screen.getByRole('button'));
  115. });
  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. act(() => {
  136. fireEvent.click(screen.getByRole('button'));
  137. });
  138. await waitFor(() => {
  139. expect(addErrorMessage).toHaveBeenCalledWith('uh oh');
  140. });
  141. });
  142. });