소스 검색

Merge child options when child appears

Guy Carmeli 6 년 전
부모
커밋
5114fdfe4c

+ 7
- 0
lib/android/app/src/main/java/com/reactnativenavigation/parse/Options.java 파일 보기

54
         topTabOptions.tabIndex = i;
54
         topTabOptions.tabIndex = i;
55
     }
55
     }
56
 
56
 
57
+    @CheckResult
58
+    public Options copy() {
59
+        return new Options().mergeWith(this);
60
+    }
61
+
57
     @CheckResult
62
     @CheckResult
58
 	public Options mergeWith(final Options other) {
63
 	public Options mergeWith(final Options other) {
59
         Options result = new Options();
64
         Options result = new Options();
60
         result.topBarOptions.mergeWith(other.topBarOptions);
65
         result.topBarOptions.mergeWith(other.topBarOptions);
61
         result.topTabsOptions.mergeWith(other.topTabsOptions);
66
         result.topTabsOptions.mergeWith(other.topTabsOptions);
67
+        result.topTabOptions.mergeWith(other.topTabOptions);
62
         result.bottomTabOptions.mergeWith(other.bottomTabOptions);
68
         result.bottomTabOptions.mergeWith(other.bottomTabOptions);
63
         result.bottomTabsOptions.mergeWith(other.bottomTabsOptions);
69
         result.bottomTabsOptions.mergeWith(other.bottomTabsOptions);
64
         return result;
70
         return result;
66
 
72
 
67
     Options withDefaultOptions(final Options other) {
73
     Options withDefaultOptions(final Options other) {
68
         topBarOptions.mergeWithDefault(other.topBarOptions);
74
         topBarOptions.mergeWithDefault(other.topBarOptions);
75
+        topTabOptions.mergeWithDefault(other.topTabOptions);
69
         topTabsOptions.mergeWithDefault(other.topTabsOptions);
76
         topTabsOptions.mergeWithDefault(other.topTabsOptions);
70
         bottomTabOptions.mergeWithDefault(other.bottomTabOptions);
77
         bottomTabOptions.mergeWithDefault(other.bottomTabOptions);
71
         bottomTabsOptions.mergeWithDefault(other.bottomTabsOptions);
78
         bottomTabsOptions.mergeWithDefault(other.bottomTabsOptions);

+ 6
- 4
lib/android/app/src/main/java/com/reactnativenavigation/parse/TopTabOptions.java 파일 보기

21
         return result;
21
         return result;
22
     }
22
     }
23
 
23
 
24
-    void mergeWith(TopTabOptions topTabsOptions) {
25
-
24
+    void mergeWith(TopTabOptions other) {
25
+        if (other.title.hasValue()) title = other.title;
26
+        if (other.fontFamily != null) fontFamily = other.fontFamily;
27
+        if (other.tabIndex >= 0) tabIndex = other.tabIndex;
26
     }
28
     }
27
 
29
 
28
-    void mergeWithDefault(TopTabOptions topTabsOptions) {
29
-
30
+    void mergeWithDefault(TopTabOptions other) {
31
+        if (fontFamily == null) fontFamily = other.fontFamily;
30
     }
32
     }
31
 }
33
 }

+ 5
- 0
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ParentController.java 파일 보기

58
 
58
 
59
     @CallSuper
59
     @CallSuper
60
     public void applyOptions(Options options, ReactComponent childComponent) {
60
     public void applyOptions(Options options, ReactComponent childComponent) {
61
+        mergeChildOptions(options);
62
+        applyOnParentController(parentController -> ((ParentController) parentController).applyOptions(this.options, childComponent));
63
+    }
64
+
65
+    private void mergeChildOptions(Options options) {
61
         this.options = this.options.mergeWith(options);
66
         this.options = this.options.mergeWith(options);
62
     }
67
     }
63
 
68
 

+ 0
- 1
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/StackController.java 파일 보기

38
     public void applyOptions(Options options, ReactComponent component) {
38
     public void applyOptions(Options options, ReactComponent component) {
39
         super.applyOptions(options, component);
39
         super.applyOptions(options, component);
40
         stackLayout.applyOptions(this.options, component);
40
         stackLayout.applyOptions(this.options, component);
41
-        applyOnParentController(parentController -> ((ParentController) parentController).applyOptions(this.options, component));
42
     }
41
     }
43
 
42
 
44
     @Override
43
     @Override

+ 3
- 1
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/ViewController.java 파일 보기

30
         boolean onViewDisappear(View view);
30
         boolean onViewDisappear(View view);
31
     }
31
     }
32
 
32
 
33
+    Options initialOptions;
33
     public Options options;
34
     public Options options;
34
 
35
 
35
     private final Activity activity;
36
     private final Activity activity;
43
     public ViewController(Activity activity, String id, Options initialOptions) {
44
     public ViewController(Activity activity, String id, Options initialOptions) {
44
         this.activity = activity;
45
         this.activity = activity;
45
         this.id = id;
46
         this.id = id;
46
-        options = initialOptions;
47
+        this.initialOptions = initialOptions;
48
+        options = initialOptions.copy();
47
     }
49
     }
48
 
50
 
49
     protected abstract T createView();
51
     protected abstract T createView();

+ 0
- 1
lib/android/app/src/main/java/com/reactnativenavigation/viewcontrollers/toptabs/TopTabsController.java 파일 보기

70
     @Override
70
     @Override
71
     public void applyOptions(Options options, ReactComponent childComponent) {
71
     public void applyOptions(Options options, ReactComponent childComponent) {
72
         super.applyOptions(options, childComponent);
72
         super.applyOptions(options, childComponent);
73
-        applyOnParentController(parentController -> ((ParentController) parentController).applyOptions(this.options, childComponent));
74
     }
73
     }
75
 
74
 
76
     @Override
75
     @Override

+ 6
- 8
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/OptionsApplyingTest.java 파일 보기

59
 
59
 
60
     @Test
60
     @Test
