1 /* 2 * Copyright (C) 2023 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 package com.android.adservices.tests.ui.libs.pages; 17 18 import static com.android.adservices.tests.ui.libs.UiConstants.NOTIFICATION_SCROLLER; 19 import static com.android.adservices.tests.ui.libs.UiUtils.LAUNCH_TIMEOUT; 20 import static com.android.adservices.tests.ui.libs.UiUtils.PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT; 21 import static com.android.adservices.tests.ui.libs.UiUtils.SCROLL_WAIT_TIME; 22 import static com.android.adservices.tests.ui.libs.UiUtils.getElement; 23 import static com.android.adservices.tests.ui.libs.UiUtils.getPageElement; 24 import static com.android.adservices.tests.ui.libs.UiUtils.getString; 25 import static com.android.adservices.tests.ui.libs.UiUtils.sysuiResSelector; 26 27 import static com.google.common.truth.Truth.assertThat; 28 29 import android.content.Context; 30 import android.os.SystemClock; 31 import android.util.Log; 32 33 import androidx.test.uiautomator.By; 34 import androidx.test.uiautomator.UiDevice; 35 import androidx.test.uiautomator.UiObject2; 36 import androidx.test.uiautomator.UiObjectNotFoundException; 37 import androidx.test.uiautomator.UiSelector; 38 import androidx.test.uiautomator.Until; 39 40 import com.android.adservices.api.R; 41 import com.android.adservices.tests.ui.libs.UiConstants; 42 43 public class NotificationPages { verifyNotification( Context context, UiDevice device, boolean isDisplayed, boolean isEuTest, UiConstants.UX ux, boolean isV2, boolean isPas, boolean isPasRenotify)44 public static void verifyNotification( 45 Context context, 46 UiDevice device, 47 boolean isDisplayed, 48 boolean isEuTest, 49 UiConstants.UX ux, 50 boolean isV2, 51 boolean isPas, 52 boolean isPasRenotify) 53 throws Exception { 54 device.openNotification(); 55 Thread.sleep(LAUNCH_TIMEOUT); 56 57 int notificationTitle = -1; 58 int notificationHeader = -1; 59 switch (ux) { 60 case GA_UX: 61 // Should match the contentTitle string in ConsentNotificationTrigger.java. 62 if (isPas || isPasRenotify) { 63 notificationTitle = 64 isPasRenotify 65 ? R.string.notificationUI_pas_re_notification_title 66 : R.string.notificationUI_pas_notification_title; 67 notificationHeader = 68 isPasRenotify 69 ? R.string.notificationUI_pas_renotify_header_title 70 : R.string.notificationUI_pas_header_title; 71 } else { 72 notificationTitle = 73 isEuTest 74 ? R.string.notificationUI_notification_ga_title_eu_v2 75 : R.string.notificationUI_notification_ga_title_v2; 76 // Should match the text in consent_notification_screen_1_ga_v2_eu.xml and 77 // consent_notification_screen_1_ga_v2_row.xml, respectively. 78 notificationHeader = 79 isEuTest 80 ? R.string.notificationUI_fledge_measurement_title_v2 81 : R.string.notificationUI_header_ga_title_v2; 82 } 83 break; 84 case BETA_UX: 85 notificationTitle = 86 isEuTest 87 ? R.string.notificationUI_notification_title_eu 88 : R.string.notificationUI_notification_title; 89 notificationHeader = 90 isEuTest 91 ? R.string.notificationUI_header_title_eu 92 : R.string.notificationUI_header_title; 93 break; 94 case U18_UX: 95 notificationTitle = R.string.notificationUI_u18_notification_title; 96 notificationHeader = R.string.notificationUI_u18_header_title; 97 break; 98 } 99 100 Log.d( 101 "adservices", 102 "Expected notification card title is: " + getString(context, notificationTitle)); 103 Log.d( 104 "adservices", 105 "Expected notification landing page title is: " 106 + getString(context, notificationHeader)); 107 108 UiSelector notificationCardSelector = 109 new UiSelector().text(getString(context, notificationTitle)); 110 111 UiObject2 scroller = 112 device.wait( 113 Until.findObject(sysuiResSelector(NOTIFICATION_SCROLLER)), LAUNCH_TIMEOUT); 114 115 UiObject2 notificationCard = 116 scroller.findObject(By.textContains(getString(context, notificationTitle))); 117 if (!isDisplayed) { 118 assertThat(notificationCard).isNull(); 119 return; 120 } 121 122 assertThat(notificationCard).isNotNull(); 123 notificationCard.click(); 124 Thread.sleep(LAUNCH_TIMEOUT); 125 UiObject2 title = getPageElement(context, device, notificationHeader); 126 127 assertThat(title).isNotNull(); 128 } 129 betaNotificationPage( Context context, UiDevice device, boolean isEuDevice, boolean isGoSettings, boolean isOptin)130 public static void betaNotificationPage( 131 Context context, 132 UiDevice device, 133 boolean isEuDevice, 134 boolean isGoSettings, 135 boolean isOptin) 136 throws UiObjectNotFoundException, InterruptedException { 137 int leftButtonResId = 138 isEuDevice 139 ? R.string.notificationUI_left_control_button_text_eu 140 : R.string.notificationUI_left_control_button_text; 141 142 int rightButtonResId = 143 isEuDevice 144 ? R.string.notificationUI_right_control_button_text_eu 145 : R.string.notificationUI_right_control_button_text; 146 147 goThroughNotificationPage(context, device, leftButtonResId, rightButtonResId); 148 UiObject2 leftControlButton = getElement(context, device, leftButtonResId); 149 UiObject2 rightControlButton = getElement(context, device, rightButtonResId); 150 151 if (isEuDevice) { 152 if (!isOptin) { 153 leftControlButton.click(); 154 } else { 155 rightControlButton.click(); 156 Thread.sleep(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT); 157 UiObject2 acceptedTitle = 158 getElement( 159 context, device, R.string.notificationUI_confirmation_accept_title); 160 assertThat(acceptedTitle).isNotNull(); 161 } 162 } else { 163 if (isGoSettings) { 164 leftControlButton.click(); 165 } else { 166 rightControlButton.click(); 167 } 168 Thread.sleep(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT); 169 } 170 } 171 betaNotificationConfirmPage( Context context, UiDevice device, boolean isGoSettings)172 public static void betaNotificationConfirmPage( 173 Context context, UiDevice device, boolean isGoSettings) 174 throws UiObjectNotFoundException, InterruptedException { 175 int leftButtonResId = R.string.notificationUI_confirmation_left_control_button_text; 176 int rightButtonResId = R.string.notificationUI_confirmation_right_control_button_text; 177 178 UiObject2 leftControlButton = getElement(context, device, leftButtonResId); 179 UiObject2 rightControlButton = getElement(context, device, rightButtonResId); 180 181 if (isGoSettings) { 182 leftControlButton.click(); 183 } else { 184 rightControlButton.click(); 185 } 186 Thread.sleep(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT); 187 } 188 euNotificationLandingPageMsmtAndFledgePage( Context context, UiDevice device, boolean isGoSettings, boolean isFlip)189 public static void euNotificationLandingPageMsmtAndFledgePage( 190 Context context, UiDevice device, boolean isGoSettings, boolean isFlip) 191 throws UiObjectNotFoundException, InterruptedException { 192 int leftButtonResId = R.string.notificationUI_left_control_button_text; 193 int rightButtonResId = R.string.notificationUI_right_control_button_text; 194 goThroughNotificationPage(context, device, leftButtonResId, rightButtonResId); 195 UiObject2 leftControlButton = getElement(context, device, leftButtonResId); 196 UiObject2 rightControlButton = getElement(context, device, rightButtonResId); 197 if (isGoSettings) { 198 leftControlButton.clickAndWait(Until.newWindow(), PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT); 199 } else { 200 rightControlButton.clickAndWait(Until.newWindow(), PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT); 201 if (isFlip) { 202 UiObject2 title2 = 203 getElement(context, device, R.string.notificationUI_header_ga_title_eu_v2); 204 assertThat(title2).isNotNull(); 205 } 206 } 207 } 208 euNotificationLandingPageTopicsPage( Context context, UiDevice device, boolean isOptin, boolean isFlip)209 public static void euNotificationLandingPageTopicsPage( 210 Context context, UiDevice device, boolean isOptin, boolean isFlip) 211 throws UiObjectNotFoundException, InterruptedException { 212 int leftButtonResId = R.string.notificationUI_left_control_button_text_eu; 213 int rightButtonResId = 214 isFlip 215 ? R.string.notificationUI_right_control_button_ga_text_eu_v2 216 : R.string.notificationUI_right_control_button_ga_text_eu; 217 goThroughNotificationPage(context, device, leftButtonResId, rightButtonResId); 218 UiObject2 leftControlButton = getElement(context, device, leftButtonResId); 219 UiObject2 rightControlButton = getElement(context, device, rightButtonResId); 220 if (isOptin) { 221 rightControlButton.click(); 222 if (!isFlip) { 223 Thread.sleep(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT); 224 UiObject2 acceptedTitle = 225 getElement( 226 context, device, R.string.notificationUI_fledge_measurement_title); 227 assertThat(acceptedTitle).isNotNull(); 228 } 229 } else { 230 leftControlButton.click(); 231 } 232 } 233 rowNotificationLandingPage( Context context, UiDevice device, boolean isGoSettings)234 public static void rowNotificationLandingPage( 235 Context context, UiDevice device, boolean isGoSettings) 236 throws UiObjectNotFoundException, InterruptedException { 237 int leftButtonResId = R.string.notificationUI_left_control_button_text; 238 int rightButtonResId = R.string.notificationUI_right_control_button_text; 239 goThroughNotificationPage(context, device, leftButtonResId, rightButtonResId); 240 UiObject2 leftControlButton = getElement(context, device, leftButtonResId); 241 UiObject2 rightControlButton = getElement(context, device, rightButtonResId); 242 if (isGoSettings) { 243 leftControlButton.click(); 244 } else { 245 rightControlButton.click(); 246 } 247 Thread.sleep(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT); 248 } 249 u18NotifiacitonLandingPage( Context context, UiDevice device, boolean isGoSettings)250 public static void u18NotifiacitonLandingPage( 251 Context context, UiDevice device, boolean isGoSettings) 252 throws UiObjectNotFoundException, InterruptedException { 253 int leftButtonResId = R.string.notificationUI_u18_left_control_button_text; 254 int rightButtonResId = R.string.notificationUI_u18_right_control_button_text; 255 goThroughNotificationPage(context, device, leftButtonResId, rightButtonResId); 256 UiObject2 leftControlButton = getElement(context, device, leftButtonResId); 257 UiObject2 rightControlButton = getElement(context, device, rightButtonResId); 258 if (isGoSettings) { 259 leftControlButton.click(); 260 } else { 261 rightControlButton.click(); 262 } 263 Thread.sleep(PRIMITIVE_UI_OBJECTS_LAUNCH_TIMEOUT); 264 UiObject2 topicTitle = getElement(context, device, R.string.settingsUI_topics_ga_title); 265 assertThat(topicTitle).isNotNull(); 266 } 267 goThroughNotificationPage( Context context, UiDevice device, int leftButtonResId, int rightButtonResId)268 public static void goThroughNotificationPage( 269 Context context, UiDevice device, int leftButtonResId, int rightButtonResId) 270 throws UiObjectNotFoundException, InterruptedException { 271 UiObject2 leftControlButton = getElement(context, device, leftButtonResId); 272 UiObject2 rightControlButton = getElement(context, device, rightButtonResId); 273 UiObject2 moreButton = 274 getElement(context, device, R.string.notificationUI_more_button_text); 275 UiObject2 scrollView = device.findObject(By.clazz("android.widget.ScrollView")); 276 int clickCount = 10; 277 while (moreButton != null && clickCount-- > 0) { 278 moreButton.click(); 279 Thread.sleep(SCROLL_WAIT_TIME); 280 moreButton = getElement(context, device, R.string.notificationUI_more_button_text); 281 } 282 leftControlButton = getElement(context, device, leftButtonResId); 283 rightControlButton = getElement(context, device, rightButtonResId); 284 assertThat(leftControlButton).isNotNull(); 285 assertThat(rightControlButton).isNotNull(); 286 assertThat(moreButton).isNull(); 287 } 288 289 /** 290 * Verifies the notification card. The new logic, we only check the notification card shows. The 291 * landing page is moved away from adservices. 292 */ verifyNotificationV2( Context context, UiDevice device, UiConstants.NotificationMode notificationMode)293 public static void verifyNotificationV2( 294 Context context, UiDevice device, UiConstants.NotificationMode notificationMode) 295 throws Exception { 296 device.openNotification(); 297 SystemClock.sleep(LAUNCH_TIMEOUT); 298 299 int notificationTitle = -1; 300 int notificationHeader = -1; 301 switch (notificationMode) { 302 case REGULAR: 303 notificationTitle = R.string.notificationUI_notification_ga_title_v2; 304 notificationHeader = R.string.notificationUI_header_ga_title_v2; 305 break; 306 case UPDATED_FIRST_TIME: 307 notificationTitle = R.string.notificationUI_pas_notification_title; 308 notificationHeader = R.string.notificationUI_pas_header_title; 309 break; 310 case UPDATED_RENOTIFY: 311 notificationTitle = R.string.notificationUI_pas_re_notification_title; 312 notificationHeader = R.string.notificationUI_pas_renotify_header_title; 313 break; 314 case LIMITED: 315 notificationTitle = R.string.notificationUI_u18_notification_title; 316 notificationHeader = R.string.notificationUI_u18_header_title; 317 break; 318 } 319 320 Log.d( 321 "adservices", 322 "Expected notification card title is: " + getString(context, notificationTitle)); 323 Log.d( 324 "adservices", 325 "Expected notification landing page title is: " 326 + getString(context, notificationHeader)); 327 328 UiObject2 scroller = 329 device.wait( 330 Until.findObject(sysuiResSelector(NOTIFICATION_SCROLLER)), LAUNCH_TIMEOUT); 331 332 UiObject2 notificationCard = 333 scroller.findObject(By.textContains(getString(context, notificationTitle))); 334 335 assertThat(notificationCard).isNotNull(); 336 notificationCard.click(); 337 SystemClock.sleep(LAUNCH_TIMEOUT); 338 } 339 } 340