chromium/chrome/browser/ash/app_list/search/search_metrics_manager_unittest.cc

// 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.

#include "chrome/browser/ash/app_list/search/search_metrics_manager.h"

#include <memory>

#include "ash/public/cpp/app_list/app_list_metrics.h"
#include "ash/public/cpp/app_list/app_list_notifier.h"
#include "base/strings/strcat.h"
#include "base/test/metrics/histogram_tester.h"
#include "chrome/browser/ash/app_list/search/search_metrics_util.h"
#include "chrome/browser/ash/app_list/search/test/search_metrics_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace app_list::test {
namespace {

using Action = SearchMetricsManager::Action;

}  // namespace

class SearchMetricsManagerTest : public testing::Test {
 protected:
  void SetUp() override {
    metrics_manager_ = std::make_unique<SearchMetricsManager>(nullptr, nullptr);
  }

  base::HistogramTester histogram_tester_;
  std::unique_ptr<SearchMetricsManager> metrics_manager_;
};

TEST_F(SearchMetricsManagerTest, OnImpression) {
  // The kMissingNotifier log comes from the constructor with null notifier.
  histogram_tester_.ExpectUniqueSample(
      base::StrCat({kHistogramPrefix, "Error"}), Error::kMissingNotifier, 1);

  Location location = Location::kList;
  const std::u16string query = u"query";
  const std::string action_histogram(
      base::StrCat({kHistogramPrefix, "ListSearch"}));
  const std::string view_histogram(
      base::StrCat({action_histogram, ".Impression"}));

  // No update for empty results.
  std::vector<Result> results;
  metrics_manager_->OnImpression(location, results, query);
  histogram_tester_.ExpectTotalCount(view_histogram, 0);
  histogram_tester_.ExpectTotalCount(action_histogram, 0);

  // Metrics Updated for non_empty results.
  results.emplace_back(CreateFakeResult(Type::ANSWER_CARD, "result_id"));
  results.emplace_back(CreateFakeResult(Type::KEYBOARD_SHORTCUT, "result_id"));
  metrics_manager_->OnImpression(location, results, query);

  histogram_tester_.ExpectTotalCount(view_histogram, 2);
  histogram_tester_.ExpectBucketCount(view_histogram, Type::ANSWER_CARD, 1);
  histogram_tester_.ExpectBucketCount(view_histogram, Type::KEYBOARD_SHORTCUT,
                                      1);
  histogram_tester_.ExpectUniqueSample(action_histogram, Action::kImpression,
                                       1);

  // Duplicate type is counted once only.
  results.emplace_back(CreateFakeResult(Type::ANSWER_CARD, "result_id"));
  metrics_manager_->OnImpression(location, results, query);

  histogram_tester_.ExpectTotalCount(view_histogram, 4);
  histogram_tester_.ExpectBucketCount(view_histogram, Type::ANSWER_CARD, 2);
  histogram_tester_.ExpectBucketCount(view_histogram, Type::KEYBOARD_SHORTCUT,
                                      2);
  histogram_tester_.ExpectUniqueSample(action_histogram, Action::kImpression,
                                       2);
}

