File indexing completed on 2024-04-14 03:54:58

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2010 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
0004     SPDX-FileCopyrightText: 2009-2018 Dominik Haumann <dhaumann@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.0-or-later
0007 */
0008 
0009 #include "undomanager_test.h"
0010 
0011 #include <katedocument.h>
0012 #include <kateglobal.h>
0013 #include <kateundomanager.h>
0014 #include <kateview.h>
0015 
0016 #include <QTest>
0017 
0018 QTEST_MAIN(UndoManagerTest)
0019 
0020 using namespace KTextEditor;
0021 
0022 UndoManagerTest::UndoManagerTest()
0023     : QObject()
0024 {
0025     KTextEditor::EditorPrivate::enableUnitTestMode();
0026 }
0027 
0028 void UndoManagerTest::testUndoRedoCount()
0029 {
0030     KTextEditor::DocumentPrivate doc;
0031 
0032     // no undo/redo items at the beginning
0033     QCOMPARE(doc.undoCount(), 0u);
0034     QCOMPARE(doc.redoCount(), 0u);
0035 
0036     doc.insertText(Cursor(0, 0), QStringLiteral("a"));
0037 
0038     // create one insert-group
0039     QCOMPARE(doc.undoCount(), 1u);
0040     QCOMPARE(doc.redoCount(), 0u);
0041 
0042     doc.undo();
0043 
0044     // move insert-group to redo items
0045     QCOMPARE(doc.undoCount(), 0u);
0046     QCOMPARE(doc.redoCount(), 1u);
0047 
0048     doc.redo();
0049 
0050     // move insert-group back to undo items
0051     QCOMPARE(doc.undoCount(), 1u);
0052     QCOMPARE(doc.redoCount(), 0u);
0053 
0054     doc.insertText(Cursor(0, 1), QStringLiteral("b"));
0055 
0056     // merge "b" into insert-group
0057     QCOMPARE(doc.undoCount(), 1u);
0058     QCOMPARE(doc.redoCount(), 0u);
0059 
0060     doc.removeText(Range(0, 1, 0, 2));
0061 
0062     // create an additional remove-group
0063     QCOMPARE(doc.undoCount(), 2u);
0064     QCOMPARE(doc.redoCount(), 0u);
0065 
0066     doc.undo();
0067 
0068     // move remove-group to redo items
0069     QCOMPARE(doc.undoCount(), 1u);
0070     QCOMPARE(doc.redoCount(), 1u);
0071 
0072     doc.insertText(Cursor(0, 1), QStringLiteral("b"));
0073 
0074     // merge "b" into insert-group
0075     // and remove remove-group
0076     QCOMPARE(doc.undoCount(), 1u);
0077     QCOMPARE(doc.redoCount(), 0u);
0078 }
0079 
0080 void UndoManagerTest::testSafePoint()
0081 {
0082     KTextEditor::DocumentPrivate doc;
0083     KateUndoManager *undoManager = doc.undoManager();
0084 
0085     doc.insertText(Cursor(0, 0), QStringLiteral("a"));
0086 
0087     // create one undo group
0088     QCOMPARE(doc.undoCount(), 1u);
0089     QCOMPARE(doc.redoCount(), 0u);
0090 
0091     undoManager->undoSafePoint();
0092     doc.insertText(Cursor(0, 1), QStringLiteral("b"));
0093 
0094     // create a second undo group (don't merge)
0095     QCOMPARE(doc.undoCount(), 2u);
0096 
0097     doc.undo();
0098 
0099     // move second undo group to redo items
0100     QCOMPARE(doc.undoCount(), 1u);
0101     QCOMPARE(doc.redoCount(), 1u);
0102 
0103     doc.insertText(Cursor(0, 1), QStringLiteral("b"));
0104 
0105     // create a second undo group again, (don't merge)
0106     QCOMPARE(doc.undoCount(), 2u);
0107     QCOMPARE(doc.redoCount(), 0u);
0108 
0109     doc.editStart();
0110     doc.insertText(Cursor(0, 2), QStringLiteral("c"));
0111     undoManager->undoSafePoint();
0112     doc.insertText(Cursor(0, 3), QStringLiteral("d"));
0113     doc.editEnd();
0114 
0115     // merge both edits into second undo group
0116     QCOMPARE(doc.undoCount(), 2u);
0117     QCOMPARE(doc.redoCount(), 0u);
0118 
0119     doc.insertText(Cursor(0, 4), QStringLiteral("e"));
0120 
0121     // create a third undo group (don't merge)
0122     QCOMPARE(doc.undoCount(), 3u);
0123     QCOMPARE(doc.redoCount(), 0u);
0124 }
0125 
0126 void UndoManagerTest::testCursorPosition()
0127 {
0128     KTextEditor::DocumentPrivate doc;
0129     KTextEditor::ViewPrivate *view = static_cast<KTextEditor::ViewPrivate *>(doc.createView(nullptr));
0130 
0131     doc.setText(
0132         QStringLiteral("aaaa bbbb cccc\n"
0133                        "dddd  ffff"));
0134     view->setCursorPosition(KTextEditor::Cursor(1, 5));
0135 
0136     doc.typeChars(view, QStringLiteral("eeee"));
0137 
0138     // cursor position: "dddd eeee| ffff"
0139     QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(1, 9));
0140 
0141     // undo once to remove "eeee", cursor position: "dddd | ffff"
0142     doc.undo();
0143     QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(1, 5));
0144 
0145     // redo once to insert "eeee" again. cursor position: "dddd eeee| ffff"
0146     doc.redo();
0147     QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(1, 9));
0148 
0149     delete view;
0150 }
0151 
0152 void UndoManagerTest::testSelectionUndo()
0153 {
0154     KTextEditor::DocumentPrivate doc;
0155     KTextEditor::ViewPrivate *view = static_cast<KTextEditor::ViewPrivate *>(doc.createView(nullptr));
0156 
0157     doc.setText(
0158         QStringLiteral("aaaa bbbb cccc\n"
0159                        "dddd eeee ffff"));
0160     view->setCursorPosition(KTextEditor::Cursor(1, 9));
0161     KTextEditor::Range selectionRange(KTextEditor::Cursor(0, 5), KTextEditor::Cursor(1, 9));
0162     view->setSelection(selectionRange);
0163 
0164     doc.typeChars(view, QStringLiteral("eeee"));
0165 
0166     // cursor position: "aaaa eeee| ffff", no selection anymore
0167     QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(0, 9));
0168     QCOMPARE(view->selection(), false);
0169 
0170     // undo to remove "eeee" and add selection and text again
0171     doc.undo();
0172     QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(1, 9));
0173     QCOMPARE(view->selection(), true);
0174     QCOMPARE(view->selectionRange(), selectionRange);
0175 
0176     // redo to insert "eeee" again and remove selection
0177     // cursor position: "aaaa eeee| ffff", no selection anymore
0178     doc.redo();
0179     QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(0, 9));
0180     QCOMPARE(view->selection(), false);
0181 
0182     delete view;
0183 }
0184 
0185 void UndoManagerTest::testUndoWordWrapBug301367()
0186 {
0187     KTextEditor::DocumentPrivate doc;
0188     doc.setWordWrap(true);
0189     doc.setWordWrapAt(20);
0190     KTextEditor::ViewPrivate *view = static_cast<KTextEditor::ViewPrivate *>(doc.createView(nullptr));
0191 
0192     QString text = QString::fromLatin1(
0193         "1234 1234 1234 1234\n"
0194         "1234 1234 1234 1234");
0195 
0196     doc.setText(text);
0197     view->setCursorPosition(KTextEditor::Cursor(0, 0));
0198 
0199     doc.typeChars(view, QStringLiteral("           "));
0200 
0201     while (doc.undoCount() > 1) {
0202         doc.undo();
0203     }
0204 
0205     // test must be exactly the same as before
0206     QCOMPARE(doc.text(), text);
0207 
0208     while (doc.redoCount() > 1) {
0209         doc.redo();
0210     }
0211 
0212     while (doc.undoCount() > 1) {
0213         doc.undo();
0214     }
0215 
0216     // test must be exactly the same as before
0217     QCOMPARE(doc.text(), text);
0218 
0219     delete view;
0220 }
0221 
0222 void UndoManagerTest::testUndoIndentBug373009()
0223 {
0224     KTextEditor::DocumentPrivate doc;
0225     KTextEditor::ViewPrivate *view = static_cast<KTextEditor::ViewPrivate *>(doc.createView(nullptr));
0226 
0227     doc.setMode(QStringLiteral("C"));
0228 
0229     QString text = QString::fromLatin1(
0230         "    while (whatever) printf (\"please fix indentation.\\n\");\n"
0231         "    return 0;");
0232     doc.setText(text);
0233 
0234     // position cursor right before return
0235     view->setCursorPosition(KTextEditor::Cursor(1, 4));
0236 
0237     QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(1, 4));
0238     QCOMPARE(doc.characterAt(view->cursorPosition()), QLatin1Char('r'));
0239 
0240     view->keyReturn();
0241 
0242     QCOMPARE(doc.undoCount(), 2);
0243 
0244     // After indent we should be able to revert with
0245     // one undo operation
0246     doc.undo();
0247     QCOMPARE(doc.text(), text);
0248 
0249     delete view;
0250 }
0251 
0252 void UndoManagerTest::testUndoAfterPastingWrappingLine()
0253 {
0254     KTextEditor::DocumentPrivate doc;
0255     std::unique_ptr<KTextEditor::ViewPrivate> view(static_cast<KTextEditor::ViewPrivate *>(doc.createView(nullptr)));
0256 
0257     const QString originalText = QStringLiteral("First Line\nSecond Line Four Words");
0258     doc.setText(originalText);
0259 
0260     // put cursor in first line and copy the whole line
0261     view->setCursorPosition({0, 0});
0262     view->copy();
0263 
0264     // select 3rd word in line
0265     view->setSelection(KTextEditor::Range(1, 12, 1, 16));
0266 
0267     // paste the copied stuff
0268     view->paste();
0269 
0270     view->show();
0271 
0272     // undo the paste
0273     while (doc.undoCount() > 1) {
0274         doc.undo();
0275     }
0276 
0277     // text should be same as original now
0278     QCOMPARE(doc.text(), originalText);
0279 }
0280 
0281 #include "moc_undomanager_test.cpp"