forked from qt-creator/qt-creator
fakevim: Use internal editor widget in tests
Use internal editor with highlighting and folding support for tests to be able to check folding commands. Change-Id: Iaab3bc9edb65c8e2a5a7efc4456e021c8a178d7f Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -35,6 +35,9 @@
|
||||
#include "fakevimplugin.h"
|
||||
#include "fakevimhandler.h"
|
||||
|
||||
#include <coreplugin/editormanager/editormanager.h>
|
||||
#include <texteditor/basetexteditor.h>
|
||||
|
||||
#include <QtTest>
|
||||
#include <QTextEdit>
|
||||
#include <QTextDocument>
|
||||
@@ -48,17 +51,26 @@
|
||||
// QTest::qSkip("Not fully implemented!", QTest::SkipSingle, __FILE__, __LINE__);
|
||||
// return;
|
||||
|
||||
// text cursor representation in comparisons (set empty to disable cursor position checking)
|
||||
// Text cursor representation in comparisons (set empty to disable cursor position checking).
|
||||
#define X "|"
|
||||
static const QString cursorString(X);
|
||||
|
||||
// a more distinct line separator in code
|
||||
// More distinct line separator in code.
|
||||
#define N "\n"
|
||||
|
||||
// document line start and end string in error text
|
||||
// Document line start and end string in error text.
|
||||
#define LINE_START "\t\t<"
|
||||
#define LINE_END ">\n"
|
||||
|
||||
// Format of message after comparison fails (used by KEYS, COMMAND).
|
||||
static const QString helpFormat =
|
||||
"\n\tBefore command [%1]:\n" \
|
||||
LINE_START "%2" LINE_END \
|
||||
"\n\tAfter the command:\n" \
|
||||
LINE_START "%3" LINE_END \
|
||||
"\n\tShould be:\n" \
|
||||
LINE_START "%4" LINE_END;
|
||||
|
||||
// Compare document contents with a expectedText.
|
||||
// Also check cursor position if the expectedText contains cursorString.
|
||||
#define COMPARE(beforeText, beforePosition, afterText, afterPosition, expectedText, cmd) \
|
||||
@@ -70,24 +82,24 @@ static const QString cursorString(X);
|
||||
before.insert(beforePosition, cursorString); \
|
||||
actual.insert(afterPosition, cursorString); \
|
||||
} \
|
||||
QString help = "\n\tBefore command [" + QString(cmd) + "]:\n" LINE_START \
|
||||
+ (before.replace('\n', LINE_END LINE_START)) \
|
||||
+ LINE_END "\n\tAfter the command:\n" LINE_START \
|
||||
+ actual.replace('\n', LINE_END LINE_START) \
|
||||
+ LINE_END "\n\tShould be:\n" LINE_START \
|
||||
+ expected.replace('\n', LINE_END LINE_START) + LINE_END; \
|
||||
QString help = helpFormat \
|
||||
.arg(QString(cmd)) \
|
||||
.arg(before.replace('\n', LINE_END LINE_START)) \
|
||||
.arg(actual.replace('\n', LINE_END LINE_START)) \
|
||||
.arg(expected.replace('\n', LINE_END LINE_START)); \
|
||||
QVERIFY2(actual == expected, help.toLatin1().constData()); \
|
||||
} while (false)
|
||||
|
||||
// Send keys and check if the expected result is same as document contents.
|
||||
// Escape is always prepended to keys so that previous command is cancled.
|
||||
// Escape is always prepended to keys so that previous command is cancelled.
|
||||
#define KEYS(keys, expected) \
|
||||
do { \
|
||||
QString beforeText(data.text()); \
|
||||
int beforePosition = data.position(); \
|
||||
data.doKeys("<ESC>" keys); \
|
||||
data.doKeys("<ESC>"); \
|
||||
data.doKeys(keys); \
|
||||
COMPARE(beforeText, beforePosition, data.text(), data.position(), (expected), (keys)); \
|
||||
} while (false);
|
||||
} while (false)
|
||||
|
||||
// Run Ex command and check if the expected result is same as document contents.
|
||||
#define COMMAND(cmd, expected) \
|
||||
@@ -96,28 +108,28 @@ static const QString cursorString(X);
|
||||
int beforePosition = data.position(); \
|
||||
data.doCommand(cmd); \
|
||||
COMPARE(beforeText, beforePosition, data.text(), data.position(), (expected), (":" cmd)); \
|
||||
} while (false);
|
||||
} while (false)
|
||||
|
||||
using namespace FakeVim::Internal;
|
||||
using namespace TextEditor;
|
||||
|
||||
namespace {
|
||||
|
||||
struct TestData
|
||||
// Data for tests containing BaseTextEditorWidget and FakeVimHAndler.
|
||||
struct FakeVimPlugin::TestData
|
||||
{
|
||||
FakeVimHandler *handler;
|
||||
QTextEdit *edit;
|
||||
QWidget parent;
|
||||
QWidget *edit;
|
||||
QString title;
|
||||
|
||||
QTextCursor cursor() const { return edit->textCursor(); }
|
||||
BaseTextEditorWidget *editor() const { return qobject_cast<BaseTextEditorWidget *>(edit); }
|
||||
|
||||
QTextCursor cursor() const { return editor()->textCursor(); }
|
||||
|
||||
int position() const
|
||||
{
|
||||
int pos = cursor().position();
|
||||
// text cursor position is never behind last character in document
|
||||
return qMax(0, qMin(pos, edit->document()->characterCount() - 2));
|
||||
return cursor().position();
|
||||
}
|
||||
|
||||
QString text() const { return edit->toPlainText(); }
|
||||
QString text() const { return editor()->toPlainText(); }
|
||||
|
||||
void setText(const QString &text)
|
||||
{
|
||||
@@ -125,23 +137,26 @@ struct TestData
|
||||
int i = str.indexOf(cursorString);
|
||||
if (!cursorString.isEmpty() && i != -1)
|
||||
str.remove(i, 1);
|
||||
edit->document()->setPlainText(str);
|
||||
editor()->document()->setPlainText(str);
|
||||
handler->setTextCursorPosition(i);
|
||||
}
|
||||
|
||||
void doCommand(const QString &cmd) { handler->handleCommand(cmd); }
|
||||
void doKeys(const QString &keys) { handler->handleInput(keys); }
|
||||
|
||||
int lines() const
|
||||
{
|
||||
QTextDocument *doc = editor()->document();
|
||||
Q_ASSERT(doc != 0);
|
||||
return doc->lineCount();
|
||||
}
|
||||
};
|
||||
|
||||
static void setup(TestData *data)
|
||||
void FakeVimPlugin::cleanup()
|
||||
{
|
||||
data->edit = new QTextEdit(&data->parent);
|
||||
data->handler = new FakeVimHandler(data->edit, &data->parent);
|
||||
data->handler->handleCommand("set startofline");
|
||||
Core::EditorManager::instance()->closeAllEditors(false);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void FakeVimPlugin::test_vim_movement()
|
||||
{
|
||||
TestData data;
|
||||
@@ -418,31 +433,31 @@ 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 ";")
|
||||
KEYS("da(", "int main" X ";");
|
||||
|
||||
data.setText("int main(int /* (unused) */, char *argv[]);");
|
||||
KEYS("f(", "int main" X "(int /* (unused) */, char *argv[]);");
|
||||
KEYS("di(", "int main(" X ");")
|
||||
KEYS("di(", "int main(" X ");");
|
||||
|
||||
data.setText("int main(int /* (unused) */, char *argv[]);");
|
||||
KEYS("2f)", "int main(int /* (unused) */, char *argv[]" X ");");
|
||||
KEYS("da(", "int main" X ";")
|
||||
KEYS("da(", "int main" X ";");
|
||||
|
||||
data.setText("int main(int /* (unused) */, char *argv[]);");
|
||||
KEYS("2f)", "int main(int /* (unused) */, char *argv[]" X ");");
|
||||
KEYS("di(", "int main(" X ");")
|
||||
KEYS("di(", "int main(" X ");");
|
||||
|
||||
data.setText("{ { { } } }");
|
||||
KEYS("2f{l", "{ { {" X " } } }")
|
||||
KEYS("da{", "{ { " X " } }")
|
||||
KEYS("da{", "{ " X " }")
|
||||
KEYS("2f{l", "{ { {" X " } } }");
|
||||
KEYS("da{", "{ { " X " } }");
|
||||
KEYS("da{", "{ " X " }");
|
||||
|
||||
data.setText("{ { { } } }");
|
||||
KEYS("2f{l", "{ { {" X " } } }")
|
||||
KEYS("2da{", "{ " X " }")
|
||||
KEYS("2f{l", "{ { {" X " } } }");
|
||||
KEYS("2da{", "{ " X " }");
|
||||
|
||||
data.setText("{" N " { " N " } " N "}");
|
||||
KEYS("di{", "{" N "}")
|
||||
KEYS("di{", "{" N "}");
|
||||
}
|
||||
|
||||
void FakeVimPlugin::test_vim_repeat()
|
||||
@@ -802,6 +817,100 @@ void FakeVimPlugin::test_vim_undo_redo()
|
||||
KEYS("u", "abc" N " " X "def" N "ghi");
|
||||
}
|
||||
|
||||
void FakeVimPlugin::test_vim_code_folding()
|
||||
{
|
||||
TestData data;
|
||||
setup(&data);
|
||||
|
||||
data.setText("int main()" N "{" N " return 0;" N "}" N "");
|
||||
|
||||
// fold/unfold function block
|
||||
data.doKeys("zc");
|
||||
QCOMPARE(data.lines(), 2);
|
||||
data.doKeys("zo");
|
||||
QCOMPARE(data.lines(), 5);
|
||||
data.doKeys("za");
|
||||
QCOMPARE(data.lines(), 2);
|
||||
|
||||
// delete whole block
|
||||
KEYS("dd", "");
|
||||
|
||||
// undo/redo
|
||||
KEYS("u", "int main()" N "{" N " return 0;" N "}" N "");
|
||||
KEYS("<c-r>", "");
|
||||
|
||||
// change block
|
||||
KEYS("uggzo", X "int main()" N "{" N " return 0;" N "}" N "");
|
||||
KEYS("ccvoid f()<esc>", "void f(" X ")" N "{" N " return 0;" N "}" N "");
|
||||
KEYS("uzc.", "void f(" X ")" N "");
|
||||
|
||||
// open/close folds recursively
|
||||
data.setText("int main()" N
|
||||
"{" N
|
||||
" if (true) {" N
|
||||
" return 0;" N
|
||||
" } else {" N
|
||||
" // comment" N
|
||||
" " X "return 2" N
|
||||
" }" N
|
||||
"}" N
|
||||
"");
|
||||
int lines = data.lines();
|
||||
// close else block
|
||||
data.doKeys("zc");
|
||||
QCOMPARE(data.lines(), lines - 3);
|
||||
// close function block
|
||||
data.doKeys("zc");
|
||||
QCOMPARE(data.lines(), lines - 8);
|
||||
// jumping to a line opens all its parent folds
|
||||
data.doKeys("6gg");
|
||||
QCOMPARE(data.lines(), lines);
|
||||
|
||||
// close recursively
|
||||
data.doKeys("zC");
|
||||
QCOMPARE(data.lines(), lines - 8);
|
||||
data.doKeys("za");
|
||||
QCOMPARE(data.lines(), lines - 3);
|
||||
data.doKeys("6gg");
|
||||
QCOMPARE(data.lines(), lines);
|
||||
data.doKeys("zA");
|
||||
QCOMPARE(data.lines(), lines - 8);
|
||||
data.doKeys("za");
|
||||
QCOMPARE(data.lines(), lines - 3);
|
||||
|
||||
// close all folds
|
||||
data.doKeys("zM");
|
||||
QCOMPARE(data.lines(), lines - 8);
|
||||
data.doKeys("zo");
|
||||
QCOMPARE(data.lines(), lines - 4);
|
||||
data.doKeys("zM");
|
||||
QCOMPARE(data.lines(), lines - 8);
|
||||
|
||||
// open all folds
|
||||
data.doKeys("zR");
|
||||
QCOMPARE(data.lines(), lines);
|
||||
|
||||
// delete folded lined if deleting to the end of the first folding line
|
||||
data.doKeys("zMgg");
|
||||
QCOMPARE(data.lines(), lines - 8);
|
||||
KEYS("wwd$", "int main" N "");
|
||||
|
||||
// undo
|
||||
KEYS("u", "int main" X "()" N
|
||||
"{" N
|
||||
" if (true) {" N
|
||||
" return 0;" N
|
||||
" } else {" N
|
||||
" // comment" N
|
||||
" return 2" N
|
||||
" }" N
|
||||
"}" N
|
||||
"");
|
||||
|
||||
NOT_IMPLEMENTED
|
||||
// Opening folds recursively isn't supported (previous position in fold isn't restored).
|
||||
}
|
||||
|
||||
void FakeVimPlugin::test_advanced_commands()
|
||||
{
|
||||
TestData data;
|
||||
@@ -949,3 +1058,8 @@ void FakeVimPlugin::test_map()
|
||||
data.doCommand("imap X <c-o>:%s/def/xxx/<cr>");
|
||||
KEYS("iX", "abc xxx");
|
||||
}
|
||||
|
||||
void FakeVimPlugin::setup(TestData *data)
|
||||
{
|
||||
setupTest(&data->title, &data->handler, &data->edit);
|
||||
}
|
||||
|
@@ -1932,6 +1932,18 @@ void FakeVimPlugin::extensionsInitialized()
|
||||
addAutoReleasedObject(d->m_statusBar);
|
||||
}
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
void FakeVimPlugin::setupTest(QString *title, FakeVimHandler **handler, QWidget **edit)
|
||||
{
|
||||
*title = QString("test.cpp");
|
||||
Core::IEditor *iedit = Core::EditorManager::openEditorWithContents(Core::Id(), title);
|
||||
Core::EditorManager::activateEditor(iedit);
|
||||
*edit = iedit->widget();
|
||||
*handler = d->m_editorToHandler.value(iedit, 0);
|
||||
(*handler)->handleCommand("set startofline");
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace FakeVim
|
||||
|
||||
|
@@ -59,6 +59,7 @@ private:
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
private slots:
|
||||
void cleanup();
|
||||
void test_vim_movement();
|
||||
void test_vim_fFtT();
|
||||
void test_vim_transform_numbers();
|
||||
@@ -73,8 +74,14 @@ private slots:
|
||||
void test_vim_marks();
|
||||
void test_vim_copy_paste();
|
||||
void test_vim_undo_redo();
|
||||
void test_vim_code_folding();
|
||||
void test_advanced_commands();
|
||||
void test_map();
|
||||
|
||||
private:
|
||||
struct TestData;
|
||||
void setup(TestData *data);
|
||||
void setupTest(QString *title, FakeVimHandler **handler, QWidget **edit);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user