react-native-navigation的迁移库

ComponentEventsObserver.test.tsx 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. import * as React from 'react';
  2. import * as renderer from 'react-test-renderer';
  3. import { ComponentEventsObserver } from './ComponentEventsObserver';
  4. import { NativeEventsReceiver } from '../adapters/NativeEventsReceiver.mock';
  5. import { EventSubscription } from '../interfaces/EventSubscription';
  6. import { Store } from '../components/Store';
  7. import { ComponentDidAppearEvent } from '../interfaces/ComponentEvents';
  8. describe('ComponentEventsObserver', () => {
  9. const mockEventsReceiver = new NativeEventsReceiver();
  10. const mockStore = new Store();
  11. const didAppearFn = jest.fn();
  12. const didDisappearFn = jest.fn();
  13. const didMountFn = jest.fn();
  14. const willUnmountFn = jest.fn();
  15. const navigationButtonPressedFn = jest.fn();
  16. const searchBarUpdatedFn = jest.fn();
  17. const searchBarCancelPressedFn = jest.fn();
  18. const previewCompletedFn = jest.fn();
  19. const modalDismissedFn = jest.fn();
  20. const screenPoppedFn = jest.fn();
  21. let subscription: EventSubscription;
  22. let uut: ComponentEventsObserver;
  23. class SimpleScreen extends React.Component<any, any> {
  24. render() {
  25. return 'Hello';
  26. }
  27. }
  28. class UnboundScreen extends React.Component<any, any> {
  29. constructor(props: any) {
  30. super(props);
  31. }
  32. componentDidMount() {
  33. didMountFn();
  34. }
  35. componentWillUnmount() {
  36. willUnmountFn();
  37. }
  38. componentDidAppear() {
  39. didAppearFn();
  40. }
  41. componentDidDisappear() {
  42. didDisappearFn();
  43. }
  44. navigationButtonPressed(event: any) {
  45. navigationButtonPressedFn(event);
  46. }
  47. modalDismissed(event: any) {
  48. modalDismissedFn(event);
  49. }
  50. searchBarUpdated(event: any) {
  51. searchBarUpdatedFn(event);
  52. }
  53. searchBarCancelPressed(event: any) {
  54. searchBarCancelPressedFn(event);
  55. }
  56. previewCompleted(event: any) {
  57. previewCompletedFn(event);
  58. }
  59. screenPopped(event: any) {
  60. screenPoppedFn(event);
  61. }
  62. render() {
  63. return 'Hello';
  64. }
  65. }
  66. class BoundScreen extends React.Component<any, any> {
  67. constructor(props: any) {
  68. super(props);
  69. subscription = uut.bindComponent(this);
  70. }
  71. componentDidMount() {
  72. didMountFn();
  73. }
  74. componentWillUnmount() {
  75. willUnmountFn();
  76. }
  77. componentDidAppear(event: ComponentDidAppearEvent) {
  78. didAppearFn(event);
  79. }
  80. componentDidDisappear() {
  81. didDisappearFn();
  82. }
  83. navigationButtonPressed(event: any) {
  84. navigationButtonPressedFn(event);
  85. }
  86. modalDismissed(event: any) {
  87. modalDismissedFn(event);
  88. }
  89. searchBarUpdated(event: any) {
  90. searchBarUpdatedFn(event);
  91. }
  92. searchBarCancelPressed(event: any) {
  93. searchBarCancelPressedFn(event);
  94. }
  95. previewCompleted(event: any) {
  96. previewCompletedFn(event);
  97. }
  98. screenPopped(event: any) {
  99. screenPoppedFn(event);
  100. }
  101. render() {
  102. return 'Hello';
  103. }
  104. }
  105. beforeEach(() => {
  106. jest.clearAllMocks();
  107. uut = new ComponentEventsObserver(mockEventsReceiver, mockStore);
  108. });
  109. it(`bindComponent expects a component with componentId`, () => {
  110. const tree = renderer.create(<SimpleScreen />);
  111. expect(() => uut.bindComponent(tree.getInstance() as any)).toThrow('');
  112. const tree2 = renderer.create(<SimpleScreen componentId={123} />);
  113. expect(() => uut.bindComponent(tree2.getInstance() as any)).toThrow('');
  114. });
  115. it(`bindComponent accepts an optional componentId`, () => {
  116. const tree = renderer.create(<UnboundScreen />);
  117. uut.bindComponent(tree.getInstance() as any, 'myCompId')
  118. expect(tree.toJSON()).toBeDefined();
  119. expect(didAppearFn).not.toHaveBeenCalled();
  120. uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
  121. expect(didAppearFn).toHaveBeenCalledTimes(1);
  122. });
  123. it(`bindComponent should use optional componentId if component has a componentId in props`, () => {
  124. const tree = renderer.create(<UnboundScreen componentId={'doNotUseThisId'} />);
  125. uut.bindComponent(tree.getInstance() as any, 'myCompId')
  126. expect(tree.toJSON()).toBeDefined();
  127. uut.notifyComponentDidAppear({ componentId: 'dontUseThisId', componentName: 'doesnt matter' });
  128. expect(didAppearFn).not.toHaveBeenCalled();
  129. uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
  130. expect(didAppearFn).toHaveBeenCalledTimes(1);
  131. });
  132. it(`bindComponent notifies listeners by componentId on events`, () => {
  133. const tree = renderer.create(<BoundScreen componentId={'myCompId'} />);
  134. expect(tree.toJSON()).toBeDefined();
  135. expect(didMountFn).toHaveBeenCalledTimes(1);
  136. expect(didAppearFn).not.toHaveBeenCalled();
  137. expect(didDisappearFn).not.toHaveBeenCalled();
  138. expect(willUnmountFn).not.toHaveBeenCalled();
  139. uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
  140. expect(didAppearFn).toHaveBeenCalledTimes(1);
  141. uut.notifyComponentDidDisappear({ componentId: 'myCompId', componentName: 'doesnt matter' });
  142. expect(didDisappearFn).toHaveBeenCalledTimes(1);
  143. uut.notifyNavigationButtonPressed({ componentId: 'myCompId', buttonId: 'myButtonId' });
  144. expect(navigationButtonPressedFn).toHaveBeenCalledTimes(1);
  145. expect(navigationButtonPressedFn).toHaveBeenCalledWith({ buttonId: 'myButtonId', componentId: 'myCompId' });
  146. uut.notifyModalDismissed({ componentId: 'myCompId', modalsDismissed: 1 });
  147. expect(modalDismissedFn).toHaveBeenCalledTimes(1);
  148. expect(modalDismissedFn).toHaveBeenLastCalledWith({ componentId: 'myCompId', modalsDismissed: 1 })
  149. uut.notifySearchBarUpdated({ componentId: 'myCompId', text: 'theText', isFocused: true });
  150. expect(searchBarUpdatedFn).toHaveBeenCalledTimes(1);
  151. expect(searchBarUpdatedFn).toHaveBeenCalledWith({ componentId: 'myCompId', text: 'theText', isFocused: true });
  152. uut.notifySearchBarCancelPressed({ componentId: 'myCompId' });
  153. expect(searchBarCancelPressedFn).toHaveBeenCalledTimes(1);
  154. expect(searchBarCancelPressedFn).toHaveBeenCalledWith({ componentId: 'myCompId' });
  155. uut.notifyPreviewCompleted({ componentId: 'myCompId' });
  156. expect(previewCompletedFn).toHaveBeenCalledTimes(1);
  157. expect(previewCompletedFn).toHaveBeenCalledWith({ componentId: 'myCompId' });
  158. uut.notifyScreenPopped({ componentId: 'myCompId' });
  159. expect(screenPoppedFn).toHaveBeenCalledTimes(1);
  160. expect(screenPoppedFn).toHaveBeenLastCalledWith({ componentId: 'myCompId' })
  161. tree.unmount();
  162. expect(willUnmountFn).toHaveBeenCalledTimes(1);
  163. });
  164. it(`componentDidAppear should receive component props from store`, () => {
  165. const event = {
  166. componentId: 'myCompId',
  167. passProps: {
  168. propA: 'propA'
  169. },
  170. componentName: 'doesnt matter'
  171. }
  172. renderer.create(<BoundScreen componentId={event.componentId} />);
  173. mockStore.updateProps(event.componentId, event.passProps)
  174. expect(didAppearFn).not.toHaveBeenCalled();
  175. uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
  176. expect(didAppearFn).toHaveBeenCalledTimes(1);
  177. expect(didAppearFn).toHaveBeenCalledWith(event);
  178. });
  179. it(`doesnt call other componentIds`, () => {
  180. renderer.create(<BoundScreen componentId={'myCompId'} />);
  181. uut.notifyComponentDidAppear({ componentId: 'other', componentName: 'doesnt matter' });
  182. expect(didAppearFn).not.toHaveBeenCalled();
  183. });
  184. it(`doesnt call unimplemented methods`, () => {
  185. const tree = renderer.create(<SimpleScreen componentId={'myCompId'} />);
  186. expect((tree.getInstance() as any).componentDidAppear).toBeUndefined();
  187. uut.bindComponent(tree.getInstance() as any);
  188. uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
  189. });
  190. it(`returns unregister fn`, () => {
  191. renderer.create(<BoundScreen componentId={'123'} />);
  192. uut.notifyComponentDidAppear({ componentId: '123', componentName: 'doesnt matter' });
  193. expect(didAppearFn).toHaveBeenCalledTimes(1);
  194. subscription.remove();
  195. uut.notifyComponentDidAppear({ componentId: '123', componentName: 'doesnt matter' });
  196. expect(didAppearFn).toHaveBeenCalledTimes(1);
  197. });
  198. it(`removeAllListenersForComponentId`, () => {
  199. renderer.create(<BoundScreen componentId={'123'} />);
  200. renderer.create(<BoundScreen componentId={'123'} />);
  201. uut.unmounted('123');
  202. uut.notifyComponentDidAppear({ componentId: '123', componentName: 'doesnt matter' });
  203. expect(didAppearFn).not.toHaveBeenCalled();
  204. });
  205. it(`supports multiple listeners with same componentId`, () => {
  206. const tree1 = renderer.create(<SimpleScreen componentId={'myCompId'} />);
  207. const tree2 = renderer.create(<SimpleScreen componentId={'myCompId'} />);
  208. const instance1 = tree1.getInstance() as any;
  209. const instance2 = tree2.getInstance() as any;
  210. instance1.componentDidAppear = jest.fn();
  211. instance2.componentDidAppear = jest.fn();
  212. const result1 = uut.bindComponent(instance1);
  213. const result2 = uut.bindComponent(instance2);
  214. expect(result1).not.toEqual(result2);
  215. uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
  216. expect(instance1.componentDidAppear).toHaveBeenCalledTimes(1);
  217. expect(instance2.componentDidAppear).toHaveBeenCalledTimes(1);
  218. result2.remove();
  219. uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
  220. expect(instance1.componentDidAppear).toHaveBeenCalledTimes(2);
  221. expect(instance2.componentDidAppear).toHaveBeenCalledTimes(1);
  222. result1.remove();
  223. uut.notifyComponentDidAppear({ componentId: 'myCompId', componentName: 'doesnt matter' });
  224. expect(instance1.componentDidAppear).toHaveBeenCalledTimes(2);
  225. expect(instance2.componentDidAppear).toHaveBeenCalledTimes(1);
  226. });
  227. it(`register for all native component events notifies self on events, once`, () => {
  228. expect(mockEventsReceiver.registerComponentDidAppearListener).not.toHaveBeenCalled();
  229. expect(mockEventsReceiver.registerComponentDidDisappearListener).not.toHaveBeenCalled();
  230. expect(mockEventsReceiver.registerNavigationButtonPressedListener).not.toHaveBeenCalled();
  231. expect(mockEventsReceiver.registerSearchBarUpdatedListener).not.toHaveBeenCalled();
  232. expect(mockEventsReceiver.registerSearchBarCancelPressedListener).not.toHaveBeenCalled();
  233. expect(mockEventsReceiver.registerPreviewCompletedListener).not.toHaveBeenCalled();
  234. uut.registerOnceForAllComponentEvents();
  235. uut.registerOnceForAllComponentEvents();
  236. uut.registerOnceForAllComponentEvents();
  237. uut.registerOnceForAllComponentEvents();
  238. expect(mockEventsReceiver.registerComponentDidAppearListener).toHaveBeenCalledTimes(1);
  239. expect(mockEventsReceiver.registerComponentDidDisappearListener).toHaveBeenCalledTimes(1);
  240. expect(mockEventsReceiver.registerNavigationButtonPressedListener).toHaveBeenCalledTimes(1);
  241. expect(mockEventsReceiver.registerSearchBarUpdatedListener).toHaveBeenCalledTimes(1);
  242. expect(mockEventsReceiver.registerSearchBarCancelPressedListener).toHaveBeenCalledTimes(1);
  243. expect(mockEventsReceiver.registerPreviewCompletedListener).toHaveBeenCalledTimes(1);
  244. });
  245. });