| Index: third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
 | 
| diff --git a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
 | 
| index 223460103846b958d5c47b0ef3de8a3bddf3ad2e..a4e45f4da1d2d3a29eaa6282c02c4c29d5507b6e 100644
 | 
| --- a/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
 | 
| +++ b/third_party/WebKit/Source/core/editing/InputMethodControllerTest.cpp
 | 
| @@ -1427,4 +1427,316 @@ TEST_F(InputMethodControllerTest, SetEmptyCompositionShouldNotMoveCaret) {
 | 
|    EXPECT_STREQ("abc\ndef", textarea->value().utf8().data());
 | 
|  }
 | 
|  
 | 
| +TEST_F(InputMethodControllerTest, WhitespaceFixup) {
 | 
| +  Element* div = insertHTMLElement(
 | 
| +      "<div id='sample' contenteditable>Initial text blah</div>", "sample");
 | 
| +
 | 
| +  // Delete "Initial"
 | 
| +  Vector<CompositionUnderline> emptyUnderlines;
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 0, 7);
 | 
| +  controller().commitText(String(""), emptyUnderlines, 0);
 | 
| +
 | 
| +  // The space at the beginning of the string should have been converted to an
 | 
| +  // nbsp
 | 
| +  EXPECT_STREQ(" text blah", div->innerHTML().utf8().data());
 | 
| +
 | 
| +  // Delete "blah"
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 6, 10);
 | 
| +  controller().commitText(String(""), emptyUnderlines, 0);
 | 
| +
 | 
| +  // The space at the end of the string should have been converted to an nbsp
 | 
| +  EXPECT_STREQ(" text ", div->innerHTML().utf8().data());
 | 
| +}
 | 
| +
 | 
| +static String getMarkedText(DocumentMarkerController& documentMarkerController,
 | 
| +                            Node* node,
 | 
| +                            int markerIndex) {
 | 
| +  DocumentMarker* marker = documentMarkerController.markers()[markerIndex];
 | 
| +  return node->textContent().substring(
 | 
| +      marker->startOffset(), marker->endOffset() - marker->startOffset());
 | 
| +}
 | 
| +
 | 
| +TEST_F(InputMethodControllerTest,
 | 
| +       Marker_WhitespaceFixupAroundMarkerNotContainingSpace) {
 | 
| +  Element* div = insertHTMLElement(
 | 
| +      "<div id='sample' contenteditable>Initial text blah</div>", "sample");
 | 
| +
 | 
| +  // Add marker under "text" (use TextMatch since Composition markers don't
 | 
| +  // persist across editing operations)
 | 
| +  EphemeralRange markerRange = PlainTextRange(8, 12).createRange(*div);
 | 
| +  document().markers().addMarker(markerRange.startPosition(),
 | 
| +                                 markerRange.endPosition(),
 | 
| +                                 DocumentMarker::TextMatch);
 | 
| +  // Delete "Initial"
 | 
| +  Vector<CompositionUnderline> emptyUnderlines;
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 0, 7);
 | 
| +  controller().commitText(String(""), emptyUnderlines, 0);
 | 
| +
 | 
| +  // Delete "blah"
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 6, 10);
 | 
| +  controller().commitText(String(""), emptyUnderlines, 0);
 | 
| +
 | 
| +  // Check that the marker is still attached to "text" and doesn't include
 | 
| +  // either space around it
 | 
| +  EXPECT_EQ(1u, document().markers().markersFor(div->firstChild()).size());
 | 
| +  EXPECT_STREQ(
 | 
| +      "text",
 | 
| +      getMarkedText(document().markers(), div->firstChild(), 0).utf8().data());
 | 
| +}
 | 
| +
 | 
| +// TODO(rlanday): The behavior tested in the following DocumentMarker tests is
 | 
| +// going to be changed so markers are not split when text they contain is
 | 
| +// deleted
 | 
| +
 | 
| +TEST_F(InputMethodControllerTest,
 | 
| +       Marker_WhitespaceFixupAroundMarkerBeginningWithSpace) {
 | 
| +  Element* div = insertHTMLElement(
 | 
| +      "<div id='sample' contenteditable>Initial text blah</div>", "sample");
 | 
| +
 | 
| +  // Add marker under " text" (use TextMatch since Composition markers don't
 | 
| +  // persist across editing operations)
 | 
| +  EphemeralRange markerRange = PlainTextRange(7, 12).createRange(*div);
 | 
| +  document().markers().addMarker(markerRange.startPosition(),
 | 
| +                                 markerRange.endPosition(),
 | 
| +                                 DocumentMarker::TextMatch);
 | 
| +  // Delete "Initial"
 | 
| +  Vector<CompositionUnderline> emptyUnderlines;
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 0, 7);
 | 
