dataExport.spec.jsx 5.1 KB

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