chromium/chrome/browser/ash/app_list/search/common/keyword_util_unittest.cc

// Copyright 2023 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/common/keyword_util.h"
#include "chrome/browser/ash/app_list/search/search_provider.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

#include "base/logging.h"

namespace app_list::list {

namespace {

/*********************** Exact String Matching Tests ***********************/

// Test for successful EXACT matching of ONE keyword in query returns pair of
// {keyword, SearchProviders}.
TEST(KeywordUtilTest, OneExactKeyword) {
  KeywordExtractedInfoList expected_1 = {
      KeywordInfo(u"app", /*relevance_score*/ 1.0,
                  {ProviderType::kInstalledApp, ProviderType::kArcAppShortcut,
                   ProviderType::kPlayStoreApp})};

  EXPECT_EQ(expected_1, ExtractKeywords(u"app test"));

  KeywordExtractedInfoList expected_2 = {
      {u"search", /*relevance_score*/ 1.0, {ProviderType::kOmnibox}}};
  EXPECT_EQ(expected_2, ExtractKeywords(u"test search"));

  KeywordExtractedInfoList expected_3 = {
      {u"android",
       /*relevance_score*/ 1.0,
       {ProviderType::kArcAppShortcut, ProviderType::kPlayStoreApp}}};
  EXPECT_EQ(expected_3, ExtractKeywords(u"/testing android */"));
}

// Test unsuccessful matching of keyword.
TEST(KeywordUtilTest, NoKeyword) {
  EXPECT_EQ(KeywordExtractedInfoList(), ExtractKeywords(u"no keyword"));
  EXPECT_EQ(KeywordExtractedInfoList(), ExtractKeywords(u"dskfhwidkj"));
  EXPECT_EQ(KeywordExtractedInfoList(), ExtractKeywords(u"beehives"));
  EXPECT_EQ(KeywordExtractedInfoList(), ExtractKeywords(u"kelp"));
}

// Test for successful matching of multiple keywords in query
// Pairs of keywords-to-providers are ordered in the same order in which the
// keywords are displayed in the query e.g. For query "help app change
// brightness", the order of keyword pairs is {"help", "app"}.
TEST(KeywordUtilTest, MultipleExactKeywords) {
  KeywordExtractedInfoList expected_1 = {
      {u"help", /*relevance_score*/ 1.0, {ProviderType::kHelpApp}},
      {u"app",
       1.0,
       {ProviderType::kInstalledApp, ProviderType::kArcAppShortcut,
        ProviderType::kPlayStoreApp}}};

  EXPECT_EQ(expected_1, ExtractKeywords(u"help app change brightness"));

  KeywordExtractedInfoList expected_2 = {
      {u"google", /*relevance_score*/ 1.0, {ProviderType::kOmnibox}},
      {u"gaming", /*relevance_score*/ 1.0, {ProviderType::kGames}},
      {u"assistant", /*relevance_score*/ 1.0, {ProviderType::kAssistantText}}};

  EXPECT_EQ(expected_2, ExtractKeywords(u"google gaming assistant"));
}

/*********************** Fuzzy String Matching Tests ***********************/

// Test for one successful fuzzy matching of keywords.
TEST(KeywordUtilTest, OneFuzzyKeyword) {
  KeywordExtractedInfoList actual_1 = ExtractKeywords(u"searchd boba");

  EXPECT_EQ(size_t{1}, actual_1.size());
  EXPECT_EQ(u"searchd", actual_1[0].query_token);
  EXPECT_EQ(std::vector<ProviderType>{ProviderType::kOmnibox},
            actual_1[0].search_providers);

  // Test for British english spelling of "personalisation" is able to match
  // with our canonical keyword which uses American spelling of
  // "personalization".
  KeywordExtractedInfoList actual_2 =
      ExtractKeywords(u"personalisation background");

  EXPECT_EQ(size_t{1}, actual_2.size());
  EXPECT_EQ(u"personalisation", actual_2[0].query_token);
  EXPECT_EQ(std::vector<ProviderType>{ProviderType::kPersonalization},
            actual_2[0].search_providers);

  KeywordExtractedInfoList actual_3 = ExtractKeywords(u"minecraft ap");

  EXPECT_EQ(size_t{1}, actual_3.size());
  EXPECT_EQ(u"ap", actual_3[0].query_token);
  EXPECT_EQ((std::vector<ProviderType>{ProviderType::kInstalledApp,
                                       ProviderType::kArcAppShortcut,
                                       ProviderType::kPlayStoreApp}),
            actual_3[0].search_providers);
}

// Test for multiple successful fuzzy matching of keywords.
TEST(KeywordUtilTest, MultipleFuzzyKeywords) {
  KeywordExtractedInfoList actual_1 = ExtractKeywords(u"setting keyboord");

  EXPECT_EQ(size_t{2}, actual_1.size());
  EXPECT_EQ(u"setting", actual_1[0].query_token);
  EXPECT_EQ(std::vector<ProviderType>{ProviderType::kOsSettings},
            actual_1[0].search_providers);

  EXPECT_EQ(u"keyboord", actual_1[1].query_token);
  EXPECT_EQ(std::vector<ProviderType>{ProviderType::kKeyboardShortcut},
            actual_1[1].search_providers);
}

// Test for both fuzzy and exact matching of keywords.
TEST(KeywordUtilTest, ExactAndFuzzyMatching) {
  KeywordExtractedInfoList actual_1 = ExtractKeywords(u"google asistant");

  EXPECT_EQ(size_t{2}, actual_1.size());
  // Check the first keyword "google" is exact match.
  EXPECT_EQ(
      KeywordInfo(u"google", /*relevance_score*/ 1.0, {ProviderType::kOmnibox}),
      actual_1[0]);
  // Check the second keyword "asisstant" is fuzzily matched.
  EXPECT_EQ(u"asistant", actual_1[1].query_token);
  EXPECT_EQ(std::vector<ProviderType>{ProviderType::kAssistantText},
            actual_1[1].search_providers);
}

/*********************** Query Stripping Tests ***********************/

// Test stripping one keyword from query
TEST(KeywordUtilTest, StripOneKeyword) {
  std::u16string query1 = u"strip keyboard from query";
  EXPECT_EQ(StripQuery(query1), u"strip from query");

  std::u16string query2 = u"help";
  EXPECT_EQ(StripQuery(query2), u"");

  std::u16string query3 = u"personalization background";
  EXPECT_EQ(StripQuery(query3), u"background");
}

// Test stripping multiple keywords form query
TEST(KeywordUtilTest, StripMultipleKeywords) {
  std::u16string query1 =
      u"strip keyboard random word in between files from query";
  EXPECT_EQ(StripQuery(query1), u"strip random word in between from query");

  std::u16string query2 = u"google gaming minecraft";
  EXPECT_EQ(StripQuery(query2), u"minecraft");

  std::u16string query3 = u"file cat drive boba gaming tetris";
  EXPECT_EQ(StripQuery(query3), u"cat boba tetris");
}

}  // namespace
}  // namespace app_list::list