| +  controller().commitText(String(""), emptyUnderlines, 0);
 | 
| +
 | 
| +  // Delete "blah"
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 6, 10);
 | 
| +  controller().commitText(String(""), emptyUnderlines, 0);
 | 
| +
 | 
| +  // Check that the marker was split when the space at the beginning was
 | 
| +  // converted to an nbsp
 | 
| +  EXPECT_EQ(2u, document().markers().markers().size());
 | 
| +  EXPECT_STREQ(
 | 
| +      "\xC2\xA0",  // UTF-8 for an nbsp
 | 
| +      getMarkedText(document().markers(), div->firstChild(), 0).utf8().data());
 | 
| +  EXPECT_STREQ(
 | 
| +      "text",
 | 
| +      getMarkedText(document().markers(), div->firstChild(), 1).utf8().data());
 | 
| +}
 | 
| +
 | 
| +TEST_F(InputMethodControllerTest,
 | 
| +       Marker_WhitespaceFixupAroundMarkerEndingWithSpace) {
 | 
| +  Element* div = insertHTMLElement(
 | 
| +      "<div id='sample' contenteditable>Initial text blah</div>", "sample");
 | 
| +
 | 
| +  // Add marker under "text " (use TextMatch since Composition markers don't
 | 
| +  // persist across editing operations)
 | 
| +  EphemeralRange markerRange = PlainTextRange(8, 13).createRange(*div);
 | 
| +  document().markers().addMarker(markerRange.startPosition(),
 | 
| +                                 markerRange.endPosition(),
 | 
| +                                 DocumentMarker::TextMatch);
 | 
| +  // Delete "Initial"
 | 
| +  Vector<CompositionUnderline> emptyUnderlines;
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 0, 7);
 | 
| +  controller().commitText(String(""), emptyUnderlines, 0);
 | 
| +
 | 
| +  // Delete "blah"
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 6, 10);
 | 
| +  controller().commitText(String(""), emptyUnderlines, 0);
 | 
| +
 | 
| +  // Check that the marker was split when the space at the end was
 | 
| +  // converted to an nbsp
 | 
| +  EXPECT_EQ(2u, document().markers().markers().size());
 | 
| +  EXPECT_STREQ(
 | 
| +      "text",
 | 
| +      getMarkedText(document().markers(), div->firstChild(), 0).utf8().data());
 | 
| +  EXPECT_STREQ(
 | 
| +      "\xC2\xA0",  // UTF-8 for an nbsp
 | 
| +      getMarkedText(document().markers(), div->firstChild(), 1).utf8().data());
 | 
| +}
 | 
| +
 | 
| +TEST_F(InputMethodControllerTest,
 | 
| +       Marker_WhitespaceFixupAroundMarkerBeginningAndEndingWithSpaces) {
 | 
| +  Element* div = insertHTMLElement(
 | 
| +      "<div id='sample' contenteditable>Initial text blah</div>", "sample");
 | 
| +
 | 
| +  // Add marker under " text " (use TextMatch since Composition markers don't
 | 
| +  // persist across editing operations)
 | 
| +  EphemeralRange markerRange = PlainTextRange(7, 13).createRange(*div);
 | 
| +  document().markers().addMarker(markerRange.startPosition(),
 | 
| +                                 markerRange.endPosition(),
 | 
| +                                 DocumentMarker::TextMatch);
 | 
| +
 | 
| +  // Delete "Initial"
 | 
| +  Vector<CompositionUnderline> emptyUnderlines;
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 0, 7);
 | 
| +  controller().commitText(String(""), emptyUnderlines, 0);
 | 
| +
 | 
| +  // Delete "blah"
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 6, 10);
 | 
| +  controller().commitText(String(""), emptyUnderlines, 0);
 | 
| +
 | 
| +  // Check that the marker was split into three pieces when the two spaces were
 | 
| +  // converted to nbsps
 | 
| +  EXPECT_EQ(3u, document().markers().markers().size());
 | 
| +  EXPECT_STREQ(
 | 
| +      "\xC2\xA0",  // UTF-8 for an nbsp
 | 
| +      getMarkedText(document().markers(), div->firstChild(), 0).utf8().data());
 | 