TEST_F(SearchMetricsManagerTest, OnImpressionLogContinue) {
  // The kMissingNotifier log comes from the constructor with null notifier.
  histogram_tester_.ExpectUniqueSample(
      base::StrCat({kHistogramPrefix, "Error"}), Error::kMissingNotifier, 1);

  Location location = Location::kContinue;
  const std::u16string query = u"query";

  const std::string total_histogram(
      base::StrCat({kHistogramPrefix, "ContinueResultCount.Total"}));
  const std::string drive_histogram(
      base::StrCat({kHistogramPrefix, "ContinueResultCount.Drive"}));
  const std::string local_histogram(
      base::StrCat({kHistogramPrefix, "ContinueResultCount.Local"}));
  const std::string help_app_histogram(
      base::StrCat({kHistogramPrefix, "ContinueResultCount.HelpApp"}));
  const std::string bool_histogram(
      base::StrCat({kHistogramPrefix, "DriveContinueResultsShown"}));

  // Without drive results.
  std::vector<Result> results;
  results.emplace_back(CreateFakeResult(Type::ZERO_STATE_FILE, "result_id"));
  results.emplace_back(CreateFakeResult(Type::HELP_APP_UPDATES, "result_id"));
  results.emplace_back(CreateFakeResult(Type::HELP_APP_UPDATES, "result_id"));
  metrics_manager_->OnImpression(location, results, query);

  histogram_tester_.ExpectUniqueSample(total_histogram, 3, 1);
  histogram_tester_.ExpectUniqueSample(drive_histogram, 0, 1);
  histogram_tester_.ExpectUniqueSample(local_histogram, 1, 1);
  histogram_tester_.ExpectUniqueSample(help_app_histogram, 2, 1);
  histogram_tester_.ExpectUniqueSample(bool_histogram, false, 1);

  // With drive results.
  results.emplace_back(CreateFakeResult(Type::ZERO_STATE_DRIVE, "result_id"));
  metrics_manager_->OnImpression(location, results, query);

  histogram_tester_.ExpectTotalCount(total_histogram, 2);
  histogram_tester_.ExpectBucketCount(total_histogram, 3, 1);
  histogram_tester_.ExpectBucketCount(total_histogram, 4, 1);

  histogram_tester_.ExpectTotalCount(drive_histogram, 2);
  histogram_tester_.ExpectBucketCount(drive_histogram, 0, 1);
  histogram_tester_.ExpectBucketCount(drive_histogram, 1, 1);

  histogram_tester_.ExpectUniqueSample(local_histogram, 1, 2);
  histogram_tester_.ExpectUniqueSample(help_app_histogram, 2, 2);

  histogram_tester_.ExpectTotalCount(bool_histogram, 2);
  histogram_tester_.ExpectBucketCount(bool_histogram, false, 1);
  histogram_tester_.ExpectBucketCount(bool_histogram, true, 1);
}

TEST_F(SearchMetricsManagerTest, OnAbandon) {
  // The kMissingNotifier log comes from the constructor with null notifier.
  histogram_tester_.ExpectUniqueSample(
      base::StrCat({kHistogramPrefix, "Error"}), Error::kMissingNotifier, 1);

  Location location = Location::kAnswerCard;
  const std::u16string query = u"query";
  const std::string action_histogram(
      base::StrCat({kHistogramPrefix, "AnswerCard"}));
  const std::string view_histogram(
      base::StrCat({action_histogram, ".Abandon"}));

  // No update for empty results.
  std::vector<Result> results;
  metrics_manager_->OnAbandon(location, results, query);
  histogram_tester_.ExpectTotalCount(view_histogram, 0);
  histogram_tester_.ExpectTotalCount(action_histogram, 0);

  // Metrics Updated for non_empty results.
  results.emplace_back(CreateFakeResult(Type::FILE_SEARCH, "result_id"));
  results.emplace_back(CreateFakeResult(Type::ASSISTANT, "result_id"));
  metrics_manager_->OnAbandon(location, results, query);

  histogram_tester_.ExpectTotalCount(view_histogram, 2);
  histogram_tester_.ExpectBucketCount(view_histogram, Type::FILE_SEARCH, 1);
  histogram_tester_.ExpectBucketCount(view_histogram, Type::ASSISTANT, 1);
  histogram_tester_.ExpectUniqueSample(action_histogram, Action::kAbandon, 1);

  // Duplicate type is counted once only.
  results.emplace_back(CreateFakeResult(Type::FILE_SEARCH, "result_id"));
  metrics_manager_->OnAbandon(location, results, query);

  histogram_tester_.ExpectTotalCount(view_histogram, 4);
  histogram_tester_.ExpectBucketCount(view_histogram, Type::FILE_SEARCH, 2);
  histogram_tester_.ExpectBucketCount(view_histogram, Type::ASSISTANT, 2);
  histogram_tester_.ExpectUniqueSample(action_histogram, Action::kAbandon, 2);
}

