summaryrefslogtreecommitdiff
path: root/adservices/apk/tests/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'adservices/apk/tests/src/com')
-rw-r--r--adservices/apk/tests/src/com/android/adservices/ui/notifications/ConsentNotificationTriggerTest.java73
-rw-r--r--adservices/apk/tests/src/com/android/adservices/ui/notifications/NotificationActivityTest.java112
-rw-r--r--adservices/apk/tests/src/com/android/adservices/ui/notifications/NotificationActivityUiAutomatorTest.java170
-rw-r--r--adservices/apk/tests/src/com/android/adservices/ui/settings/AdServicesSettingsActivityWrapper.java34
-rw-r--r--adservices/apk/tests/src/com/android/adservices/ui/settings/SettingsActivityTest.java423
-rw-r--r--adservices/apk/tests/src/com/android/adservices/ui/settings/SettingsActivityUiAutomatorTest.java471
6 files changed, 707 insertions, 576 deletions
diff --git a/adservices/apk/tests/src/com/android/adservices/ui/notifications/ConsentNotificationTriggerTest.java b/adservices/apk/tests/src/com/android/adservices/ui/notifications/ConsentNotificationTriggerTest.java
index 31bba31bc8..cc9d5ab749 100644
--- a/adservices/apk/tests/src/com/android/adservices/ui/notifications/ConsentNotificationTriggerTest.java
+++ b/adservices/apk/tests/src/com/android/adservices/ui/notifications/ConsentNotificationTriggerTest.java
@@ -27,13 +27,20 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
-import android.content.pm.PackageManager;
import androidx.core.app.NotificationManagerCompat;
+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.service.FlagsFactory;
import com.android.adservices.service.consent.ConsentManager;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
@@ -48,6 +55,8 @@ import org.mockito.quality.Strictness;
@RunWith(AndroidJUnit4.class)
public class ConsentNotificationTriggerTest {
private static final String NOTIFICATION_CHANNEL_ID = "PRIVACY_SANDBOX_CHANNEL";
+ private static final int LAUNCH_TIMEOUT = 5000;
+ private static UiDevice sDevice;
@Mock private NotificationManagerCompat mNotificationManagerCompat;
@Mock private ConsentManager mConsentManager;
@@ -59,17 +68,21 @@ public class ConsentNotificationTriggerTest {
@Before
public void setUp() {
mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ // Initialize UiDevice instance
+ sDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
}
@Test
- public void testEuNotification() throws InterruptedException {
+ public void testEuNotification() throws InterruptedException, UiObjectNotFoundException {
MockitoAnnotations.initMocks(this);
mStaticMockSession =
ExtendedMockito.mockitoSession()
+ .spyStatic(FlagsFactory.class)
.strictness(Strictness.WARN)
.initMocks(this)
.startMocking();
try {
+ ExtendedMockito.doReturn(FlagsFactory.getFlagsForTest()).when(FlagsFactory::getFlags);
mNotificationManager = mContext.getSystemService(NotificationManager.class);
final String expectedTitle =
mContext.getString(R.string.notificationUI_notification_title_eu);
@@ -87,14 +100,32 @@ public class ConsentNotificationTriggerTest {
.isEqualTo(expectedTitle);
assertThat(notification.extras.getCharSequence(Notification.EXTRA_TEXT))
.isEqualTo(expectedContent);
- Thread.sleep(5000); // wait 5s to make sure that Notification disappears.
+
+ sDevice.openNotification();
+ sDevice.wait(Until.hasObject(By.pkg("com.android.systemui")), LAUNCH_TIMEOUT);
+ UiObject scroller =
+ sDevice.findObject(
+ new UiSelector()
+ .packageName("com.android.systemui")
+ .resourceId(
+ "com.android.systemui:id/notification_stack_scroller"));
+ assertThat(scroller.exists()).isTrue();
+ UiSelector notificationCardSelector =
+ new UiSelector().text(getString(R.string.notificationUI_notification_title_eu));
+ UiObject notificationCard = scroller.getChild(notificationCardSelector);
+ assertThat(notificationCard.exists()).isTrue();
+
+ notificationCard.click();
+ Thread.sleep(LAUNCH_TIMEOUT);
+ UiObject title = getElement(R.string.notificationUI_header_title_eu);
+ assertThat(title.exists()).isTrue();
} finally {
mStaticMockSession.finishMocking();
}
}
@Test
- public void testNonEuNotifications() throws InterruptedException {
+ public void testNonEuNotifications() throws InterruptedException, UiObjectNotFoundException {
MockitoAnnotations.initMocks(this);
mStaticMockSession =
ExtendedMockito.mockitoSession()
@@ -114,7 +145,7 @@ public class ConsentNotificationTriggerTest {
Thread.sleep(1000); // wait 1s to make sure that Notification is displayed.
verify(mConsentManager).enable(any(Context.class));
- verify(mConsentManager).recordNotificationDisplayed(any(PackageManager.class));
+ verify(mConsentManager).recordNotificationDisplayed();
verifyNoMoreInteractions(mConsentManager);
assertThat(mNotificationManager.getActiveNotifications()).hasLength(1);
final Notification notification =
@@ -124,7 +155,27 @@ public class ConsentNotificationTriggerTest {
.isEqualTo(expectedTitle);
assertThat(notification.extras.getCharSequence(Notification.EXTRA_TEXT))
.isEqualTo(expectedContent);
- Thread.sleep(5000); // wait 5s to make sure that Notification disappears.
+
+ sDevice.openNotification();
+ sDevice.wait(Until.hasObject(By.pkg("com.android.systemui")), LAUNCH_TIMEOUT);
+
+ UiObject scroller =
+ sDevice.findObject(
+ new UiSelector()
+ .packageName("com.android.systemui")
+ .resourceId(
+ "com.android.systemui:id/notification_stack_scroller"));
+ assertThat(scroller.exists()).isTrue();
+ UiObject notificationCard =
+ scroller.getChild(
+ new UiSelector()
+ .text(getString(R.string.notificationUI_notification_title)));
+ assertThat(notificationCard.exists()).isTrue();
+
+ notificationCard.click();
+ Thread.sleep(LAUNCH_TIMEOUT);
+ UiObject title = getElement(R.string.notificationUI_header_title);
+ assertThat(title.exists()).isTrue();
} finally {
mStaticMockSession.finishMocking();
}
@@ -148,10 +199,18 @@ public class ConsentNotificationTriggerTest {
ConsentNotificationTrigger.showConsentNotification(mContext, true);
- verify(mConsentManager).recordNotificationDisplayed(any(PackageManager.class));
+ verify(mConsentManager).recordNotificationDisplayed();
verifyNoMoreInteractions(mConsentManager);
} finally {
mStaticMockSession.finishMocking();
}
}
+
+ private String getString(int resourceId) {
+ return ApplicationProvider.getApplicationContext().getResources().getString(resourceId);
+ }
+
+ private UiObject getElement(int resId) {
+ return sDevice.findObject(new UiSelector().text(getString(resId)));
+ }
}
diff --git a/adservices/apk/tests/src/com/android/adservices/ui/notifications/NotificationActivityTest.java b/adservices/apk/tests/src/com/android/adservices/ui/notifications/NotificationActivityTest.java
deleted file mode 100644
index e02dab4b08..0000000000
--- a/adservices/apk/tests/src/com/android/adservices/ui/notifications/NotificationActivityTest.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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 androidx.test.espresso.Espresso.onView;
-import static androidx.test.espresso.action.ViewActions.click;
-import static androidx.test.espresso.assertion.ViewAssertions.matches;
-import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static androidx.test.espresso.matcher.ViewMatchers.withId;
-import static androidx.test.espresso.matcher.ViewMatchers.withText;
-
-import static org.mockito.ArgumentMatchers.any;
-
-import android.content.Context;
-import android.content.Intent;
-
-import androidx.test.core.app.ActivityScenario;
-
-import com.android.adservices.api.R;
-import com.android.adservices.service.common.BackgroundJobsManager;
-import com.android.adservices.ui.settings.AdServicesSettingsActivity;
-import com.android.adservices.ui.settings.fragments.AdServicesSettingsMainFragment;
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
-import com.android.dx.mockito.inline.extended.StaticMockitoSession;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.MockitoAnnotations;
-import org.mockito.quality.Strictness;
-
-/** Tests for {@link ConsentNotificationActivity}. */
-public class NotificationActivityTest {
- private static final String NOTIFICATION_INTENT = "android.test.adservices.ui.NOTIFICATIONS";
- private StaticMockitoSession mStaticMockSession;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- mStaticMockSession =
- ExtendedMockito.mockitoSession()
- .spyStatic(BackgroundJobsManager.class)
- .strictness(Strictness.WARN)
- .initMocks(this)
- .startMocking();
- ExtendedMockito.doNothing()
- .when(() -> BackgroundJobsManager.scheduleAllBackgroundJobs(any(Context.class)));
-
- Intent mIntent = new Intent(NOTIFICATION_INTENT);
- mIntent.putExtra("isEUDevice", false);
- ActivityScenario.launch(mIntent);
- }
-
- @After
- public void teardown() {
- if (mStaticMockSession != null) {
- mStaticMockSession.finishMocking();
- }
- }
-
- /**
- * Test if {@link AdServicesSettingsMainFragment} is displayed in {@link
- * AdServicesSettingsActivity}.
- */
- @Test
- public void test_FragmentContainer_isDisplayed() {
- onView(withId(R.id.fragment_container_view)).check(matches(isDisplayed()));
- }
-
- /**
- * Test if {@link ConsentNotificationFragment} is displayed in {@link
- * ConsentNotificationActivity}.
- */
- @Test
- public void test_ConsentNotificationFragment_isDisplayed() {
- checkConsentNotificationFragmentIsDisplayed();
- }
-
- @Test
- public void test_ConsentNotificationConfirmationFragment_isDisplayed() {
- launchEUActivity();
- checkConsentNotificationFragmentIsDisplayed();
-
- onView(withId(R.id.rightControlButton)).perform(click());
-
- onView(withId(R.id.consent_notification_accept_confirmation_view))
- .check(matches(isDisplayed()));
- }
-
- private void checkConsentNotificationFragmentIsDisplayed() {
- onView(withText(R.string.notificationUI_header_title)).check(matches(isDisplayed()));
- }
-
- private void launchEUActivity() {
- Intent mIntent = new Intent(NOTIFICATION_INTENT);
- mIntent.putExtra("isEUDevice", true);
- ActivityScenario.launch(mIntent);
- }
-}
diff --git a/adservices/apk/tests/src/com/android/adservices/ui/notifications/NotificationActivityUiAutomatorTest.java b/adservices/apk/tests/src/com/android/adservices/ui/notifications/NotificationActivityUiAutomatorTest.java
new file mode 100644
index 0000000000..cd072cc619
--- /dev/null
+++ b/adservices/apk/tests/src/com/android/adservices/ui/notifications/NotificationActivityUiAutomatorTest.java
@@ -0,0 +1,170 @@
+/*
+ * 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 static org.mockito.Mockito.spy;
+
+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.service.FlagsFactory;
+import com.android.adservices.service.PhFlags;
+import com.android.adservices.service.common.BackgroundJobsManager;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.mockito.MockitoSession;
+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 Context sContext;
+ private static UiDevice sDevice;
+ private static Intent sIntent;
+ private MockitoSession mStaticMockSession;
+ private PhFlags mPhFlags;
+
+ @Before
+ public void setup() throws UiObjectNotFoundException, IOException {
+ MockitoAnnotations.initMocks(this);
+ mStaticMockSession =
+ ExtendedMockito.mockitoSession()
+ .spyStatic(PhFlags.class)
+ .spyStatic(BackgroundJobsManager.class)
+ .spyStatic(FlagsFactory.class)
+ .strictness(Strictness.WARN)
+ .initMocks(this)
+ .startMocking();
+ ExtendedMockito.doReturn(FlagsFactory.getFlagsForTest()).when(FlagsFactory::getFlags);
+ ExtendedMockito.doNothing()
+ .when(() -> BackgroundJobsManager.scheduleAllBackgroundJobs(any(Context.class)));
+ mPhFlags = spy(PhFlags.getInstance());
+ doReturn(true).when(mPhFlags).getUIDialogsFeatureEnabled();
+ ExtendedMockito.doReturn(mPhFlags).when(PhFlags::getInstance);
+
+ // Initialize UiDevice instance
+ sDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+ // Start from the home screen
+ sDevice.pressHome();
+
+ // Wait for launcher
+ final String launcherPackage = sDevice.getLauncherPackageName();
+ assertThat(launcherPackage).isNotNull();
+ sDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT);
+
+ // Create intent
+ sContext = ApplicationProvider.getApplicationContext();
+ sIntent = new Intent(NOTIFICATION_TEST_PACKAGE);
+ sIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ }
+
+ @After
+ public void teardown() {
+ if (mStaticMockSession != null) {
+ 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 {
+ 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();
+ }
+
+ private void startActivity(boolean isEUActivity) {
+ // Send intent
+ sIntent.putExtra("isEUDevice", isEUActivity);
+ sContext.startActivity(sIntent);
+
+ // Wait for the app to appear
+ 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)));
+ }
+}
diff --git a/adservices/apk/tests/src/com/android/adservices/ui/settings/AdServicesSettingsActivityWrapper.java b/adservices/apk/tests/src/com/android/adservices/ui/settings/AdServicesSettingsActivityWrapper.java
deleted file mode 100644
index c58e51e53c..0000000000
--- a/adservices/apk/tests/src/com/android/adservices/ui/settings/AdServicesSettingsActivityWrapper.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.settings;
-
-import com.android.adservices.service.PhFlags;
-import com.android.adservices.ui.settings.viewmodels.TopicsViewModel;
-
-
-/**
- * Wrapper class for {@link AdServicesSettingsActivity} used for testing purposes only. Instantiates
- * a {@link AdServicesSettingsActivity} with the custom constructor that can be passed a a mocked
- * view model provider. This is needed because the some view models (such as the {@link
- * TopicsViewModel}) will ultimately need to call {@link PhFlags} to read system settings, which
- * requires the READ_DEVICE_CONFIG permission that is only granted to the real PP API process and
- * not the process used for the test application.
- */
-public class AdServicesSettingsActivityWrapper extends AdServicesSettingsActivity {
- public AdServicesSettingsActivityWrapper() {
- super(new SettingsActivityTest().generateMockedViewModelProvider());
- }
-}
diff --git a/adservices/apk/tests/src/com/android/adservices/ui/settings/SettingsActivityTest.java b/adservices/apk/tests/src/com/android/adservices/ui/settings/SettingsActivityTest.java
deleted file mode 100644
index de13095766..0000000000
--- a/adservices/apk/tests/src/com/android/adservices/ui/settings/SettingsActivityTest.java
+++ /dev/null
@@ -1,423 +0,0 @@
-/*
- * 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.settings;
-
-import static androidx.test.espresso.Espresso.onView;
-import static androidx.test.espresso.Espresso.pressBack;
-import static androidx.test.espresso.action.ViewActions.click;
-import static androidx.test.espresso.assertion.ViewAssertions.matches;
-import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
-import static androidx.test.espresso.matcher.ViewMatchers.isChecked;
-import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static androidx.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast;
-import static androidx.test.espresso.matcher.ViewMatchers.withClassName;
-import static androidx.test.espresso.matcher.ViewMatchers.withId;
-import static androidx.test.espresso.matcher.ViewMatchers.withText;
-
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-
-import android.content.Context;
-import android.graphics.Rect;
-import android.util.Log;
-import android.view.View;
-import android.widget.HorizontalScrollView;
-import android.widget.ListView;
-import android.widget.ScrollView;
-import android.widget.Switch;
-
-import androidx.core.widget.NestedScrollView;
-import androidx.lifecycle.ViewModelProvider;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.espresso.PerformException;
-import androidx.test.espresso.UiController;
-import androidx.test.espresso.ViewAction;
-import androidx.test.espresso.action.ViewActions;
-import androidx.test.espresso.matcher.ViewMatchers;
-import androidx.test.espresso.util.HumanReadables;
-import androidx.test.ext.junit.rules.ActivityScenarioRule;
-
-import com.android.adservices.api.R;
-import com.android.adservices.data.topics.Topic;
-import com.android.adservices.service.common.BackgroundJobsManager;
-import com.android.adservices.service.consent.App;
-import com.android.adservices.service.consent.ConsentManager;
-import com.android.adservices.ui.settings.fragments.AdServicesSettingsMainFragment;
-import com.android.adservices.ui.settings.viewmodels.AppsViewModel;
-import com.android.adservices.ui.settings.viewmodels.MainViewModel;
-import com.android.adservices.ui.settings.viewmodels.TopicsViewModel;
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
-
-import com.google.common.collect.ImmutableList;
-
-import junit.framework.AssertionFailedError;
-
-import org.hamcrest.Matcher;
-import org.hamcrest.Matchers;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-/** Tests for {@link AdServicesSettingsActivity}. */
-public class SettingsActivityTest {
- static ViewModelProvider sViewModelProvider = Mockito.mock(ViewModelProvider.class);
- static ConsentManager sConsentManager;
- private MockitoSession mStaticMockSession;
-
- private static final class NestedScrollToAction implements ViewAction {
- private static final String TAG =
- androidx.test.espresso.action.ScrollToAction.class.getSimpleName();
-
- @Override
- public Matcher<View> getConstraints() {
- return Matchers.allOf(
- ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE),
- ViewMatchers.isDescendantOfA(
- Matchers.anyOf(
- ViewMatchers.isAssignableFrom(NestedScrollView.class),
- ViewMatchers.isAssignableFrom(ScrollView.class),
- ViewMatchers.isAssignableFrom(HorizontalScrollView.class),
- ViewMatchers.isAssignableFrom(ListView.class))));
- }
-
- @Override
- public void perform(UiController uiController, View view) {
- if (isDisplayingAtLeast(90).matches(view)) {
- Log.i(TAG, "View is already displayed. Returning.");
- return;
- }
- Rect rect = new Rect();
- view.getDrawingRect(rect);
- if (!view.requestRectangleOnScreen(rect, true /* immediate */)) {
- Log.w(TAG, "Scrolling to view was requested, but none of the parents scrolled.");
- }
- uiController.loopMainThreadUntilIdle();
- if (!isDisplayingAtLeast(90).matches(view)) {
- throw new PerformException.Builder()
- .withActionDescription(this.getDescription())
- .withViewDescription(HumanReadables.describe(view))
- .withCause(
- new RuntimeException(
- "Scrolling to view was attempted, but the view is not "
- + "displayed"))
- .build();
- }
- }
-
- @Override
- public String getDescription() {
- return "scroll to";
- }
- }
-
- private static ViewAction nestedScrollTo() {
- return ViewActions.actionWithAssertions(new NestedScrollToAction());
- }
-
- /**
- * {@link ActivityScenarioRule} is a JUnit {@link Rule @Rule} to launch your activity under
- * test.
- *
- * <p>Rules are interceptors which are executed for each test method and are important building
- * blocks of Junit tests.
- */
- @Rule
- public ActivityScenarioRule mRule =
- new ActivityScenarioRule<>(AdServicesSettingsActivityWrapper.class);
-
- /**
- * This is used by {@link AdServicesSettingsActivityWrapper}. Provides a mocked {@link
- * ViewModelProvider} that serves mocked view models, which use a mocked {@link ConsentManager},
- * which gives mocked data.
- *
- * @return the mocked {@link ViewModelProvider}
- */
- public ViewModelProvider generateMockedViewModelProvider() {
- sConsentManager =
- spy(ConsentManager.getInstance(ApplicationProvider.getApplicationContext()));
- List<Topic> tempList = new ArrayList<>();
- tempList.add(Topic.create(10001, 1, 1));
- tempList.add(Topic.create(10002, 1, 1));
- tempList.add(Topic.create(10003, 1, 1));
- ImmutableList<Topic> topicsList = ImmutableList.copyOf(tempList);
- doReturn(topicsList).when(sConsentManager).getKnownTopicsWithConsent();
-
- tempList = new ArrayList<>();
- tempList.add(Topic.create(10004, 1, 1));
- tempList.add(Topic.create(10005, 1, 1));
- ImmutableList<Topic> blockedTopicsList = ImmutableList.copyOf(tempList);
- doReturn(blockedTopicsList).when(sConsentManager).getTopicsWithRevokedConsent();
-
- List<App> appTempList = new ArrayList<>();
- appTempList.add(App.create("app1"));
- appTempList.add(App.create("app2"));
- ImmutableList<App> appsList = ImmutableList.copyOf(appTempList);
- doReturn(appsList).when(sConsentManager).getKnownAppsWithConsent();
-
- appTempList = new ArrayList<>();
- appTempList.add(App.create("app3"));
- ImmutableList<App> blockedAppsList = ImmutableList.copyOf(appTempList);
- doReturn(blockedAppsList).when(sConsentManager).getAppsWithRevokedConsent();
-
- doNothing().when(sConsentManager).resetTopicsAndBlockedTopics();
- try {
- doNothing().when(sConsentManager).resetAppsAndBlockedApps();
- } catch (IOException e) {
- e.printStackTrace();
- }
- doNothing().when(sConsentManager).resetMeasurement();
-
- TopicsViewModel topicsViewModel =
- new TopicsViewModel(ApplicationProvider.getApplicationContext(), sConsentManager);
- AppsViewModel appsViewModel =
- new AppsViewModel(ApplicationProvider.getApplicationContext(), sConsentManager);
- MainViewModel mainViewModel =
- new MainViewModel(ApplicationProvider.getApplicationContext(), sConsentManager);
- doReturn(topicsViewModel).when(sViewModelProvider).get(TopicsViewModel.class);
- doReturn(mainViewModel).when(sViewModelProvider).get(MainViewModel.class);
- doReturn(appsViewModel).when(sViewModelProvider).get(AppsViewModel.class);
- return sViewModelProvider;
- }
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- mStaticMockSession =
- ExtendedMockito.mockitoSession()
- .spyStatic(BackgroundJobsManager.class)
- .strictness(Strictness.WARN)
- .initMocks(this)
- .startMocking();
- ExtendedMockito.doNothing()
- .when(() -> BackgroundJobsManager.scheduleAllBackgroundJobs(any(Context.class)));
- }
-
- @After
- public void teardown() {
- if (mStaticMockSession != null) {
- mStaticMockSession.finishMocking();
- }
- }
-
- /**
- * Test if {@link AdServicesSettingsMainFragment} is displayed in {@link
- * AdServicesSettingsActivity}.
- */
- @Test
- public void test_FragmentContainer_isDisplayed() {
- giveConsentIfNeeded();
- onView(withId(R.id.fragment_container_view)).check(matches(isDisplayed()));
- }
-
- /**
- * Test if the strings (settingsUI_topics_title, settingsUI_apps_title,
- * settingsUI_main_view_title) are displayed in {@link AdServicesSettingsMainFragment}.
- */
- @Test
- public void test_MainFragmentView_isDisplayed() {
- giveConsentIfNeeded();
- onView(withText(R.string.settingsUI_privacy_sandbox_beta_switch_title))
- .perform(nestedScrollTo())
- .check(matches(isDisplayed()));
- onView(withText(R.string.settingsUI_topics_title))
- .perform(nestedScrollTo())
- .check(matches(isDisplayed()));
- onView(withText(R.string.settingsUI_apps_title))
- .perform(nestedScrollTo())
- .check(matches(isDisplayed()));
- }
-
- /** Test if {@link MainViewModel} works if Activity is recreated (simulates rotate phone). */
- @Test
- public void test_MainViewModel_getConsent() {
- giveConsentIfNeeded();
- onView(withId(R.id.main_fragment))
- .check(
- matches(
- hasDescendant(
- Matchers.allOf(
- withClassName(Matchers.is(Switch.class.getName())),
- isChecked()))));
- onView(withText(R.string.settingsUI_privacy_sandbox_beta_switch_title))
- .perform(nestedScrollTo(), click());
-
- mRule.getScenario().recreate();
- onView(withId(R.id.main_fragment))
- .check(
- matches(
- hasDescendant(
- Matchers.allOf(
- withClassName(Matchers.is(Switch.class.getName())),
- Matchers.not(isChecked())))));
-
- // Give consent back
- onView(withText(R.string.settingsUI_privacy_sandbox_beta_switch_title))
- .perform(nestedScrollTo(), click());
- onView(withId(R.id.main_fragment))
- .check(
- matches(
- hasDescendant(
- Matchers.allOf(
- withClassName(Matchers.is(Switch.class.getName())),
- isChecked()))));
- }
-
- /**
- * Test if the Topics button in the main fragment opens the topics fragment, and the back button
- * returns to the main fragment.
- */
- @Test
- public void test_TopicsView() {
- giveConsentIfNeeded();
-
- assertMainFragmentDisplayed();
-
- onView(withText(R.string.settingsUI_topics_title)).perform(nestedScrollTo(), click());
-
- assertTopicsFragmentDisplayed();
-
- pressBack();
-
- assertMainFragmentDisplayed();
- }
-
- /**
- * Test if the Topics button in the main fragment opens the topics fragment, and the back button
- * returns to the main fragment.
- */
- @Test
- public void test_BlockedTopicsView() {
- giveConsentIfNeeded();
-
- assertMainFragmentDisplayed();
-
- onView(withText(R.string.settingsUI_topics_title)).perform(nestedScrollTo(), click());
-
- assertTopicsFragmentDisplayed();
-
- onView(withId(R.id.blocked_topics_button)).perform(nestedScrollTo(), click());
-
- assertBlockedTopicsFragmentDisplayed();
-
- pressBack();
-
- assertTopicsFragmentDisplayed();
-
- pressBack();
-
- assertMainFragmentDisplayed();
- }
-
- /**
- * Test if the Topics button in the main fragment opens the topics fragment, and the back button
- * returns to the main fragment.
- */
- @Test
- public void test_AppsView() {
- giveConsentIfNeeded();
-
- assertMainFragmentDisplayed();
-
- onView(withText(R.string.settingsUI_apps_title)).perform(nestedScrollTo(), click());
-
- assertAppsFragmentDisplayed();
-
- pressBack();
-
- assertMainFragmentDisplayed();
- }
-
- /**
- * Test if the Topics button in the main fragment opens the topics fragment, and the back button
- * returns to the main fragment.
- */
- @Test
- public void test_BlockedAppsView() {
- giveConsentIfNeeded();
-
- assertMainFragmentDisplayed();
-
- onView(withText(R.string.settingsUI_apps_title)).perform(nestedScrollTo(), click());
-
- assertAppsFragmentDisplayed();
-
- onView(withId(R.id.blocked_apps_button)).perform(nestedScrollTo(), click());
-
- assertBlockedAppsFragmentDisplayed();
-
- pressBack();
-
- assertAppsFragmentDisplayed();
-
- pressBack();
-
- assertMainFragmentDisplayed();
- }
-
- private void assertMainFragmentDisplayed() {
- onView(withText(R.string.settingsUI_main_view_subtitle))
- .perform(nestedScrollTo())
- .check(matches(isDisplayed()));
- }
-
- private void assertTopicsFragmentDisplayed() {
- onView(withText(R.string.settingsUI_topics_view_subtitle))
- .perform(nestedScrollTo())
- .check(matches(isDisplayed()));
- }
-
- private void assertAppsFragmentDisplayed() {
- onView(withText(R.string.settingsUI_apps_view_subtitle))
- .perform(nestedScrollTo())
- .check(matches(isDisplayed()));
- }
-
- private void assertBlockedTopicsFragmentDisplayed() {
- onView(withId(R.id.blocked_topics_list)).check(matches(isDisplayed()));
- }
-
- private void assertBlockedAppsFragmentDisplayed() {
- onView(withId(R.id.blocked_apps_list)).check(matches(isDisplayed()));
- }
-
- private void giveConsentIfNeeded() {
- try {
- onView(withId(R.id.main_fragment))
- .check(
- matches(
- hasDescendant(
- Matchers.allOf(
- withClassName(
- Matchers.is(Switch.class.getName())),
- isChecked()))));
- } catch (AssertionFailedError e) {
- // Give consent
- onView(withText(R.string.settingsUI_privacy_sandbox_beta_switch_title))
- .perform(nestedScrollTo(), click());
- }
- }
-}
diff --git a/adservices/apk/tests/src/com/android/adservices/ui/settings/SettingsActivityUiAutomatorTest.java b/adservices/apk/tests/src/com/android/adservices/ui/settings/SettingsActivityUiAutomatorTest.java
new file mode 100644
index 0000000000..65184b5eb2
--- /dev/null
+++ b/adservices/apk/tests/src/com/android/adservices/ui/settings/SettingsActivityUiAutomatorTest.java
@@ -0,0 +1,471 @@
+/*
+ * 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.settings;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.lifecycle.ViewModelProvider;
+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.UiScrollable;
+import androidx.test.uiautomator.UiSelector;
+import androidx.test.uiautomator.Until;
+
+import com.android.adservices.api.R;
+import com.android.adservices.data.topics.Topic;
+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.App;
+import com.android.adservices.service.consent.ConsentManager;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class SettingsActivityUiAutomatorTest {
+ private static final String PRIVACY_SANDBOX_TEST_PACKAGE = "android.test.adservices.ui.MAIN";
+ private static final int LAUNCH_TIMEOUT = 5000;
+ private static UiDevice sDevice;
+ static ViewModelProvider sViewModelProvider = Mockito.mock(ViewModelProvider.class);
+ static ConsentManager sConsentManager;
+ private MockitoSession mStaticMockSession;
+ private PhFlags mPhFlags;
+ private ConsentManager mConsentManager;
+
+ @Before
+ public void setup() throws UiObjectNotFoundException, IOException {
+ // Static mocking
+ mStaticMockSession =
+ ExtendedMockito.mockitoSession()
+ .spyStatic(PhFlags.class)
+ .spyStatic(FlagsFactory.class)
+ .spyStatic(BackgroundJobsManager.class)
+ .spyStatic(ConsentManager.class)
+ .strictness(Strictness.WARN)
+ .initMocks(this)
+ .startMocking();
+ ExtendedMockito.doReturn(FlagsFactory.getFlagsForTest()).when(FlagsFactory::getFlags);
+
+ // prepare objects used by static mocking
+ mConsentManager =
+ spy(ConsentManager.getInstance(ApplicationProvider.getApplicationContext()));
+ List<Topic> tempList = new ArrayList<>();
+ tempList.add(Topic.create(10001, 1, 1));
+ tempList.add(Topic.create(10002, 1, 1));
+ tempList.add(Topic.create(10003, 1, 1));
+ ImmutableList<Topic> topicsList = ImmutableList.copyOf(tempList);
+ doReturn(topicsList).when(mConsentManager).getKnownTopicsWithConsent();
+
+ tempList = new ArrayList<>();
+ tempList.add(Topic.create(10004, 1, 1));
+ tempList.add(Topic.create(10005, 1, 1));
+ ImmutableList<Topic> blockedTopicsList = ImmutableList.copyOf(tempList);
+ doReturn(blockedTopicsList).when(mConsentManager).getTopicsWithRevokedConsent();
+
+ List<App> appTempList = new ArrayList<>();
+ appTempList.add(App.create("app1"));
+ appTempList.add(App.create("app2"));
+ ImmutableList<App> appsList = ImmutableList.copyOf(appTempList);
+ doReturn(appsList).when(mConsentManager).getKnownAppsWithConsent();
+
+ appTempList = new ArrayList<>();
+ appTempList.add(App.create("app3"));
+ ImmutableList<App> blockedAppsList = ImmutableList.copyOf(appTempList);
+ doReturn(blockedAppsList).when(mConsentManager).getAppsWithRevokedConsent();
+
+ doNothing().when(mConsentManager).resetTopicsAndBlockedTopics();
+ doNothing().when(mConsentManager).resetTopics();
+ doNothing().when(mConsentManager).revokeConsentForTopic(any(Topic.class));
+ doNothing().when(mConsentManager).restoreConsentForTopic(any(Topic.class));
+ try {
+ doNothing().when(mConsentManager).resetAppsAndBlockedApps();
+ doNothing().when(mConsentManager).resetApps();
+ doNothing().when(mConsentManager).revokeConsentForApp(any(App.class));
+ doNothing().when(mConsentManager).restoreConsentForApp(any(App.class));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ doNothing().when(mConsentManager).resetMeasurement();
+
+ ExtendedMockito.doNothing()
+ .when(() -> BackgroundJobsManager.scheduleAllBackgroundJobs(any(Context.class)));
+ mPhFlags = spy(PhFlags.getInstance());
+ doReturn(true).when(mPhFlags).getUIDialogsFeatureEnabled();
+ ExtendedMockito.doReturn(mPhFlags).when(PhFlags::getInstance);
+ ExtendedMockito.doReturn(mConsentManager)
+ .when(() -> ConsentManager.getInstance(any(Context.class)));
+
+ // Initialize UiDevice instance
+ sDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
+
+ // Start from the home screen
+ sDevice.pressHome();
+
+ // Wait for launcher
+ final String launcherPackage = sDevice.getLauncherPackageName();
+ assertThat(launcherPackage).isNotNull();
+ sDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT);
+
+ // launch app
+ Context context = ApplicationProvider.getApplicationContext();
+ Intent intent = new Intent(PRIVACY_SANDBOX_TEST_PACKAGE);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+
+ // Wait for the app to appear
+ sDevice.wait(
+ Until.hasObject(By.pkg(PRIVACY_SANDBOX_TEST_PACKAGE).depth(0)), LAUNCH_TIMEOUT);
+
+ // set consent to true if not
+ UiObject mainSwitch =
+ sDevice.findObject(new UiSelector().className("android.widget.Switch"));
+ assertThat(mainSwitch.exists()).isTrue();
+ if (!mainSwitch.isChecked()) mainSwitch.click();
+ assertThat(mainSwitch.isChecked()).isTrue();
+ }
+
+ @After
+ public void teardown() {
+ if (mStaticMockSession != null) {
+ mStaticMockSession.finishMocking();
+ }
+ }
+
+ private void scrollToAndClick(int resId) throws UiObjectNotFoundException {
+ UiScrollable scrollView =
+ new UiScrollable(
+ new UiSelector().scrollable(true).className("android.widget.ScrollView"));
+ UiObject element =
+ sDevice.findObject(
+ new UiSelector().childSelector(new UiSelector().text(getString(resId))));
+ scrollView.scrollIntoView(element);
+ element.click();
+ }
+
+ private UiObject getElement(int resId) {
+ return sDevice.findObject(new UiSelector().text(getString(resId)));
+ }
+
+ private UiObject getElement(int resId, int index) {
+ return sDevice.findObject(new UiSelector().text(getString(resId)).instance(index));
+ }
+
+ private String getString(int resourceId) {
+ return ApplicationProvider.getApplicationContext().getResources().getString(resourceId);
+ }
+
+ @Test
+ public void optOutDialogTest() throws UiObjectNotFoundException {
+ UiObject mainSwitch =
+ sDevice.findObject(new UiSelector().className("android.widget.Switch"));
+ assertThat(mainSwitch.exists()).isTrue();
+
+ // click switch
+ mainSwitch.click();
+ UiObject dialogTitle = getElement(R.string.settingsUI_dialog_opt_out_title);
+ UiObject positiveText = getElement(R.string.settingsUI_dialog_opt_out_positive_text);
+ assertThat(dialogTitle.exists()).isTrue();
+ assertThat(positiveText.exists()).isTrue();
+
+ // confirm
+ positiveText.click();
+ assertThat(mainSwitch.isChecked()).isFalse();
+
+ // reset to opted in
+ mainSwitch.click();
+ assertThat(mainSwitch.isChecked()).isTrue();
+
+ // click switch
+ mainSwitch.click();
+ dialogTitle = getElement(R.string.settingsUI_dialog_opt_out_title);
+ UiObject negativeText = getElement(R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle.exists()).isTrue();
+ assertThat(negativeText.exists()).isTrue();
+
+ // cancel
+ negativeText.click();
+ assertThat(mainSwitch.isChecked()).isTrue();
+ }
+
+ @Test
+ public void blockTopicDialogTest() throws UiObjectNotFoundException {
+ // open topics view
+ scrollToAndClick(R.string.settingsUI_topics_title);
+ UiObject blockTopicText = getElement(R.string.settingsUI_block_topic_title, 0);
+ assertThat(blockTopicText.exists()).isTrue();
+
+ // click block
+ blockTopicText.click();
+ UiObject dialogTitle = getElement(R.string.settingsUI_dialog_block_topic_message);
+ UiObject positiveText = getElement(R.string.settingsUI_dialog_block_topic_positive_text);
+ assertThat(dialogTitle.exists()).isTrue();
+ assertThat(positiveText.exists()).isTrue();
+
+ // confirm
+ positiveText.click();
+ verify(mConsentManager).revokeConsentForTopic(any(Topic.class));
+ blockTopicText = getElement(R.string.settingsUI_block_topic_title, 0);
+ assertThat(blockTopicText.exists()).isTrue();
+
+ // click block again
+ blockTopicText.click();
+ dialogTitle = getElement(R.string.settingsUI_dialog_block_topic_message);
+ UiObject negativeText = getElement(R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle.exists()).isTrue();
+ assertThat(negativeText.exists()).isTrue();
+
+ // cancel and verify it has still only been called once
+ negativeText.click();
+ verify(mConsentManager).revokeConsentForTopic(any(Topic.class));
+ }
+
+ @Test
+ public void unblockTopicDialogTest() throws UiObjectNotFoundException {
+ // open topics view
+ scrollToAndClick(R.string.settingsUI_topics_title);
+
+ // open blocked topics view
+ scrollToAndClick(R.string.settingsUI_blocked_topics_title);
+ UiObject unblockTopicText = getElement(R.string.settingsUI_unblock_topic_title, 0);
+ assertThat(unblockTopicText.exists()).isTrue();
+
+ // click unblock
+ unblockTopicText.click();
+ UiObject dialogTitle = getElement(R.string.settingsUI_dialog_unblock_topic_message);
+ UiObject positiveText = getElement(R.string.settingsUI_dialog_unblock_topic_positive_text);
+ assertThat(dialogTitle.exists()).isTrue();
+ assertThat(positiveText.exists()).isTrue();
+
+ // confirm
+ positiveText.click();
+ verify(mConsentManager).restoreConsentForTopic(any(Topic.class));
+ unblockTopicText = getElement(R.string.settingsUI_unblock_topic_title, 0);
+ assertThat(unblockTopicText.exists()).isTrue();
+ }
+
+ @Test
+ public void resetTopicDialogTest() throws UiObjectNotFoundException {
+ // open topics view
+ scrollToAndClick(R.string.settingsUI_topics_title);
+
+ // click reset
+ scrollToAndClick(R.string.settingsUI_reset_topics_title);
+ UiObject dialogTitle = getElement(R.string.settingsUI_dialog_reset_topic_message);
+ UiObject positiveText = getElement(R.string.settingsUI_dialog_reset_topic_positive_text);
+ assertThat(dialogTitle.exists()).isTrue();
+ assertThat(positiveText.exists()).isTrue();
+
+ // confirm
+ positiveText.click();
+ verify(mConsentManager).resetTopics();
+
+ // click reset again
+ scrollToAndClick(R.string.settingsUI_reset_topics_title);
+ dialogTitle = getElement(R.string.settingsUI_dialog_reset_topic_message);
+ UiObject negativeText = getElement(R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle.exists()).isTrue();
+ assertThat(negativeText.exists()).isTrue();
+
+ // cancel and verify it has still only been called once
+ negativeText.click();
+ verify(mConsentManager).resetTopics();
+ }
+
+ @Test
+ public void blockAppDialogTest() throws UiObjectNotFoundException, IOException {
+ // open apps view
+ scrollToAndClick(R.string.settingsUI_apps_title);
+ UiObject blockAppText = getElement(R.string.settingsUI_block_app_title, 0);
+ assertThat(blockAppText.exists()).isTrue();
+
+ // click block
+ blockAppText.click();
+ UiObject dialogTitle = getElement(R.string.settingsUI_dialog_block_app_message);
+ UiObject positiveText = getElement(R.string.settingsUI_dialog_block_app_positive_text);
+ assertThat(dialogTitle.exists()).isTrue();
+ assertThat(positiveText.exists()).isTrue();
+
+ // confirm
+ positiveText.click();
+ verify(mConsentManager).revokeConsentForApp(any(App.class));
+ blockAppText = getElement(R.string.settingsUI_block_app_title, 0);
+ assertThat(blockAppText.exists()).isTrue();
+
+ // click block again
+ blockAppText.click();
+ dialogTitle = getElement(R.string.settingsUI_dialog_block_app_message);
+ UiObject negativeText = getElement(R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle.exists()).isTrue();
+ assertThat(negativeText.exists()).isTrue();
+
+ // cancel and verify it has still only been called once
+ negativeText.click();
+ verify(mConsentManager).revokeConsentForApp(any(App.class));
+ }
+
+ @Test
+ public void unblockAppDialogTest() throws UiObjectNotFoundException, IOException {
+ // open apps view
+ scrollToAndClick(R.string.settingsUI_apps_title);
+
+ // open blocked apps view
+ scrollToAndClick(R.string.settingsUI_blocked_apps_title);
+ UiObject unblockAppText = getElement(R.string.settingsUI_unblock_app_title, 0);
+ assertThat(unblockAppText.exists()).isTrue();
+
+ // click unblock
+ unblockAppText.click();
+ UiObject dialogTitle = getElement(R.string.settingsUI_dialog_unblock_app_message);
+ UiObject positiveText = getElement(R.string.settingsUI_dialog_unblock_app_positive_text);
+ assertThat(dialogTitle.exists()).isTrue();
+ assertThat(positiveText.exists()).isTrue();
+
+ // confirm
+ positiveText.click();
+ verify(mConsentManager).restoreConsentForApp(any(App.class));
+ unblockAppText = getElement(R.string.settingsUI_unblock_app_title, 0);
+ assertThat(unblockAppText.exists()).isTrue();
+ }
+
+ @Test
+ public void resetAppDialogTest() throws UiObjectNotFoundException, IOException {
+ // open apps view
+ scrollToAndClick(R.string.settingsUI_apps_title);
+
+ // click reset
+ scrollToAndClick(R.string.settingsUI_reset_apps_title);
+ UiObject dialogTitle = getElement(R.string.settingsUI_dialog_reset_app_message);
+ UiObject positiveText = getElement(R.string.settingsUI_dialog_reset_app_positive_text);
+ assertThat(dialogTitle.exists()).isTrue();
+ assertThat(positiveText.exists()).isTrue();
+
+ // confirm
+ positiveText.click();
+ verify(mConsentManager).resetApps();
+
+ // click reset again
+ scrollToAndClick(R.string.settingsUI_reset_apps_title);
+ dialogTitle = getElement(R.string.settingsUI_dialog_reset_app_message);
+ UiObject negativeText = getElement(R.string.settingsUI_dialog_negative_text);
+ assertThat(dialogTitle.exists()).isTrue();
+ assertThat(negativeText.exists()).isTrue();
+
+ // cancel and verify it has still only been called once
+ negativeText.click();
+ verify(mConsentManager).resetApps();
+ }
+
+ @Test
+ public void disableDialogFeatureTest() throws UiObjectNotFoundException {
+ doReturn(false).when(mPhFlags).getUIDialogsFeatureEnabled();
+ UiObject mainSwitch =
+ sDevice.findObject(new UiSelector().className("android.widget.Switch"));
+ assertThat(mainSwitch.exists()).isTrue();
+
+ // click switch
+ mainSwitch.click();
+ UiObject dialogTitle = getElement(R.string.settingsUI_dialog_opt_out_title);
+ assertThat(dialogTitle.exists()).isFalse();
+ assertThat(mainSwitch.isChecked()).isFalse();
+
+ // click switch again
+ mainSwitch.click();
+ assertThat(mainSwitch.isChecked()).isTrue();
+
+ // open topics view
+ scrollToAndClick(R.string.settingsUI_topics_title);
+ UiObject blockTopicText = getElement(R.string.settingsUI_block_topic_title, 0);
+ assertThat(blockTopicText.exists()).isTrue();
+
+ // block topic
+ blockTopicText.click();
+ dialogTitle = getElement(R.string.settingsUI_dialog_block_topic_message);
+ assertThat(dialogTitle.exists()).isFalse();
+ verify(mConsentManager).revokeConsentForTopic(any(Topic.class));
+
+ // reset topic
+ scrollToAndClick(R.string.settingsUI_reset_topics_title);
+ dialogTitle = getElement(R.string.settingsUI_dialog_reset_topic_message);
+ assertThat(dialogTitle.exists()).isFalse();
+ verify(mConsentManager).resetTopics();
+
+ // open unblock topic view
+ scrollToAndClick(R.string.settingsUI_blocked_topics_title);
+ UiObject unblockTopicText = getElement(R.string.settingsUI_unblock_topic_title, 0);
+ assertThat(unblockTopicText.exists()).isTrue();
+
+ // click unblock
+ unblockTopicText.click();
+ dialogTitle = getElement(R.string.settingsUI_dialog_unblock_topic_message);
+ assertThat(dialogTitle.exists()).isFalse();
+ verify(mConsentManager).restoreConsentForTopic(any(Topic.class));
+ }
+
+ /**
+ * Test for the Button to show blocked topics when the list of Topics is Empty The Button should
+ * be disabled if blocked topics is empty
+ *
+ * @throws UiObjectNotFoundException
+ */
+ @Test
+ public void blockedTopicsWhenEmptyStateButtonTest() throws UiObjectNotFoundException {
+ // Return an empty topics list
+ doReturn(ImmutableList.of()).when(mConsentManager).getKnownTopicsWithConsent();
+ // Return a non-empty blocked topics list
+ List<Topic> tempList = new ArrayList<>();
+ tempList.add(Topic.create(10004, 1, 1));
+ tempList.add(Topic.create(10005, 1, 1));
+ ImmutableList<Topic> blockedTopicsList = ImmutableList.copyOf(tempList);
+ doReturn(blockedTopicsList).when(mConsentManager).getTopicsWithRevokedConsent();
+ // navigate to topics page
+ scrollToAndClick(R.string.settingsUI_topics_title);
+ UiObject blockedTopicsWhenEmptyStateButton =
+ sDevice.findObject(
+ new UiSelector()
+ .className("android.widget.Button")
+ .text(getString(R.string.settingsUI_blocked_topics_title)));
+
+ assertThat(blockedTopicsWhenEmptyStateButton.isEnabled()).isTrue();
+ }
+}