indicators.spec.jsx 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. import React from 'react';
  2. import {ThemeProvider} from 'emotion-theming';
  3. import {mount} from 'enzyme';
  4. import theme from 'app/utils/theme';
  5. import Indicators from 'app/components/indicators';
  6. import IndicatorStore from 'app/stores/indicatorStore';
  7. import {
  8. clear,
  9. addSuccessMessage,
  10. addErrorMessage,
  11. addMessage,
  12. } from 'app/actionCreators/indicator';
  13. // Make sure we use `duration: null` to test add/remove
  14. jest.useFakeTimers();
  15. describe('Indicators', function() {
  16. let wrapper;
  17. beforeEach(function() {
  18. wrapper = mount(
  19. <ThemeProvider theme={theme}>
  20. <Indicators />
  21. </ThemeProvider>
  22. );
  23. clear();
  24. jest.runAllTimers();
  25. });
  26. it('renders nothing by default', function() {
  27. expect(wrapper.find('ToastIndicator')).toHaveLength(0);
  28. });
  29. it('has a loading indicator by default', function() {
  30. // when "type" is empty, we should treat it as loading state
  31. IndicatorStore.add('Loading');
  32. wrapper.update();
  33. expect(wrapper.find('ToastIndicator')).toHaveLength(1);
  34. });
  35. it('adds and removes a toast by calling IndicatorStore directly', function() {
  36. // when "type" is empty, we should treat it as loading state
  37. let indicator = IndicatorStore.add('Loading');
  38. wrapper.update();
  39. expect(wrapper.find('ToastIndicator')).toHaveLength(1);
  40. expect(wrapper.find('Message').text()).toBe('Loading');
  41. jest.runAllTimers();
  42. wrapper.update();
  43. expect(wrapper.find('ToastIndicator')).toHaveLength(1);
  44. // Old indicator gets replaced when a new one is added
  45. IndicatorStore.remove(indicator);
  46. jest.runAllTimers();
  47. wrapper.update();
  48. expect(wrapper.find('ToastIndicator')).toHaveLength(0);
  49. });
  50. // This is a common pattern used throughout the code for API calls
  51. it('adds and replaces toast by calling IndicatorStore directly', function() {
  52. IndicatorStore.add('Loading');
  53. wrapper.update();
  54. expect(wrapper.find('ToastIndicator')).toHaveLength(1);
  55. expect(wrapper.find('Message').text()).toBe('Loading');
  56. // Old indicator gets replaced when a new one is added
  57. IndicatorStore.add('success', 'success');
  58. jest.runAllTimers();
  59. wrapper.update();
  60. expect(wrapper.find('ToastIndicator')).toHaveLength(1);
  61. expect(wrapper.find('Message').text()).toBe('success');
  62. });
  63. it('does not have loading indicator when "type" is empty (default)', function() {
  64. addMessage('Loading', '', {duration: null});
  65. jest.runAllTimers();
  66. wrapper.update();
  67. expect(wrapper.find('LoadingIndicator')).toHaveLength(0);
  68. });
  69. it('has a loading indicator when type is "loading"', function() {
  70. addMessage('Loading', 'loading', {duration: null});
  71. jest.runAllTimers();
  72. wrapper.update();
  73. expect(wrapper.find('LoadingIndicator')).toHaveLength(1);
  74. });
  75. it('adds and removes toast by calling action creators', function() {
  76. // action creators don't return anything
  77. addMessage('Loading', '', {duration: null});
  78. jest.runAllTimers();
  79. wrapper.update();
  80. expect(wrapper.find('ToastIndicator')).toHaveLength(1);
  81. expect(wrapper.find('Message').text()).toBe('Loading');
  82. // If no indicator is specified, will remove all indicators
  83. clear();
  84. jest.runAllTimers();
  85. wrapper.update();
  86. expect(wrapper.find('ToastIndicator')).toHaveLength(0);
  87. });
  88. it('adds and replaces toast by calling action creators', function() {
  89. addMessage('Loading', '', {duration: null});
  90. jest.runAllTimers();
  91. wrapper.update();
  92. expect(wrapper.find('ToastIndicator')).toHaveLength(1);
  93. expect(wrapper.find('Message').text()).toBe('Loading');
  94. // Old indicator gets replaced when a new one is added
  95. addMessage('success', 'success', {duration: null});
  96. jest.runAllTimers();
  97. wrapper.update();
  98. expect(wrapper.find('ToastIndicator')).toHaveLength(1);
  99. expect(wrapper.find('Message').text()).toBe('success');
  100. });
  101. it('adds and replaces toasts by calling action creators helpers', function() {
  102. // Old indicator gets replaced when a new one is added
  103. addSuccessMessage('success', null);
  104. jest.runAllTimers();
  105. wrapper.update();
  106. expect(wrapper.find('ToastIndicator')).toHaveLength(1);
  107. expect(wrapper.find('Message').text()).toBe('success');
  108. clear();
  109. addErrorMessage('error', null);
  110. jest.runAllTimers();
  111. wrapper.update();
  112. expect(wrapper.find('ToastIndicator')).toHaveLength(1);
  113. expect(wrapper.find('Message').text()).toBe('error');
  114. });
  115. it('appends toasts', function() {
  116. addMessage('Loading', '', {append: true, duration: null});
  117. jest.runAllTimers();
  118. wrapper.update();
  119. expect(wrapper.find('ToastIndicator')).toHaveLength(1);
  120. expect(wrapper.find('Message').text()).toBe('Loading');
  121. addMessage('Success', 'success', {append: true, duration: null});
  122. jest.runAllTimers();
  123. wrapper.update();
  124. expect(wrapper.find('ToastIndicator')).toHaveLength(2);
  125. // Toasts get appended to the end
  126. expect(
  127. wrapper
  128. .find('Message')
  129. .at(1)
  130. .text()
  131. ).toBe('Success');
  132. addMessage('Error', 'error', {append: true, duration: null});
  133. jest.runAllTimers();
  134. wrapper.update();
  135. expect(wrapper.find('ToastIndicator')).toHaveLength(3);
  136. // Toasts get appended to the end
  137. expect(
  138. wrapper
  139. .find('Message')
  140. .at(2)
  141. .text()
  142. ).toBe('Error');
  143. // clears all toasts
  144. clear();
  145. jest.runAllTimers();
  146. wrapper.update();
  147. expect(wrapper.find('ToastIndicator')).toHaveLength(0);
  148. });
  149. it('dismisses on click', function() {
  150. addMessage('Loading', '', {append: true, duration: null});
  151. jest.runAllTimers();
  152. wrapper.update();
  153. expect(wrapper.find('ToastIndicator')).toHaveLength(1);
  154. expect(wrapper.find('Message').text()).toBe('Loading');
  155. wrapper.find('ToastIndicator').simulate('click');
  156. jest.runAllTimers();
  157. wrapper.update();
  158. expect(wrapper.find('ToastIndicator')).toHaveLength(0);
  159. });
  160. it('hides after 10s', function() {
  161. addMessage('Duration', '', {append: true, duration: 10000});
  162. jest.advanceTimersByTime(9000);
  163. wrapper.update();
  164. expect(wrapper.find('Indicators')).toHaveLength(1);
  165. expect(wrapper.find('Indicators').prop('items')).toHaveLength(1);
  166. expect(wrapper.find('Message').text()).toBe('Duration');
  167. // Still visible
  168. jest.advanceTimersByTime(999);
  169. wrapper.update();
  170. expect(wrapper.find('Indicators').prop('items')).toHaveLength(1);
  171. // ToastIndicator still exist because of animations
  172. // but `items` prop should be empty
  173. jest.advanceTimersByTime(2);
  174. wrapper.update();
  175. expect(wrapper.find('Indicators').prop('items')).toHaveLength(0);
  176. // After animation timeout
  177. jest.advanceTimersByTime(1000);
  178. wrapper.update();
  179. expect(wrapper.find('ToastIndicator')).toHaveLength(0);
  180. });
  181. });