TEST_F(SearchMetricsManagerTest, OnLaunch) {
  // The kMissingNotifier log comes from the constructor with null notifier.
  histogram_tester_.ExpectUniqueSample(
      base::StrCat({kHistogramPrefix, "Error"}), Error::kMissingNotifier, 1);

  Location location = Location::kAnswerCard;
  const std::u16string query = u"query";

  std::vector<Result> shown_results;
  shown_results.emplace_back(CreateFakeResult(Type::FILE_SEARCH, "fake_id_0"));
  shown_results.emplace_back(CreateFakeResult(Type::FILE_SEARCH, "fake_id_1"));
  Result launched_result = CreateFakeResult(Type::FILE_SEARCH, "fake_id_2");
  shown_results.emplace_back(launched_result);
  shown_results.emplace_back(
      CreateFakeResult(Type::HELP_APP_UPDATES, "fake_id_3"));
  shown_results.emplace_back(CreateFakeResult(Type::ASSISTANT, "fake_id_4"));

  metrics_manager_->OnLaunch(location, launched_result, shown_results, query);

  const std::string action_histogram(
      base::StrCat({kHistogramPrefix, "AnswerCard"}));
  const std::string launch_histogram(
      base::StrCat({action_histogram, ".Launch"}));
  const std::string ignore_histogram(
      base::StrCat({action_histogram, ".Ignore"}));
  const std::string index_histogram(
      base::StrCat({action_histogram, ".LaunchIndex"}));

  // Update the action histogram.
  histogram_tester_.ExpectUniqueSample(action_histogram, Action::kLaunch, 1);

  // Update histogram for the launched result.
  histogram_tester_.ExpectUniqueSample(launch_histogram, Type::FILE_SEARCH, 1);

  // Update histogram for the ignored result.
  histogram_tester_.ExpectTotalCount(ignore_histogram, 2);
  histogram_tester_.ExpectBucketCount(ignore_histogram, Type::HELP_APP_UPDATES,
                                      1);
  histogram_tester_.ExpectBucketCount(ignore_histogram, Type::ASSISTANT, 1);

  // Update the index histogram.
  histogram_tester_.ExpectUniqueSample(index_histogram, 2, 1);
}

TEST_F(SearchMetricsManagerTest, OnIgnore) {
  // The kMissingNotifier log comes from the constructor with null notifier.
  histogram_tester_.ExpectUniqueSample(
      base::StrCat({kHistogramPrefix, "Error"}), Error::kMissingNotifier, 1);

  Location location = Location::kAnswerCard;
  const std::u16string query = u"query";
  const std::string action_histogram(
      base::StrCat({kHistogramPrefix, "AnswerCard"}));
  const std::string view_histogram(base::StrCat({action_histogram, ".Ignore"}));

  // No update for empty results.
  std::vector<Result> results;
  metrics_manager_->OnIgnore(location, results, query);
  histogram_tester_.ExpectTotalCount(view_histogram, 0);
  histogram_tester_.ExpectTotalCount(action_histogram, 0);

  // Metrics Updated for non_empty results.
  results.emplace_back(CreateFakeResult(Type::FILE_SEARCH, "result_id"));
  results.emplace_back(CreateFakeResult(Type::ASSISTANT, "result_id"));
  metrics_manager_->OnIgnore(location, results, query);

  histogram_tester_.ExpectTotalCount(view_histogram, 2);
  histogram_tester_.ExpectBucketCount(view_histogram, Type::FILE_SEARCH, 1);
  histogram_tester_.ExpectBucketCount(view_histogram, Type::ASSISTANT, 1);
  histogram_tester_.ExpectUniqueSample(action_histogram, Action::kIgnore, 1);

  // Duplicate type is counted once only.
  results.emplace_back(CreateFakeResult(Type::FILE_SEARCH, "result_id"));
  metrics_manager_->OnIgnore(location, results, query);

  histogram_tester_.ExpectTotalCount(view_histogram, 4);
  histogram_tester_.ExpectBucketCount(view_histogram, Type::FILE_SEARCH, 2);
  histogram_tester_.ExpectBucketCount(view_histogram, Type::ASSISTANT, 2);
  histogram_tester_.ExpectUniqueSample(action_histogram, Action::kIgnore, 2);
}

}  // namespace app_list::test