| // Copyright 2021 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/input_method/grammar_manager.h" |
| |
| #include "base/test/metrics/histogram_tester.h" |
| #include "chrome/browser/ash/input_method/assistive_window_properties.h" |
| #include "chrome/browser/ash/input_method/grammar_service_client.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chromeos/services/machine_learning/public/cpp/fake_service_connection.h" |
| #include "components/spellcheck/common/spellcheck_result.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/base/ime/ash/ime_bridge.h" |
| #include "ui/base/ime/ash/mock_ime_input_context_handler.h" |
| #include "ui/base/ime/text_input_flags.h" |
| #include "ui/events/base_event_utils.h" |
| #include "ui/events/keycodes/dom/dom_code.h" |
| |
| namespace ash { |
| namespace input_method { |
| namespace { |
| |
| using ::testing::_; |
| |
| const char16_t kShowGrammarSuggestionMessage[] = |
| u"Grammar correction suggested. Press tab to access; escape to dismiss."; |
| const char16_t kDismissGrammarSuggestionMessage[] = u"Suggestion dismissed."; |
| const char16_t kAcceptGrammarSuggestionMessage[] = u"Suggestion accepted."; |
| const char16_t kIgnoreGrammarSuggestionMessage[] = u"Suggestion ignored."; |
| const char16_t kSuggestionButtonMessage[] = |
| u"Suggestion correct. Button. Press enter to accept; escape to dismiss."; |
| const char16_t kIgnoreButtonMessage[] = |
| u"Ignore suggestion. Button. Press enter to ignore the suggestion; escape " |
| u"to dismiss."; |
| |
| class TestGrammarServiceClient : public GrammarServiceClient { |
| public: |
| TestGrammarServiceClient() {} |
| ~TestGrammarServiceClient() override = default; |
| |
| bool RequestTextCheck(Profile* profile, |
| const std::u16string& text, |
| TextCheckCompleteCallback callback) override { |
| std::vector<ui::GrammarFragment> grammar_results; |
| for (size_t i = 0; i < text.size(); i++) { |
| if (text.substr(i, 5) == u"error") { |
| grammar_results.emplace_back(gfx::Range(i, i + 5), "correct"); |
| } |
| } |
| std::move(callback).Run(true, grammar_results); |
| return true; |
| } |
| }; |
| |
| ui::KeyEvent CreateKeyEvent(const ui::DomCode& code) { |
| return ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_UNKNOWN, code, ui::EF_NONE, |
| ui::DomKey::NONE, ui::EventTimeForNow()); |
| } |
| |
| class MockSuggestionHandler : public SuggestionHandlerInterface { |
| public: |
| MOCK_METHOD(bool, |
| DismissSuggestion, |
| (int context_id, std::string* error), |
| (override)); |
| MOCK_METHOD(bool, |
| SetSuggestion, |
| (int context_id, |
| const ui::ime::SuggestionDetails& details, |
| std::string* error), |
| (override)); |
| MOCK_METHOD(bool, |
| AcceptSuggestion, |
| (int context_id, std::string* error), |
| (override)); |
| MOCK_METHOD(void, |
| OnSuggestionsChanged, |
| (const std::vector<std::string>& suggestions), |
| (override)); |
| MOCK_METHOD(bool, |
| SetButtonHighlighted, |
| (int context_id, |
| const ui::ime::AssistiveWindowButton& button, |
| bool highlighted, |
| std::string* error), |
| (override)); |
| MOCK_METHOD(void, |
| ClickButton, |
| (const ui::ime::AssistiveWindowButton& button), |
| (override)); |
| MOCK_METHOD(bool, |
| AcceptSuggestionCandidate, |
| (int context_id, |
| const std::u16string& candidate, |
| size_t delete_previous_utf16_len, |
| bool use_replace_surrounding_text, |
| std::string* error), |
| (override)); |
| MOCK_METHOD(bool, |
| SetAssistiveWindowProperties, |
| (int context_id, |
| const AssistiveWindowProperties& assistive_window, |
| std::string* error), |
| (override)); |
| MOCK_METHOD(void, Announce, (const std::u16string& message), (override)); |
| }; |
| |
| class GrammarManagerTest : public testing::Test { |
| protected: |
| void SetUp() override { |
| profile_ = std::make_unique<TestingProfile>(); |
| IMEBridge::Get()->SetInputContextHandler(&mock_ime_input_context_handler_); |
| chromeos::machine_learning::ServiceConnection:: |
| UseFakeServiceConnectionForTesting(&fake_service_connection_); |
| chromeos::machine_learning::ServiceConnection::GetInstance()->Initialize(); |
| } |
| |
| content::BrowserTaskEnvironment task_environment_{ |
| base::test::TaskEnvironment::TimeSource::MOCK_TIME}; |
| |
| std::unique_ptr<TestingProfile> profile_; |
| chromeos::machine_learning::FakeServiceConnectionImpl |
| fake_service_connection_; |
| MockIMEInputContextHandler mock_ime_input_context_handler_; |
| }; |
| |
| TEST_F(GrammarManagerTest, HandlesSingleGrammarCheckResult) { |
| MockSuggestionHandler mock_suggestion_handler; |
| GrammarManager manager(profile_.get(), |
| std::make_unique<TestGrammarServiceClient>(), |
| &mock_suggestion_handler); |
| base::HistogramTester histogram_tester; |
| |
| manager.OnFocus(1, SpellcheckMode::kUnspecified); |
| manager.OnSurroundingTextChanged(u"", gfx::Range(0)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(0)); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| |
| auto grammar_fragments = |
| mock_ime_input_context_handler_.get_grammar_fragments(); |
| EXPECT_EQ(grammar_fragments.size(), 1u); |
| EXPECT_EQ(grammar_fragments[0].range, gfx::Range(9, 14)); |
| EXPECT_EQ(grammar_fragments[0].suggestion, "correct"); |
| histogram_tester.ExpectUniqueSample("InputMethod.Assistive.Grammar.Actions", |
| 0 /*GrammarAction::kUnderlined*/, 1); |
| } |
| |
| TEST_F(GrammarManagerTest, RecordsUnderlinesMetricsWithoutDups) { |
| MockSuggestionHandler mock_suggestion_handler; |
| GrammarManager manager(profile_.get(), |
| std::make_unique<TestGrammarServiceClient>(), |
| &mock_suggestion_handler); |
| base::HistogramTester histogram_tester; |
| |
| manager.OnFocus(1, SpellcheckMode::kUnspecified); |
| manager.OnSurroundingTextChanged(u"", gfx::Range(0)); |
| manager.OnSurroundingTextChanged(u"There is error error", gfx::Range(0)); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| histogram_tester.ExpectUniqueSample("InputMethod.Assistive.Grammar.Actions", |
| 0 /*GrammarAction::kUnderlined*/, 2); |
| |
| manager.OnSurroundingTextChanged(u"There is error error error", |
| gfx::Range(0)); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| histogram_tester.ExpectUniqueSample("InputMethod.Assistive.Grammar.Actions", |
| 0 /*GrammarAction::kUnderlined*/, 3); |
| } |
| |
| TEST_F(GrammarManagerTest, DoesNotRunGrammarCheckOnTextFieldWithSpellcheckOff) { |
| MockSuggestionHandler mock_suggestion_handler; |
| GrammarManager manager(profile_.get(), |
| std::make_unique<TestGrammarServiceClient>(), |
| &mock_suggestion_handler); |
| base::HistogramTester histogram_tester; |
| |
| manager.OnFocus(1, SpellcheckMode::kDisabled); |
| manager.OnSurroundingTextChanged(u"", gfx::Range(0)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(0)); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| |
| auto grammar_fragments = |
| mock_ime_input_context_handler_.get_grammar_fragments(); |
| EXPECT_EQ(grammar_fragments.size(), 0u); |
| histogram_tester.ExpectUniqueSample("InputMethod.Assistive.Grammar.Actions", |
| 0 /*GrammarAction::kUnderlined*/, 0); |
| } |
| |
| TEST_F(GrammarManagerTest, ChecksLastSentenceImmediately) { |
| MockSuggestionHandler mock_suggestion_handler; |
| GrammarManager manager(profile_.get(), |
| std::make_unique<TestGrammarServiceClient>(), |
| &mock_suggestion_handler); |
| |
| manager.OnFocus(1); |
| manager.OnSurroundingTextChanged(u"", gfx::Range(0)); |
| manager.OnSurroundingTextChanged(u"There is error. And another error.", |
| gfx::Range(20)); |
| task_environment_.FastForwardBy(base::Milliseconds(250)); |
| |
| auto grammar_fragments = |
| mock_ime_input_context_handler_.get_grammar_fragments(); |
| EXPECT_EQ(grammar_fragments.size(), 1u); |
| EXPECT_EQ(grammar_fragments[0].range, gfx::Range(9, 14)); |
| EXPECT_EQ(grammar_fragments[0].suggestion, "correct"); |
| } |
| |
| TEST_F(GrammarManagerTest, ChecksBothLastAndCurrentSentence) { |
| MockSuggestionHandler mock_suggestion_handler; |
| GrammarManager manager(profile_.get(), |
| std::make_unique<TestGrammarServiceClient>(), |
| &mock_suggestion_handler); |
| |
| manager.OnFocus(1); |
| manager.OnSurroundingTextChanged(u"", gfx::Range(0)); |
| manager.OnSurroundingTextChanged(u"There is error. And another error.", |
| gfx::Range(20)); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| |
| auto grammar_fragments = |
| mock_ime_input_context_handler_.get_grammar_fragments(); |
| EXPECT_EQ(grammar_fragments.size(), 2u); |
| EXPECT_EQ(grammar_fragments[0].range, gfx::Range(9, 14)); |
| EXPECT_EQ(grammar_fragments[0].suggestion, "correct"); |
| EXPECT_EQ(grammar_fragments[1].range, gfx::Range(28, 33)); |
| EXPECT_EQ(grammar_fragments[1].suggestion, "correct"); |
| } |
| |
| TEST_F(GrammarManagerTest, HandlesMultipleGrammarCheckResults) { |
| MockSuggestionHandler mock_suggestion_handler; |
| GrammarManager manager(profile_.get(), |
| std::make_unique<TestGrammarServiceClient>(), |
| &mock_suggestion_handler); |
| |
| manager.OnFocus(1); |
| manager.OnSurroundingTextChanged(u"", gfx::Range(0)); |
| manager.OnSurroundingTextChanged(u"There is error error.", gfx::Range(0)); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| |
| auto grammar_fragments = |
| mock_ime_input_context_handler_.get_grammar_fragments(); |
| EXPECT_EQ(grammar_fragments.size(), 2u); |
| EXPECT_EQ(grammar_fragments[0].range, gfx::Range(9, 14)); |
| EXPECT_EQ(grammar_fragments[0].suggestion, "correct"); |
| EXPECT_EQ(grammar_fragments[1].range, gfx::Range(15, 20)); |
| EXPECT_EQ(grammar_fragments[0].suggestion, "correct"); |
| } |
| |
| TEST_F(GrammarManagerTest, ClearsPreviousMarkersUponGettingNewResults) { |
| MockSuggestionHandler mock_suggestion_handler; |
| GrammarManager manager(profile_.get(), |
| std::make_unique<TestGrammarServiceClient>(), |
| &mock_suggestion_handler); |
| |
| manager.OnFocus(1); |
| manager.OnSurroundingTextChanged(u"", gfx::Range(0)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(0)); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| |
| auto grammar_fragments = |
| mock_ime_input_context_handler_.get_grammar_fragments(); |
| EXPECT_EQ(grammar_fragments.size(), 1u); |
| EXPECT_EQ(grammar_fragments[0].range, gfx::Range(9, 14)); |
| EXPECT_EQ(grammar_fragments[0].suggestion, "correct"); |
| |
| manager.OnSurroundingTextChanged(u"There is a new error.", gfx::Range(0)); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| |
| auto updated_grammar_fragments = |
| mock_ime_input_context_handler_.get_grammar_fragments(); |
| EXPECT_EQ(updated_grammar_fragments.size(), 1u); |
| EXPECT_EQ(updated_grammar_fragments[0].range, gfx::Range(15, 20)); |
| EXPECT_EQ(updated_grammar_fragments[0].suggestion, "correct"); |
| } |
| |
| TEST_F(GrammarManagerTest, ShowsAndDismissesGrammarSuggestion) { |
| ::testing::StrictMock<MockSuggestionHandler> mock_suggestion_handler; |
| GrammarManager manager(profile_.get(), |
| std::make_unique<TestGrammarServiceClient>(), |
| &mock_suggestion_handler); |
| base::HistogramTester histogram_tester; |
| |
| manager.OnFocus(1); |
| manager.OnSurroundingTextChanged(u"", gfx::Range(0)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(0)); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| |
| AssistiveWindowProperties expected_properties; |
| expected_properties.type = ash::ime::AssistiveWindowType::kGrammarSuggestion; |
| expected_properties.candidates = {u"correct"}; |
| expected_properties.visible = true; |
| expected_properties.announce_string = kShowGrammarSuggestionMessage; |
| |
| EXPECT_CALL(mock_suggestion_handler, |
| SetAssistiveWindowProperties(1, expected_properties, _)); |
| |
| mock_ime_input_context_handler_.set_cursor_range(gfx::Range(10, 10)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(10)); |
| histogram_tester.ExpectBucketCount("InputMethod.Assistive.Grammar.Actions", |
| 1 /*GrammarAction::kWindowShown*/, 1); |
| |
| EXPECT_CALL(mock_suggestion_handler, DismissSuggestion(1, _)); |
| EXPECT_CALL(mock_suggestion_handler, |
| Announce(std::u16string(kDismissGrammarSuggestionMessage))); |
| |
| manager.OnKeyEvent(CreateKeyEvent(ui::DomCode::ESCAPE)); |
| } |
| |
| TEST_F(GrammarManagerTest, DoesntShowGrammarSuggestionWhenUndoWindowIsShown) { |
| ::testing::StrictMock<MockSuggestionHandler> mock_suggestion_handler; |
| GrammarManager manager(profile_.get(), |
| std::make_unique<TestGrammarServiceClient>(), |
| &mock_suggestion_handler); |
| base::HistogramTester histogram_tester; |
| |
| manager.OnFocus(1); |
| manager.OnSurroundingTextChanged(u"", gfx::Range(0)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(0)); |
| mock_ime_input_context_handler_.SetAutocorrectRange(gfx::Range(9, 14), |
| base::DoNothing()); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| |
| auto grammar_fragments = |
| mock_ime_input_context_handler_.get_grammar_fragments(); |
| EXPECT_EQ(grammar_fragments.size(), 1u); |
| EXPECT_EQ(grammar_fragments[0].range, gfx::Range(9, 14)); |
| EXPECT_EQ(grammar_fragments[0].suggestion, "correct"); |
| |
| // No EXPECT_CALL comparing with the last test case because suggestion window |
| // should not show. |
| |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(10)); |
| histogram_tester.ExpectBucketCount("InputMethod.Assistive.Grammar.Actions", |
| 1 /*GrammarAction::kWindowShown*/, 0); |
| } |
| |
| TEST_F(GrammarManagerTest, DismissesSuggestionWhenSelectingARange) { |
| ::testing::StrictMock<MockSuggestionHandler> mock_suggestion_handler; |
| GrammarManager manager(profile_.get(), |
| std::make_unique<TestGrammarServiceClient>(), |
| &mock_suggestion_handler); |
| |
| manager.OnFocus(1); |
| manager.OnSurroundingTextChanged(u"", gfx::Range(0)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(0)); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| |
| AssistiveWindowProperties expected_properties; |
| expected_properties.type = ash::ime::AssistiveWindowType::kGrammarSuggestion; |
| expected_properties.candidates = {u"correct"}; |
| expected_properties.visible = true; |
| expected_properties.announce_string = kShowGrammarSuggestionMessage; |
| |
| EXPECT_CALL(mock_suggestion_handler, |
| SetAssistiveWindowProperties(1, expected_properties, _)); |
| |
| mock_ime_input_context_handler_.set_cursor_range(gfx::Range(10, 10)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(10)); |
| |
| EXPECT_CALL(mock_suggestion_handler, DismissSuggestion(1, _)); |
| |
| mock_ime_input_context_handler_.set_cursor_range(gfx::Range(9, 10)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(9, 10)); |
| } |
| |
| TEST_F(GrammarManagerTest, HighlightsAndCommitsGrammarSuggestionWithTab) { |
| ::testing::StrictMock<MockSuggestionHandler> mock_suggestion_handler; |
| GrammarManager manager(profile_.get(), |
| std::make_unique<TestGrammarServiceClient>(), |
| &mock_suggestion_handler); |
| base::HistogramTester histogram_tester; |
| |
| mock_ime_input_context_handler_.Reset(); |
| |
| manager.OnFocus(1); |
| manager.OnSurroundingTextChanged(u"", gfx::Range(0)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(0)); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| |
| EXPECT_CALL(mock_suggestion_handler, SetAssistiveWindowProperties(1, _, _)); |
| mock_ime_input_context_handler_.set_cursor_range(gfx::Range(10, 10)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(10)); |
| |
| ui::ime::AssistiveWindowButton suggestion_button{ |
| .id = ui::ime::ButtonId::kSuggestion, |
| .window_type = ash::ime::AssistiveWindowType::kGrammarSuggestion, |
| .announce_string = kSuggestionButtonMessage, |
| }; |
| EXPECT_CALL(mock_suggestion_handler, |
| SetButtonHighlighted(1, suggestion_button, true, _)); |
| manager.OnKeyEvent(CreateKeyEvent(ui::DomCode::TAB)); |
| EXPECT_CALL(mock_suggestion_handler, DismissSuggestion(1, _)); |
| EXPECT_CALL(mock_suggestion_handler, |
| Announce(std::u16string(kAcceptGrammarSuggestionMessage))); |
| manager.OnKeyEvent(CreateKeyEvent(ui::DomCode::ENTER)); |
| task_environment_.FastForwardBy(base::Milliseconds(200)); |
| |
| EXPECT_EQ( |
| mock_ime_input_context_handler_.delete_surrounding_text_call_count(), 1); |
| auto deleteSurroundingTextArg = |
| mock_ime_input_context_handler_.last_delete_surrounding_text_arg(); |
| EXPECT_EQ(deleteSurroundingTextArg.num_char16s_before_cursor, 1u); |
| EXPECT_EQ(deleteSurroundingTextArg.num_char16s_after_cursor, 4u); |
| |
| EXPECT_EQ(mock_ime_input_context_handler_.commit_text_call_count(), 1); |
| EXPECT_EQ(mock_ime_input_context_handler_.last_commit_text(), u"correct"); |
| histogram_tester.ExpectBucketCount("InputMethod.Assistive.Grammar.Actions", |
| 2 /*GrammarAction::kAccepted*/, 1); |
| } |
| |
| TEST_F(GrammarManagerTest, HighlightsAndCommitsGrammarSuggestionWithUpArrow) { |
| ::testing::StrictMock<MockSuggestionHandler> mock_suggestion_handler; |
| GrammarManager manager(profile_.get(), |
| std::make_unique<TestGrammarServiceClient>(), |
| &mock_suggestion_handler); |
| base::HistogramTester histogram_tester; |
| |
| mock_ime_input_context_handler_.Reset(); |
| |
| manager.OnFocus(1); |
| manager.OnSurroundingTextChanged(u"", gfx::Range(0)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(0)); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| |
| EXPECT_CALL(mock_suggestion_handler, SetAssistiveWindowProperties(1, _, _)); |
| mock_ime_input_context_handler_.set_cursor_range(gfx::Range(10, 10)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(10)); |
| |
| ui::ime::AssistiveWindowButton suggestion_button{ |
| .id = ui::ime::ButtonId::kSuggestion, |
| .window_type = ash::ime::AssistiveWindowType::kGrammarSuggestion, |
| .announce_string = kSuggestionButtonMessage, |
| }; |
| EXPECT_CALL(mock_suggestion_handler, |
| SetButtonHighlighted(1, suggestion_button, true, _)); |
| manager.OnKeyEvent(CreateKeyEvent(ui::DomCode::ARROW_UP)); |
| EXPECT_CALL(mock_suggestion_handler, DismissSuggestion(1, _)); |
| EXPECT_CALL(mock_suggestion_handler, |
| Announce(std::u16string(kAcceptGrammarSuggestionMessage))); |
| manager.OnKeyEvent(CreateKeyEvent(ui::DomCode::ENTER)); |
| task_environment_.FastForwardBy(base::Milliseconds(200)); |
| |
| EXPECT_EQ( |
| mock_ime_input_context_handler_.delete_surrounding_text_call_count(), 1); |
| auto deleteSurroundingTextArg = |
| mock_ime_input_context_handler_.last_delete_surrounding_text_arg(); |
| EXPECT_EQ(deleteSurroundingTextArg.num_char16s_before_cursor, 1u); |
| EXPECT_EQ(deleteSurroundingTextArg.num_char16s_after_cursor, 4u); |
| |
| EXPECT_EQ(mock_ime_input_context_handler_.commit_text_call_count(), 1); |
| EXPECT_EQ(mock_ime_input_context_handler_.last_commit_text(), u"correct"); |
| histogram_tester.ExpectBucketCount("InputMethod.Assistive.Grammar.Actions", |
| 2 /*GrammarAction::kAccepted*/, 1); |
| } |
| |
| TEST_F(GrammarManagerTest, IgnoresGrammarSuggestion) { |
| ::testing::StrictMock<MockSuggestionHandler> mock_suggestion_handler; |
| GrammarManager manager(profile_.get(), |
| std::make_unique<TestGrammarServiceClient>(), |
| &mock_suggestion_handler); |
| base::HistogramTester histogram_tester; |
| |
| mock_ime_input_context_handler_.Reset(); |
| |
| manager.OnFocus(1); |
| manager.OnSurroundingTextChanged(u"", gfx::Range(0)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(0)); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| |
| EXPECT_EQ(mock_ime_input_context_handler_.get_grammar_fragments().size(), 1u); |
| EXPECT_CALL(mock_suggestion_handler, SetAssistiveWindowProperties(1, _, _)); |
| mock_ime_input_context_handler_.set_cursor_range(gfx::Range(10, 10)); |
| manager.OnSurroundingTextChanged(u"There is error.", gfx::Range(10)); |
| |
| ui::ime::AssistiveWindowButton suggestion_button{ |
| .id = ui::ime::ButtonId::kSuggestion, |
| .window_type = ash::ime::AssistiveWindowType::kGrammarSuggestion, |
| .announce_string = kSuggestionButtonMessage, |
| }; |
| ui::ime::AssistiveWindowButton ignore_button{ |
| .id = ui::ime::ButtonId::kIgnoreSuggestion, |
| .window_type = ash::ime::AssistiveWindowType::kGrammarSuggestion, |
| .announce_string = kIgnoreButtonMessage, |
| }; |
| |
| EXPECT_CALL(mock_suggestion_handler, |
| SetButtonHighlighted(1, suggestion_button, true, _)); |
| manager.OnKeyEvent(CreateKeyEvent(ui::DomCode::TAB)); |
| EXPECT_CALL(mock_suggestion_handler, |
| SetButtonHighlighted(1, ignore_button, true, _)); |
| manager.OnKeyEvent(CreateKeyEvent(ui::DomCode::TAB)); |
| EXPECT_CALL(mock_suggestion_handler, DismissSuggestion(1, _)); |
| EXPECT_CALL(mock_suggestion_handler, |
| Announce(std::u16string(kIgnoreGrammarSuggestionMessage))); |
| manager.OnKeyEvent(CreateKeyEvent(ui::DomCode::ENTER)); |
| |
| EXPECT_EQ(mock_ime_input_context_handler_.get_grammar_fragments().size(), 0u); |
| EXPECT_EQ( |
| mock_ime_input_context_handler_.delete_surrounding_text_call_count(), 0); |
| EXPECT_EQ(mock_ime_input_context_handler_.commit_text_call_count(), 0); |
| histogram_tester.ExpectBucketCount("InputMethod.Assistive.Grammar.Actions", |
| 3 /*GrammarAction::kIgnored*/, 1); |
| |
| manager.OnSurroundingTextChanged(u"There is error. There is error.", |
| gfx::Range(20)); |
| task_environment_.FastForwardBy(base::Milliseconds(2500)); |
| EXPECT_EQ(mock_ime_input_context_handler_.get_grammar_fragments().size(), 0u); |
| } |
| |
| } // namespace |
| } // namespace input_method |
| } // namespace ash |