react-native-navigation的迁移库

LayoutTreeCrawler.test.ts 5.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. import * as React from 'react';
  2. import { LayoutType } from './LayoutType';
  3. import { LayoutTreeCrawler } from './LayoutTreeCrawler';
  4. import { Store } from '../components/Store';
  5. import { mock, instance, verify, deepEqual, when } from 'ts-mockito';
  6. import { OptionsProcessor } from './OptionsProcessor';
  7. import { Options } from '../interfaces/Options';
  8. describe('LayoutTreeCrawler', () => {
  9. let uut: LayoutTreeCrawler;
  10. let mockedStore: Store;
  11. let mockedOptionsProcessor: OptionsProcessor;
  12. beforeEach(() => {
  13. mockedStore = mock(Store);
  14. mockedOptionsProcessor = mock(OptionsProcessor);
  15. uut = new LayoutTreeCrawler(instance(mockedStore), instance(mockedOptionsProcessor));
  16. });
  17. it('saves passProps into store for Component nodes', () => {
  18. const node = {
  19. id: 'testId',
  20. type: LayoutType.BottomTabs,
  21. children: [
  22. {
  23. id: 'testId',
  24. type: LayoutType.Component,
  25. data: { name: 'the name', passProps: { myProp: 123 } },
  26. children: []
  27. }
  28. ],
  29. data: {}
  30. };
  31. uut.crawl(node);
  32. verify(mockedStore.updateProps('testId', deepEqual({ myProp: 123 }))).called();
  33. });
  34. it('Components: injects options from original component class static property', () => {
  35. when(mockedStore.getComponentClassForName('theComponentName')).thenReturn(
  36. () =>
  37. class extends React.Component {
  38. static options(): Options {
  39. return { popGesture: true };
  40. }
  41. }
  42. );
  43. const node = {
  44. id: 'testId',
  45. type: LayoutType.Component,
  46. data: { name: 'theComponentName', options: {} },
  47. children: []
  48. };
  49. uut.crawl(node);
  50. expect(node.data.options).toEqual({ popGesture: true });
  51. });
  52. it('Components: injects options from original component class static property', () => {
  53. when(mockedStore.getComponentClassForName('theComponentName')).thenReturn(
  54. () =>
  55. class extends React.Component {
  56. static options = {
  57. popGesture: true
  58. };
  59. }
  60. );
  61. const node = {
  62. id: 'testId',
  63. type: LayoutType.Component,
  64. data: { name: 'theComponentName', options: {} },
  65. children: []
  66. };
  67. uut.crawl(node);
  68. expect(node.data.options).toEqual({ popGesture: true });
  69. });
  70. it('Components: crawl does not cache options', () => {
  71. when(mockedStore.getComponentClassForName('theComponentName')).thenReturn(
  72. () =>
  73. class extends React.Component {
  74. static options(props: { title?: string }) {
  75. return { topBar: { title: { text: props.title } } };
  76. }
  77. }
  78. );
  79. const node = {
  80. id: 'testId',
  81. type: LayoutType.Component,
  82. data: { name: 'theComponentName', options: {}, passProps: { title: 'title' } },
  83. children: []
  84. };
  85. uut.crawl(node);
  86. expect(node.data.options).toEqual({ topBar: { title: { text: 'title' } } });
  87. const node2 = {
  88. id: 'testId',
  89. type: LayoutType.Component,
  90. data: { name: 'theComponentName', options: {} },
  91. children: []
  92. };
  93. uut.crawl(node2);
  94. expect(node2.data.options).toEqual({ topBar: { title: {} } });
  95. });
  96. it('Components: merges options from component class static property with passed options, favoring passed options', () => {
  97. when(mockedStore.getComponentClassForName('theComponentName')).thenReturn(
  98. () =>
  99. class extends React.Component {
  100. static options() {
  101. return {
  102. bazz: 123,
  103. inner: { foo: 'this gets overriden' },
  104. opt: 'exists only in static'
  105. };
  106. }
  107. }
  108. );
  109. const node = {
  110. id: 'testId',
  111. type: LayoutType.Component,
  112. data: {
  113. name: 'theComponentName',
  114. options: {
  115. aaa: 'exists only in passed',
  116. bazz: 789,
  117. inner: { foo: 'this should override same keys' }
  118. }
  119. },
  120. children: []
  121. };
  122. uut.crawl(node);
  123. expect(node.data.options).toEqual({
  124. aaa: 'exists only in passed',
  125. bazz: 789,
  126. inner: { foo: 'this should override same keys' },
  127. opt: 'exists only in static'
  128. });
  129. });
  130. it('Components: must contain data name', () => {
  131. const node = { type: LayoutType.Component, data: {}, children: [], id: 'testId' };
  132. expect(() => uut.crawl(node)).toThrowError('Missing component data.name');
  133. });
  134. it('Components: options default obj', () => {
  135. when(mockedStore.getComponentClassForName('theComponentName')).thenReturn(
  136. () => class extends React.Component {}
  137. );
  138. const node = {
  139. id: 'testId',
  140. type: LayoutType.Component,
  141. data: { name: 'theComponentName', options: {} },
  142. children: []
  143. };
  144. uut.crawl(node);
  145. expect(node.data.options).toEqual({});
  146. });
  147. it('Components: omits passProps after processing so they are not passed over the bridge', () => {
  148. const node = {
  149. id: 'testId',
  150. type: LayoutType.Component,
  151. data: {
  152. name: 'compName',
  153. passProps: { someProp: 'here' }
  154. },
  155. children: []
  156. };
  157. uut.crawl(node);
  158. expect(node.data.passProps).toBeUndefined();
  159. });
  160. });