chromium/chrome/android/junit/src/org/chromium/chrome/browser/feedback/FeedFeedbackCollectorTest.java

// Copyright 2015 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.feedback;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.os.Bundle;
import android.os.Looper;

import androidx.annotation.Nullable;

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.robolectric.annotation.Config;
import org.robolectric.annotation.LooperMode;
import org.robolectric.shadows.ShadowLooper;

import org.chromium.base.Callback;
import org.chromium.base.ThreadUtils;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
import org.chromium.components.signin.base.CoreAccountInfo;
import org.chromium.components.signin.identitymanager.IdentityManager;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/** Test for {@link FeedFeedbackCollector}. */
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
@LooperMode(LooperMode.Mode.LEGACY)
public class FeedFeedbackCollectorTest {
    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
    // Enable the Features class, so we can override command line switches in the test.
    @Mock private Activity mActivity;
    @Mock private Profile mProfile;
    @Mock private CoreAccountInfo mAccountInfo;

    // Test constants.
    private static final String CATEGORY_TAG = "category_tag";
    private static final String DESCRIPTION = "description";

    public static final String CARD_URL = "CardUrl";
    public static final String CARD_PUBLISHER = "CardPublisher";
    public static final String CARD_PUBLISHING_DATE = "CardPublishingDate";
    public static final String CARD_TITLE = "CardTitle";

    public static final String THE_URL = "https://www.google.com";
    public static final String THE_PUBLISHER = "Google";
    public static final String THE_PUBLISHING_DATE = "July 4, 1776";
    public static final String THE_TITLE = "Declaration of Independence";

    private static void verifySynchronousSources(Bundle bundle) {
        assertTrue(bundle.containsKey(CARD_URL));
        assertTrue(bundle.containsKey(CARD_PUBLISHER));
        assertTrue(bundle.containsKey(CARD_PUBLISHING_DATE));
        assertTrue(bundle.containsKey(CARD_TITLE));
        assertEquals(THE_URL, bundle.getString(CARD_URL));
        assertEquals(THE_PUBLISHER, bundle.getString(CARD_PUBLISHER));
        assertEquals(THE_PUBLISHING_DATE, bundle.getString(CARD_PUBLISHING_DATE));
        assertEquals(THE_TITLE, bundle.getString(CARD_TITLE));
    }

    private static class EmptyFeedFeedbackCollector extends FeedFeedbackCollector {
        EmptyFeedFeedbackCollector(
                Activity activity,
                Profile profile,
                @Nullable String url,
                @Nullable String categoryTag,
                @Nullable String description,
                @Nullable ScreenshotSource screenshotSource,
                @Nullable Map<String, String> feedContext,
                Callback<FeedbackCollector> callback) {
            super(
                    activity,
                    categoryTag,
                    description,
                    screenshotSource,
                    new FeedFeedbackCollector.InitParams(profile, url, feedContext),
                    callback,
                    null);
        }

        // Override the async feedback sources to return an empty list, so we are only testing ths
        // sync sources.
        @Override
        protected List<AsyncFeedbackSource> buildAsynchronousFeedbackSources(
                FeedFeedbackCollector.InitParams initParams) {
            return new ArrayList<>();
        }
    }

    @Before
    public void setUp() {
        ThreadUtils.setUiThread(Looper.getMainLooper());
        when(mAccountInfo.getEmail()).thenReturn(null);
        IdentityServicesProvider.setInstanceForTests(mock(IdentityServicesProvider.class));
        when(IdentityServicesProvider.get().getIdentityManager(any()))
                .thenReturn(mock(IdentityManager.class));
        when(IdentityServicesProvider.get()
                        .getIdentityManager(any())
                        .getPrimaryAccountInfo(anyInt()))
                .thenReturn(mAccountInfo);
    }

    @Test
    @Feature({"Feed"})
    public void testFeedSynchronousData() {
        @SuppressWarnings("unchecked")
        Callback<FeedbackCollector> callback = mock(Callback.class);
        Map<String, String> feedContext = new HashMap<String, String>();
        feedContext.put(CARD_URL, THE_URL);
        feedContext.put(CARD_PUBLISHER, THE_PUBLISHER);
        feedContext.put(CARD_PUBLISHING_DATE, THE_PUBLISHING_DATE);
        feedContext.put(CARD_TITLE, THE_TITLE);

        FeedFeedbackCollector collector =
                new EmptyFeedFeedbackCollector(
                        mActivity,
                        mProfile,
                        null,
                        CATEGORY_TAG,
                        DESCRIPTION,
                        null,
                        feedContext,
                        (result) -> callback.onResult(result));

        ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
        verify(callback, times(1)).onResult(collector);

        ThreadUtils.runOnUiThreadBlocking(
                () -> {
                    verifySynchronousSources(collector.getBundle());
                    assertFalse(
                            collector
                                    .getBundle()
                                    .containsKey(
                                            FeedbackContextFeedbackSource.FEEDBACK_CONTEXT_KEY));
                    assertEquals(CATEGORY_TAG, collector.getCategoryTag());
                    assertEquals(DESCRIPTION, collector.getDescription());
                });
    }
}