Commit 49e7ec74 authored by Lukas Holecek's avatar Lukas Holecek Committed by hjk
Browse files

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: default avatarhjk <qthjk@ovi.com>
parent 9f737301
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
#include "fakevimplugin.h" #include "fakevimplugin.h"
#include "fakevimhandler.h" #include "fakevimhandler.h"
#include <coreplugin/editormanager/editormanager.h>
#include <texteditor/basetexteditor.h>
#include <QtTest> #include <QtTest>
#include <QTextEdit> #include <QTextEdit>
#include <QTextDocument> #include <QTextDocument>
...@@ -48,17 +51,26 @@ ...@@ -48,17 +51,26 @@
// QTest::qSkip("Not fully implemented!", QTest::SkipSingle, __FILE__, __LINE__); // QTest::qSkip("Not fully implemented!", QTest::SkipSingle, __FILE__, __LINE__);
// return; // 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 "|" #define X "|"
static const QString cursorString(X); static const QString cursorString(X);
// a more distinct line separator in code // More distinct line separator in code.
#define N "\n" #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_START "\t\t<"
#define LINE_END ">\n" #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. // Compare document contents with a expectedText.
// Also check cursor position if the expectedText contains cursorString. // Also check cursor position if the expectedText contains cursorString.
#define COMPARE(beforeText, beforePosition, afterText, afterPosition, expectedText, cmd) \ #define COMPARE(beforeText, beforePosition, afterText, afterPosition, expectedText, cmd) \
...@@ -70,24 +82,24 @@ static const QString cursorString(X); ...@@ -70,24 +82,24 @@ static const QString cursorString(X);
before.insert(beforePosition, cursorString); \ before.insert(beforePosition, cursorString); \
actual.insert(afterPosition, cursorString); \ actual.insert(afterPosition, cursorString); \
} \ } \
QString help = "\n\tBefore command [" + QString(cmd) + "]:\n" LINE_START \ QString help = helpFormat \
+ (before.replace('\n', LINE_END LINE_START)) \ .arg(QString(cmd)) \
+ LINE_END "\n\tAfter the command:\n" LINE_START \ .arg(before.replace('\n', LINE_END LINE_START)) \
+ actual.replace('\n', LINE_END LINE_START) \ .arg(actual.replace('\n', LINE_END LINE_START)) \
+ LINE_END "\n\tShould be:\n" LINE_START \ .arg(expected.replace('\n', LINE_END LINE_START)); \
+ expected.replace('\n', LINE_END LINE_START) + LINE_END; \
QVERIFY2(actual == expected, help.toLatin1().constData()); \ QVERIFY2(actual == expected, help.toLatin1().constData()); \
} while (false) } while (false)
// Send keys and check if the expected result is same as document contents. // 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) \ #define KEYS(keys, expected) \
do { \ do { \
QString beforeText(data.text()); \ QString beforeText(data.text()); \
int beforePosition = data.position(); \ int beforePosition = data.position(); \
data.doKeys("<ESC>" keys); \ data.doKeys("<ESC>"); \
data.doKeys(keys); \
COMPARE(beforeText, beforePosition, data.text(), data.position(), (expected), (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. // Run Ex command and check if the expected result is same as document contents.
#define COMMAND(cmd, expected) \ #define COMMAND(cmd, expected) \
...@@ -96,28 +108,28 @@ static const QString cursorString(X); ...@@ -96,28 +108,28 @@ static const QString cursorString(X);
int beforePosition = data.position(); \ int beforePosition = data.position(); \
data.doCommand(cmd); \ data.doCommand(cmd); \
COMPARE(beforeText, beforePosition, data.text(), data.position(), (expected), (":" cmd)); \ COMPARE(beforeText, beforePosition, data.text(), data.position(), (expected), (":" cmd)); \
} while (false); } while (false)
using namespace FakeVim::Internal; using namespace FakeVim::Internal;
using namespace TextEditor;
namespace { // Data for tests containing BaseTextEditorWidget and FakeVimHAndler.
struct FakeVimPlugin::TestData
struct TestData
{ {
FakeVimHandler *handler; FakeVimHandler *handler;
QTextEdit *edit; QWidget *edit;
QWidget parent; QString title;
BaseTextEditorWidget *editor() const { return qobject_cast<BaseTextEditorWidget *>(edit); }
QTextCursor cursor() const { return edit->textCursor(); } QTextCursor cursor() const { return editor()->textCursor(); }
int position() const int position() const
{ {
int pos = cursor().position(); return cursor().position();
// text cursor position is never behind last character in document
return qMax(0, qMin(pos, edit->document()->characterCount() - 2));
} }
QString text() const { return edit->toPlainText(); } QString text() const { return editor()->toPlainText(); }
void setText(const QString &text) void setText(const QString &text)
{ {
...@@ -125,23 +137,26 @@ struct TestData ...@@ -125,23 +137,26 @@ struct TestData
int i = str.indexOf(cursorString); int i = str.indexOf(cursorString);
if (!cursorString.isEmpty() && i != -1) if (!cursorString.isEmpty() && i != -1)
str.remove(i, 1); str.remove(i, 1);
edit->document()->setPlainText(str); editor()->document()->setPlainText(str);
handler->setTextCursorPosition(i); handler->setTextCursorPosition(i);
} }
void doCommand(const QString &cmd) { handler->handleCommand(cmd); } void doCommand(const QString &cmd) { handler->handleCommand(cmd); }
void doKeys(const QString &keys) { handler->handleInput(keys); } 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); Core::EditorManager::instance()->closeAllEditors(false);
data->handler = new FakeVimHandler(data->edit, &data->parent);
data->handler->handleCommand("set startofline");
} }
} // namespace
void FakeVimPlugin::test_vim_movement() void FakeVimPlugin::test_vim_movement()
{ {
TestData data; TestData data;
...@@ -418,31 +433,31 @@ void FakeVimPlugin::test_vim_block_selection() ...@@ -418,31 +433,31 @@ void FakeVimPlugin::test_vim_block_selection()
data.setText("int main(int /* (unused) */, char *argv[]);"); data.setText("int main(int /* (unused) */, char *argv[]);");
KEYS("f(", "int main" X "(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[]);"); data.setText("int main(int /* (unused) */, char *argv[]);");
KEYS("f(", "int main" X "(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[]);"); data.setText("int main(int /* (unused) */, char *argv[]);");
KEYS("2f)", "int main(int /* (unused) */, char *argv[]" X ");"); 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[]);"); data.setText("int main(int /* (unused) */, char *argv[]);");
KEYS("2f)", "int main(int /* (unused) */, char *argv[]" X ");"); KEYS("2f)", "int main(int /* (unused) */, char *argv[]" X ");");
KEYS("di(", "int main(" X ");") KEYS("di(", "int main(" X ");");
data.setText("{ { { } } }"); data.setText("{ { { } } }");
KEYS("2f{l", "{ { {" X " } } }") KEYS("2f{l", "{ { {" X " } } }");
KEYS("da{", "{ { " X " } }") KEYS("da{", "{ { " X " } }");
KEYS("da{", "{ " X " }") KEYS("da{", "{ " X " }");
data.setText("{ { { } } }"); data.setText("{ { { } } }");
KEYS("2f{l", "{ { {" X " } } }") KEYS("2f{l", "{ { {" X " } } }");
KEYS("2da{", "{ " X " }") KEYS("2da{", "{ " X " }");
data.setText("{" N " { " N " } " N "}"); data.setText("{" N " { " N " } " N "}");
KEYS("di{", "{" N "}") KEYS("di{", "{" N "}");
} }
void FakeVimPlugin::test_vim_repeat() void FakeVimPlugin::test_vim_repeat()
...@@ -802,6 +817,100 @@ void FakeVimPlugin::test_vim_undo_redo() ...@@ -802,6 +817,100 @@ void FakeVimPlugin::test_vim_undo_redo()
KEYS("u", "abc" N " " X "def" N "ghi"); 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() void FakeVimPlugin::test_advanced_commands()
{ {
TestData data; TestData data;
...@@ -949,3 +1058,8 @@ void FakeVimPlugin::test_map() ...@@ -949,3 +1058,8 @@ void FakeVimPlugin::test_map()
data.doCommand("imap X <c-o>:%s/def/xxx/<cr>"); data.doCommand("imap X <c-o>:%s/def/xxx/<cr>");
KEYS("iX", "abc xxx"); KEYS("iX", "abc xxx");
} }
void FakeVimPlugin::setup(TestData *data)
{
setupTest(&data->title, &data->handler, &data->edit);
}
...@@ -1932,6 +1932,18 @@ void FakeVimPlugin::extensionsInitialized() ...@@ -1932,6 +1932,18 @@ void FakeVimPlugin::extensionsInitialized()
addAutoReleasedObject(d->m_statusBar); 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 Internal
} // namespace FakeVim } // namespace FakeVim
......
...@@ -59,6 +59,7 @@ private: ...@@ -59,6 +59,7 @@ private:
#ifdef WITH_TESTS #ifdef WITH_TESTS
private slots: private slots:
void cleanup();
void test_vim_movement(); void test_vim_movement();
void test_vim_fFtT(); void test_vim_fFtT();
void test_vim_transform_numbers(); void test_vim_transform_numbers();
...@@ -73,8 +74,14 @@ private slots: ...@@ -73,8 +74,14 @@ private slots:
void test_vim_marks(); void test_vim_marks();
void test_vim_copy_paste(); void test_vim_copy_paste();
void test_vim_undo_redo(); void test_vim_undo_redo();
void test_vim_code_folding();
void test_advanced_commands(); void test_advanced_commands();
void test_map(); void test_map();
private:
struct TestData;
void setup(TestData *data);
void setupTest(QString *title, FakeVimHandler **handler, QWidget **edit);
#endif #endif
}; };
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment