chromium/chrome/browser/ui/android/google_bottom_bar/java/src/org/chromium/chrome/browser/ui/google_bottom_bar/GoogleBottomBarActionsHandlerTest.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.ui.google_bottom_bar;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import static org.chromium.chrome.browser.gsa.GSAUtils.GSA_CLASS_NAME;
import static org.chromium.chrome.browser.gsa.GSAUtils.GSA_PACKAGE_NAME;
import static org.chromium.chrome.browser.gsa.GSAUtils.VOICE_SEARCH_INTENT_ACTION;
import static org.chromium.chrome.browser.ui.google_bottom_bar.BottomBarConfig.ButtonId.PIH_BASIC;
import static org.chromium.chrome.browser.ui.google_bottom_bar.GoogleBottomBarActionsHandler.EXTRA_IS_LAUNCHED_FROM_CHROME_SEARCH_ENTRYPOINT;
import static org.chromium.chrome.browser.ui.google_bottom_bar.GoogleBottomBarLogger.BUTTON_CLICKED_HISTOGRAM;

import android.app.Activity;
import android.app.PendingIntent;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.view.View;

import androidx.test.ext.junit.rules.ActivityScenarioRule;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
import org.robolectric.shadows.ShadowLog;
import org.robolectric.shadows.ShadowPackageManager;

import org.chromium.base.supplier.Supplier;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.HistogramWatcher;
import org.chromium.chrome.browser.lens.LensController;
import org.chromium.chrome.browser.lens.LensEntryPoint;
import org.chromium.chrome.browser.lens.LensIntentParams;
import org.chromium.chrome.browser.share.ShareDelegate;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.ui.google_bottom_bar.BottomBarConfig.ButtonId;
import org.chromium.chrome.browser.ui.google_bottom_bar.GoogleBottomBarLogger.GoogleBottomBarButtonEvent;
import org.chromium.components.browser_ui.widget.textbubble.TextBubble;
import org.chromium.ui.base.TestActivity;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.url.GURL;

import java.lang.ref.WeakReference;
import java.util.Set;

/** Unit tests for {@link BottomBarConfig}. */
@RunWith(BaseRobolectricTestRunner.class)
@Config(
        manifest = Config.NONE,
        shadows = {ShadowLog.class, GoogleBottomBarActionsHandlerTest.ShadowLensController.class})
public class GoogleBottomBarActionsHandlerTest {
    private static final String TEST_URI = "https://www.test.com/";

    private final GURL mGURL = new GURL(TEST_URI);

    @Implements(LensController.class)
    public static class ShadowLensController {
        public static boolean sIsAvailable;

        public static LensController sController;

        public static LensController getInstance() {
            if (sController == null) {
                sController = mock(LensController.class);
            }
            doReturn(sIsAvailable).when(sController).isLensEnabled(any());
            return sController;
        }

        @Resetter
        public static void reset() {
            sIsAvailable = false;
            sController = null;
        }
    }

    @Rule
    public ActivityScenarioRule<TestActivity> mActivityScenarioRule =
            new ActivityScenarioRule<>(TestActivity.class);

    @Mock private WindowAndroid mWindowAndroid;
    @Mock private Tab mTab;
    @Mock private Supplier<Tab> mTabSupplier;

    @Mock private ShareDelegate mShareDelegate;
    @Mock private Supplier<ShareDelegate> mShareDelegateSupplier;

    @Captor private ArgumentCaptor<LensIntentParams> mLensIntentParamsArgumentCaptor;

    private Activity mActivity;
    private GoogleBottomBarActionsHandler mGoogleBottomBarActionsHandler;
    private HistogramWatcher mHistogramWatcher;
    private ShadowPackageManager mShadowPackageManager;

    @Before
    public void setup() {
        mActivityScenarioRule.getScenario().onActivity(activity -> mActivity = activity);
        MockitoAnnotations.initMocks(this);
        mGoogleBottomBarActionsHandler =
                new GoogleBottomBarActionsHandler(mActivity, mTabSupplier, mShareDelegateSupplier);

        mShadowPackageManager =
                Shadows.shadowOf(RuntimeEnvironment.application.getPackageManager());

        when(mTabSupplier.get()).thenReturn(mTab);
        when(mTab.getUrl()).thenReturn(mGURL);
        when(mTab.getWindowAndroid()).thenReturn(mWindowAndroid);
        when(mWindowAndroid.getContext()).thenReturn(new WeakReference<>(mActivity));
        when(mShareDelegateSupplier.get()).thenReturn(mShareDelegate);
    }

