Browse Source

layout tree crawling

Daniel Zlotin 8 years ago
parent
commit
df6729aa9c

+ 7
- 1
playground/e2e/app.test.js View File

12
     expect(elementByLabel('This is tab 1')).toBeVisible();
12
     expect(elementByLabel('This is tab 1')).toBeVisible();
13
   });
13
   });
14
 
14
 
15
+  it('passing props and functions', () => {
16
+    elementByLabel('Switch to tab based app').tap();
17
+    expect(elementByLabel('Hello from a function!')).toBeVisible();
18
+  });
19
+
15
   xit('switch to tabs with side menus', () => {
20
   xit('switch to tabs with side menus', () => {
16
     elementByLabel('Switch to tab based app with side menus').tap();
21
     elementByLabel('Switch to tab based app with side menus').tap();
17
-    // expect(elementByLabel('This is a tab screen')).toBeVisible();
22
+    elementByLabel('Switch to tab based app with side menus').swipeRight();
23
+    expect(elementByLabel('This is a side menu screen')).toBeVisible();
18
   });
24
   });
19
 });
25
 });
20
 
26
 

+ 1
- 1
playground/package.json View File

4
   "private": true,
4
   "private": true,
5
   "scripts": {
5
   "scripts": {
6
     "quickinstall": "node ./scripts/quickInstall.js",
6
     "quickinstall": "node ./scripts/quickInstall.js",
7
-    "start": "adb reverse tcp:8081 tcp:8081; watchman watch-del-all; react-native start --reset-cache",
7
+    "start": "adb reverse tcp:8081 tcp:8081; watchman watch-del-all; react-native start",
8
     "xcode": "open ios/playground.xcodeproj",
8
     "xcode": "open ios/playground.xcodeproj",
9
     "android": "cd android && ./gradlew installDebug",
9
     "android": "cd android && ./gradlew installDebug",
10
     "e2e": "node ./scripts/e2e.ios.js"
10
     "e2e": "node ./scripts/e2e.ios.js"

+ 11
- 2
playground/src/containers/SimpleScreen.js View File

3
 
3
 
4
 class SimpleScreen extends Component {
4
 class SimpleScreen extends Component {
5
   render() {
5
   render() {
6
-    const text = this.props.text || 'Simple Screen';
7
     return (
6
     return (
8
       <View style={styles.root}>
7
       <View style={styles.root}>
9
-        <Text style={styles.h1}>{text}</Text>
8
+        <Text style={styles.h1}>{this.props.text || 'Simple Screen'}</Text>
9
+        {this.renderTextFromFunctionInProps()}
10
       </View>
10
       </View>
11
     );
11
     );
12
   }
12
   }
13
+
14
+  renderTextFromFunctionInProps() {
15
+    if (!this.props.myFunction) {
16
+      return undefined;
17
+    }
18
+    return (
19
+      <Text style={styles.h1}>{this.props.myFunction()}</Text>
20
+    );
21
+  }
13
 }
22
 }
14
 export default SimpleScreen;
23
 export default SimpleScreen;
15
 
24
 

+ 2
- 1
playground/src/containers/WelcomeScreen.js View File

25
           container: {
25
           container: {
26
             name: 'com.example.SimpleScreen',
26
             name: 'com.example.SimpleScreen',
27
             passProps: {
27
             passProps: {
28
-              text: 'This is tab 1'
28
+              text: 'This is tab 1',
29
+              myFunction: () => 'Hello from a function!'
29
             }
30
             }
30
           }
31
           }
31
         },
32
         },

+ 8
- 12
src/commands/Commands.js View File

1
-import * as _ from 'lodash';
1
+import _ from 'lodash';
2
 import LayoutTreeParser from './LayoutTreeParser';
2
 import LayoutTreeParser from './LayoutTreeParser';
3
+import LayoutTreeCrawler from './LayoutTreeCrawler';
3
 
4
 