| +  EXPECT_STREQ(
 | 
| +      "text",
 | 
| +      getMarkedText(document().markers(), div->firstChild(), 1).utf8().data());
 | 
| +  EXPECT_STREQ(
 | 
| +      "\xC2\xA0",  // UTF-8 for an nbsp
 | 
| +      getMarkedText(document().markers(), div->firstChild(), 2).utf8().data());
 | 
| +}
 | 
| +
 | 
| +TEST_F(InputMethodControllerTest, Marker_ReplaceStartOfMarker) {
 | 
| +  Element* div = insertHTMLElement(
 | 
| +      "<div id='sample' contenteditable>Initial text</div>", "sample");
 | 
| +
 | 
| +  // Add marker under "Initial text"
 | 
| +  EphemeralRange markerRange = PlainTextRange(0, 12).createRange(*div);
 | 
| +  document().markers().addMarker(markerRange.startPosition(),
 | 
| +                                 markerRange.endPosition(),
 | 
| +                                 DocumentMarker::TextMatch);
 | 
| +
 | 
| +  // Replace "Initial" with "Original"
 | 
| +  Vector<CompositionUnderline> emptyUnderlines;
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 0, 7);
 | 
| +  controller().commitText(String("Original"), emptyUnderlines, 0);
 | 
| +
 | 
| +  // Verify marker is under "al text"
 | 
| +  // ("Initial" and "Original" have "al" as a common suffix)
 | 
| +  EXPECT_EQ(1u, document().markers().markers().size());
 | 
| +  EXPECT_STREQ(
 | 
| +      "al text",
 | 
| +      getMarkedText(document().markers(), div->firstChild(), 0).utf8().data());
 | 
| +}
 | 
| +
 | 
| +TEST_F(InputMethodControllerTest, Marker_ReplaceTextContainsStartOfMarker) {
 | 
| +  Element* div = insertHTMLElement(
 | 
| +      "<div id='sample' contenteditable>This is some initial text</div>",
 | 
| +      "sample");
 | 
| +
 | 
| +  // Add marker under "initial text"
 | 
| +  EphemeralRange markerRange = PlainTextRange(13, 25).createRange(*div);
 | 
| +  document().markers().addMarker(markerRange.startPosition(),
 | 
| +                                 markerRange.endPosition(),
 | 
| +                                 DocumentMarker::TextMatch);
 | 
| +
 | 
| +  // Replace "some initial" with "boring"
 | 
| +  Vector<CompositionUnderline> emptyUnderlines;
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 8, 20);
 | 
| +  controller().commitText(String("boring"), emptyUnderlines, 0);
 | 
| +
 | 
| +  // Verify marker is under " text"
 | 
| +  EXPECT_EQ(1u, document().markers().markers().size());
 | 
| +  EXPECT_STREQ(
 | 
| +      " text",
 | 
| +      getMarkedText(document().markers(), div->firstChild(), 0).utf8().data());
 | 
| +}
 | 
| +
 | 
| +TEST_F(InputMethodControllerTest, Marker_ReplaceEndOfMarker) {
 | 
| +  Element* div = insertHTMLElement(
 | 
| +      "<div id='sample' contenteditable>Initial text</div>", "sample");
 | 
| +
 | 
| +  // Add marker under "Initial text"
 | 
| +  EphemeralRange markerRange = PlainTextRange(0, 12).createRange(*div);
 | 
| +  document().markers().addMarker(markerRange.startPosition(),
 | 
| +                                 markerRange.endPosition(),
 | 
| +                                 DocumentMarker::TextMatch);
 | 
| +
 | 
| +  // Replace "text" with "string"
 | 
| +  Vector<CompositionUnderline> emptyUnderlines;
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 8, 12);
 | 
| +  controller().commitText(String("string"), emptyUnderlines, 0);
 | 
| +
 | 
| +  // Verify marker is under "Initial "
 | 
| +  EXPECT_EQ(1u, document().markers().markers().size());
 | 
| +  EXPECT_STREQ(
 | 
| +      "Initial ",
 | 
| +      getMarkedText(document().markers(), div->firstChild(), 0).utf8().data());
 | 
| +}
 | 
| +
 | 