61
     public void initialOptionsAppliedOnAppear() throws Exception {
61
     public void initialOptionsAppliedOnAppear() throws Exception {
62
-        assertThat(uut.options).isSameAs(initialNavigationOptions);
63
-        initialNavigationOptions.topBarOptions.title = new Text("the title");
62
+        uut.options.topBarOptions.title = new Text("the title");
64
         StackController stackController = new StackController(activity, "stackId", new Options());
63
         StackController stackController = new StackController(activity, "stackId", new Options());
65
         stackController.animatePush(uut, new MockPromise() {});
64
         stackController.animatePush(uut, new MockPromise() {});
66
         assertThat(stackController.getTopBar().getTitle()).isEmpty();
65
         assertThat(stackController.getTopBar().getTitle()).isEmpty();
106
 
105
 
107
     @Test
106
     @Test
108
     public void appliesTopBarTextColor() throws Exception {
107
     public void appliesTopBarTextColor() throws Exception {
109
-        assertThat(uut.options).isSameAs(initialNavigationOptions);
108
+        assertThat(uut.initialOptions).isSameAs(initialNavigationOptions);
110
         stackController.animatePush(uut, new MockPromise() {
109
         stackController.animatePush(uut, new MockPromise() {
111
             @Override
110
             @Override
112
             public void resolve(@Nullable Object value) {
111
             public void resolve(@Nullable Object value) {
123
 
122
 
124
     @Test
123
     @Test
125
     public void appliesTopBarTextSize() throws Exception {
124
     public void appliesTopBarTextSize() throws Exception {
126
-        assertThat(uut.options).isSameAs(initialNavigationOptions);
125
+        assertThat(uut.initialOptions).isSameAs(initialNavigationOptions);
127
         initialNavigationOptions.topBarOptions.title = new Text("the title");
126
         initialNavigationOptions.topBarOptions.title = new Text("the title");
128
         uut.ensureViewIsCreated();
127
         uut.ensureViewIsCreated();
129
         uut.onViewAppeared();
128
         uut.onViewAppeared();
139
 
138
 
140
     @Test
139
     @Test
141
     public void appliesTopBarHidden() throws Exception {
140
     public void appliesTopBarHidden() throws Exception {
142
-        assertThat(uut.options).isSameAs(initialNavigationOptions);
141
+        assertThat(uut.initialOptions).isSameAs(initialNavigationOptions);
143
         initialNavigationOptions.topBarOptions.title = new Text("the title");
142
         initialNavigationOptions.topBarOptions.title = new Text("the title");
144
         uut.ensureViewIsCreated();
143
         uut.ensureViewIsCreated();
145
         uut.onViewAppeared();
144
         uut.onViewAppeared();
154
 
153
 
155
     @Test
154
     @Test
156
     public void appliesDrawUnder() throws Exception {
155
     public void appliesDrawUnder() throws Exception {
157
-        assertThat(uut.options).isSameAs(initialNavigationOptions);
158
-        initialNavigationOptions.topBarOptions.title = new Text("the title");
159
-        initialNavigationOptions.topBarOptions.drawBehind = Options.BooleanOptions.False;
156
+        uut.options.topBarOptions.title = new Text("the title");
157
+        uut.options.topBarOptions.drawBehind = Options.BooleanOptions.False;
160
         uut.ensureViewIsCreated();
158
         uut.ensureViewIsCreated();
161
         uut.onViewAppeared();
159
         uut.onViewAppeared();
162
         stackController.animatePush(uut, new MockPromise() {
160
         stackController.animatePush(uut, new MockPromise() {

+ 61
- 14
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/ParentControllerTest.java 파일 보기

1
 package com.reactnativenavigation.viewcontrollers;
1
 package com.reactnativenavigation.viewcontrollers;
2
 
2
 
3
-import android.app.*;
4
-import android.support.annotation.*;
5
-import android.view.*;
6
-import android.widget.*;
7
-
8
-import com.reactnativenavigation.*;
9
-import com.reactnativenavigation.mocks.*;
3
+import android.app.Activity;
4
+import android.support.annotation.NonNull;
5
+import android.view.ViewGroup;
6
+import android.widget.FrameLayout;
7
+
8
+import com.reactnativenavigation.BaseTest;
9
+import com.reactnativenavigation.mocks.MockPromise;
10
+import com.reactnativenavigation.mocks.SimpleViewController;
10
 import com.reactnativenavigation.parse.Options;
11
 import com.reactnativenavigation.parse.Options;
12
+import com.reactnativenavigation.parse.Text;
13
+import com.reactnativenavigation.views.ReactComponent;
11
 
14
 
12
-import org.junit.*;
15
+import org.junit.Test;
16
+import org.mockito.ArgumentCaptor;
13
 
17
 
14
-import java.util.*;
18
+import java.util.ArrayList;
19
+import java.util.Collection;
20
+import java.util.List;
15
 
21
 
16
-import static org.assertj.core.api.Java6Assertions.*;
17
-import static org.mockito.Mockito.*;
22
+import static org.assertj.core.api.Java6Assertions.assertThat;
23
+import static org.mockito.Mockito.spy;
24
+import static org.mockito.Mockito.times;
25
+import static org.mockito.Mockito.verify;
18
 
26
 
19
 public class ParentControllerTest extends BaseTest {
27
 public class ParentControllerTest extends BaseTest {
20
 
28
 
29
+    public static final String INITIAL_TITLE = "initial title";
21
     private Activity activity;
30
     private Activity activity;
22
     private List<ViewController> children;
31
     private List<ViewController> children;
23
     private ParentController uut;
32
     private ParentController uut;
27
         super.beforeEach();
36
         super.beforeEach();
28
         activity = newActivity();
37
         activity = newActivity();
29
         children = new ArrayList<>();
38
         children = new ArrayList<>();
30
-        uut = new ParentController(activity, "uut", new Options()) {
39
+        Options initialOptions = new Options();
40
+        initialOptions.topBarOptions.title = new Text(INITIAL_TITLE);
41
+        uut = spy(new ParentController(activity, "uut", initialOptions) {
31
 
42
 
32
             @NonNull
43
             @NonNull
33
             @Override
44
             @Override
34
             protected ViewGroup createView() {
45
             protected ViewGroup createView() {
35
-                return new FrameLayout(activity);
46
+                FrameLayout layout = new FrameLayout(activity);
47
+                for (ViewController child : children) {
48
+                    child.setParentController(this);
49
+                    layout.addView(child.getView());
50
+                }
51
+                return layout;
36
             }
52
             }
37
 
53
 
38
             @NonNull
54
             @NonNull
40
             public Collection<ViewController> getChildControllers() {
56
             public Collection<ViewController> getChildControllers() {
41
                 return children;
57
                 return children;
42
             }
58
             }
43
-        };
59
+        });
44
     }
60
     }
45
 
61
 
46
     @Test
62
     @Test
95
         child1.onViewAppeared();
111
         child1.onViewAppeared();
96
         verify(stackController, times(1)).clearOptions();
112
         verify(stackController, times(1)).clearOptions();
97
     }
113
     }
114
+
115
+    @Test
116
+    public void mergeOptions_optionsAreMergedWhenChildAppears() throws Exception {
117
+        Options options = new Options();
118
+        options.topBarOptions.title = new Text("new title");
119
+        ViewController child1 = spy(new SimpleViewController(activity, "child1", options));
120
+        children.add(child1);
121
+        uut.ensureViewIsCreated();
122
+
123
+        child1.ensureViewIsCreated();
124
+        child1.onViewAppeared();
125
+        ArgumentCaptor<Options> optionsCaptor = ArgumentCaptor.forClass(Options.class);
126
+        ArgumentCaptor<ReactComponent> viewCaptor = ArgumentCaptor.forClass(ReactComponent.class);
127
+        verify(uut, times(1)).applyOptions(optionsCaptor.capture(), viewCaptor.capture());
128
+        assertThat(optionsCaptor.getValue().topBarOptions.title.get()).isEqualTo("new title");
129
+        assertThat(viewCaptor.getValue()).isEqualTo(child1.getView());
130
+    }
131
+
132
+    @Test
133
+    public void mergeOptions_initialParentOptionsAreNotMutatedWhenChildAppears() throws Exception {
134
+        Options options = new Options();
135
+        options.topBarOptions.title = new Text("new title");
136
+        ViewController child1 = spy(new SimpleViewController(activity, "child1", options));
137
+        children.add(child1);
138
+
139
+        uut.ensureViewIsCreated();
140
+
141
+        child1.ensureViewIsCreated();
142
+        child1.onViewAppeared();
143
+        assertThat(uut.initialOptions.topBarOptions.title.get()).isEqualTo(INITIAL_TITLE);
144
+    }
98
 }
145
 }

+ 17
- 4
lib/android/app/src/test/java/com/reactnativenavigation/viewcontrollers/TopTabsViewControllerTest.java 파일 보기

15
 import com.reactnativenavigation.views.TopTabsLayoutCreator;
15
 import com.reactnativenavigation.views.TopTabsLayoutCreator;
16
 import com.reactnativenavigation.views.TopTabsViewPager;
16
 import com.reactnativenavigation.views.TopTabsViewPager;
17
 
17
 
18
+import org.assertj.core.api.Assertions;
18
 import org.junit.Test;
19
 import org.junit.Test;
19
 import org.mockito.Mockito;
20
 import org.mockito.Mockito;
20
 
21
 
62
         for (int i = 0; i < SIZE; i++) {
63
         for (int i = 0; i < SIZE; i++) {
63
             final Options options = new Options();
64
             final Options options = new Options();
64
             options.topTabOptions.title = new Text("Tab " + i);
65
             options.topTabOptions.title = new Text("Tab " + i);
65
-            options.topBarOptions.title = new Text("Title " + i);
66
+            options.topBarOptions.title = new Text(createTabTopBarTitle(i));
66
             result.add(options);
67
             result.add(options);
67
         }
68
         }
68
         return result;
69
         return result;
162
         tabControllers.get(1).ensureViewIsCreated();
163
         tabControllers.get(1).ensureViewIsCreated();
163
 
164
 
164
         uut.onViewAppeared();
165
         uut.onViewAppeared();
165
-        verify(uut, times(1)).applyOptions(tabOptions.get(0), tabView(0));
166
+        ReactComponent currentTab = tabView(0);
167
+        verify(uut, times(1)).applyOptions(any(Options.class), eq(currentTab));
168
+        Assertions.assertThat(uut.options.topBarOptions.title.get()).isEqualTo(createTabTopBarTitle(0));
169
+
166
         uut.switchToTab(1);
170
         uut.switchToTab(1);
167
-        verify(uut, times(1)).applyOptions(tabOptions.get(1), tabView(1));
171
+        currentTab = tabView(1);
172
+        verify(uut, times(1)).applyOptions(any(Options.class), eq(currentTab));
173
+        Assertions.assertThat(uut.options.topBarOptions.title.get()).isEqualTo(createTabTopBarTitle(1));
174
+
168
         uut.switchToTab(0);
175
         uut.switchToTab(0);
169
-        verify(uut, times(2)).applyOptions(tabOptions.get(0), tabView(0));
176
+        currentTab = tabView(0);
177
+        verify(uut, times(2)).applyOptions(any(Options.class), eq(currentTab));
178
+        Assertions.assertThat(uut.options.topBarOptions.title.get()).isEqualTo(createTabTopBarTitle(0));
170
     }
179
     }
171
 
180
 
172
     private TestReactView getActualTabView(int index) {
181
     private TestReactView getActualTabView(int index) {
187
     private IReactView tab(TopTabsViewPager topTabs, final int index) {
196
     private IReactView tab(TopTabsViewPager topTabs, final int index) {
188
         return (IReactView) ((ViewGroup) topTabs.getChildAt(index)).getChildAt(0);
197
         return (IReactView) ((ViewGroup) topTabs.getChildAt(index)).getChildAt(0);
189
     }
198
     }
199
+
200
+    private String createTabTopBarTitle(int i) {
201
+        return "Title " + i;
202
+    }
190
 }
203
 }