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
     await elementById(testIDs.POP_BUTTON).tap();
118
     await elementById(testIDs.POP_BUTTON).tap();
119
     await expect(elementById(testIDs.TOP_BAR_ELEMENT)).toBeVisible();
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
     expect(node.children[0].id).toEqual('BottomTabs+UNIQUE_ID');
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
   it('crawls a layout tree and ensures data exists', () => {
28
   it('crawls a layout tree and ensures data exists', () => {
23
     const node: any = { type: LayoutType.Stack, children: [{ type: LayoutType.BottomTabs }] };
29
     const node: any = { type: LayoutType.Stack, children: [{ type: LayoutType.BottomTabs }] };
24
     uut.crawl(node);
30
     uut.crawl(node);

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

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

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

61
 
61
 
62
     it('bottom tabs', () => {
62
     it('bottom tabs', () => {
63
       const result = uut.parse(LayoutExamples.bottomTabs);
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
       expect(result.type).toEqual(LayoutType.BottomTabs);
66
       expect(result.type).toEqual(LayoutType.BottomTabs);
66
       expect(result.data).toEqual({});
67
       expect(result.data).toEqual({});
67
       expect(result.children.length).toEqual(3);
68
       expect(result.children.length).toEqual(3);
72
 
73
 
73
     it('side menus', () => {
74
     it('side menus', () => {
74
       const result = uut.parse(LayoutExamples.sideMenu);
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
       expect(result.type).toEqual(LayoutType.SideMenuRoot);
78
       expect(result.type).toEqual(LayoutType.SideMenuRoot);
77
       expect(result.data).toEqual({});
79
       expect(result.data).toEqual({});
78
       expect(result.children.length).toEqual(3);
80
       expect(result.children.length).toEqual(3);
93
 
95
 
94
     it('top tabs', () => {
96
     it('top tabs', () => {
95
       const result = uut.parse(LayoutExamples.topTabs);
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
       expect(result.type).toEqual(LayoutType.TopTabs);
100
       expect(result.type).toEqual(LayoutType.TopTabs);
98
       expect(result.data).toEqual({ options: LayoutExamples.options });
101
       expect(result.data).toEqual({ options: LayoutExamples.options });
99
       expect(result.children.length).toEqual(5);
102
       expect(result.children.length).toEqual(5);
124
     expect(uut.parse({ topTabs: { options } }).data.options).toBe(options);
127
     expect(uut.parse({ topTabs: { options } }).data.options).toBe(options);
125
     expect(uut.parse({ sideMenu: { options, center: { component: {} } } }).data.options).toBe(options);
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
 /* Layout Examples: */
147
 /* Layout Examples: */

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

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

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

24
     this.onClickBackHandler = this.onClickBackHandler.bind(this);
24
     this.onClickBackHandler = this.onClickBackHandler.bind(this);
25
     this.onClickPushTopTabsScreen = this.onClickPushTopTabsScreen.bind(this);
25
     this.onClickPushTopTabsScreen = this.onClickPushTopTabsScreen.bind(this);
26
     this.onClickShowStaticLifecycleOverlay = this.onClickShowStaticLifecycleOverlay.bind(this);
26
     this.onClickShowStaticLifecycleOverlay = this.onClickShowStaticLifecycleOverlay.bind(this);
27
+    this.onClickProvidedId = this.onClickProvidedId.bind(this);
27
   }
28
   }
28
 
29
 
29
   render() {
30
   render() {
41
         <Button title='Show Modal' testID={testIDs.SHOW_MODAL_BUTTON} onPress={this.onClickShowModal} />
42
         <Button title='Show Modal' testID={testIDs.SHOW_MODAL_BUTTON} onPress={this.onClickShowModal} />
42
         <Button title='Show Redbox' testID={testIDs.SHOW_REDBOX_BUTTON} onPress={this.onClickShowRedbox} />
43
         <Button title='Show Redbox' testID={testIDs.SHOW_REDBOX_BUTTON} onPress={this.onClickShowRedbox} />
43
         <Button title='Orientation' testID={testIDs.ORIENTATION_BUTTON} onPress={this.onClickPushOrientationMenuScreen} />
44
         <Button title='Orientation' testID={testIDs.ORIENTATION_BUTTON} onPress={this.onClickPushOrientationMenuScreen} />
45
+        <Button title='Provided Id' testID={testIDs.PROVIDED_ID} onPress={this.onClickProvidedId} />
44
         <Text style={styles.footer}>{`this.props.componentId = ${this.props.componentId}`}</Text>
46
         <Text style={styles.footer}>{`this.props.componentId = ${this.props.componentId}`}</Text>
45
       </View>
47
       </View>
46
     );
48
     );
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
 module.exports = WelcomeScreen;
375
 module.exports = WelcomeScreen;

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

13
   SHOW_MODAL_BUTTON: `SHOW_MODAL_BUTTON`,
13
   SHOW_MODAL_BUTTON: `SHOW_MODAL_BUTTON`,
14
   SHOW_REDBOX_BUTTON: `SHOW_REDBOX_BUTTON`,
14
   SHOW_REDBOX_BUTTON: `SHOW_REDBOX_BUTTON`,
15
   ORIENTATION_BUTTON: `ORIENTATION_BUTTON`,
15
   ORIENTATION_BUTTON: `ORIENTATION_BUTTON`,
16
+  PROVIDED_ID: `PROVIDED_ID`,
16
   DISMISS_MODAL_BUTTON: `DISMISS_MODAL_BUTTON`,
17
   DISMISS_MODAL_BUTTON: `DISMISS_MODAL_BUTTON`,
17
   DISMISS_UNKNOWN_MODAL_BUTTON: `DISMISS_UNKNOWN_MODAL_BUTTON`,
18
   DISMISS_UNKNOWN_MODAL_BUTTON: `DISMISS_UNKNOWN_MODAL_BUTTON`,
18
   DISMISS_ALL_MODALS_BUTTON: `DISMISS_ALL_MODALS_BUTTON`,
19
   DISMISS_ALL_MODALS_BUTTON: `DISMISS_ALL_MODALS_BUTTON`,