diff --git a/src/plugins/fakevim/fakevim_test.cpp b/src/plugins/fakevim/fakevim_test.cpp
index ba44896c6322d007279937ce3af15eb9987b03db..3a5010abc29ee38a64d0c1eb67e72e7783483ee5 100644
--- a/src/plugins/fakevim/fakevim_test.cpp
+++ b/src/plugins/fakevim/fakevim_test.cpp
@@ -41,6 +41,7 @@
 #include <QtTest>
 #include <QTextEdit>
 #include <QTextDocument>
+#include <QTextBlock>
 
 /*!
  * Tests after this macro will be skipped and warning printed.
@@ -78,9 +79,11 @@ static const QString helpFormat =
         QString before(beforeText); \
         QString actual(afterText); \
         QString expected(expectedText); \
+        data.oldPosition = beforePosition; \
+        data.oldText = before; \
         if (!cursorString.isEmpty() && expected.contains(cursorString)) {\
-            before.insert(beforePosition, cursorString); \
-            actual.insert(afterPosition, cursorString); \
+            before = textWithCursor(before, beforePosition); \
+            actual = textWithCursor(actual, afterPosition); \
         } \
         QString help = helpFormat \
             .arg(QString(cmd)) \
@@ -110,9 +113,43 @@ static const QString helpFormat =
         COMPARE(beforeText, beforePosition, data.text(), data.position(), (expected), (":" cmd)); \
     } while (false)
 
+// Test undo, redo and repeat of last single command. This doesn't test cursor position.
+#define INTEGRITY() \
+    do { \
+        data.doKeys("<ESC>"); \
+        const int newPosition = data.position(); \
+        const int oldPosition = data.oldPosition; \
+        const QString redo = data.text(); \
+        KEYS("u", data.oldText); \
+        const QTextCursor tc = data.cursor(); \
+        const int pos = tc.position(); \
+        const int col = tc.positionInBlock(); \
+        const int line = tc.block().blockNumber(); \
+        const QTextDocument *doc = data.editor()->document(); \
+        KEYS("<c-r>", textWithCursor(redo, doc->findBlockByNumber(line), col)); \
+        KEYS("u", textWithCursor(data.oldText, pos)); \
+        data.setPosition(oldPosition); \
+        KEYS(".", textWithCursor(redo, newPosition)); \
+    } while (false)
+
 using namespace FakeVim::Internal;
 using namespace TextEditor;
 
+namespace {
+
+QString textWithCursor(const QString &text, int position)
+{
+    return (position == -1) ? text : (text.left(position) + cursorString + text.mid(position));
+}
+
+QString textWithCursor(const QString &text, const QTextBlock &block, int column)
+{
+    const int pos = block.position() + qMin(column, qMax(0, block.length() - 2));
+    return text.left(pos) + cursorString + text.mid(pos);
+}
+
+} // namespace
+
 // Data for tests containing BaseTextEditorWidget and FakeVimHAndler.
 struct FakeVimPlugin::TestData
 {
@@ -120,6 +157,9 @@ struct FakeVimPlugin::TestData
     QWidget *edit;
     QString title;
 
+    int oldPosition;
+    QString oldText;
+
     BaseTextEditorWidget *editor() const { return qobject_cast<BaseTextEditorWidget *>(edit); }
 
     QTextCursor cursor() const { return editor()->textCursor(); }
@@ -129,6 +169,11 @@ struct FakeVimPlugin::TestData
         return cursor().position();
     }
 
+    void setPosition(int position)
+    {
+        handler->setTextCursorPosition(position);
+    }
+
     QString text() const { return editor()->toPlainText(); }
 
     void setText(const QString &text)
@@ -138,7 +183,7 @@ struct FakeVimPlugin::TestData
         if (!cursorString.isEmpty() && i != -1)
             str.remove(i, 1);
         editor()->document()->setPlainText(str);
-        handler->setTextCursorPosition(i);
+        setPosition(i);
     }
 
     void doCommand(const QString &cmd) { handler->handleCommand(cmd); }
@@ -261,14 +306,18 @@ void FakeVimPlugin::test_vim_transform_numbers()
 
     data.setText("8");
     KEYS("<c-a>", X "9");
+    INTEGRITY();
     KEYS("<c-x>", X "8");
+    INTEGRITY();
     KEYS("<c-a>", X "9");
     KEYS("<c-a>", "1" X "0");
     KEYS("<c-a>", "1" X "1");
     KEYS("5<c-a>", "1" X "6");
+    INTEGRITY();
     KEYS("10<c-a>", "2" X "6");
     KEYS("h100<c-a>", "12" X "6");
     KEYS("100<c-x>", "2" X "6");
+    INTEGRITY();
     KEYS("10<c-x>", "1" X "6");
     KEYS("5<c-x>", "1" X "1");
     KEYS("5<c-x>", X "6");
@@ -307,24 +356,33 @@ void FakeVimPlugin::test_vim_delete()
 
     data.setText("123" N "456");
     KEYS("x",  "23" N "456");
+    INTEGRITY();
     KEYS("dd", "456");
+    INTEGRITY();
     KEYS("2x", "6");
+    INTEGRITY();
     KEYS("dd", "");
+    INTEGRITY();
 
     data.setText("void main()");
     KEYS("dt(", "()");
+    INTEGRITY();
 
     data.setText("void main()");
     KEYS("df(", ")");
+    INTEGRITY();
 
-    data.setText("void main()");
-    KEYS("wD", "void ");
+    data.setText("void " X "main()");
+    KEYS("D", "void ");
+    INTEGRITY();
     KEYS("ggd$", "");
 
     data.setText("abc def ghi");
     KEYS("2dw", X "ghi");
+    INTEGRITY();
     data.setText("abc def ghi");
     KEYS("d2w", X "ghi");
+    INTEGRITY();
 
     data.setText("abc  " N "  def" N "  ghi" N "jkl");
     KEYS("3dw", X "jkl");
@@ -338,6 +396,7 @@ void FakeVimPlugin::test_vim_delete()
     // delete on an empty line
     data.setText("a" N X "" N "  b");
     KEYS("d$", "a" N X "" N "  b");
+    INTEGRITY();
 
     // delete in empty document
     data.setText("");
@@ -354,9 +413,11 @@ void FakeVimPlugin::test_vim_delete_inner_word()
 
     data.setText("abc def ghi jkl");
     KEYS("3diw", X  " ghi jkl");
+    INTEGRITY();
 
     data.setText("abc " X "  def");
     KEYS("diw", "abc" X "def");
+    INTEGRITY();
     KEYS("diw", "");
 
     data.setText("abc  " N "  def");
@@ -399,7 +460,9 @@ void FakeVimPlugin::test_vim_delete_a_word()
 
     data.setText("abc" X " def ghi");
     KEYS("daw", "abc" X " ghi");
+    INTEGRITY();
     KEYS("daw", "ab" X "c");
+    INTEGRITY();
     KEYS("daw", "");
 
     data.setText(X " ghi jkl");
@@ -408,6 +471,7 @@ void FakeVimPlugin::test_vim_delete_a_word()
 
     data.setText("abc def ghi jkl");
     KEYS("3daw", X "jkl");
+    INTEGRITY();
 
     // remove trailing spaces
     data.setText("abc  " N "  def" N "  ghi" N "jkl");
@@ -436,6 +500,7 @@ void FakeVimPlugin::test_vim_change_a_word()
 
     data.setText("abc " X "def ghi");
     KEYS("caw#", "abc #" X "ghi");
+    INTEGRITY();
     data.setText("abc d" X "ef ghi");
     KEYS("caw#", "abc #" X "ghi");
     data.setText("abc de" X "f ghi");
@@ -443,6 +508,7 @@ void FakeVimPlugin::test_vim_change_a_word()
 
     data.setText("abc de" X "f ghi jkl");
     KEYS("2caw#", "abc #" X "jkl");
+    INTEGRITY();
 
     data.setText("abc" X " def ghi jkl");
     KEYS("2caw#", "abc#" X " jkl");
@@ -466,10 +532,12 @@ void FakeVimPlugin::test_vim_change_replace()
     // change empty line
     data.setText("a" N X "" N "  b");
     KEYS("ccABC", "a" N "ABC" X N "  b");
+    INTEGRITY();
 
     // change on empty line
     data.setText("a" N X "" N "  b");
     KEYS("c$ABC<esc>", "a" N "AB" X "C" N "  b");
+    INTEGRITY();
     KEYS("u", "a" N X "" N "  b");
     KEYS("rA", "a" N X "" N "  b");
 
@@ -498,6 +566,7 @@ void FakeVimPlugin::test_vim_change_replace()
          "  int i = 0;" X N
          "}" N
          "");
+    INTEGRITY();
 
     KEYS("uS" "int i = 0;" N "int j = 1;",
          "int main()" N
@@ -516,10 +585,12 @@ void FakeVimPlugin::test_vim_block_selection()
     data.setText("int main(int /* (unused) */, char *argv[]);");
     KEYS("f(", "int main" X "(int /* (unused) */, char *argv[]);");
     KEYS("da(", "int main" X ";");
