blob: b09bcde897d7ff947032950a77ead79ef2836fdc [file] [log] [blame]
Jason Monk88529052016-11-04 13:29:58 -04001/*
Jason Monk340b0e52017-03-08 14:57:56 -05002 * Copyright (C) 2017 The Android Open Source Project
Jason Monk88529052016-11-04 13:29:58 -04003 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11 * KIND, either express or implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
Jason Monk340b0e52017-03-08 14:57:56 -050015package android.testing;
16
17import static org.junit.Assert.assertNotNull;
Jason Monk88529052016-11-04 13:29:58 -040018
19import android.annotation.Nullable;
20import android.app.Fragment;
21import android.app.FragmentController;
22import android.app.FragmentHostCallback;
23import android.app.FragmentManagerNonConfig;
Jason Monkde850bb2017-02-01 19:26:30 -050024import android.graphics.PixelFormat;
Jason Monk88529052016-11-04 13:29:58 -040025import android.os.Handler;
Jason Monk88529052016-11-04 13:29:58 -040026import android.os.Parcelable;
Jason Monk340b0e52017-03-08 14:57:56 -050027import android.support.test.InstrumentationRegistry;
Jason Monk88529052016-11-04 13:29:58 -040028import android.view.LayoutInflater;
29import android.view.View;
Jason Monkde850bb2017-02-01 19:26:30 -050030import android.view.WindowManager;
31import android.view.WindowManager.LayoutParams;
Jason Monk88529052016-11-04 13:29:58 -040032import android.widget.FrameLayout;
33
34import org.junit.After;
35import org.junit.Before;
Jason Monk340b0e52017-03-08 14:57:56 -050036import org.junit.Rule;
Jason Monk88529052016-11-04 13:29:58 -040037import org.junit.Test;
38
39import java.io.FileDescriptor;
40import java.io.PrintWriter;
41
42/**
43 * Base class for fragment class tests. Just adding one for any fragment will push it through
44 * general lifecycle events and ensure no basic leaks are happening. This class also implements
45 * the host for subclasses, so they can push it into desired states and do any unit testing
46 * required.
47 */
Jason Monk340b0e52017-03-08 14:57:56 -050048public abstract class BaseFragmentTest {
Jason Monk88529052016-11-04 13:29:58 -040049
50 private static final int VIEW_ID = 42;
51 private final Class<? extends Fragment> mCls;
Jason Monk88529052016-11-04 13:29:58 -040052 private Handler mHandler;
53 private FrameLayout mView;
54 protected FragmentController mFragments;
55 protected Fragment mFragment;
56
Jason Monk340b0e52017-03-08 14:57:56 -050057 @Rule
58 public final TestableContext mContext = getContext();
59
60 public BaseFragmentTest(Class<? extends Fragment> cls) {
Jason Monk88529052016-11-04 13:29:58 -040061 mCls = cls;
62 }
63
64 @Before
Jason Monk28d5d222017-02-02 13:08:31 -050065 public void setupFragment() throws Exception {
Jason Monk88529052016-11-04 13:29:58 -040066 mView = new FrameLayout(mContext);
67 mView.setId(VIEW_ID);
Jason Monk28d5d222017-02-02 13:08:31 -050068
Jason Monk340b0e52017-03-08 14:57:56 -050069 assertNotNull("BaseFragmentTest must be tagged with @RunWithLooper",
70 TestableLooper.get(this));
Jason Monk28d5d222017-02-02 13:08:31 -050071 TestableLooper.get(this).runWithLooper(() -> {
72 mHandler = new Handler();
73
74 mFragment = mCls.newInstance();
Jason Monk88529052016-11-04 13:29:58 -040075 mFragments = FragmentController.createController(new HostCallbacks());
76 mFragments.attachHost(null);
77 mFragments.getFragmentManager().beginTransaction()
78 .replace(VIEW_ID, mFragment)
79 .commit();
80 });
81 }
82
Jason Monk340b0e52017-03-08 14:57:56 -050083 protected TestableContext getContext() {
84 return new TestableContext(InstrumentationRegistry.getContext());
Jason Monk28d5d222017-02-02 13:08:31 -050085 }
86
Jason Monk88529052016-11-04 13:29:58 -040087 @After
Jason Monk28d5d222017-02-02 13:08:31 -050088 public void tearDown() throws Exception {
Jason Monk88529052016-11-04 13:29:58 -040089 if (mFragments != null) {
90 // Set mFragments to null to let it know not to destroy.
Jason Monk28d5d222017-02-02 13:08:31 -050091 TestableLooper.get(this).runWithLooper(() -> mFragments.dispatchDestroy());
Jason Monk88529052016-11-04 13:29:58 -040092 }
Jason Monk88529052016-11-04 13:29:58 -040093 }
94
95 @Test
96 public void testCreateDestroy() {
Jason Monk28d5d222017-02-02 13:08:31 -050097 mFragments.dispatchCreate();
98 processAllMessages();
Jason Monk88529052016-11-04 13:29:58 -040099 destroyFragments();
100 }
101
102 @Test
103 public void testStartStop() {
Jason Monk28d5d222017-02-02 13:08:31 -0500104 mFragments.dispatchStart();
105 processAllMessages();
106 mFragments.dispatchStop();
107 processAllMessages();
Jason Monk88529052016-11-04 13:29:58 -0400108 }
109
110 @Test
111 public void testResumePause() {
Jason Monk28d5d222017-02-02 13:08:31 -0500112 mFragments.dispatchResume();
113 processAllMessages();
114 mFragments.dispatchPause();
115 processAllMessages();
Jason Monk88529052016-11-04 13:29:58 -0400116 }
117
118 @Test
Jason Monkde850bb2017-02-01 19:26:30 -0500119 public void testAttachDetach() {
120 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
121 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
122 LayoutParams.TYPE_SYSTEM_ALERT,
123 0, PixelFormat.TRANSLUCENT);
Jason Monk28d5d222017-02-02 13:08:31 -0500124 mFragments.dispatchResume();
125 processAllMessages();
Jason Monkde850bb2017-02-01 19:26:30 -0500126 attachFragmentToWindow();
127 detachFragmentToWindow();
Jason Monk28d5d222017-02-02 13:08:31 -0500128 mFragments.dispatchPause();
129 processAllMessages();
Jason Monkde850bb2017-02-01 19:26:30 -0500130 }
131
132 @Test
Jason Monk88529052016-11-04 13:29:58 -0400133 public void testRecreate() {
Jason Monk28d5d222017-02-02 13:08:31 -0500134 mFragments.dispatchResume();
135 processAllMessages();
Jason Monk64b214e2017-03-27 13:40:59 -0400136 recreateFragment();
Jason Monk28d5d222017-02-02 13:08:31 -0500137 processAllMessages();
Jason Monk88529052016-11-04 13:29:58 -0400138 }
139
140 @Test
141 public void testMultipleResumes() {
Jason Monk28d5d222017-02-02 13:08:31 -0500142 mFragments.dispatchResume();
143 processAllMessages();
144 mFragments.dispatchStop();
145 processAllMessages();
146 mFragments.dispatchResume();
147 processAllMessages();
148 }
149
Jason Monk64b214e2017-03-27 13:40:59 -0400150 protected void recreateFragment() {
151 mFragments.dispatchPause();
152 Parcelable p = mFragments.saveAllState();
153 mFragments.dispatchDestroy();
154
155 mFragments = FragmentController.createController(new HostCallbacks());
156 mFragments.attachHost(null);
157 mFragments.restoreAllState(p, (FragmentManagerNonConfig) null);
158 mFragments.dispatchResume();
159 mFragment = mFragments.getFragmentManager().findFragmentById(VIEW_ID);
160 }
161
Jason Monk28d5d222017-02-02 13:08:31 -0500162 protected void attachFragmentToWindow() {
163 ViewUtils.attachView(mView);
164 TestableLooper.get(this).processMessages(1);
165 }
166
167 protected void detachFragmentToWindow() {
168 ViewUtils.detachView(mView);
169 TestableLooper.get(this).processMessages(1);
Jason Monk88529052016-11-04 13:29:58 -0400170 }
171
172 protected void destroyFragments() {
Jason Monk28d5d222017-02-02 13:08:31 -0500173 mFragments.dispatchDestroy();
174 processAllMessages();
Jason Monk88529052016-11-04 13:29:58 -0400175 mFragments = null;
176 }
177
Jason Monk28d5d222017-02-02 13:08:31 -0500178 protected void processAllMessages() {
179 TestableLooper.get(this).processAllMessages();
Jason Monk88529052016-11-04 13:29:58 -0400180 }
181
182 private View findViewById(int id) {
183 return mView.findViewById(id);
184 }
185
Jason Monk340b0e52017-03-08 14:57:56 -0500186 private class HostCallbacks extends FragmentHostCallback<BaseFragmentTest> {
Jason Monk88529052016-11-04 13:29:58 -0400187 public HostCallbacks() {
Jason Monk340b0e52017-03-08 14:57:56 -0500188 super(mContext, BaseFragmentTest.this.mHandler, 0);
Jason Monk88529052016-11-04 13:29:58 -0400189 }
190
191 @Override
Jason Monk340b0e52017-03-08 14:57:56 -0500192 public BaseFragmentTest onGetHost() {
193 return BaseFragmentTest.this;
Jason Monk88529052016-11-04 13:29:58 -0400194 }
195
196 @Override
197 public void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
198 }
199
200 @Override
201 public boolean onShouldSaveFragmentState(Fragment fragment) {
202 return true; // True for now.
203 }
204
205 @Override
206 public LayoutInflater onGetLayoutInflater() {
207 return LayoutInflater.from(mContext);
208 }
209
210 @Override
211 public boolean onUseFragmentManagerInflaterFactory() {
212 return true;
213 }
214
215 @Override
216 public boolean onHasWindowAnimations() {
217 return false;
218 }
219
220 @Override
221 public int onGetWindowAnimations() {
222 return 0;
223 }
224
225 @Override
226 public void onAttachFragment(Fragment fragment) {
227 }
228
229 @Nullable
230 @Override
231 public View onFindViewById(int id) {
Jason Monk340b0e52017-03-08 14:57:56 -0500232 return BaseFragmentTest.this.findViewById(id);
Jason Monk88529052016-11-04 13:29:58 -0400233 }
234
235 @Override
236 public boolean onHasView() {
237 return true;
238 }
239 }
240}