OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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 "core/editing/suggestion/TextSuggestionController.h" |
| 6 |
| 7 #include "core/editing/EditingTestBase.h" |
| 8 #include "core/editing/FrameSelection.h" |
| 9 #include "core/editing/markers/DocumentMarkerController.h" |
| 10 #include "core/editing/spellcheck/SpellChecker.h" |
| 11 |
| 12 namespace blink { |
| 13 |
| 14 class TextSuggestionControllerTest : public EditingTestBase {}; |
| 15 |
| 16 TEST_F(TextSuggestionControllerTest, ApplySpellCheckSuggestion) { |
| 17 SetBodyContent( |
| 18 "<div contenteditable>" |
| 19 "spllchck" |
| 20 "</div>"); |
| 21 Element* div = GetDocument().QuerySelector("div"); |
| 22 Node* text = div->firstChild(); |
| 23 |
| 24 GetDocument().Markers().AddSpellingMarker( |
| 25 EphemeralRange(Position(text, 0), Position(text, 8))); |
| 26 // Select immediately before misspelling |
| 27 GetDocument().GetFrame()->Selection().SetSelection( |
| 28 SelectionInDOMTree::Builder() |
| 29 .SetBaseAndExtent(Position(text, 0), Position(text, 0)) |
| 30 .Build()); |
| 31 GetDocument() |
| 32 .GetFrame() |
| 33 ->GetTextSuggestionController() |
| 34 .ApplySpellCheckSuggestion("spellcheck"); |
| 35 |
| 36 EXPECT_EQ("spellcheck", text->textContent()); |
| 37 } |
| 38 |
| 39 TEST_F(TextSuggestionControllerTest, DeleteActiveSuggestionRange_DeleteAtEnd) { |
| 40 SetBodyContent( |
| 41 "<div contenteditable>" |
| 42 "word1 word2" |
| 43 "</div>"); |
| 44 Element* div = GetDocument().QuerySelector("div"); |
| 45 Node* text = div->firstChild(); |
| 46 |
| 47 // Mark "word2" as the active suggestion range |
| 48 GetDocument().Markers().AddActiveSuggestionMarker( |
| 49 EphemeralRange(Position(text, 6), Position(text, 11)), Color::kBlack, |
| 50 StyleableMarker::Thickness::kThin, Color::kBlack); |
| 51 // Select immediately before word2 |
| 52 GetDocument().GetFrame()->Selection().SetSelection( |
| 53 SelectionInDOMTree::Builder() |
| 54 .SetBaseAndExtent(Position(text, 6), Position(text, 6)) |
| 55 .Build()); |
| 56 GetDocument() |
| 57 .GetFrame() |
| 58 ->GetTextSuggestionController() |
| 59 .DeleteActiveSuggestionRange(); |
| 60 |
| 61 EXPECT_EQ("word1\xA0", text->textContent()); |
| 62 } |
| 63 |
| 64 TEST_F(TextSuggestionControllerTest, |
| 65 DeleteActiveSuggestionRange_DeleteInMiddle) { |
| 66 SetBodyContent( |
| 67 "<div contenteditable>" |
| 68 "word1 word2 word3" |
| 69 "</div>"); |
| 70 Element* div = GetDocument().QuerySelector("div"); |
| 71 Node* text = div->firstChild(); |
| 72 |
| 73 // Mark "word2" as the active suggestion range |
| 74 GetDocument().Markers().AddActiveSuggestionMarker( |
| 75 EphemeralRange(Position(text, 6), Position(text, 11)), Color::kBlack, |
| 76 StyleableMarker::Thickness::kThin, Color::kBlack); |
| 77 // Select immediately before word2 |
| 78 GetDocument().GetFrame()->Selection().SetSelection( |
| 79 SelectionInDOMTree::Builder() |
| 80 .SetBaseAndExtent(Position(text, 6), Position(text, 6)) |
| 81 .Build()); |
| 82 GetDocument() |
| 83 .GetFrame() |
| 84 ->GetTextSuggestionController() |
| 85 .DeleteActiveSuggestionRange(); |
| 86 |
| 87 // One of the extra spaces around "word2" should have been removed |
| 88 EXPECT_EQ("word1\xA0word3", text->textContent()); |
| 89 } |
| 90 |
| 91 TEST_F(TextSuggestionControllerTest, |
| 92 DeleteActiveSuggestionRange_DeleteAtBeginningWithSpaceAfter) { |
| 93 SetBodyContent( |
| 94 "<div contenteditable>" |
| 95 "word1 word2" |
| 96 "</div>"); |
| 97 Element* div = GetDocument().QuerySelector("div"); |
| 98 Node* text = div->firstChild(); |
| 99 |
| 100 // Mark "word1" as the active suggestion range |
| 101 GetDocument().Markers().AddActiveSuggestionMarker( |
| 102 EphemeralRange(Position(text, 0), Position(text, 5)), Color::kBlack, |
| 103 StyleableMarker::Thickness::kThin, Color::kBlack); |
| 104 // Select immediately before word1 |
| 105 GetDocument().GetFrame()->Selection().SetSelection( |
| 106 SelectionInDOMTree::Builder() |
| 107 .SetBaseAndExtent(Position(text, 0), Position(text, 0)) |
| 108 .Build()); |
| 109 GetDocument() |
| 110 .GetFrame() |
| 111 ->GetTextSuggestionController() |
| 112 .DeleteActiveSuggestionRange(); |
| 113 |
| 114 // The space after "word1" should have been removed (to avoid leaving an |
| 115 // empty space at the beginning of the composition) |
| 116 EXPECT_EQ("word2", text->textContent()); |
| 117 } |
| 118 |
| 119 TEST_F(TextSuggestionControllerTest, |
| 120 DeleteActiveSuggestionRange_DeleteEntireRange) { |
| 121 SetBodyContent( |
| 122 "<div contenteditable>" |
| 123 "word1" |
| 124 "</div>"); |
| 125 Element* div = GetDocument().QuerySelector("div"); |
| 126 Node* text = div->firstChild(); |
| 127 |
| 128 // Mark "word1" as the active suggestion range |
| 129 GetDocument().Markers().AddActiveSuggestionMarker( |
| 130 EphemeralRange(Position(text, 0), Position(text, 5)), Color::kBlack, |
| 131 StyleableMarker::Thickness::kThin, Color::kBlack); |
| 132 // Select immediately before word1 |
| 133 GetDocument().GetFrame()->Selection().SetSelection( |
| 134 SelectionInDOMTree::Builder() |
| 135 .SetBaseAndExtent(Position(text, 0), Position(text, 0)) |
| 136 .Build()); |
| 137 GetDocument() |
| 138 .GetFrame() |
| 139 ->GetTextSuggestionController() |
| 140 .DeleteActiveSuggestionRange(); |
| 141 |
| 142 EXPECT_EQ("", text->textContent()); |
| 143 } |
| 144 |
| 145 // The following two cases test situations that probably shouldn't occur in |
| 146 // normal use (spell check/suggestoin markers not spanning a whole word), but |
| 147 // are included anyway to verify that DeleteActiveSuggestionRange() is |
| 148 // well-behaved in these cases |
| 149 |
| 150 TEST_F(TextSuggestionControllerTest, |
| 151 DeleteActiveSuggestionRange_DeleteRangeWithTextBeforeAndSpaceAfter) { |
| 152 SetBodyContent( |
| 153 "<div contenteditable>" |
| 154 "word1word2 word3" |
| 155 "</div>"); |
| 156 Element* div = GetDocument().QuerySelector("div"); |
| 157 Node* text = div->firstChild(); |
| 158 |
| 159 // Mark "word2" as the active suggestion range |
| 160 GetDocument().Markers().AddActiveSuggestionMarker( |
| 161 EphemeralRange(Position(text, 5), Position(text, 10)), Color::kBlack, |
| 162 StyleableMarker::Thickness::kThin, Color::kBlack); |
| 163 // Select immediately before word2 |
| 164 GetDocument().GetFrame()->Selection().SetSelection( |
| 165 SelectionInDOMTree::Builder() |
| 166 .SetBaseAndExtent(Position(text, 5), Position(text, 5)) |
| 167 .Build()); |
| 168 GetDocument() |
| 169 .GetFrame() |
| 170 ->GetTextSuggestionController() |
| 171 .DeleteActiveSuggestionRange(); |
| 172 |
| 173 EXPECT_EQ("word1\xA0word3", text->textContent()); |
| 174 } |
| 175 |
| 176 TEST_F(TextSuggestionControllerTest, |
| 177 DeleteActiveSuggestionRange_DeleteRangeWithSpaceBeforeAndTextAfter) { |
| 178 SetBodyContent( |
| 179 "<div contenteditable>" |
| 180 "word1 word2word3" |
| 181 "</div>"); |
| 182 Element* div = GetDocument().QuerySelector("div"); |
| 183 Node* text = div->firstChild(); |
| 184 |
| 185 // Mark "word2" as the active suggestion range |
| 186 GetDocument().Markers().AddActiveSuggestionMarker( |
| 187 EphemeralRange(Position(text, 6), Position(text, 11)), Color::kBlack, |
| 188 StyleableMarker::Thickness::kThin, Color::kBlack); |
| 189 // Select immediately before word2 |
| 190 GetDocument().GetFrame()->Selection().SetSelection( |
| 191 SelectionInDOMTree::Builder() |
| 192 .SetBaseAndExtent(Position(text, 6), Position(text, 6)) |
| 193 .Build()); |
| 194 GetDocument() |
| 195 .GetFrame() |
| 196 ->GetTextSuggestionController() |
| 197 .DeleteActiveSuggestionRange(); |
| 198 |
| 199 EXPECT_EQ("word1\xA0word3", text->textContent()); |
| 200 } |
| 201 |
| 202 TEST_F(TextSuggestionControllerTest, |
| 203 DeleteActiveSuggestionRange_DeleteAtBeginningWithTextAfter) { |
| 204 SetBodyContent( |
| 205 "<div contenteditable>" |
| 206 "word1word2" |
| 207 "</div>"); |
| 208 Element* div = GetDocument().QuerySelector("div"); |
| 209 Node* text = div->firstChild(); |
| 210 |
| 211 // Mark "word1" as the active suggestion range |
| 212 GetDocument().Markers().AddActiveSuggestionMarker( |
| 213 EphemeralRange(Position(text, 0), Position(text, 5)), Color::kBlack, |
| 214 StyleableMarker::Thickness::kThin, Color::kBlack); |
| 215 // Select immediately before word1 |
| 216 GetDocument().GetFrame()->Selection().SetSelection( |
| 217 SelectionInDOMTree::Builder() |
| 218 .SetBaseAndExtent(Position(text, 0), Position(text, 0)) |
| 219 .Build()); |
| 220 GetDocument() |
| 221 .GetFrame() |
| 222 ->GetTextSuggestionController() |
| 223 .DeleteActiveSuggestionRange(); |
| 224 |
| 225 EXPECT_EQ("word2", text->textContent()); |
| 226 } |
| 227 |
| 228 TEST_F(TextSuggestionControllerTest, |
| 229 DeleteActiveSuggestionRange_NewWordAddedToDictionary) { |
| 230 SetBodyContent( |
| 231 "<div contenteditable>" |
| 232 "embiggen" |
| 233 "</div>"); |
| 234 Element* div = GetDocument().QuerySelector("div"); |
| 235 Node* text = div->firstChild(); |
| 236 |
| 237 // Mark "embiggen" as misspelled |
| 238 GetDocument().Markers().AddSpellingMarker( |
| 239 EphemeralRange(Position(text, 0), Position(text, 8))); |
| 240 // Select inside before "embiggen" |
| 241 GetDocument().GetFrame()->Selection().SetSelection( |
| 242 SelectionInDOMTree::Builder() |
| 243 .SetBaseAndExtent(Position(text, 1), Position(text, 1)) |
| 244 .Build()); |
| 245 |
| 246 // Add some other word to the dictionary |
| 247 GetDocument() |
| 248 .GetFrame() |
| 249 ->GetTextSuggestionController() |
| 250 .NewWordAddedToDictionary("cromulent"); |
| 251 // Verify the spelling marker is still present |
| 252 EXPECT_TRUE(GetDocument() |
| 253 .GetFrame() |
| 254 ->GetSpellChecker() |
| 255 .GetSpellCheckMarkerUnderSelection()); |
| 256 |
| 257 // Add "embiggen" to the dictionary |
| 258 GetDocument() |
| 259 .GetFrame() |
| 260 ->GetTextSuggestionController() |
| 261 .NewWordAddedToDictionary("embiggen"); |
| 262 // Verify the spelling marker is gone |
| 263 EXPECT_FALSE(GetDocument() |
| 264 .GetFrame() |
| 265 ->GetSpellChecker() |
| 266 .GetSpellCheckMarkerUnderSelection()); |
| 267 } |
| 268 |
| 269 } // namespace blink |
OLD | NEW |