4
 export default class Commands {
5
 export default class Commands {
5
   constructor(nativeCommandsSender, uniqueIdProvider, store) {
6
   constructor(nativeCommandsSender, uniqueIdProvider, store) {
6
     this.nativeCommandsSender = nativeCommandsSender;
7
     this.nativeCommandsSender = nativeCommandsSender;
7
-    this.layoutTreeParser = new LayoutTreeParser(uniqueIdProvider);
8
-    this.store = store;
8
+    this.uniqueIdProvider = uniqueIdProvider;
9
+    this.layoutTreeParser = new LayoutTreeParser();
10
+    this.layoutTreeCrawler = new LayoutTreeCrawler(uniqueIdProvider, store);
9
   }
11
   }
10
 
12
 
11
   setRoot(simpleApi) {
13
   setRoot(simpleApi) {
12
-    const layout = this.layoutTreeParser.parseFromSimpleJSON(simpleApi);
13
-    this._savePassProps(layout);
14
+    const input = _.cloneDeep(simpleApi);
15
+    const layout = this.layoutTreeParser.parseFromSimpleJSON(input);
16
+    this.layoutTreeCrawler.crawl(layout);
14
     this.nativeCommandsSender.setRoot(layout);
17
     this.nativeCommandsSender.setRoot(layout);
15
   }
18
   }
16
-
17
-  _savePassProps(node) {
18
-    if (node.type === 'Container') {
19
-      this.store.setPropsForContainerId(node.id, node.data.passProps);
20
-    }
21
-    _.forEach(node.children, (child) => this._savePassProps(child));
22
-  }
23
 }
19
 }

+ 9
- 1
src/commands/Commands.test.js View File

8
   beforeEach(() => {
8
   beforeEach(() => {
9
     const NativeCommandsSender = jest.genMockFromModule('../adapters/NativeCommandsSender').default;
9
     const NativeCommandsSender = jest.genMockFromModule('../adapters/NativeCommandsSender').default;
10
     mockCommandsSender = new NativeCommandsSender();
10
     mockCommandsSender = new NativeCommandsSender();
11
+
11
     const mockIdProvider = { generate: (prefix) => `${prefix}+UNIQUE_ID` };
12
     const mockIdProvider = { generate: (prefix) => `${prefix}+UNIQUE_ID` };
13
+
12
     const Store = require('../containers/Store').default;
14
     const Store = require('../containers/Store').default;
13
     store = new Store();
15
     store = new Store();
14
 
16
 
17
   });
19
   });
18
 
20
 
