chromium/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/AdMeasurementFragmentTest.java

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.privacy_sandbox;

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.assertThat;
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
import static androidx.test.espresso.matcher.ViewMatchers.isChecked;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withParent;
import static androidx.test.espresso.matcher.ViewMatchers.withText;

import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.view.View;

import androidx.annotation.StringRes;
import androidx.test.filters.SmallTest;

import org.hamcrest.Matcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.Batch;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.UserActionTester;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.profiles.ProfileManager;
import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
import org.chromium.chrome.test.ChromeBrowserTestRule;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.util.ChromeRenderTestRule;
import org.chromium.components.policy.test.annotations.Policies;
import org.chromium.components.prefs.PrefService;
import org.chromium.components.user_prefs.UserPrefs;
import org.chromium.ui.test.util.RenderTestRule;
import org.chromium.ui.test.util.ViewUtils;

import java.io.IOException;

/** Tests {@link AdMeasurementFragment} */
@RunWith(ChromeJUnit4ClassRunner.class)
@Batch(Batch.PER_CLASS)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
public final class AdMeasurementFragmentTest {
    @Rule public ChromeBrowserTestRule mChromeBrowserTestRule = new ChromeBrowserTestRule();

    @Rule
    public ChromeRenderTestRule mRenderTestRule =
            ChromeRenderTestRule.Builder.withPublicCorpus()
                    .setBugComponent(RenderTestRule.Component.UI_SETTINGS_PRIVACY)
                    .build();

    @Rule
    public SettingsActivityTestRule<AdMeasurementFragment> mSettingsActivityTestRule =
            new SettingsActivityTestRule<>(AdMeasurementFragment.class);

    private UserActionTester mUserActionTester;

    @Before
    public void setUp() {
        mUserActionTester = new UserActionTester();
    }

    @After
    public void tearDown() {
        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    PrefService prefService =
                            UserPrefs.get(ProfileManager.getLastUsedRegularProfile());
                    prefService.clearPref(Pref.PRIVACY_SANDBOX_M1_AD_MEASUREMENT_ENABLED);
                });

        mUserActionTester.tearDown();
    }

    private void startAdMeasuremenSettings() {
        mSettingsActivityTestRule.startSettingsActivity();
        ViewUtils.onViewWaiting(
                allOf(
                        withText(R.string.settings_ad_measurement_page_title),
                        withParent(withId(R.id.action_bar))));
    }

    private Matcher<View> getAdMeasurementToggleMatcher() {
        return allOf(
                withId(R.id.switchWidget),
                withParent(
                        withParent(
                                hasDescendant(
                                        withText(
                                                R.string
                                                        .settings_ad_measurement_page_toggle_label)))));
    }

    private View getRootView(@StringRes int text) {
        View[] view = {null};
        onView(withText(text)).check(((v, e) -> view[0] = v.getRootView()));
        ThreadUtils.runOnUiThreadBlocking(() -> RenderTestRule.sanitize(view[0]));
        return view[0];
    }

    private void setAdMeasurementPrefEnabled(boolean isEnabled) {
        ThreadUtils.runOnUiThreadBlocking(
                () ->
                        AdMeasurementFragment.setAdMeasurementPrefEnabled(
                                ProfileManager.getLastUsedRegularProfile(), isEnabled));
    }

    private boolean isAdMeasurementPrefEnabled() {
        return ThreadUtils.runOnUiThreadBlocking(
                () ->
                        AdMeasurementFragment.isAdMeasurementPrefEnabled(
                                ProfileManager.getLastUsedRegularProfile()));
    }

    @Test
    @SmallTest
    @Feature({"RenderTest"})
    public void testRenderAdMeasurement() throws IOException {
        setAdMeasurementPrefEnabled(true);
        startAdMeasuremenSettings();
        mRenderTestRule.render(
                getRootView(R.string.settings_ad_measurement_page_toggle_sub_label),
                "ad_measurement_page_toggle_on");
    }

    @Test
    @SmallTest
    public void testToggleUncheckedWhenAdMeasurementOff() {
        setAdMeasurementPrefEnabled(false);
        startAdMeasuremenSettings();
        onView(getAdMeasurementToggleMatcher()).check(matches(not(isChecked())));
    }

    @Test
    @SmallTest
    public void testToggleCheckedWhenAdMeasurementOn() {
        setAdMeasurementPrefEnabled(true);
        startAdMeasuremenSettings();
        onView(getAdMeasurementToggleMatcher()).check(matches(isChecked()));
    }

    @Test
    @SmallTest
    public void testTurnAdMeasurementOn() {
        setAdMeasurementPrefEnabled(false);
        startAdMeasuremenSettings();
        onView(getAdMeasurementToggleMatcher()).perform(click());

        assertTrue(isAdMeasurementPrefEnabled());
        assertThat(
                mUserActionTester.getActions(),
                hasItems("Settings.PrivacySandbox.AdMeasurement.Enabled"));
    }

    @Test
    @SmallTest
    public void testTurnAdMeasurementOff() {
        setAdMeasurementPrefEnabled(true);
        startAdMeasuremenSettings();
        onView(getAdMeasurementToggleMatcher()).perform(click());

        assertFalse(isAdMeasurementPrefEnabled());
        assertThat(
                mUserActionTester.getActions(),
                hasItems("Settings.PrivacySandbox.AdMeasurement.Disabled"));
    }

    @Test
    @SmallTest
    @Policies.Add({
        @Policies.Item(key = "PrivacySandboxAdMeasurementEnabled", string = "false"),
        @Policies.Item(key = "PrivacySandboxPromptEnabled", string = "false")
    })
    public void testAdMeasurementManaged() {
        startAdMeasuremenSettings();

        // Check default state and try to press the toggle.
        assertFalse(isAdMeasurementPrefEnabled());
        onView(getAdMeasurementToggleMatcher()).check(matches(not(isChecked())));
        onView(getAdMeasurementToggleMatcher()).perform(click());

        // Check that the state of the pref and the toggle did not change.
        assertFalse(isAdMeasurementPrefEnabled());
        onView(getAdMeasurementToggleMatcher()).check(matches(not(isChecked())));
    }
}