Browse Source

Id 2652 (#2731)

* generate id only when not already provided

* allows passing id

* fixes #2652
Daniel Zlotin 6 years ago
parent
commit
76fea63d87
No account linked to committer's email address

+ 5
- 0
e2e/ScreenStyle.test.js View File

@@ -118,4 +118,9 @@ describe('screen style', () => {
118 118
     await elementById(testIDs.POP_BUTTON).tap();
119 119
     await expect(elementById(testIDs.TOP_BAR_ELEMENT)).toBeVisible();
120 120
   });
121
+
122
+  it('supports user-provided id', async () => {
123
+    await elementById(testIDs.PROVIDED_ID).tap();
124
+    await expect(elementByLabel('User provided id')).toBeVisible();
125
+  });
121 126
 });

+ 6
- 0
lib/src/commands/LayoutTreeCrawler.test.ts View File

@@ -19,6 +19,12 @@ describe('LayoutTreeCrawler', () => {
19 19
     expect(node.children[0].id).toEqual('BottomTabs+UNIQUE_ID');
20 20
   });
21 21
 
22
+  it('does not generate unique id when already provided', () => {
23
+    const node = { id: 'user defined id', type: LayoutType.Stack };
24
+    uut.crawl(node);
25
+    expect(node.id).toEqual('user defined id');
26
+  });
27
+
22 28
   it('crawls a layout tree and ensures data exists', () => {
23 29
     const node: any = { type: LayoutType.Stack, children: [{ type: LayoutType.BottomTabs }] };
24 30
     uut.crawl(node);

+ 1
- 1
lib/src/commands/LayoutTreeCrawler.ts View File

@@ -23,7 +23,7 @@ export class LayoutTreeCrawler {
23 23
 
24 24
   crawl(node: LayoutNode): void {
25 25
     this._assertKnownLayoutType(node.type);
26
-    node.id = this.uniqueIdProvider.generate(node.type);
26
+    node.id = node.id || this.uniqueIdProvider.generate(node.type);
27 27
     node.data = node.data || {};
28 28
     node.children = node.children || [];
29 29
     if (node.type === LayoutType.Component) {

+ 21
- 3
lib/src/commands/LayoutTreeParser.test.ts View File

@@ -61,7 +61,8 @@ describe('LayoutTreeParser', () => {
61 61
 
62 62
     it('bottom tabs', () => {
63 63
       const result = uut.parse(LayoutExamples.bottomTabs);
64
-      expect(_.keys(result)).toEqual(['type', 'data', 'children']);
64
+      expect(_.keys(result)).toEqual(['id', 'type', 'data', 'children']);
65
+      expect(result.id).toEqual(undefined);
65 66
       expect(result.type).toEqual(LayoutType.BottomTabs);
66 67
       expect(result.data).toEqual({});
67 68
       expect(result.children.length).toEqual(3);
@@ -72,7 +73,8 @@ describe('LayoutTreeParser', () => {
72 73
 
73 74
     it('side menus', () => {
74 75
       const result = uut.parse(LayoutExamples.sideMenu);
75
-      expect(_.keys(result)).toEqual(['type', 'data', 'children']);
76
+      expect(_.keys(result)).toEqual(['id', 'type', 'data', 'children']);
77
+      expect(result.id).toEqual(undefined);
76 78
       expect(result.type).toEqual(LayoutType.SideMenuRoot);
77 79
       expect(result.data).toEqual({});
78 80
       expect(result.children.length).toEqual(3);
@@ -93,7 +95,8 @@ describe('LayoutTreeParser', () => {
93 95
 
94 96
     it('top tabs', () => {
95 97
       const result = uut.parse(LayoutExamples.topTabs);
96
-      expect(_.keys(result)).toEqual(['type', 'data', 'children']);
98
+      expect(_.keys(result)).toEqual(['id', 'type', 'data', 'children']);
99
+      expect(result.id).toEqual(undefined);
97 100
       expect(result.type).toEqual(LayoutType.TopTabs);
98 101
       expect(result.data).toEqual({ options: LayoutExamples.options });
99 102
       expect(result.children.length).toEqual(5);
@@ -124,6 +127,21 @@ describe('LayoutTreeParser', () => {
124 127
     expect(uut.parse({ topTabs: { options } }).data.options).toBe(options);
125 128
     expect(uut.parse({ sideMenu: { options, center: { component: {} } } }).data.options).toBe(options);
126 129
   });
130
+
131
+  it('pass user provided id as is', () => {
132
+    const component = { id: 'compId' };
133
+    expect(uut.parse({ component }).id).toEqual('compId');
134
+    expect(uut.parse({ stack: { id: 'stackId' } }).id).toEqual('stackId');
135
+    expect(uut.parse({ stack: { children: [{ component }] } }).children[0].id).toEqual('compId');
136
+    expect(uut.parse({ bottomTabs: { id: 'myId' } }).id).toEqual('myId');
137
+    expect(uut.parse({ bottomTabs: { children: [{ component }] } }).children[0].id).toEqual('compId');
138
+    expect(uut.parse({ topTabs: { id: 'myId' } }).id).toEqual('myId');
139
+    expect(uut.parse({ topTabs: { children: [{ component }] } }).children[0].id).toEqual('compId');
140
+    expect(uut.parse({ sideMenu: { id: 'myId', center: { component } } }).id).toEqual('myId');
141
+    expect(uut.parse({ sideMenu: { center: { id: 'myId', component } } }).children[0].id).toEqual('myId');
142
+    expect(uut.parse({ sideMenu: { center: { component }, left: { id: 'theId', component } } }).children[0].id).toEqual('theId');
143
+    expect(uut.parse({ sideMenu: { center: { component }, right: { id: 'theId', component } } }).children[1].id).toEqual('theId');
144
+  });
127 145
 });
128 146
 
129 147
 /* Layout Examples: */

+ 8
- 0
lib/src/commands/LayoutTreeParser.ts View File

@@ -24,6 +24,7 @@ export class LayoutTreeParser {
24 24
 
25 25
   _topTabs(api): LayoutNode {
26 26
     return {
27
+      id: api.id,
27 28
       type: LayoutType.TopTabs,
28 29
       data: { options: api.options },
29 30
       children: _.map(api.children, this.parse)
@@ -32,6 +33,7 @@ export class LayoutTreeParser {
32 33
 
33 34
   _sideMenu(api): LayoutNode {
34 35
     return {
36
+      id: api.id,
35 37
       type: LayoutType.SideMenuRoot,
36 38
       data: { options: api.options },
37 39
       children: this._sideMenuChildren(api)
@@ -45,18 +47,21 @@ export class LayoutTreeParser {
45 47
     const children: LayoutNode[] = [];
46 48
     if (api.left) {
47 49
       children.push({
50
+        id: api.left.id,
48 51
         type: LayoutType.SideMenuLeft,
49 52
         data: {},
50 53
         children: [this.parse(api.left)]
51 54
       });
52 55
     }
53 56
     children.push({
57
+      id: api.center.id,
54 58
       type: LayoutType.SideMenuCenter,
55 59
       data: {},
56 60
       children: [this.parse(api.center)]
57 61
     });
58 62
     if (api.right) {
59 63
       children.push({
64
+        id: api.right.id,
60 65
         type: LayoutType.SideMenuRight,
61 66
         data: {},
62 67
         children: [this.parse(api.right)]
@@ -67,6 +72,7 @@ export class LayoutTreeParser {
67 72
 
68 73
   _bottomTabs(api): LayoutNode {
69 74
     return {
75
+      id: api.id,
70 76
       type: LayoutType.BottomTabs,
71 77
       data: { options: api.options },
72 78
       children: _.map(api.children, this.parse)
@@ -75,6 +81,7 @@ export class LayoutTreeParser {
75 81
 
76 82
   _stack(api): LayoutNode {
77 83
     return {
84
+      id: api.id,
78 85
       type: LayoutType.Stack,
79 86
       data: { name: api.name, options: api.options },
80 87
       children: _.map(api.children, this.parse)
@@ -83,6 +90,7 @@ export class LayoutTreeParser {
83 90
 
84 91
   _component(api): LayoutNode {
85 92
     return {
93
+      id: api.id,
86 94
       type: LayoutType.Component,
87 95
       data: { name: api.name, options: api.options, passProps: api.passProps },
88 96
       children: []

+ 22
- 0
playground/src/screens/WelcomeScreen.js View File

@@ -24,6 +24,7 @@ class WelcomeScreen extends Component {
24 24
     this.onClickBackHandler = this.onClickBackHandler.bind(this);
25 25
     this.onClickPushTopTabsScreen = this.onClickPushTopTabsScreen.bind(this);
26 26
     this.onClickShowStaticLifecycleOverlay = this.onClickShowStaticLifecycleOverlay.bind(this);
27
+    this.onClickProvidedId = this.onClickProvidedId.bind(this);
27 28
   }
28 29
 
29 30
   render() {
@@ -41,6 +42,7 @@ class WelcomeScreen extends Component {
41 42
         <Button title='Show Modal' testID={testIDs.SHOW_MODAL_BUTTON} onPress={this.onClickShowModal} />
42 43
         <Button title='Show Redbox' testID={testIDs.SHOW_REDBOX_BUTTON} onPress={this.onClickShowRedbox} />
43 44
         <Button title='Orientation' testID={testIDs.ORIENTATION_BUTTON} onPress={this.onClickPushOrientationMenuScreen} />
45
+        <Button title='Provided Id' testID={testIDs.PROVIDED_ID} onPress={this.onClickProvidedId} />
44 46
         <Text style={styles.footer}>{`this.props.componentId = ${this.props.componentId}`}</Text>
45 47
       </View>
46 48
     );
@@ -348,6 +350,26 @@ class WelcomeScreen extends Component {
348 350
       }
349 351
     });
350 352
   }
353
+
354
+  onClickProvidedId() {
355
+    Navigation.showModal({
356
+      stack: {
357
+        children: [
358
+          {
359
+            component: {
360
+              name: 'navigation.playground.TextScreen',
361
+              id: 'my unique id'
362
+            }
363
+          }
364
+        ]
365
+      }
366
+    });
367
+    Navigation.setOptions('my unique id', {
368
+      topBar: {
369
+        title: 'User provided id'
370
+      }
371
+    });
372
+  }
351 373
 }
352 374
 
353 375
 module.exports = WelcomeScreen;

+ 1
- 0
playground/src/testIDs.js View File

@@ -13,6 +13,7 @@ module.exports = {
13 13
   SHOW_MODAL_BUTTON: `SHOW_MODAL_BUTTON`,
14 14
   SHOW_REDBOX_BUTTON: `SHOW_REDBOX_BUTTON`,
15 15
   ORIENTATION_BUTTON: `ORIENTATION_BUTTON`,
16
+  PROVIDED_ID: `PROVIDED_ID`,
16 17
   DISMISS_MODAL_BUTTON: `DISMISS_MODAL_BUTTON`,
17 18
   DISMISS_UNKNOWN_MODAL_BUTTON: `DISMISS_UNKNOWN_MODAL_BUTTON`,
18 19
   DISMISS_ALL_MODALS_BUTTON: `DISMISS_ALL_MODALS_BUTTON`,