| +TEST_F(InputMethodControllerTest, Marker_ReplaceTextContainsEndOfMarker) {
 | 
| +  Element* div = insertHTMLElement(
 | 
| +      "<div id='sample' contenteditable>This is some initial text</div>",
 | 
| +      "sample");
 | 
| +
 | 
| +  // Add marker under "some initial"
 | 
| +  EphemeralRange markerRange = PlainTextRange(8, 20).createRange(*div);
 | 
| +  document().markers().addMarker(markerRange.startPosition(),
 | 
| +                                 markerRange.endPosition(),
 | 
| +                                 DocumentMarker::TextMatch);
 | 
| +
 | 
| +  // Replace "initial text" with "content"
 | 
| +  Vector<CompositionUnderline> emptyUnderlines;
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 13, 25);
 | 
| +  controller().commitText(String("content"), emptyUnderlines, 0);
 | 
| +
 | 
| +  EXPECT_STREQ("This is some content", div->innerHTML().utf8().data());
 | 
| +
 | 
| +  // Verify marker is under "some "
 | 
| +  EXPECT_EQ(1u, document().markers().markers().size());
 | 
| +  EXPECT_STREQ(
 | 
| +      "some ",
 | 
| +      getMarkedText(document().markers(), div->firstChild(), 0).utf8().data());
 | 
| +}
 | 
| +
 | 
| +TEST_F(InputMethodControllerTest, Marker_ReplaceEntireMarker) {
 | 
| +  Element* div = insertHTMLElement(
 | 
| +      "<div id='sample' contenteditable>Initial text</div>", "sample");
 | 
| +
 | 
| +  // Add marker under "text"
 | 
| +  EphemeralRange markerRange = PlainTextRange(8, 12).createRange(*div);
 | 
| +  document().markers().addMarker(markerRange.startPosition(),
 | 
| +                                 markerRange.endPosition(),
 | 
| +                                 DocumentMarker::TextMatch);
 | 
| +
 | 
| +  // Replace "text" with "string"
 | 
| +  Vector<CompositionUnderline> emptyUnderlines;
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 8, 12);
 | 
| +  controller().commitText(String("string"), emptyUnderlines, 0);
 | 
| +
 | 
| +  // Verify marker was removed
 | 
| +  EXPECT_EQ(0u, document().markers().markers().size());
 | 
| +}
 | 
| +
 | 
| +TEST_F(InputMethodControllerTest, Marker_ReplaceTextWithMarkerAtBeginning) {
 | 
| +  Element* div = insertHTMLElement(
 | 
| +      "<div id='sample' contenteditable>Initial text</div>", "sample");
 | 
| +
 | 
| +  // Add marker under "Initial"
 | 
| +  EphemeralRange markerRange = PlainTextRange(0, 7).createRange(*div);
 | 
| +  document().markers().addMarker(markerRange.startPosition(),
 | 
| +                                 markerRange.endPosition(),
 | 
| +                                 DocumentMarker::TextMatch);
 | 
| +
 | 
| +  EXPECT_EQ(1u, document().markers().markers().size());
 | 
| +
 | 
| +  // Replace "Initial text" with "New string"
 | 
| +  Vector<CompositionUnderline> emptyUnderlines;
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 0, 12);
 | 
| +  controller().commitText(String("New string"), emptyUnderlines, 0);
 | 
| +
 | 
| +  // Verify marker was removed
 | 
| +  EXPECT_EQ(0u, document().markers().markers().size());
 | 
| +}
 | 
| +
 | 
| +TEST_F(InputMethodControllerTest, Marker_ReplaceTextWithMarkerAtEnd) {
 | 
| +  Element* div = insertHTMLElement(
 | 
| +      "<div id='sample' contenteditable>Initial text</div>", "sample");
 | 
| +
 | 
| +  // Add marker under "text"
 | 
| +  EphemeralRange markerRange = PlainTextRange(8, 12).createRange(*div);
 | 
| +  document().markers().addMarker(markerRange.startPosition(),
 | 
| +                                 markerRange.endPosition(),
 | 
| +                                 DocumentMarker::TextMatch);
 | 
| +
 | 
| +  EXPECT_EQ(1u, document().markers().markers().size());
 | 
| +
 | 
| +  // Replace "Initial text" with "New string"
 | 
| +  Vector<CompositionUnderline> emptyUnderlines;
 | 
| +  controller().setCompositionFromExistingText(emptyUnderlines, 0, 12);
 | 
| +  controller().commitText(String("New string"), emptyUnderlines, 0);
 | 
| +
 | 
| +  // Verify marker was removed
 | 
| +  EXPECT_EQ(0u, document().markers().markers().size());
 | 
| +}
 | 
| +
 | 
|  }  // namespace blink
 | 
| 
 |