    @After
    public void tearDown() {
        ShadowLensController.reset();
        if (mHistogramWatcher != null) {
            mHistogramWatcher.assertExpected();
            mHistogramWatcher.close();
            mHistogramWatcher = null;
        }
    }

    @Test
    public void testSaveAction_buttonConfigHasPendingIntent_startsPendingIntent()
            throws PendingIntent.CanceledException {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.SAVE_EMBEDDER);
        PendingIntent pendingIntent = mock(PendingIntent.class);
        Context context = mActivity.getApplicationContext();
        BottomBarConfig.ButtonConfig buttonConfig =
                new BottomBarConfig.ButtonConfig(
                        ButtonId.SAVE,
                        context.getDrawable(R.drawable.bookmark),
                        "Save button",
                        /* pendingIntent= */ pendingIntent);

        View.OnClickListener clickListener =
                mGoogleBottomBarActionsHandler.getClickListener(buttonConfig);
        clickListener.onClick(new View(context));

        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
        verify(pendingIntent)
                .send(eq(mActivity), anyInt(), captor.capture(), any(), any(), any(), any());
        assertEquals(Uri.parse(TEST_URI), captor.getValue().getData());
    }

    @Test
    public void testSaveAction_buttonConfigHasNoPendingIntent_showsTooltip() {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.SAVE_DISABLED);
        Context context = mActivity;
        View buttonView = new View(context);
        BottomBarConfig.ButtonConfig buttonConfig =
                new BottomBarConfig.ButtonConfig(
                        ButtonId.SAVE,
                        context.getDrawable(R.drawable.bookmark),
                        context.getString(
                                R.string.google_bottom_bar_save_disabled_button_description),
                        /* pendingIntent= */ null);
        TextBubble.setSkipShowCheckForTesting(true);

        View.OnClickListener clickListener =
                mGoogleBottomBarActionsHandler.getClickListener(buttonConfig);
        clickListener.onClick(buttonView);

        Set<TextBubble> textBubbleSet = TextBubble.getTextBubbleSetForTesting();
        assertEquals(1, textBubbleSet.size());
    }

    @Test
    public void testShareAction_buttonConfigHasPendingIntent_startsPendingIntent()
            throws PendingIntent.CanceledException {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.SHARE_EMBEDDER);
        PendingIntent pendingIntent = mock(PendingIntent.class);
        Context context = mActivity.getApplicationContext();
        View buttonView = new View(context);
        BottomBarConfig.ButtonConfig buttonConfig =
                new BottomBarConfig.ButtonConfig(
                        ButtonId.SHARE,
                        context.getDrawable(R.drawable.ic_share_white_24dp),
                        context.getString(R.string.google_bottom_bar_share_button_description),
                        pendingIntent);

        View.OnClickListener clickListener =
                mGoogleBottomBarActionsHandler.getClickListener(buttonConfig);
        clickListener.onClick(buttonView);

        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
        verify(pendingIntent)
                .send(eq(mActivity), anyInt(), captor.capture(), any(), any(), any(), any());
        assertEquals(Uri.parse(TEST_URI), captor.getValue().getData());
    }

    @Test
    public void testShareAction_initiateShareForCurrentTab() {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.SHARE_CHROME);
        Context context = mActivity.getApplicationContext();
        View buttonView = new View(context);
        BottomBarConfig.ButtonConfig buttonConfig =
                new BottomBarConfig.ButtonConfig(
                        ButtonId.SHARE,
                        context.getDrawable(R.drawable.ic_share_white_24dp),
                        context.getString(R.string.google_bottom_bar_share_button_description),
                        /* pendingIntent= */ null);

        View.OnClickListener clickListener =
                mGoogleBottomBarActionsHandler.getClickListener(buttonConfig);
        clickListener.onClick(buttonView);

        verify(mShareDelegate)
                .share(eq(mTab), eq(false), eq(ShareDelegate.ShareOrigin.GOOGLE_BOTTOM_BAR));
    }

    @Test
    public void testPageInsightsAction_buttonConfigHasPendingIntent_startsPendingIntent()
            throws PendingIntent.CanceledException {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.PIH_EMBEDDER);
        PendingIntent pendingIntent = mock(PendingIntent.class);
        Context context = mActivity.getApplicationContext();
        View buttonView = new View(context);
        BottomBarConfig.ButtonConfig buttonConfig =
                new BottomBarConfig.ButtonConfig(
                        PIH_BASIC,
                        context.getDrawable(R.drawable.bottom_bar_page_insights_icon),
                        context.getString(
                                R.string.google_bottom_bar_page_insights_button_description),
                        pendingIntent);

        View.OnClickListener clickListener =
                mGoogleBottomBarActionsHandler.getClickListener(buttonConfig);
        clickListener.onClick(buttonView);

        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
        verify(pendingIntent)
                .send(eq(mActivity), anyInt(), captor.capture(), any(), any(), any(), any());
        assertEquals(Uri.parse(TEST_URI), captor.getValue().getData());
    }

    @Test
    public void testPageInsightsAction_buttonConfigHasNoPendingIntent_logsError() {
        mHistogramWatcher =
                HistogramWatcher.newBuilder().expectNoRecords(BUTTON_CLICKED_HISTOGRAM).build();
        Context context = mActivity.getApplicationContext();
        View buttonView = new View(context);
        BottomBarConfig.ButtonConfig buttonConfig =
                new BottomBarConfig.ButtonConfig(
                        PIH_BASIC,
                        context.getDrawable(R.drawable.bottom_bar_page_insights_icon),
                        context.getString(
                                R.string.google_bottom_bar_page_insights_button_description),
                        /* pendingIntent= */ null);

        View.OnClickListener clickListener =
                mGoogleBottomBarActionsHandler.getClickListener(buttonConfig);
        clickListener.onClick(buttonView);

        ShadowLog.LogItem logItem = ShadowLog.getLogsForTag("cr_GBBActionHandler").get(0);
        assertEquals(logItem.msg, "Can't perform action with id: 1 as pending intent is null.");
    }

    @Test
    public void testCustomAction_buttonConfigHasNoPendingIntent_logsError() {
        mHistogramWatcher =
                HistogramWatcher.newBuilder().expectNoRecords(BUTTON_CLICKED_HISTOGRAM).build();
        Context context = mActivity.getApplicationContext();
        View buttonView = new View(context);
        Drawable icon = mock(Drawable.class);
        BottomBarConfig.ButtonConfig buttonConfig =
                new BottomBarConfig.ButtonConfig(
                        ButtonId.CUSTOM,
                        icon,
                        /* description= */ "Description",
                        /* pendingIntent= */ null);

        View.OnClickListener clickListener =
                mGoogleBottomBarActionsHandler.getClickListener(buttonConfig);
        clickListener.onClick(buttonView);

        ShadowLog.LogItem logItem = ShadowLog.getLogsForTag("cr_GBBActionHandler").get(0);
        assertEquals(logItem.msg, "Can't perform action with id: 8 as pending intent is null.");
    }

    @Test
    public void testCustomAction_buttonConfigHasPendingIntent_startsPendingIntent()
            throws PendingIntent.CanceledException {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.CUSTOM_EMBEDDER);
        Context context = mActivity.getApplicationContext();
        View buttonView = new View(context);
        PendingIntent pendingIntent = mock(PendingIntent.class);
        Drawable icon = mock(Drawable.class);
        BottomBarConfig.ButtonConfig buttonConfig =
                new BottomBarConfig.ButtonConfig(
                        ButtonId.CUSTOM,
                        icon,
                        /* description= */ "Description",
                        /* pendingIntent= */ pendingIntent);

        View.OnClickListener clickListener =
                mGoogleBottomBarActionsHandler.getClickListener(buttonConfig);
        clickListener.onClick(buttonView);

        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
        verify(pendingIntent)
                .send(eq(mActivity), anyInt(), captor.capture(), any(), any(), any(), any());
        assertEquals(Uri.parse(TEST_URI), captor.getValue().getData());
    }

    @Test(expected = IllegalStateException.class)
    public void
            testSearchAction_buttonConfigHasNoPendingIntent_canNotBeResolved_throwsIllegalStateException() {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.SEARCH_CHROME);
        Context context = mActivity.getApplicationContext();
        View buttonView = new View(context);
        Drawable icon = mock(Drawable.class);
        BottomBarConfig.ButtonConfig buttonConfig =
                new BottomBarConfig.ButtonConfig(
                        ButtonId.SEARCH,
                        icon,
                        /* description= */ "Description",
                        /* pendingIntent= */ null);

        View.OnClickListener clickListener =
                mGoogleBottomBarActionsHandler.getClickListener(buttonConfig);
        clickListener.onClick(buttonView);

        assertNull(Shadows.shadowOf(mActivity).getNextStartedActivityForResult());
        ShadowLog.LogItem logItem = ShadowLog.getLogsForTag("cr_GBBActionHandler").get(0);
        assertEquals(logItem.msg, "Can't resolve activity for action: openGoogleAppSearch");
    }

    @Test
    public void
            testSearchAction_buttonConfigHasNoPendingIntent_canBeResolved_googleAppSearchIntentStarted() {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.SEARCH_CHROME);
        Context context = mActivity.getApplicationContext();
        View buttonView = new View(context);
        Drawable icon = mock(Drawable.class);
        BottomBarConfig.ButtonConfig buttonConfig =
                new BottomBarConfig.ButtonConfig(
                        ButtonId.SEARCH,
                        icon,
                        /* description= */ "Description",
                        /* pendingIntent= */ null);
        Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
        intent.setPackage(GSA_PACKAGE_NAME);
        mShadowPackageManager.addResolveInfoForIntent(intent, new ResolveInfo());

        View.OnClickListener clickListener =
                mGoogleBottomBarActionsHandler.getClickListener(buttonConfig);
        clickListener.onClick(buttonView);

        Intent startedIntent = Shadows.shadowOf(mActivity).getNextStartedActivityForResult().intent;
        assertEquals(SearchManager.INTENT_ACTION_GLOBAL_SEARCH, startedIntent.getAction());
        assertEquals(GSA_PACKAGE_NAME, startedIntent.getPackage());
        assertTrue(
                startedIntent
                        .getExtras()
                        .containsKey(EXTRA_IS_LAUNCHED_FROM_CHROME_SEARCH_ENTRYPOINT));
    }

    @Test
    public void testSearchAction_buttonConfigHasPendingIntent_startsPendingIntent()
            throws PendingIntent.CanceledException {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.SEARCH_EMBEDDER);
        Context context = mActivity.getApplicationContext();
        View buttonView = new View(context);
        PendingIntent pendingIntent = mock(PendingIntent.class);
        Drawable icon = mock(Drawable.class);
        BottomBarConfig.ButtonConfig buttonConfig =
                new BottomBarConfig.ButtonConfig(
                        ButtonId.SEARCH,
                        icon,
                        /* description= */ "Description",
                        /* pendingIntent= */ pendingIntent);

        View.OnClickListener clickListener =
                mGoogleBottomBarActionsHandler.getClickListener(buttonConfig);
        clickListener.onClick(buttonView);

        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
        verify(pendingIntent)
                .send(eq(mActivity), anyInt(), captor.capture(), any(), any(), any(), any());
        assertEquals(Uri.parse(TEST_URI), captor.getValue().getData());
    }

    @Test(expected = IllegalStateException.class)
    public void
            testHomeAction_buttonConfigHasNoPendingIntent_canNotBeResolved_throwsIllegalStateException() {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.HOME_CHROME);
        Context context = mActivity.getApplicationContext();
        View buttonView = new View(context);
        Drawable icon = mock(Drawable.class);
        BottomBarConfig.ButtonConfig buttonConfig =
                new BottomBarConfig.ButtonConfig(
                        ButtonId.HOME,
                        icon,
                        /* description= */ "Description",
                        /* pendingIntent= */ null);

        View.OnClickListener clickListener =
                mGoogleBottomBarActionsHandler.getClickListener(buttonConfig);
        clickListener.onClick(buttonView);

        ShadowLog.LogItem logItem = ShadowLog.getLogsForTag("cr_GBBActionHandler").get(0);
        assertEquals(logItem.msg, "Can't resolve activity for action: openGoogleAppHome");
    }

    @Test
    public void
            testHomeAction_buttonConfigHasNoPendingIntent_canBeResolved_googleAppHomeIntentStarted() {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.HOME_CHROME);
        Context context = mActivity.getApplicationContext();
        View buttonView = new View(context);
        Drawable icon = mock(Drawable.class);
        BottomBarConfig.ButtonConfig buttonConfig =
                new BottomBarConfig.ButtonConfig(
                        ButtonId.HOME,
                        icon,
                        /* description= */ "Description",
                        /* pendingIntent= */ null);
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_INFO);
        intent.setClassName(GSA_PACKAGE_NAME, GSA_CLASS_NAME);
        mShadowPackageManager.addResolveInfoForIntent(intent, new ResolveInfo());

        View.OnClickListener clickListener =
                mGoogleBottomBarActionsHandler.getClickListener(buttonConfig);
        clickListener.onClick(buttonView);

        Intent startedIntent = Shadows.shadowOf(mActivity).getNextStartedActivityForResult().intent;
        assertEquals(Intent.ACTION_MAIN, startedIntent.getAction());
        assertEquals(1, startedIntent.getCategories().size());
        assertTrue(startedIntent.getCategories().contains(Intent.CATEGORY_INFO));
        assertEquals(GSA_PACKAGE_NAME, startedIntent.getComponent().getPackageName());
        assertEquals(GSA_CLASS_NAME, startedIntent.getComponent().getShortClassName());
        assertTrue(
                startedIntent
                        .getExtras()
                        .containsKey(EXTRA_IS_LAUNCHED_FROM_CHROME_SEARCH_ENTRYPOINT));
    }

    @Test
    public void testHomeAction_buttonConfigHasPendingIntent_startsPendingIntent()
            throws PendingIntent.CanceledException {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.HOME_EMBEDDER);
        Context context = mActivity.getApplicationContext();
        View buttonView = new View(context);
        PendingIntent pendingIntent = mock(PendingIntent.class);
        Drawable icon = mock(Drawable.class);
        BottomBarConfig.ButtonConfig buttonConfig =
                new BottomBarConfig.ButtonConfig(
                        ButtonId.HOME,
                        icon,
                        /* description= */ "Description",
                        /* pendingIntent= */ pendingIntent);

        View.OnClickListener clickListener =
                mGoogleBottomBarActionsHandler.getClickListener(buttonConfig);
        clickListener.onClick(buttonView);

        ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
        verify(pendingIntent)
                .send(eq(mActivity), anyInt(), captor.capture(), any(), any(), any(), any());
        assertEquals(Uri.parse(TEST_URI), captor.getValue().getData());
    }

    @Test(expected = IllegalStateException.class)
    public void testOnSearchboxHomeTap_canNotBeResolved_throwsIllegalStateException() {
        mGoogleBottomBarActionsHandler.onSearchboxHomeTap();

        assertNull(Shadows.shadowOf(mActivity).getNextStartedActivityForResult());
        ShadowLog.LogItem logItem = ShadowLog.getLogsForTag("cr_GBBActionHandler").get(0);
        assertEquals(logItem.msg, "Can't resolve activity for action: openGoogleAppHome");
    }

    @Test
    public void testOnSearchboxHomeTap_canBeResolved_googleAppHomeIntentStarted() {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.SEARCHBOX_HOME);
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_INFO);
        intent.setClassName(GSA_PACKAGE_NAME, GSA_CLASS_NAME);
        mShadowPackageManager.addResolveInfoForIntent(intent, new ResolveInfo());

        mGoogleBottomBarActionsHandler.onSearchboxHomeTap();

        Intent startedIntent = Shadows.shadowOf(mActivity).getNextStartedActivityForResult().intent;
        assertEquals(Intent.ACTION_MAIN, startedIntent.getAction());
        assertEquals(1, startedIntent.getCategories().size());
        assertTrue(startedIntent.getCategories().contains(Intent.CATEGORY_INFO));
        assertEquals(GSA_PACKAGE_NAME, startedIntent.getComponent().getPackageName());
        assertEquals(GSA_CLASS_NAME, startedIntent.getComponent().getShortClassName());
        assertTrue(
                startedIntent
                        .getExtras()
                        .containsKey(EXTRA_IS_LAUNCHED_FROM_CHROME_SEARCH_ENTRYPOINT));
    }

    @Test(expected = IllegalStateException.class)
    public void testOnSearchboxHintTextTap_canNotBeResolved_throwsIllegalStateException() {
        mGoogleBottomBarActionsHandler.onSearchboxHintTextTap();

        assertNull(Shadows.shadowOf(mActivity).getNextStartedActivityForResult());
        ShadowLog.LogItem logItem = ShadowLog.getLogsForTag("cr_GBBActionHandler").get(0);
        assertEquals(logItem.msg, "Can't resolve activity for action: openGoogleAppSearch");
    }

    @Test
    public void testOnSearchboxHintTextTap_canBeResolved_googleAppSearchIntentStarted() {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.SEARCHBOX_SEARCH);
        Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
        intent.setPackage(GSA_PACKAGE_NAME);
        mShadowPackageManager.addResolveInfoForIntent(intent, new ResolveInfo());

        mGoogleBottomBarActionsHandler.onSearchboxHintTextTap();

        Intent startedIntent = Shadows.shadowOf(mActivity).getNextStartedActivityForResult().intent;
        assertEquals(SearchManager.INTENT_ACTION_GLOBAL_SEARCH, startedIntent.getAction());
        assertEquals(GSA_PACKAGE_NAME, startedIntent.getPackage());
        assertTrue(
                startedIntent
                        .getExtras()
                        .containsKey(EXTRA_IS_LAUNCHED_FROM_CHROME_SEARCH_ENTRYPOINT));
    }

    @Test(expected = IllegalStateException.class)
    public void testOnSearchboxMicTap_canNotBeResolved_throwsIllegalStateException() {
        mGoogleBottomBarActionsHandler.onSearchboxMicTap();

        assertNull(Shadows.shadowOf(mActivity).getNextStartedActivityForResult());
        ShadowLog.LogItem logItem = ShadowLog.getLogsForTag("cr_GBBActionHandler").get(0);
        assertEquals(logItem.msg, "Can't resolve activity for action: openGoogleAppVoiceSearch");
    }

    @Test
    public void testOnSearchboxMicTap_canBeResolved_googleAppVoiceSearchIntentStarted() {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM,
                        GoogleBottomBarButtonEvent.SEARCHBOX_VOICE_SEARCH);
        Intent intent = new Intent(VOICE_SEARCH_INTENT_ACTION);
        intent.setPackage(GSA_PACKAGE_NAME);
        mShadowPackageManager.addResolveInfoForIntent(intent, new ResolveInfo());

        mGoogleBottomBarActionsHandler.onSearchboxMicTap();

        Intent startedIntent = Shadows.shadowOf(mActivity).getNextStartedActivityForResult().intent;
        assertEquals(VOICE_SEARCH_INTENT_ACTION, startedIntent.getAction());
        assertEquals(GSA_PACKAGE_NAME, startedIntent.getPackage());
        assertTrue(
                startedIntent
                        .getExtras()
                        .containsKey(EXTRA_IS_LAUNCHED_FROM_CHROME_SEARCH_ENTRYPOINT));
    }

    @Test
    public void testOnSearchboxLensTap_lensNotEnabled_lensNotStarted() {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.SEARCHBOX_LENS);
        ShadowLensController.sIsAvailable = false;

        Context context = mActivity;
        mGoogleBottomBarActionsHandler.onSearchboxLensTap(new View(context));

        verify(ShadowLensController.getInstance(), never()).startLens(any(), any());
    }

    @Test
    public void testOnSearchboxLensTap_lensEnabled_lensStarted() {
        mHistogramWatcher =
                HistogramWatcher.newSingleRecordWatcher(
                        BUTTON_CLICKED_HISTOGRAM, GoogleBottomBarButtonEvent.SEARCHBOX_LENS);
        ShadowLensController.sIsAvailable = true;

        Context context = mActivity;
        mGoogleBottomBarActionsHandler.onSearchboxLensTap(new View(context));

        verify(ShadowLensController.getInstance())
                .startLens(any(), mLensIntentParamsArgumentCaptor.capture());
        LensIntentParams params = mLensIntentParamsArgumentCaptor.getValue();
        assertEquals(LensEntryPoint.GOOGLE_BOTTOM_BAR, params.getLensEntryPoint());
    }
}