Index: third_party/WebKit/Source/core/editing/suggestion/TextSuggestionControllerTest.cpp |
diff --git a/third_party/WebKit/Source/core/editing/suggestion/TextSuggestionControllerTest.cpp b/third_party/WebKit/Source/core/editing/suggestion/TextSuggestionControllerTest.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..387b9699661433142dc1e1212da21ef2560db5b5 |
--- /dev/null |
+++ b/third_party/WebKit/Source/core/editing/suggestion/TextSuggestionControllerTest.cpp |
@@ -0,0 +1,271 @@ |
+// 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 |