1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chromeos/components/quick_answers/search_result_parsers/definition_result_parser.h"
6 
7 #include <memory>
8 #include <string>
9 
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 
14 namespace chromeos {
15 namespace quick_answers {
16 namespace {
17 
18 using base::Value;
19 
20 }
21 
22 class DefinitionResultParserTest : public testing::Test {
23  public:
DefinitionResultParserTest()24   DefinitionResultParserTest()
25       : parser_(std::make_unique<DefinitionResultParser>()) {}
26 
27   DefinitionResultParserTest(const DefinitionResultParserTest&) = delete;
28   DefinitionResultParserTest& operator=(const DefinitionResultParserTest&) =
29       delete;
30 
31  protected:
BuildDictionaryResult(const std::string & query_term,const std::string & phonetic_str,const std::string & definition)32   Value BuildDictionaryResult(const std::string& query_term,
33                               const std::string& phonetic_str,
34                               const std::string& definition) {
35     Value result(Value::Type::DICTIONARY);
36 
37     if (!query_term.empty())
38       result.SetStringPath("dictionaryResult.queryTerm", query_term);
39 
40     // Build definition entry.
41     Value entries(Value::Type::LIST);
42     Value entry(Value::Type::DICTIONARY);
43 
44     // Build phonetics.
45     if (!phonetic_str.empty()) {
46       Value phonetics(Value::Type::LIST);
47       Value phonetic(Value::Type::DICTIONARY);
48       phonetic.SetStringPath("text", phonetic_str);
49       phonetics.Append(std::move(phonetic));
50       entry.SetPath("phonetics", std::move(phonetics));
51     }
52 
53     // Build definition.
54     if (!definition.empty()) {
55       Value sense_families(Value::Type::LIST);
56       Value sense_family(Value::Type::DICTIONARY);
57       Value senses(Value::Type::LIST);
58       Value sense(Value::Type::DICTIONARY);
59       sense.SetStringPath("definition.text", definition);
60       senses.Append(std::move(sense));
61       sense_family.SetPath("senses", std::move(senses));
62       sense_families.Append(std::move(sense_family));
63       entry.SetPath("senseFamilies", std::move(sense_families));
64     }
65 
66     entries.Append(std::move(entry));
67 
68     result.SetPath("dictionaryResult.entries", std::move(entries));
69 
70     return result;
71   }
72 
73   std::unique_ptr<DefinitionResultParser> parser_;
74 };
75 
TEST_F(DefinitionResultParserTest,Success)76 TEST_F(DefinitionResultParserTest, Success) {
77   Value result =
78       BuildDictionaryResult("unfathomable", "ˌənˈfaT͟Həməb(ə)",
79                             "incapable of being fully explored or understood.");
80   QuickAnswer quick_answer;
81   EXPECT_TRUE(parser_->Parse(&result, &quick_answer));
82 
83   const auto& expected_title = "unfathomable · /ˌənˈfaT͟Həməb(ə)/";
84   const auto& expected_answer =
85       "incapable of being fully explored or understood.";
86   EXPECT_EQ(ResultType::kDefinitionResult, quick_answer.result_type);
87   EXPECT_EQ(expected_answer, quick_answer.primary_answer);
88   EXPECT_EQ(expected_title, quick_answer.secondary_answer);
89 
90   EXPECT_EQ(1u, quick_answer.title.size());
91   EXPECT_EQ(1u, quick_answer.first_answer_row.size());
92   auto* answer =
93       static_cast<QuickAnswerText*>(quick_answer.first_answer_row[0].get());
94   EXPECT_EQ(base::UTF8ToUTF16(expected_answer), answer->text);
95   EXPECT_EQ(gfx::kGoogleGrey700, answer->color);
96   auto* title = static_cast<QuickAnswerText*>(quick_answer.title[0].get());
97   EXPECT_EQ(base::UTF8ToUTF16(expected_title), title->text);
98   EXPECT_EQ(gfx::kGoogleGrey900, title->color);
99 }
100 
TEST_F(DefinitionResultParserTest,EmptyValue)101 TEST_F(DefinitionResultParserTest, EmptyValue) {
102   Value result(Value::Type::DICTIONARY);
103   QuickAnswer quick_answer;
104   EXPECT_FALSE(parser_->Parse(&result, &quick_answer));
105 }
106 
TEST_F(DefinitionResultParserTest,NoQueryTerm)107 TEST_F(DefinitionResultParserTest, NoQueryTerm) {
108   Value result =
109       BuildDictionaryResult("", "ˌənˈfaT͟Həməb(ə)l",
110                             "incapable of being fully explored or understood.");
111   QuickAnswer quick_answer;
112   EXPECT_FALSE(parser_->Parse(&result, &quick_answer));
113 }
114 
TEST_F(DefinitionResultParserTest,NoPhonetic)115 TEST_F(DefinitionResultParserTest, NoPhonetic) {
116   Value result = BuildDictionaryResult(
117       "unfathomable", "", "incapable of being fully explored or understood.");
118   QuickAnswer quick_answer;
119   EXPECT_TRUE(parser_->Parse(&result, &quick_answer));
120 
121   const auto& expected_title = "unfathomable";
122   const auto& expected_answer =
123       "incapable of being fully explored or understood.";
124   EXPECT_EQ(ResultType::kDefinitionResult, quick_answer.result_type);
125   EXPECT_EQ(expected_answer, quick_answer.primary_answer);
126   EXPECT_EQ(expected_title, quick_answer.secondary_answer);
127 }
128 
TEST_F(DefinitionResultParserTest,NoDefinition)129 TEST_F(DefinitionResultParserTest, NoDefinition) {
130   Value result = BuildDictionaryResult("unfathomable", "ˌənˈfaT͟Həməb(ə)l", "");
131   QuickAnswer quick_answer;
132   EXPECT_FALSE(parser_->Parse(&result, &quick_answer));
133 }
134 
135 }  // namespace quick_answers
136 }  // namespace chromeos
137