dataExport.spec.jsx 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import {Organization} from 'fixtures/js-stubs/organization';
  2. import {routerContext} from 'fixtures/js-stubs/routerContext';
  3. import {act, fireEvent, render, screen, waitFor} from 'sentry-test/reactTestingLibrary';
  4. import {addErrorMessage} from 'sentry/actionCreators/indicator';
  5. import WrappedDataExport from 'sentry/components/dataExport';
  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: 'Issues-by-Tag',
  15. queryInfo: {project_id: '1', group_id: '1027', key: 'user'},
  16. };
  17. const mockRouterContext = mockOrganization =>
  18. 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', 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. fireEvent.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. act(() => {
  68. fireEvent.click(screen.getByRole('button'));
  69. });
  70. expect(postDataExport).toHaveBeenCalledWith(
  71. `/organizations/${mockAuthorizedOrg.slug}/data-export/`,
  72. {
  73. data: {
  74. query_type: mockPayload.queryType,
  75. query_info: mockPayload.queryInfo,
  76. },
  77. method: 'POST',
  78. error: expect.anything(),
  79. success: expect.anything(),
  80. }
  81. );
  82. await waitFor(() => {
  83. expect(screen.getByRole('button')).toBeDisabled();
  84. });
  85. });
  86. it('should reset the state when receiving a new payload', async function () {
  87. MockApiClient.addMockResponse({
  88. url: `/organizations/${mockAuthorizedOrg.slug}/data-export/`,
  89. method: 'POST',
  90. body: {id: 721},
  91. });
  92. const {rerender} = render(<WrappedDataExport payload={mockPayload} />, {
  93. context: mockRouterContext(mockAuthorizedOrg),
  94. });
  95. act(() => {
  96. fireEvent.click(screen.getByText(/Export All to CSV/));
  97. });
  98. await waitFor(() => {
  99. expect(screen.getByRole('button')).toBeDisabled();
  100. });
  101. rerender(<WrappedDataExport payload={{...mockPayload, queryType: 'Discover'}} />);
  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. act(() => {
  116. fireEvent.click(screen.getByRole('button'));
  117. });
  118. await waitFor(() => {
  119. expect(addErrorMessage).toHaveBeenCalledWith(
  120. "We tried our hardest, but we couldn't export your data. Give it another go."
  121. );
  122. });
  123. await waitFor(() => {
  124. expect(screen.getByRole('button')).toBeEnabled();
  125. });
  126. });
  127. it('should display provided error message', async function () {
  128. MockApiClient.addMockResponse({
  129. url: `/organizations/${mockAuthorizedOrg.slug}/data-export/`,
  130. method: 'POST',
  131. statusCode: 400,
  132. body: {detail: 'uh oh'},
  133. });
  134. render(<WrappedDataExport payload={mockPayload} />, {
  135. context: mockRouterContext(mockAuthorizedOrg),
  136. });
  137. act(() => {
  138. fireEvent.click(screen.getByRole('button'));
  139. });
  140. await waitFor(() => {
  141. expect(addErrorMessage).toHaveBeenCalledWith('uh oh');
  142. });
  143. });
  144. });