blob: 4dc6c4c198a1859aaa2318f55534fbc1da76d880 [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.adservices.ui.notifications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doReturn;
import android.content.Context;
import android.content.Intent;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject;
import androidx.test.uiautomator.UiObjectNotFoundException;
import androidx.test.uiautomator.UiSelector;
import androidx.test.uiautomator.Until;
import com.android.adservices.api.R;
import com.android.adservices.common.AdservicesTestHelper;
import com.android.adservices.service.Flags;
import com.android.adservices.service.FlagsFactory;
import com.android.adservices.service.PhFlags;
import com.android.adservices.service.common.BackgroundJobsManager;
import com.android.adservices.service.consent.ConsentManager;
import com.android.adservices.ui.util.ApkTestUtil;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.modules.utils.build.SdkLevel;
import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;
import org.mockito.Spy;
import org.mockito.quality.Strictness;
import java.io.IOException;
@RunWith(AndroidJUnit4.class)
public class NotificationActivityUiAutomatorTest {
private static final String NOTIFICATION_TEST_PACKAGE =
"android.test.adservices.ui.NOTIFICATIONS";
private static final int LAUNCH_TIMEOUT = 5000;
private static final UiDevice sDevice =
UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
private MockitoSession mStaticMockSession;
@Mock private ConsentManager mConsentManager;
@Spy private Context mContext;
// TODO(b/261216850): Migrate this NotificationActivity to non-mock test
@Mock private Flags mMockFlags;
@Before
public void setup() throws UiObjectNotFoundException, IOException {
// Skip the test if it runs on unsupported platforms.
Assume.assumeTrue(ApkTestUtil.isDeviceSupported());
mContext = InstrumentationRegistry.getInstrumentation().getContext();
MockitoAnnotations.initMocks(this);
mStaticMockSession =
ExtendedMockito.mockitoSession()
.spyStatic(PhFlags.class)
.spyStatic(BackgroundJobsManager.class)
.spyStatic(FlagsFactory.class)
.spyStatic(ConsentManager.class)
.strictness(Strictness.WARN)
.initMocks(this)
.startMocking();
doReturn(false).when(mMockFlags).getEuNotifFlowChangeEnabled();
doReturn(true).when(mMockFlags).getUIDialogsFeatureEnabled();
doReturn(true).when(mMockFlags).isUiFeatureTypeLoggingEnabled();
doReturn(true).when(mMockFlags).getRecordManualInteractionEnabled();
ExtendedMockito.doReturn(mMockFlags).when(FlagsFactory::getFlags);
ExtendedMockito.doReturn(mConsentManager)
.when(() -> ConsentManager.getInstance(any(Context.class)));
ExtendedMockito.doNothing()
.when(() -> BackgroundJobsManager.scheduleAllBackgroundJobs(any(Context.class)));
sDevice.pressHome();
final String launcherPackage = sDevice.getLauncherPackageName();
assertThat(launcherPackage).isNotNull();
sDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT);
}
@After
public void teardown() throws Exception {
if (!ApkTestUtil.isDeviceSupported()) return;
AdservicesTestHelper.killAdservicesProcess(mContext);
mStaticMockSession.finishMocking();
}
@Test
public void moreButtonTest() throws UiObjectNotFoundException, InterruptedException {
startActivity(true);
UiObject leftControlButton =
getElement(R.string.notificationUI_left_control_button_text_eu);
UiObject rightControlButton =
getElement(R.string.notificationUI_right_control_button_text_eu);
UiObject moreButton = getElement(R.string.notificationUI_more_button_text);
assertThat(leftControlButton.exists()).isFalse();
assertThat(rightControlButton.exists()).isFalse();
assertThat(moreButton.exists()).isTrue();
while (moreButton.exists()) {
moreButton.click();
Thread.sleep(2000);
}
assertThat(leftControlButton.exists()).isTrue();
assertThat(rightControlButton.exists()).isTrue();
assertThat(moreButton.exists()).isFalse();
}
@Test
public void acceptedConfirmationScreenTest()
throws UiObjectNotFoundException, InterruptedException {
doReturn(false).when(mMockFlags).getGaUxFeatureEnabled();
startActivity(true);
UiObject leftControlButton =
getElement(R.string.notificationUI_left_control_button_text_eu);
UiObject rightControlButton =
getElement(R.string.notificationUI_right_control_button_text_eu);
UiObject moreButton = getElement(R.string.notificationUI_more_button_text);
assertThat(leftControlButton.exists()).isFalse();
assertThat(rightControlButton.exists()).isFalse();
assertThat(moreButton.exists()).isTrue();
while (moreButton.exists()) {
moreButton.click();
Thread.sleep(2000);
}
assertThat(leftControlButton.exists()).isTrue();
assertThat(rightControlButton.exists()).isTrue();
assertThat(moreButton.exists()).isFalse();
rightControlButton.click();
UiObject acceptedTitle = getElement(R.string.notificationUI_confirmation_accept_title);
assertThat(acceptedTitle.exists()).isTrue();
}
@Test
public void notificationEuGaTest() throws UiObjectNotFoundException, InterruptedException {
doReturn(true).when(mMockFlags).getGaUxFeatureEnabled();
startActivity(true);
UiObject notificationEuGaTitle = getElement(R.string.notificationUI_header_ga_title_eu);
assertThat(notificationEuGaTitle.exists()).isTrue();
UiObject leftControlButton =
getElement(R.string.notificationUI_left_control_button_text_eu);
UiObject rightControlButton =
getElement(R.string.notificationUI_right_control_button_ga_text_eu);
UiObject moreButton = getElement(R.string.notificationUI_more_button_text);
verifyControlsAndMoreButtonAreDisplayed(leftControlButton, rightControlButton, moreButton);
}
@Test
public void notificationRowGaTest() throws UiObjectNotFoundException, InterruptedException {
doReturn(true).when(mMockFlags).getGaUxFeatureEnabled();
startActivity(false);
UiObject notificationGaTitle = getElement(R.string.notificationUI_header_ga_title);
assertThat(notificationGaTitle.exists()).isTrue();
UiObject leftControlButton = getElement(R.string.notificationUI_left_control_button_text);
UiObject rightControlButton = getElement(R.string.notificationUI_right_control_button_text);
UiObject moreButton = getElement(R.string.notificationUI_more_button_text);
}
@Test
public void privacyPolicyLinkTest() throws UiObjectNotFoundException {
// TODO(277094594) fix broken Link Test on S
Assume.assumeTrue(SdkLevel.isAtLeastT());
ExtendedMockito.doReturn(true).when(mMockFlags).getGaUxFeatureEnabled();
String packageNameOfDefaultBrowser =
ApkTestUtil.getDefaultBrowserPkgName(sDevice, mContext);
sDevice.pressHome();
/* isEUActivity false: Rest of World Notification landing page */
startActivity(false);
/* find the expander and click to expand to get the content */
UiObject moreExpander =
ApkTestUtil.scrollTo(sDevice, R.string.notificationUI_ga_container1_control_text);
moreExpander.click();
UiObject sentence =
ApkTestUtil.scrollTo(
sDevice, R.string.notificationUI_learn_more_from_privacy_policy);
if (isDefaultBrowserOpenedAfterClicksOnTheBottomOfSentence(
packageNameOfDefaultBrowser, sentence, 20)) {
return;
}
if (sDevice.getCurrentPackageName().equals(packageNameOfDefaultBrowser)) {
return;
}
Assert.fail("Web browser not found after several clicks on the last line");
}
@Test
public void acceptedConfirmationScreenGaTest()
throws UiObjectNotFoundException, InterruptedException {
doReturn(true).when(mMockFlags).getGaUxFeatureEnabled();
startActivity(true);
UiObject leftControlButton =
getElement(R.string.notificationUI_left_control_button_text_eu);
UiObject rightControlButton =
getElement(R.string.notificationUI_right_control_button_ga_text_eu);
UiObject moreButton = getElement(R.string.notificationUI_more_button_text);
verifyControlsAndMoreButtonAreDisplayed(leftControlButton, rightControlButton, moreButton);
rightControlButton.click();
UiObject acceptedTitle = getElement(R.string.notificationUI_fledge_measurement_title);
assertThat(acceptedTitle.exists()).isTrue();
UiObject leftControlButtonOnSecondPage =
getElement(R.string.notificationUI_confirmation_left_control_button_text);
UiObject rightControlButtonOnSecondPage =
getElement(R.string.notificationUI_confirmation_right_control_button_text);
UiObject moreButtonOnSecondPage = getElement(R.string.notificationUI_more_button_text);
verifyControlsAndMoreButtonAreDisplayed(
leftControlButtonOnSecondPage,
rightControlButtonOnSecondPage,
moreButtonOnSecondPage);
}
@Test
public void declinedConfirmationScreenGaTest()
throws UiObjectNotFoundException, InterruptedException {
doReturn(true).when(mMockFlags).getGaUxFeatureEnabled();
startActivity(true);
UiObject leftControlButton =
getElement(R.string.notificationUI_left_control_button_text_eu);
UiObject rightControlButton =
getElement(R.string.notificationUI_right_control_button_ga_text_eu);
UiObject moreButton = getElement(R.string.notificationUI_more_button_text);
verifyControlsAndMoreButtonAreDisplayed(leftControlButton, rightControlButton, moreButton);
leftControlButton.click();
UiObject acceptedTitle = getElement(R.string.notificationUI_fledge_measurement_title);
assertThat(acceptedTitle.exists()).isTrue();
UiObject leftControlButtonOnSecondPage =
getElement(R.string.notificationUI_confirmation_left_control_button_text);
UiObject rightControlButtonOnSecondPage =
getElement(R.string.notificationUI_confirmation_right_control_button_text);
UiObject moreButtonOnSecondPage = getElement(R.string.notificationUI_more_button_text);
verifyControlsAndMoreButtonAreDisplayed(
leftControlButtonOnSecondPage,
rightControlButtonOnSecondPage,
moreButtonOnSecondPage);
}
private void verifyControlsAndMoreButtonAreDisplayed(
UiObject leftControlButton, UiObject rightControlButton, UiObject moreButton)
throws UiObjectNotFoundException, InterruptedException {
UiObject scrollView =
sDevice.findObject(new UiSelector().className("android.widget.ScrollView"));
if (scrollView.isScrollable()) {
// there should be a more button
assertThat(leftControlButton.exists()).isFalse();
assertThat(rightControlButton.exists()).isFalse();
assertThat(moreButton.exists()).isTrue();
while (moreButton.exists()) {
moreButton.click();
Thread.sleep(2000);
}
assertThat(leftControlButton.exists()).isTrue();
assertThat(rightControlButton.exists()).isTrue();
assertThat(moreButton.exists()).isFalse();
} else {
assertThat(leftControlButton.exists()).isTrue();
assertThat(rightControlButton.exists()).isTrue();
assertThat(moreButton.exists()).isFalse();
}
}
private void startActivity(boolean isEUActivity) {
Intent intent = new Intent(NOTIFICATION_TEST_PACKAGE);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("isEUDevice", isEUActivity);
mContext.startActivity(intent);
sDevice.wait(Until.hasObject(By.pkg(NOTIFICATION_TEST_PACKAGE).depth(0)), LAUNCH_TIMEOUT);
}
private String getString(int resourceId) {
return ApplicationProvider.getApplicationContext().getResources().getString(resourceId);
}
private UiObject getElement(int resId) {
return sDevice.findObject(new UiSelector().text(getString(resId)));
}
private boolean isDefaultBrowserOpenedAfterClicksOnTheBottomOfSentence(
String packageNameOfDefaultBrowser, UiObject sentence, int countOfClicks)
throws UiObjectNotFoundException {
int right = sentence.getBounds().right,
bottom = sentence.getBounds().bottom,
left = sentence.getBounds().left;
for (int x = left; x < right; x += (right - left) / countOfClicks) {
sDevice.click(x, bottom - 2);
if (sDevice.getCurrentPackageName().equals(packageNameOfDefaultBrowser)) {
return true;
}
}
return false;
}
}