// 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/spellchecker/spelling_request.h"
#include <memory>
#include <string>
#include <vector>
#include "base/functional/callback_helpers.h"
#include "components/spellcheck/common/spellcheck_result.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
struct RemoteCheckTestCase {
std::string test_name;
std::u16string text;
std::vector<SpellCheckResult> initial_results;
std::vector<SpellCheckResult> expected_converted_results;
};
SpellCheckResult MakeResult(int pos, int length) {
return SpellCheckResult(SpellCheckResult::Decoration::SPELLING, pos, length,
u"");
}
class SpellingRequestRemoteCheckUnitTest
: public testing::TestWithParam<RemoteCheckTestCase> {
public:
SpellingRequestRemoteCheckUnitTest() {
spelling_request_ = SpellingRequest::CreateForTest(
u"", base::DoNothing(), base::DoNothing(), base::DoNothing());
}
~SpellingRequestRemoteCheckUnitTest() override = default;
protected:
content::BrowserTaskEnvironment task_environment_;
std::unique_ptr<SpellingRequest> spelling_request_;
};
// Helper for setting the test case's name.
static std::string DescribeParams(
const testing::TestParamInfo<RemoteCheckTestCase>& info) {
return info.param.test_name;
}
std::vector<RemoteCheckTestCase> BuildTestCases() {
std::vector<RemoteCheckTestCase> test_cases = {
RemoteCheckTestCase{"no_results_all_ascii",
u"This has no spelling mistakes 1 2 3",
{},
{}},
RemoteCheckTestCase{
"some_results_all_ascii",
u"Tihs has 3 speling mistkes",
{MakeResult(0, 4), MakeResult(11, 7), MakeResult(19, 7)},
{MakeResult(0, 4), MakeResult(11, 7), MakeResult(19, 7)}},
RemoteCheckTestCase{
"no_results_non_ascii",
u"\u00e9\u00c8\u00e7\u00e2\u062c\u305c\u000a\u0020\u00ef",
{},
{}},
RemoteCheckTestCase{"some_results_non_ascii",
u"\u00e9\u00c8\u00e7 tihs\u00e2\u062c is "
u"\u305c\u000a a \u0020 mistke\u00ef",
{MakeResult(4, 4), MakeResult(21, 6)},
{MakeResult(4, 4), MakeResult(21, 6)}},
RemoteCheckTestCase{
"no_results_some_surrogate_pairs",
u"π¨βπ©βπ¦βπ¦ This π has π§πΏ emojis",
// The code point representation of the emojis in the above string is:
// "\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66
// This \ud83d\ude01 has \ud83e\uddd1\ud83c\udfff emojis"
{},
{}},
RemoteCheckTestCase{
"some_results_some_surrogate_pairs",
u"π¨βπ©βπ¦βπ¦ Tihs π has π§πΏ emjis",
// The code point representation of the emojis in the above string is:
// "\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66
// Tihs \ud83d\ude01 has \ud83e\uddd1\ud83c\udfff emjis"
{MakeResult(8, 4), MakeResult(22, 5)},
{MakeResult(12, 4), MakeResult(29, 5)}},
RemoteCheckTestCase{
"surrogate_pairs_inside_word",
u"I ufortπ¨βπ©βπ¦βπ¦ππ§πΏunately cant",
// The code point representation of the emojis in the above string is:
// "I ufort\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d
// \ud83d\udc66\ud83d\ude01\ud83e\uddd1\ud83c\udfffunately cant"
{MakeResult(2, 22), MakeResult(25, 4)},
{MakeResult(2, 29), MakeResult(32, 4)}}};
return test_cases;
}
INSTANTIATE_TEST_SUITE_P(/* No prefix */,
SpellingRequestRemoteCheckUnitTest,
testing::ValuesIn(BuildTestCases()),
DescribeParams);
// Tests that remote results have their position value correctly adjusted to
// the corresponding code point position.
TEST_P(SpellingRequestRemoteCheckUnitTest, OnRemoteCheckCompleted) {
const RemoteCheckTestCase& param = GetParam();
spelling_request_->OnRemoteCheckCompleted(true, param.text,
param.initial_results);
const std::vector<SpellCheckResult>& actual_converted_results =
spelling_request_->remote_results_;
EXPECT_EQ(actual_converted_results.size(),
param.expected_converted_results.size());
for (const auto& expected : param.expected_converted_results) {
bool found = false;
for (const auto& actual : actual_converted_results) {
if (expected.decoration == actual.decoration &&
expected.location == actual.location &&
expected.length == actual.length) {
found = true;
break;
}
}
EXPECT_TRUE(found) << "Result with pos = " << expected.location
<< " and length = " << expected.length << " not found.";
}
}