react-native-navigation的迁移库

ComponentEventsObserver.test.tsx 12KB

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