chromium/chrome/browser/safety_hub/android/javatests/src/org/chromium/chrome/browser/safety_hub/SafetyHubHatsBridgeTest.java

// Copyright 2024 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.safety_hub;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;

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.Features;
import org.chromium.base.test.util.JniMocker;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.profiles.ProfileManager;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.ChromeTabUtils;
import org.chromium.content_public.browser.WebContents;

import java.util.concurrent.ExecutionException;

/** Tests for {@link SafetyHubHatsBridge}. */
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@Batch(Batch.PER_CLASS)
@Features.EnableFeatures(ChromeFeatureList.SAFETY_HUB_ANDROID_SURVEY)
public class SafetyHubHatsBridgeTest {
    private static final String TEST_URL1 = "https://www.example.com/";
    private static final String TEST_URL2 = "https://www.google.com/";

    @Rule public JniMocker mJniMocker = new JniMocker();
    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();

    @Rule
    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();

    @Mock private SafetyHubHatsBridge.Natives mSafetyHubHatsBridgeNatives;

    private TabModelSelector mTabModelSelector;
    private Profile mProfile;
    private ChromeTabbedActivity mActivity;

    @Before
    public void setUp() throws ExecutionException {
        ThreadUtils.setThreadAssertsDisabledForTesting(true);

        mJniMocker.mock(SafetyHubHatsBridgeJni.TEST_HOOKS, mSafetyHubHatsBridgeNatives);
        doReturn(true)
                .when(mSafetyHubHatsBridgeNatives)
                .triggerHatsSurveyIfEnabled(any(), any(), any());

        mActivityTestRule.startMainActivityOnBlankPage();
        mTabModelSelector = mActivityTestRule.getActivity().getTabModelSelectorSupplier().get();
        ThreadUtils.runOnUiThreadBlocking(
                () -> mProfile = ProfileManager.getLastUsedRegularProfile());
        mActivity = mActivityTestRule.getActivity();
    }

    @Test
    @SmallTest
    public void testTriggerControlHatsSurvey() {
        SafetyHubHatsBridge safetyHubHatsBridge = new SafetyHubHatsBridge(mProfile);
        safetyHubHatsBridge.triggerControlHatsSurvey(mTabModelSelector);

        verifyHatsTrigger(SafetyHubHatsBridge.CONTROL_NOTIFICATION_MODULE);
    }

    @Test
    @SmallTest
    public void testTriggerProactiveHatsSurvey() {
        SafetyHubHatsBridge safetyHubHatsBridge = new SafetyHubHatsBridge(mProfile);
        safetyHubHatsBridge.triggerProactiveHatsSurvey(
                mTabModelSelector, MagicStackEntry.ModuleType.PASSWORDS);

        verifyHatsTrigger(MagicStackEntry.ModuleType.PASSWORDS);
    }

    private void verifyHatsTrigger(String moduleType) {
        verify(mSafetyHubHatsBridgeNatives, never())
                .triggerHatsSurveyIfEnabled(eq(mProfile), any(WebContents.class), eq(moduleType));

        // Verify that the survey is NOT triggered on an Incognito tab.
        ChromeTabUtils.fullyLoadUrlInNewTab(
                InstrumentationRegistry.getInstrumentation(),
                mActivity,
                TEST_URL1,
                /* incognito= */ true);
        verify(mSafetyHubHatsBridgeNatives, never())
                .triggerHatsSurveyIfEnabled(eq(mProfile), any(WebContents.class), eq(moduleType));

        // Verify that the survey is triggered on next page load on a regular tab.
        ChromeTabUtils.fullyLoadUrlInNewTab(
                InstrumentationRegistry.getInstrumentation(),
                mActivity,
                TEST_URL2,
                /* incognito= */ false);
        verify(mSafetyHubHatsBridgeNatives, times(1))
                .triggerHatsSurveyIfEnabled(eq(mProfile), any(WebContents.class), eq(moduleType));

        // Verify that there are no more attempts to trigger the survey.
        ChromeTabUtils.fullyLoadUrlInNewTab(
                InstrumentationRegistry.getInstrumentation(),
                mActivity,
                TEST_URL1,
                /* incognito= */ false);
        verify(mSafetyHubHatsBridgeNatives, times(1))
                .triggerHatsSurveyIfEnabled(eq(mProfile), any(WebContents.class), eq(moduleType));
    }
}