blob: 387b9699661433142dc1e1212da21ef2560db5b5 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "core/editing/suggestion/TextSuggestionController.h"
#include "core/editing/EditingTestBase.h"
#include "core/editing/FrameSelection.h"
#include "core/editing/markers/DocumentMarkerController.h"
#include "core/editing/spellcheck/SpellChecker.h"
namespace blink {
class TextSuggestionControllerTest : public EditingTestBase {};
TEST_F(TextSuggestionControllerTest, ApplySpellCheckSuggestion) {
SetBodyContent(
"<div contenteditable>"
"spllchck"
"</div>");
Element* div = GetDocument().QuerySelector("div");
Node* text = div->firstChild();
GetDocument().Markers().AddSpellingMarker(
EphemeralRange(Position(text, 0), Position(text, 8)));
// Select immediately before misspelling
GetDocument().GetFrame()->Selection().SetSelection(
SelectionInDOMTree::Builder()
.SetBaseAndExtent(Position(text, 0), Position(text, 0))
.Build());
GetDocument()
.GetFrame()
->GetTextSuggestionController()
.ApplySpellCheckSuggestion("spellcheck");
EXPECT_EQ("spellcheck", text->textContent());
}
TEST_F(TextSuggestionControllerTest, DeleteActiveSuggestionRange_DeleteAtEnd) {
SetBodyContent(
"<div contenteditable>"
"word1 word2"
"</div>");
Element* div = GetDocument().QuerySelector("div");
Node* text = div->firstChild();
// Mark "word2" as the active suggestion range
GetDocument().Markers().AddActiveSuggestionMarker(
EphemeralRange(Position(text, 6), Position(text, 11)), Color::kBlack,
StyleableMarker::Thickness::kThin, Color::kBlack);
// Select immediately before word2
GetDocument().GetFrame()->Selection().SetSelection(
SelectionInDOMTree::Builder()
.SetBaseAndExtent(Position(text, 6), Position(text, 6))
.Build());
GetDocument()
.GetFrame()
->GetTextSuggestionController()
.DeleteActiveSuggestionRange();
EXPECT_EQ("word1\xA0", text->textContent());
}
TEST_F(TextSuggestionControllerTest,
DeleteActiveSuggestionRange_DeleteInMiddle) {
SetBodyContent(
"<div contenteditable>"
"word1 word2 word3"
"</div>");
Element* div = GetDocument().QuerySelector("div");
Node* text = div->firstChild();
// Mark "word2" as the active suggestion range
GetDocument().Markers().AddActiveSuggestionMarker(
EphemeralRange(Position(text, 6), Position(text, 11)), Color::kBlack,
StyleableMarker::Thickness::kThin, Color::kBlack);
// Select immediately before word2
GetDocument().GetFrame()->Selection().SetSelection(
SelectionInDOMTree::Builder()
.SetBaseAndExtent(Position(text, 6), Position(text, 6))
.Build());
GetDocument()
.GetFrame()
->GetTextSuggestionController()
.DeleteActiveSuggestionRange();
// One of the extra spaces around "word2" should have been removed
EXPECT_EQ("word1\xA0word3", text->textContent());
}
TEST_F(TextSuggestionControllerTest,
DeleteActiveSuggestionRange_DeleteAtBeginningWithSpaceAfter) {
SetBodyContent(
"<div contenteditable>"
"word1 word2"
"</div>");
Element* div = GetDocument().QuerySelector("div");
Node* text = div->firstChild();
// Mark "word1" as the active suggestion range
GetDocument().Markers().AddActiveSuggestionMarker(
EphemeralRange(Position(text, 0), Position(text, 5)), Color::kBlack,
StyleableMarker::Thickness::kThin, Color::kBlack);
// Select immediately before word1
GetDocument().GetFrame()->Selection().SetSelection(
SelectionInDOMTree::Builder()
.SetBaseAndExtent(Position(text, 0), Position(text, 0))
.Build());
GetDocument()
.GetFrame()
->GetTextSuggestionController()
.DeleteActiveSuggestionRange();
// The space after "word1" should have been removed (to avoid leaving an
// empty space at the beginning of the composition)
EXPECT_EQ("word2", text->textContent());
}
TEST_F(TextSuggestionControllerTest,
DeleteActiveSuggestionRange_DeleteEntireRange) {
SetBodyContent(
"<div contenteditable>"
"word1"
"</div>");
Element* div = GetDocument().QuerySelector("div");
Node* text = div->firstChild();
// Mark "word1" as the active suggestion range
GetDocument().Markers().AddActiveSuggestionMarker(
EphemeralRange(Position(text, 0), Position(text, 5)), Color::kBlack,
StyleableMarker::Thickness::kThin, Color::kBlack);
// Select immediately before word1
GetDocument().GetFrame()->Selection().SetSelection(
SelectionInDOMTree::Builder()
.SetBaseAndExtent(Position(text, 0), Position(text, 0))
.Build());
GetDocument()
.GetFrame()
->GetTextSuggestionController()
.DeleteActiveSuggestionRange();
EXPECT_EQ("", text->textContent());
}
// The following two cases test situations that probably shouldn't occur in
// normal use (spell check/suggestoin markers not spanning a whole word), but
// are included anyway to verify that DeleteActiveSuggestionRange() is
// well-behaved in these cases
TEST_F(TextSuggestionControllerTest,
DeleteActiveSuggestionRange_DeleteRangeWithTextBeforeAndSpaceAfter) {
SetBodyContent(
"<div contenteditable>"
"word1word2 word3"
"</div>");
Element* div = GetDocument().QuerySelector("div");
Node* text = div->firstChild();
// Mark "word2" as the active suggestion range
GetDocument().Markers().AddActiveSuggestionMarker(
EphemeralRange(Position(text, 5), Position(text, 10)), Color::kBlack,
StyleableMarker::Thickness::kThin, Color::kBlack);
// Select immediately before word2
GetDocument().GetFrame()->Selection().SetSelection(
SelectionInDOMTree::Builder()
.SetBaseAndExtent(Position(text, 5), Position(text, 5))
.Build());
GetDocument()
.GetFrame()
->GetTextSuggestionController()
.DeleteActiveSuggestionRange();
EXPECT_EQ("word1\xA0word3", text->textContent());
}
TEST_F(TextSuggestionControllerTest,
DeleteActiveSuggestionRange_DeleteRangeWithSpaceBeforeAndTextAfter) {
SetBodyContent(
"<div contenteditable>"
"word1 word2word3"
"</div>");
Element* div = GetDocument().QuerySelector("div");
Node* text = div->firstChild();
// Mark "word2" as the active suggestion range
GetDocument().Markers().AddActiveSuggestionMarker(
EphemeralRange(Position(text, 6), Position(text, 11)), Color::kBlack,
StyleableMarker::Thickness::kThin, Color::kBlack);
// Select immediately before word2
GetDocument().GetFrame()->Selection().SetSelection(
SelectionInDOMTree::Builder()
.SetBaseAndExtent(Position(text, 6), Position(text, 6))
.Build());
GetDocument()
.GetFrame()
->GetTextSuggestionController()
.DeleteActiveSuggestionRange();
EXPECT_EQ("word1\xA0word3", text->textContent());
}
TEST_F(TextSuggestionControllerTest,
DeleteActiveSuggestionRange_DeleteAtBeginningWithTextAfter) {
SetBodyContent(
"<div contenteditable>"
"word1word2"
"</div>");
Element* div = GetDocument().QuerySelector("div");
Node* text = div->firstChild();
// Mark "word1" as the active suggestion range
GetDocument().Markers().AddActiveSuggestionMarker(
EphemeralRange(Position(text, 0), Position(text, 5)), Color::kBlack,
StyleableMarker::Thickness::kThin, Color::kBlack);
// Select immediately before word1
GetDocument().GetFrame()->Selection().SetSelection(
SelectionInDOMTree::Builder()
.SetBaseAndExtent(Position(text, 0), Position(text, 0))
.Build());
GetDocument()
.GetFrame()
->GetTextSuggestionController()
.DeleteActiveSuggestionRange();
EXPECT_EQ("word2", text->textContent());
}
TEST_F(TextSuggestionControllerTest,
DeleteActiveSuggestionRange_NewWordAddedToDictionary) {
SetBodyContent(
"<div contenteditable>"
"embiggen"
"</div>");
Element* div = GetDocument().QuerySelector("div");
Node* text = div->firstChild();
// Mark "embiggen" as misspelled
GetDocument().Markers().AddSpellingMarker(
EphemeralRange(Position(text, 0), Position(text, 8)));
// Select inside before "embiggen"
GetDocument().GetFrame()->Selection().SetSelection(
SelectionInDOMTree::Builder()
.SetBaseAndExtent(Position(text, 1), Position(text, 1))
.Build());
// Add some other word to the dictionary
GetDocument()
.GetFrame()
->GetTextSuggestionController()
.NewWordAddedToDictionary("cromulent");
// Verify the spelling marker is still present
EXPECT_NE(nullptr, GetDocument()
.GetFrame()
->GetSpellChecker()
.GetSpellCheckMarkerUnderSelection()
.first);
// Add "embiggen" to the dictionary
GetDocument()
.GetFrame()
->GetTextSuggestionController()
.NewWordAddedToDictionary("embiggen");
// Verify the spelling marker is gone
EXPECT_EQ(nullptr, GetDocument()
.GetFrame()
->GetSpellChecker()
.GetSpellCheckMarkerUnderSelection()
.first);
}
} // namespace blink