+    INTEGRITY();
 
     data.setText("int main(int /* (unused) */, char *argv[]);");
     KEYS("f(", "int main" X "(int /* (unused) */, char *argv[]);");
     KEYS("di(", "int main(" X ");");
+    INTEGRITY();
 
     data.setText("int main(int /* (unused) */, char *argv[]);");
     KEYS("2f)", "int main(int /* (unused) */, char *argv[]" X ");");
@@ -533,10 +604,12 @@ void FakeVimPlugin::test_vim_block_selection()
     KEYS("2f{l", "{ { {" X " } } }");
     KEYS("da{", "{ { " X " } }");
     KEYS("da{", "{ " X " }");
+    INTEGRITY();
 
     data.setText("{ { { } } }");
     KEYS("2f{l", "{ { {" X " } } }");
     KEYS("2da{", "{ " X " }");
+    INTEGRITY();
 
     data.setText("{" N " { " N " } " N "}");
     KEYS("di{", "{" N "}");
@@ -556,6 +629,7 @@ void FakeVimPlugin::test_vim_repeat()
     data.setText("abc" N "def" N "ghi");
     KEYS("dd", X "def" N "ghi");
     KEYS(".", X "ghi");
+    INTEGRITY();
 
     // delete to next word
     data.setText("abc def ghi jkl");
