1 /* 2 * Copyright 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.wear.widget; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertNull; 22 import static org.junit.Assert.fail; 23 24 import android.app.Activity; 25 import android.support.test.annotation.UiThreadTest; 26 import android.support.test.filters.MediumTest; 27 import android.support.test.rule.ActivityTestRule; 28 import android.support.test.runner.AndroidJUnit4; 29 import android.view.View; 30 import android.view.ViewGroup; 31 import android.widget.LinearLayout; 32 import android.widget.TextView; 33 34 import androidx.wear.R; 35 import androidx.wear.widget.util.WakeLockRule; 36 37 import org.junit.Before; 38 import org.junit.Rule; 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 import org.mockito.Mock; 42 import org.mockito.MockitoAnnotations; 43 44 import java.util.concurrent.CountDownLatch; 45 import java.util.concurrent.TimeUnit; 46 47 @MediumTest 48 @RunWith(AndroidJUnit4.class) 49 public class ConfirmationOverlayTest { 50 51 @Rule 52 public final WakeLockRule wakeLock = new WakeLockRule(); 53 54 @Rule 55 public final ActivityTestRule<ConfirmationOverlayTestActivity> mActivityRule = 56 new ActivityTestRule<>(ConfirmationOverlayTestActivity.class, true, true); 57 58 @Mock 59 private ConfirmationOverlay.OnAnimationFinishedListener mOnAnimationFinishedListener; 60 61 private LinearLayout mLinearLayout; 62 private TextView mActualTextView; 63 64 @Before 65 public void setUp() { 66 MockitoAnnotations.initMocks(this); 67 } 68 69 private Activity setupActivity() { 70 Activity activity = mActivityRule.getActivity(); 71 mLinearLayout = new LinearLayout(activity); 72 activity.setContentView(mLinearLayout); 73 return activity; 74 } 75 76 @Test 77 public void testDefaults_onActivity() throws Throwable { 78 final CountDownLatch latch = new CountDownLatch(1); 79 final ConfirmationOverlay overlay = new ConfirmationOverlay(); 80 81 mActivityRule.runOnUiThread(new Runnable() { 82 @Override 83 public void run() { 84 final Activity activity = setupActivity(); 85 overlay.showOn(activity); 86 getOverlayViews(getContentView(activity)); 87 assertEquals(View.GONE, mActualTextView.getVisibility()); 88 ConfirmationOverlay.OnAnimationFinishedListener onAnimationFinishedListener = 89 new ConfirmationOverlay.OnAnimationFinishedListener() { 90 @Override 91 public void onAnimationFinished() { 92 latch.countDown(); 93 } 94 }; 95 overlay.setFinishedAnimationListener(onAnimationFinishedListener); 96 overlay.hide(); 97 } 98 }); 99 latch.await(5000, TimeUnit.MILLISECONDS); 100 assertEquals(0, latch.getCount()); 101 assertNull(getContentView(mActivityRule.getActivity())); 102 } 103 104 @Test 105 @UiThreadTest 106 public void testDefaults_onView() { 107 setupActivity(); 108 ConfirmationOverlay overlay = new ConfirmationOverlay(); 109 110 overlay.showAbove(mLinearLayout); 111 getOverlayViews(mLinearLayout.getRootView()); 112 assertEquals(View.GONE, mActualTextView.getVisibility()); 113 114 overlay.hide(); 115 assertEquals(0, mLinearLayout.getChildCount()); 116 } 117 118 @Test 119 public void testSuccess_onActivity() throws Throwable { 120 final CountDownLatch latch = new CountDownLatch(1); 121 final ConfirmationOverlay overlay = new ConfirmationOverlay() 122 .setType(ConfirmationOverlay.SUCCESS_ANIMATION) 123 .setFinishedAnimationListener(mOnAnimationFinishedListener) 124 .setMessage("Sent"); 125 126 mActivityRule.runOnUiThread(new Runnable() { 127 @Override 128 public void run() { 129 final Activity activity = setupActivity(); 130 overlay.showOn(activity); 131 getOverlayViews(getContentView(activity)); 132 assertEquals("Sent", mActualTextView.getText()); 133 ConfirmationOverlay.OnAnimationFinishedListener onAnimationFinishedListener = 134 new ConfirmationOverlay.OnAnimationFinishedListener() { 135 @Override 136 public void onAnimationFinished() { 137 latch.countDown(); 138 } 139 }; 140 overlay.setFinishedAnimationListener(onAnimationFinishedListener); 141 overlay.hide(); 142 } 143 }); 144 latch.await(5000, TimeUnit.MILLISECONDS); 145 assertEquals(0, latch.getCount()); 146 assertNull(getContentView(mActivityRule.getActivity())); 147 } 148 149 @Test 150 public void testFailure_onActivity() throws Throwable { 151 final CountDownLatch latch = new CountDownLatch(1); 152 final ConfirmationOverlay overlay = new ConfirmationOverlay() 153 .setType(ConfirmationOverlay.FAILURE_ANIMATION) 154 .setFinishedAnimationListener(mOnAnimationFinishedListener) 155 .setMessage("Failed"); 156 157 mActivityRule.runOnUiThread(new Runnable() { 158 @Override 159 public void run() { 160 final Activity activity = setupActivity(); 161 overlay.showOn(activity); 162 getOverlayViews(getContentView(activity)); 163 assertEquals("Failed", mActualTextView.getText()); 164 ConfirmationOverlay.OnAnimationFinishedListener onAnimationFinishedListener = 165 new ConfirmationOverlay.OnAnimationFinishedListener() { 166 @Override 167 public void onAnimationFinished() { 168 latch.countDown(); 169 } 170 }; 171 overlay.setFinishedAnimationListener(onAnimationFinishedListener); 172 overlay.hide(); 173 } 174 }); 175 latch.await(5000, TimeUnit.MILLISECONDS); 176 assertEquals(0, latch.getCount()); 177 assertNull(getContentView(mActivityRule.getActivity())); 178 } 179 180 @Test 181 public void testOpenOnPhone_onActivity() throws Throwable { 182 final CountDownLatch latch = new CountDownLatch(1); 183 final ConfirmationOverlay overlay = new ConfirmationOverlay() 184 .setType(ConfirmationOverlay.OPEN_ON_PHONE_ANIMATION) 185 .setFinishedAnimationListener(mOnAnimationFinishedListener) 186 .setMessage("Opening..."); 187 188 mActivityRule.runOnUiThread(new Runnable() { 189 @Override 190 public void run() { 191 final Activity activity = setupActivity(); 192 overlay.showOn(activity); 193 getOverlayViews(getContentView(activity)); 194 assertEquals("Opening...", mActualTextView.getText()); 195 ConfirmationOverlay.OnAnimationFinishedListener onAnimationFinishedListener = 196 new ConfirmationOverlay.OnAnimationFinishedListener() { 197 @Override 198 public void onAnimationFinished() { 199 latch.countDown(); 200 } 201 }; 202 overlay.setFinishedAnimationListener(onAnimationFinishedListener); 203 overlay.hide(); 204 } 205 }); 206 latch.await(5000, TimeUnit.MILLISECONDS); 207 assertEquals(0, latch.getCount()); 208 assertNull(getContentView(mActivityRule.getActivity())); 209 } 210 211 @Test 212 @UiThreadTest 213 public void testThrowsExceptionOnInvalidType() { 214 Activity activity = setupActivity(); 215 try { 216 new ConfirmationOverlay().setType(-1).showOn(activity); 217 fail("Expected ConfirmationOverlay to throw an exception when given an invalid type."); 218 } catch (IllegalStateException e) { 219 // Success. 220 } 221 } 222 223 @Test 224 public void testOverlayVisibleDuringSpecifiedDuration() throws Throwable { 225 final CountDownLatch latch = new CountDownLatch(1); 226 final int overlayDurationMillis = 2000; 227 final ConfirmationOverlay overlay = 228 new ConfirmationOverlay() 229 .setType(ConfirmationOverlay.SUCCESS_ANIMATION) 230 .setDuration(overlayDurationMillis); 231 232 mActivityRule.runOnUiThread(new Runnable() { 233 @Override 234 public void run() { 235 final Activity activity = setupActivity(); 236 overlay.showOn(activity); 237 ConfirmationOverlay.OnAnimationFinishedListener onAnimationFinishedListener = 238 new ConfirmationOverlay.OnAnimationFinishedListener() { 239 @Override 240 public void onAnimationFinished() { 241 latch.countDown(); 242 } 243 }; 244 overlay.setFinishedAnimationListener(onAnimationFinishedListener); 245 } 246 }); 247 latch.await(overlayDurationMillis - 1000, TimeUnit.MILLISECONDS); 248 assertEquals(1, latch.getCount()); 249 assertNotNull(getContentView(mActivityRule.getActivity())); 250 } 251 252 @Test 253 public void testOverlayHiddenAfterSpecifiedDuration() throws Throwable { 254 final CountDownLatch latch = new CountDownLatch(1); 255 final int overlayDurationMillis = 2000; 256 final ConfirmationOverlay overlay = 257 new ConfirmationOverlay() 258 .setType(ConfirmationOverlay.SUCCESS_ANIMATION) 259 .setDuration(overlayDurationMillis); 260 261 mActivityRule.runOnUiThread(new Runnable() { 262 @Override 263 public void run() { 264 final Activity activity = setupActivity(); 265 overlay.showOn(activity); 266 ConfirmationOverlay.OnAnimationFinishedListener onAnimationFinishedListener = 267 new ConfirmationOverlay.OnAnimationFinishedListener() { 268 @Override 269 public void onAnimationFinished() { 270 latch.countDown(); 271 } 272 }; 273 overlay.setFinishedAnimationListener(onAnimationFinishedListener); 274 } 275 }); 276 latch.await(overlayDurationMillis + 100, TimeUnit.MILLISECONDS); 277 assertEquals(0, latch.getCount()); 278 assertNull(getContentView(mActivityRule.getActivity())); 279 } 280 281 private static View getContentView(Activity activity) { 282 ViewGroup viewGroup = activity.getWindow().findViewById(android.R.id.content); 283 284 // Return the second child, since the first is the LinearLayout added in setup(). 285 return viewGroup.getChildAt(1); 286 } 287 288 private void getOverlayViews(View parent) { 289 mActualTextView = parent.findViewById(R.id.wearable_support_confirmation_overlay_message); 290 } 291 } 292