19
   describe('setRoot', () => {
21
   describe('setRoot', () => {
20
-    it('sends setRoot to native after parsing into layoutTree', () => {
22
+    it('sends setRoot to native after parsing into a correct layout tree', () => {
21
       uut.setRoot({
23
       uut.setRoot({
22
         container: {
24
         container: {
23
           name: 'com.example.MyScreen'
25
           name: 'com.example.MyScreen'
41
       });
43
       });
42
     });
44
     });
43
 
45
 
46
+    it('deep clones input to avoid mutation errors', () => {
47
+      const obj = {};
48
+      uut.setRoot({ container: { inner: obj } });
49
+      expect(mockCommandsSender.setRoot.mock.calls[0][0].children[0].data.inner).not.toBe(obj);
50
+    });
51
+
44
     it('passProps into containers', () => {
52
     it('passProps into containers', () => {
45
       expect(store.getPropsForContainerId('Container+UNIQUE_ID')).toEqual({});
53
       expect(store.getPropsForContainerId('Container+UNIQUE_ID')).toEqual({});
46
       uut.setRoot(SimpleLayouts.singleScreenWithAditionalParams);
54
       uut.setRoot(SimpleLayouts.singleScreenWithAditionalParams);

+ 27
- 0
src/commands/LayoutTreeCrawler.js View File

1
+import _ from 'lodash';
2
+import LayoutTypes from './LayoutTypes';
3
+
4
+export default class LayoutTreeCrawler {
5
+  constructor(uniqueIdProvider, store) {
6
+    this.uniqueIdProvider = uniqueIdProvider;
7
+    this.store = store;
8
+    this.crawl = this.crawl.bind(this);
9
+  }
10
+
11
+  crawl(node) {
12
+    this._assertKnownLayoutType(node.type);
13
+    node.id = this.uniqueIdProvider.generate(node.type);
14
+    node.data = node.data || {};
15
+    node.children = node.children || [];
16
+    if (node.type === LayoutTypes.Container) {
17
+      this.store.setPropsForContainerId(node.id, node.data.passProps);
18
+    }
19
+    _.forEach(node.children, this.crawl);
20
+  }
21
+
22
+  _assertKnownLayoutType(type) {
23
+    if (!_.includes(LayoutTypes, type)) {
24
+      throw new Error(`Unknown layout type ${type}`);
25
+    }
26
+  }
27
+}

+ 47
- 0
src/commands/LayoutTreeCrawler.test.js View File

1
+import LayoutTypes from './LayoutTypes';
2
+
3
+describe('LayoutTreeCrawler', () => {
4
+  let uut;
5
+  let store;
6
+
7
+  beforeEach(() => {
8
+    const LayoutTreeCrawler = require('./LayoutTreeCrawler').default;
9
+    const uniqueIdProvider = { generate: (prefix) => `${prefix}+UNIQUE_ID` };
10
+    const Store = require('../containers/Store').default;
11
+    store = new Store();
12
+
13
+    uut = new LayoutTreeCrawler(uniqueIdProvider, store);
14
+  });
15
+
16
+  it('crawls a layout tree and adds unique id to each node', () => {
17
+    const node = { type: LayoutTypes.Container, children: [{ type: LayoutTypes.Tabs }] };
18
+    uut.crawl(node);
19
+    expect(node.id).toEqual('Container+UNIQUE_ID');
20
+    expect(node.children[0].id).toEqual('Tabs+UNIQUE_ID');
21
+  });
22
+
23
+  it('crawls a layout tree and ensures data exists', () => {
24
+    const node = { type: LayoutTypes.Container, children: [{ type: LayoutTypes.Tabs }] };
25
+    uut.crawl(node);
26
+    expect(node.data).toEqual({});
27
+    expect(node.children[0].data).toEqual({});
28
+  });
29
+
30
+  it('crawls a layout tree and ensures children exists', () => {
31
+    const node = { type: LayoutTypes.Container, children: [{ type: LayoutTypes.Tabs }] };
32
+    uut.crawl(node);
33
+    expect(node.children[0].children).toEqual([]);
34
+  });
35
+
36
+  it('crawls a layout tree and asserts known layout type', () => {
37
+    const node = { type: LayoutTypes.Container, children: [{ type: 'Bob' }] };
38
+    expect(() => uut.crawl(node)).toThrow(new Error('Unknown layout type Bob'));
39
+  });
40
+
41
+  it('saves passProps into store for Container nodes', () => {
42
+    const node = { type: LayoutTypes.Tabs, children: [{ type: LayoutTypes.Container, data: { passProps: { myProp: 123 } } }] };
43
+    expect(store.getPropsForContainerId('Container+UNIQUE_ID')).toEqual({});
44
+    uut.crawl(node);
45
+    expect(store.getPropsForContainerId('Container+UNIQUE_ID')).toEqual({ myProp: 123 });
46
+  });
47
+});

+ 32
- 49
src/commands/LayoutTreeParser.js View File

1
 import * as _ from 'lodash';
1
 import * as _ from 'lodash';
2
-
3
-const Types = {
4
-  Container: 'Container',
5
-  ContainerStack: 'ContainerStack',
6
-  Tabs: 'Tabs',
7
-  SideMenuRoot: 'SideMenuRoot',
8
-  SideMenuCenter: 'SideMenuCenter',
9
-  SideMenuLeft: 'SideMenuLeft',
10
-  SideMenuRight: 'SideMenuRight'
11
-};
2
+import LayoutTypes from './LayoutTypes';
12
 
3
 
13
 export default class LayoutTreeParser {
4
 export default class LayoutTreeParser {
14
-  constructor(uniqueIdProvider) {
15
-    this.uniqueIdProvider = uniqueIdProvider;
16
-  }
17
-
5
+  /**
6
+   * returns correct layout tree of {type, children, data?}
7
+   */
18
   parseFromSimpleJSON(simpleJsonApi) {
8
   parseFromSimpleJSON(simpleJsonApi) {
19
-    const input = _.cloneDeep(simpleJsonApi);
20
-    if (input.sideMenu) {
21
-      return this._createSideMenu(input);
9
+    if (simpleJsonApi.sideMenu) {
10
+      return this._createSideMenu(simpleJsonApi);
22
     }
11
     }
23
-    if (input.tabs) {
24
-      return this._createTabs(input.tabs);
12
+    if (simpleJsonApi.tabs) {
13
+      return this._createTabs(simpleJsonApi.tabs);
25
     }
14
     }
26
-    return this._createContainerStackWithContainer(input.container);
27
-  }
28
-
29
-  _node(node) {
30
-    node.id = this.uniqueIdProvider.generate(node.type);
31
-    node.children = node.children || [];
32
-    node.data = node.data || {};
33
-    return node;
15
+    return this._createContainerStackWithContainer(simpleJsonApi.container);
34
   }
16
   }
35
 
17
 
36
   _createTabs(tabs) {
18
   _createTabs(tabs) {
37
-    return this._node({
38
-      type: Types.Tabs,
19
+    return {
20
+      type: LayoutTypes.Tabs,
39
       children: _.map(tabs, (t) => this._createContainerStackWithContainer(t.container))
21
       children: _.map(tabs, (t) => this._createContainerStackWithContainer(t.container))
40
-    });
22
+    };
41
   }
23
   }
42
 
24
 
43
   _createContainerStackWithContainer(container) {
25
   _createContainerStackWithContainer(container) {
44
-    return this._node({
45
-      type: Types.ContainerStack,
26
+    return {
27
+      type: LayoutTypes.ContainerStack,
46
       children: [this._createContainer(container)]
28
       children: [this._createContainer(container)]
47
-    });
29
+    };
48
   }
30
   }
49
 
31
 
50
   _createContainer(container) {
32
   _createContainer(container) {
51
-    return this._node({
52
-      type: Types.Container,
53
-      data: container
54
-    });
33
+    return {
34
+      type: LayoutTypes.Container,
35
+      data: container,
36
+      children: []
37
+    };
55
   }
38
   }
56
 
39
 
57
   _createSideMenu(layout) {
40
   _createSideMenu(layout) {
58
-    return this._node({
59
-      type: Types.SideMenuRoot,
41
+    return {
42
+      type: LayoutTypes.SideMenuRoot,
60
       children: this._createSideMenuChildren(layout)
43
       children: this._createSideMenuChildren(layout)
61
-    });
44
+    };
62
   }
45
   }
63
 
46
 
64
   _createSideMenuChildren(layout) {
47
   _createSideMenuChildren(layout) {
65
     const children = [];
48
     const children = [];
66
     if (layout.sideMenu.left) {
49
     if (layout.sideMenu.left) {
67
-      children.push(this._node({
68
-        type: Types.SideMenuLeft,
50
+      children.push({
51
+        type: LayoutTypes.SideMenuLeft,
69
         children: [this._createContainer(layout.sideMenu.left.container)]
52
         children: [this._createContainer(layout.sideMenu.left.container)]
70
-      }));
53
+      });
71
     }
54
     }
72
-    children.push(this._node({
73
-      type: Types.SideMenuCenter,
55
+    children.push({
56
+      type: LayoutTypes.SideMenuCenter,
74
       children: [
57
       children: [
75
         layout.tabs ? this._createTabs(layout.tabs) : this._createContainerStackWithContainer(layout.container)
58
         layout.tabs ? this._createTabs(layout.tabs) : this._createContainerStackWithContainer(layout.container)
76
       ]
59
       ]
77
-    }));
60
+    });
78
     if (layout.sideMenu.right) {
61
     if (layout.sideMenu.right) {
79
-      children.push(this._node({
80
-        type: Types.SideMenuRight,
62
+      children.push({
63
+        type: LayoutTypes.SideMenuRight,
81
         children: [this._createContainer(layout.sideMenu.right.container)]
64
         children: [this._createContainer(layout.sideMenu.right.container)]
82
-      }));
65
+      });
83
     }
66
     }
84
     return children;
67
     return children;
85
   }
68
   }

+ 1
- 94
src/commands/LayoutTreeParser.test.js View File

4
   let uut;
4
   let uut;
5
 
5
 
6
   beforeEach(() => {
6
   beforeEach(() => {
7
-    const uniqueIdProvider = { generate: (prefix) => `${prefix}+UNIQUE_ID` };
8
     const LayoutTreeParser = require('./LayoutTreeParser').default;
7
     const LayoutTreeParser = require('./LayoutTreeParser').default;
9
-    uut = new LayoutTreeParser(uniqueIdProvider);
10
-  });
11
-
12
-  it('adds uniqueId to containers', () => {
13
-    const input = { container: {} };
14
-    expect(uut.parseFromSimpleJSON(input))
15
-      .toEqual({
16
-        type: 'ContainerStack',
17
-        id: 'ContainerStack+UNIQUE_ID',
18
-        children: [
19
-          {
20
-            type: 'Container',
21
-            id: 'Container+UNIQUE_ID',
22
-            data: {},
23
-            children: []
24
-          }
25
-        ],
26
-        data: {}
27
-      });
28
-  });
29
-
30
-  it('deep clones to avoid mutations', () => {
31
-    const obj = {};
32
-    const result = uut.parseFromSimpleJSON({ container: { foo: obj } });
33
-    expect(result.children[0].data.foo).not.toBe(obj);
8
+    uut = new LayoutTreeParser();
34
   });
9
   });
35
 
10
 
36
   it('parses single screen', () => {
11
   it('parses single screen', () => {
37
     expect(uut.parseFromSimpleJSON(SimpleLayouts.singleScreenApp))
12
     expect(uut.parseFromSimpleJSON(SimpleLayouts.singleScreenApp))
38
       .toEqual({
13
       .toEqual({
39
         type: 'ContainerStack',
14
         type: 'ContainerStack',
40
-        id: 'ContainerStack+UNIQUE_ID',
41
-        data: {},
42
         children: [
15
         children: [
43
           {
16
           {
44
             type: 'Container',
17
             type: 'Container',
45
-            id: 'Container+UNIQUE_ID',
46
             data: {
18
             data: {
47
               name: 'com.example.MyScreen'
19
               name: 'com.example.MyScreen'
48
             },
20
             },
56
     expect(uut.parseFromSimpleJSON(SimpleLayouts.singleScreenWithAditionalParams))
28
     expect(uut.parseFromSimpleJSON(SimpleLayouts.singleScreenWithAditionalParams))
57
       .toEqual({
29
       .toEqual({
58
         type: 'ContainerStack',
30
         type: 'ContainerStack',
59
-        id: 'ContainerStack+UNIQUE_ID',
60
-        data: {},
61
         children: [
31
         children: [
62
           {
32
           {
63
             type: 'Container',
33
             type: 'Container',
64
-            id: 'Container+UNIQUE_ID',
65
             children: [],
34
             children: [],
66
             data: {
35
             data: {
67
               name: 'com.example.MyScreen',
36
               name: 'com.example.MyScreen',
82
     expect(uut.parseFromSimpleJSON(SimpleLayouts.tabBasedApp))
51
     expect(uut.parseFromSimpleJSON(SimpleLayouts.tabBasedApp))
83
       .toEqual({
52
       .toEqual({
84
         type: 'Tabs',
53
         type: 'Tabs',
85
-        id: 'Tabs+UNIQUE_ID',
86
-        data: {},
87
         children: [
54
         children: [
88
           {
55
           {
89
             type: 'ContainerStack',
56
             type: 'ContainerStack',
90
-            id: 'ContainerStack+UNIQUE_ID',
91
-            data: {},
92
             children: [
57
             children: [
93
               {
58
               {
94
                 type: 'Container',
59
                 type: 'Container',
95
-                id: 'Container+UNIQUE_ID',
96
                 children: [],
60
                 children: [],
97
                 data: {
61
                 data: {
98
                   name: 'com.example.ATab'
62
                   name: 'com.example.ATab'
102
           },
66
           },
103
           {
67
           {
104
             type: 'ContainerStack',
68
             type: 'ContainerStack',
105
-            id: 'ContainerStack+UNIQUE_ID',
106
-            data: {},
107
             children: [
69
             children: [
108
               {
70
               {
109
                 type: 'Container',
71
                 type: 'Container',
110
-                id: 'Container+UNIQUE_ID',
111
                 children: [],
72
                 children: [],
112
                 data: {
73
                 data: {
113
                   name: 'com.example.SecondTab'
74
                   name: 'com.example.SecondTab'
117
           },
78
           },
118
           {
79
           {
119
             type: 'ContainerStack',
80
             type: 'ContainerStack',
120
-            id: 'ContainerStack+UNIQUE_ID',
121
-            data: {},
122
             children: [
81
             children: [
123
               {
82
               {
124
                 type: 'Container',
83
                 type: 'Container',
125
-                id: 'Container+UNIQUE_ID',
126
                 children: [],
84
                 children: [],
127
                 data: {
85
                 data: {
128
                   name: 'com.example.ATab'
86
                   name: 'com.example.ATab'
138
     expect(uut.parseFromSimpleJSON(SimpleLayouts.singleWithSideMenu))
96
     expect(uut.parseFromSimpleJSON(SimpleLayouts.singleWithSideMenu))
139
       .toEqual({
97
       .toEqual({
140
         type: 'SideMenuRoot',
98
         type: 'SideMenuRoot',
141
-        id: 'SideMenuRoot+UNIQUE_ID',
142
-        data: {},
143
         children: [
99
         children: [
144
           {
100
           {
145
             type: 'SideMenuLeft',
101
             type: 'SideMenuLeft',
146
-            id: 'SideMenuLeft+UNIQUE_ID',
147
-            data: {},
148
             children: [
102
             children: [
149
               {
103
               {
150
                 type: 'Container',
104
                 type: 'Container',
151
-                id: 'Container+UNIQUE_ID',
152
                 data: {
105
                 data: {
153
                   name: 'com.example.SideMenu'
106
                   name: 'com.example.SideMenu'
154
                 },
107
                 },
158
           },
111
           },
159
           {
112
           {
160
             type: 'SideMenuCenter',
113
             type: 'SideMenuCenter',
161
-            id: 'SideMenuCenter+UNIQUE_ID',
162
-            data: {},
163
             children: [
114
             children: [
164
               {
115
               {
165
                 type: 'ContainerStack',
116
                 type: 'ContainerStack',
166
-                id: 'ContainerStack+UNIQUE_ID',
167
-                data: {},
168
                 children: [
117
                 children: [
169
                   {
118
                   {
170
                     type: 'Container',
119
                     type: 'Container',
171
-                    id: 'Container+UNIQUE_ID',
172
                     data: {
120
                     data: {
173
                       name: 'com.example.MyScreen'
121
                       name: 'com.example.MyScreen'
174
                     },
122
                     },
186
     expect(uut.parseFromSimpleJSON(SimpleLayouts.singleWithRightSideMenu))
134
     expect(uut.parseFromSimpleJSON(SimpleLayouts.singleWithRightSideMenu))
187
       .toEqual({
135
       .toEqual({
188
         type: 'SideMenuRoot',
136
         type: 'SideMenuRoot',
189
-        id: 'SideMenuRoot+UNIQUE_ID',
190
-        data: {},
191
         children: [
137
         children: [
192
           {
138
           {
193
             type: 'SideMenuCenter',
139
             type: 'SideMenuCenter',
194
-            id: 'SideMenuCenter+UNIQUE_ID',
195
-            data: {},
196
             children: [
140
             children: [
197
               {
141
               {
198
                 type: 'ContainerStack',
142
                 type: 'ContainerStack',
199
-                id: 'ContainerStack+UNIQUE_ID',
200
-                data: {},
201
                 children: [
143
                 children: [
202
                   {
144
                   {
203
                     type: 'Container',
145
                     type: 'Container',
204
-                    id: 'Container+UNIQUE_ID',
205
                     data: {
146
                     data: {
206
                       name: 'com.example.MyScreen'
147
                       name: 'com.example.MyScreen'
207
                     },
148
                     },
213
           },
154
           },
214
           {
155
           {
215
             type: 'SideMenuRight',
156
             type: 'SideMenuRight',
216
-            id: 'SideMenuRight+UNIQUE_ID',
217
-            data: {},
218
             children: [
157
             children: [
219
               {
158
               {
220
                 type: 'Container',
159
                 type: 'Container',
221
-                id: 'Container+UNIQUE_ID',
222
                 data: {
160
                 data: {
223
                   name: 'com.example.SideMenu'
161
                   name: 'com.example.SideMenu'
224
                 },
162
                 },
234
     expect(uut.parseFromSimpleJSON(SimpleLayouts.singleWithBothMenus))
172
     expect(uut.parseFromSimpleJSON(SimpleLayouts.singleWithBothMenus))
235
       .toEqual({
173
       .toEqual({
236
         type: 'SideMenuRoot',
174
         type: 'SideMenuRoot',
237
-        id: 'SideMenuRoot+UNIQUE_ID',
238
-        data: {},
239
         children: [
175
         children: [
240
           {
176
           {
241
             type: 'SideMenuLeft',
177
             type: 'SideMenuLeft',
242
-            id: 'SideMenuLeft+UNIQUE_ID',
243
-            data: {},
244
             children: [
178
             children: [
245
               {
179
               {
246
                 type: 'Container',
180
                 type: 'Container',
247
-                id: 'Container+UNIQUE_ID',
248
                 data: {
181
                 data: {
249
                   name: 'com.example.Menu1'
182
                   name: 'com.example.Menu1'
250
                 },
183
                 },
254
           },
187
           },
255
           {
188
           {
256
             type: 'SideMenuCenter',
189
             type: 'SideMenuCenter',
257
-            id: 'SideMenuCenter+UNIQUE_ID',
258
-            data: {},
259
             children: [
190
             children: [
260
               {
191
               {
261
                 type: 'ContainerStack',
192
                 type: 'ContainerStack',
262
-                id: 'ContainerStack+UNIQUE_ID',
263
-                data: {},
264
                 children: [
193
                 children: [
265
                   {
194
                   {
266
                     type: 'Container',
195
                     type: 'Container',
267
-                    id: 'Container+UNIQUE_ID',
268
                     data: {
196
                     data: {
269
                       name: 'com.example.MyScreen'
197
                       name: 'com.example.MyScreen'
270
                     },
198
                     },
276
           },
204
           },
277
           {
205
           {
278
             type: 'SideMenuRight',
206
             type: 'SideMenuRight',
279
-            id: 'SideMenuRight+UNIQUE_ID',
280
-            data: {},
281
             children: [
207
             children: [
282
               {
208
               {
283
                 type: 'Container',
209
                 type: 'Container',
284
-                id: 'Container+UNIQUE_ID',
285
                 data: {
210
                 data: {
286
                   name: 'com.example.Menu2'
211
                   name: 'com.example.Menu2'
287
                 },
212
                 },
297
     expect(uut.parseFromSimpleJSON(SimpleLayouts.tabBasedWithBothSideMenus))
222
     expect(uut.parseFromSimpleJSON(SimpleLayouts.tabBasedWithBothSideMenus))
298
       .toEqual({
223
       .toEqual({
299
         type: 'SideMenuRoot',
224
         type: 'SideMenuRoot',
300
-        id: 'SideMenuRoot+UNIQUE_ID',
301
-        data: {},
302
         children: [
225
         children: [
303
           {
226
           {
304
             type: 'SideMenuLeft',
227
             type: 'SideMenuLeft',
305
-            id: 'SideMenuLeft+UNIQUE_ID',
306
-            data: {},
307
             children: [
228
             children: [
308
               {
229
               {
309
                 type: 'Container',
230
                 type: 'Container',
310
-                id: 'Container+UNIQUE_ID',
311
                 data: {
231
                 data: {
312
                   name: 'com.example.Menu1'
232
                   name: 'com.example.Menu1'
313
                 },
233
                 },
317
           },
237
           },
318
           {
238
           {
319
             type: 'SideMenuCenter',
239
             type: 'SideMenuCenter',
320
-            id: 'SideMenuCenter+UNIQUE_ID',
321
-            data: {},
322
             children: [
240
             children: [
323
               {
241
               {
324
                 type: 'Tabs',
242
                 type: 'Tabs',
325
-                id: 'Tabs+UNIQUE_ID',
326
-                data: {},
327
                 children: [
243
                 children: [
328
                   {
244
                   {
329
                     type: 'ContainerStack',
245
                     type: 'ContainerStack',
330
-                    id: 'ContainerStack+UNIQUE_ID',
331
-                    data: {},
332
                     children: [
246
                     children: [
333
                       {
247
                       {
334
                         type: 'Container',
248
                         type: 'Container',
335
-                        id: 'Container+UNIQUE_ID',
336
                         data: {
249
                         data: {
337
                           name: 'com.example.FirstTab'
250
                           name: 'com.example.FirstTab'
338
                         },
251
                         },
342
                   },
255
                   },
343
                   {
256
                   {
344
                     type: 'ContainerStack',
257
                     type: 'ContainerStack',
345
-                    id: 'ContainerStack+UNIQUE_ID',
346
-                    data: {},
347
                     children: [
258
                     children: [
348
                       {
259
                       {
349
                         type: 'Container',
260
                         type: 'Container',
350
-                        id: 'Container+UNIQUE_ID',
351
                         data: {
261
                         data: {
352
                           name: 'com.example.SecondTab'
262
                           name: 'com.example.SecondTab'
353
                         },
263
                         },
361
           },
271
           },
362
           {
272
           {
363
             type: 'SideMenuRight',
273
             type: 'SideMenuRight',
364
-            id: 'SideMenuRight+UNIQUE_ID',
365
-            data: {},
366
             children: [
274
             children: [
367
               {
275
               {
368
                 type: 'Container',
276
                 type: 'Container',
369
-                id: 'Container+UNIQUE_ID',
370
                 data: {
277
                 data: {
371
                   name: 'com.example.Menu2'
278
                   name: 'com.example.Menu2'
372
                 },
279
                 },

+ 9
- 0
src/commands/LayoutTypes.js View File

1
+export default {
2
+  Container: 'Container',
3
+  ContainerStack: 'ContainerStack',
4
+  Tabs: 'Tabs',
5
+  SideMenuRoot: 'SideMenuRoot',
6
+  SideMenuCenter: 'SideMenuCenter',
7
+  SideMenuLeft: 'SideMenuLeft',
8
+  SideMenuRight: 'SideMenuRight'
9
+};