@@ -713,6 +787,7 @@ void FakeVimPlugin::test_vim_indent()
         "    " X "ghi" N
         "    jkl" N
         "mno");
+    INTEGRITY();
     KEYS("k3<<",
         "abc" N
         X "def" N
@@ -735,6 +810,7 @@ void FakeVimPlugin::test_vim_indent()
 
     data.setText("abc");
     KEYS(">>", "    " X "abc");
+    INTEGRITY();
 
     data.setText("abc");
     data.doCommand("set shiftwidth=2");
@@ -752,6 +828,7 @@ void FakeVimPlugin::test_vim_indent()
     data.doCommand("set shiftwidth=7");
     data.setText("abc");
     KEYS(">>", "\t\t abc");
+    INTEGRITY();
 }
 
 void FakeVimPlugin::test_vim_marks()
@@ -792,6 +869,7 @@ void FakeVimPlugin::test_vim_copy_paste()
     data.setText("123" N "456");
     KEYS("yyp", "123" N X "123" N "456");
     KEYS("2p", "123" N "123" N X "123" N "123" N "456");
+    INTEGRITY();
 
     data.setText("123 456");
     KEYS("yw2P", "123 123" X " 123 456");
@@ -944,6 +1022,7 @@ void FakeVimPlugin::test_vim_code_autoindent()
          "   return 0;" X N
          "}" N
          "");
+    INTEGRITY();
     KEYS("O" "int i = 0;",
          "int main()" N
          "{" N
@@ -951,6 +1030,7 @@ void FakeVimPlugin::test_vim_code_autoindent()
          "   return 0;" N
          "}" N
          "");
+    INTEGRITY();
     KEYS("ddO" "int i = 0;" N "int j = 0;",
          "int main()" N
          "{" N
@@ -988,6 +1068,7 @@ void FakeVimPlugin::test_vim_code_autoindent()
          "{" N
          X "}" N
          "");
+    INTEGRITY();
 }
 
 void FakeVimPlugin::test_vim_code_folding()
diff --git a/src/plugins/fakevim/fakevimhandler.cpp b/src/plugins/fakevim/fakevimhandler.cpp
index 17fc839c75ad3bbf69fca992639a7d18a57c1cb2..0acb12c5bb2e6dc9fc43d7b9ecef6be0c5f12da5 100644
--- a/src/plugins/fakevim/fakevimhandler.cpp
+++ b/src/plugins/fakevim/fakevimhandler.cpp
@@ -6464,12 +6464,9 @@ void FakeVimHandler::handleReplay(const QString &keys)
 
 void FakeVimHandler::handleInput(const QString &keys)
 {
-    Mode oldMode = d->m_mode;
-    d->m_mode = CommandMode;
     Inputs inputs(keys);
     foreach (const Input &input, inputs)
         d->handleKey(input);
-    d->m_mode = oldMode;
 }
 
 void FakeVimHandler::setCurrentFileName(const QString &fileName)