diff options
Diffstat (limited to 'tests/gui/TestGui.cpp')
-rw-r--r-- | tests/gui/TestGui.cpp | 209 |
1 files changed, 194 insertions, 15 deletions
diff --git a/tests/gui/TestGui.cpp b/tests/gui/TestGui.cpp index 6805e1053..b2ccd332d 100644 --- a/tests/gui/TestGui.cpp +++ b/tests/gui/TestGui.cpp @@ -17,6 +17,7 @@ */ #include "TestGui.h" +#include "TestGlobal.h" #include <QAction> #include <QApplication> @@ -25,11 +26,11 @@ #include <QLabel> #include <QMimeData> #include <QPushButton> +#include <QCheckBox> #include <QSpinBox> #include <QPlainTextEdit> #include <QComboBox> #include <QTemporaryFile> -#include <QTest> #include <QToolBar> #include <QToolButton> #include <QTimer> @@ -45,10 +46,12 @@ #include "core/Metadata.h" #include "core/Tools.h" #include "crypto/Crypto.h" +#include "crypto/kdf/AesKdf.h" #include "format/KeePass2Reader.h" #include "gui/DatabaseTabWidget.h" #include "gui/DatabaseWidget.h" #include "gui/CloneDialog.h" +#include "gui/PasswordEdit.h" #include "gui/TotpDialog.h" #include "gui/SetupTotpDialog.h" #include "gui/FileDialog.h" @@ -59,12 +62,16 @@ #include "gui/entry/EntryView.h" #include "gui/group/GroupModel.h" #include "gui/group/GroupView.h" +#include "gui/group/EditGroupWidget.h" #include "keys/PasswordKey.h" void TestGui::initTestCase() { QVERIFY(Crypto::init()); Config::createTempFileInstance(); + // Disable autosave so we can test the modified file indicator + Config::instance()->set("AutoSaveAfterEveryChange", false); + m_mainWindow = new MainWindow(); m_tabWidget = m_mainWindow->findChild<DatabaseTabWidget*>("tabWidget"); m_mainWindow->show(); @@ -115,10 +122,56 @@ void TestGui::cleanup() triggerAction("actionDatabaseClose"); Tools::wait(100); + if (m_db) { + delete m_db; + } m_db = nullptr; + + if (m_dbWidget) { + delete m_dbWidget; + } m_dbWidget = nullptr; } +void TestGui::testCreateDatabase() +{ + QTemporaryFile tmpFile; + QVERIFY(tmpFile.open()); + QString tmpFileName = tmpFile.fileName(); + tmpFile.remove(); + + fileDialog()->setNextFileName(tmpFileName); + triggerAction("actionDatabaseNew"); + + DatabaseWidget* dbWidget = m_tabWidget->currentDatabaseWidget(); + + QWidget* databaseNewWidget = dbWidget->findChild<QWidget*>("changeMasterKeyWidget"); + PasswordEdit* editPassword = databaseNewWidget->findChild<PasswordEdit*>("enterPasswordEdit"); + QVERIFY(editPassword->isVisible()); + + QLineEdit* editPasswordRepeat = databaseNewWidget->findChild<QLineEdit*>("repeatPasswordEdit"); + QVERIFY(editPasswordRepeat->isVisible()); + + m_tabWidget->currentDatabaseWidget()->setCurrentWidget(databaseNewWidget); + + QTest::keyClicks(editPassword, "test"); + QTest::keyClicks(editPasswordRepeat, "test"); + QTest::keyClick(editPasswordRepeat, Qt::Key_Enter); + + // Auto-save after every change is enabled by default, ensure the db saves right away + QTRY_VERIFY(m_tabWidget->tabText(m_tabWidget->currentIndex()).contains("*")); + + m_db = m_tabWidget->currentDatabaseWidget()->database(); + + // there is a new empty db + QCOMPARE(m_db->rootGroup()->children().size(), 0); + + // close the new database + MessageBox::setNextAnswer(QMessageBox::No); + triggerAction("actionDatabaseClose"); + Tools::wait(100); +} + void TestGui::testMergeDatabase() { // It is safe to ignore the warning this line produces @@ -227,6 +280,7 @@ void TestGui::testTabs() void TestGui::testEditEntry() { QToolBar* toolBar = m_mainWindow->findChild<QToolBar*>("toolBar"); + int editCount = 0; // Select the first entry in the database EntryView* entryView = m_dbWidget->findChild<EntryView*>("entryView"); @@ -253,7 +307,24 @@ void TestGui::testEditEntry() QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Apply), Qt::LeftButton); QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode); QCOMPARE(entry->title(), QString("Sample Entry_test")); - QCOMPARE(entry->historyItems().size(), 1); + QCOMPARE(entry->historyItems().size(), ++editCount); + + // Test entry colors (simulate choosing a color) + editEntryWidget->setCurrentPage(1); + auto fgColor = QColor(Qt::red); + auto bgColor = QColor(Qt::blue); + // Set foreground color + auto colorButton = editEntryWidget->findChild<QPushButton*>("fgColorButton"); + auto colorCheckBox = editEntryWidget->findChild<QCheckBox*>("fgColorCheckBox"); + colorButton->setProperty("color", fgColor); + colorCheckBox->setChecked(true); + // Set background color + colorButton = editEntryWidget->findChild<QPushButton*>("bgColorButton"); + colorCheckBox = editEntryWidget->findChild<QCheckBox*>("bgColorCheckBox"); + colorButton->setProperty("color", bgColor); + colorCheckBox->setChecked(true); + QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Apply), Qt::LeftButton); + QCOMPARE(entry->historyItems().size(), ++editCount); // Test protected attributes editEntryWidget->setCurrentPage(1); @@ -285,10 +356,82 @@ void TestGui::testEditEntry() // Confirm edit was made QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode); QCOMPARE(entry->title(), QString("Sample Entry_test")); - QCOMPARE(entry->historyItems().size(), 2); + QCOMPARE(entry->foregroundColor(), fgColor); + QCOMPARE(entryItem.data(Qt::ForegroundRole), QVariant(fgColor)); + QCOMPARE(entry->backgroundColor(), bgColor); + QCOMPARE(entryItem.data(Qt::BackgroundRole), QVariant(bgColor)); + QCOMPARE(entry->historyItems().size(), ++editCount); // Confirm modified indicator is showing QTRY_COMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("%1*").arg(m_dbFileName)); + + // Test copy & paste newline sanitization + QTest::mouseClick(entryEditWidget, Qt::LeftButton); + QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode); + titleEdit->setText("multiline\ntitle"); + editEntryWidget->findChild<QLineEdit*>("usernameEdit")->setText("multiline\nusername"); + editEntryWidget->findChild<QLineEdit*>("passwordEdit")->setText("multiline\npassword"); + editEntryWidget->findChild<QLineEdit*>("passwordRepeatEdit")->setText("multiline\npassword"); + editEntryWidget->findChild<QLineEdit*>("urlEdit")->setText("multiline\nurl"); + QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + + QCOMPARE(entry->title(), QString("multiline title")); + QCOMPARE(entry->username(), QString("multiline username")); + // here we keep newlines, so users can't lock themselves out accidentally + QCOMPARE(entry->password(), QString("multiline\npassword")); + QCOMPARE(entry->url(), QString("multiline url")); +} + +void TestGui::testSearchEditEntry() +{ + // Regression test for Issue #1447 -- Uses example from issue description + + // Find buttons for group creation + EditGroupWidget* editGroupWidget = m_dbWidget->findChild<EditGroupWidget*>("editGroupWidget"); + QLineEdit* nameEdit = editGroupWidget->findChild<QLineEdit*>("nameEdit"); + QDialogButtonBox* editGroupWidgetButtonBox = editGroupWidget->findChild<QDialogButtonBox*>("buttonBox"); + + // Add groups "Good" and "Bad" + m_dbWidget->createGroup(); + QTest::keyClicks(nameEdit, "Good"); + QTest::mouseClick(editGroupWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + m_dbWidget->groupView()->setCurrentGroup(m_db->rootGroup()); // Makes "Good" and "Bad" on the same level + m_dbWidget->createGroup(); + QTest::keyClicks(nameEdit, "Bad"); + QTest::mouseClick(editGroupWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + m_dbWidget->groupView()->setCurrentGroup(m_db->rootGroup()); + + // Find buttons for entry creation + QToolBar* toolBar = m_mainWindow->findChild<QToolBar*>("toolBar"); + QWidget* entryNewWidget = toolBar->widgetForAction(m_mainWindow->findChild<QAction*>("actionEntryNew")); + EditEntryWidget* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget"); + QLineEdit* titleEdit = editEntryWidget->findChild<QLineEdit*>("titleEdit"); + QDialogButtonBox* editEntryWidgetButtonBox = editEntryWidget->findChild<QDialogButtonBox*>("buttonBox"); + + // Create "Doggy" in "Good" + Group* goodGroup = m_dbWidget->currentGroup()->findChildByName(QString("Good")); + m_dbWidget->groupView()->setCurrentGroup(goodGroup); + QTest::mouseClick(entryNewWidget, Qt::LeftButton); + QTest::keyClicks(titleEdit, "Doggy"); + QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton); + // Select "Bad" group in groupView + Group* badGroup = m_db->rootGroup()->findChildByName(QString("Bad")); + m_dbWidget->groupView()->setCurrentGroup(badGroup); + + // Search for "Doggy" entry + SearchWidget* searchWidget = toolBar->findChild<SearchWidget*>("SearchWidget"); + QLineEdit* searchTextEdit = searchWidget->findChild<QLineEdit*>("searchEdit"); + QTest::mouseClick(searchTextEdit, Qt::LeftButton); + QTest::keyClicks(searchTextEdit, "Doggy"); + QTRY_VERIFY(m_dbWidget->isInSearchMode()); + + // Goto "Doggy"'s edit view + QTest::keyClick(searchTextEdit, Qt::Key_Return); + QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode); + + // Check the path in header is "parent-group > entry" + QCOMPARE(m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget")->findChild<QLabel*>("headerLabel")->text(), + QString("Good > Doggy > Edit entry")); } void TestGui::testAddEntry() @@ -418,15 +561,13 @@ void TestGui::testPasswordEntryEntropy() editNewPassword->setText(""); QTest::keyClicks(editNewPassword, "YQC3kbXbjC652dTDH"); - QCOMPARE(entropyLabel->text(), QString("Entropy: 96.07 bit")); + QCOMPARE(entropyLabel->text(), QString("Entropy: 95.83 bit")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Good")); editNewPassword->setText(""); QTest::keyClicks(editNewPassword, "Bs5ZFfthWzR8DGFEjaCM6bGqhmCT4km"); QCOMPARE(entropyLabel->text(), QString("Entropy: 174.59 bit")); QCOMPARE(strengthLabel->text(), QString("Password Quality: Excellent")); - - // We are done } void TestGui::testDicewareEntryEntropy() @@ -650,7 +791,7 @@ void TestGui::testDeleteEntry() QWidget* entryDeleteWidget = toolBar->widgetForAction(entryDeleteAction); QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode); - clickIndex(entryView->model()->index(1, 0), entryView, Qt::LeftButton); + clickIndex(entryView->model()->index(1, 1), entryView, Qt::LeftButton); QVERIFY(entryDeleteWidget->isVisible()); QVERIFY(entryDeleteWidget->isEnabled()); QVERIFY(!m_db->metadata()->recycleBin()); @@ -661,8 +802,8 @@ void TestGui::testDeleteEntry() QCOMPARE(entryView->model()->rowCount(), 3); QCOMPARE(m_db->metadata()->recycleBin()->entries().size(), 1); - clickIndex(entryView->model()->index(1, 0), entryView, Qt::LeftButton); - clickIndex(entryView->model()->index(2, 0), entryView, Qt::LeftButton, Qt::ControlModifier); + clickIndex(entryView->model()->index(1, 1), entryView, Qt::LeftButton); + clickIndex(entryView->model()->index(2, 1), entryView, Qt::LeftButton, Qt::ControlModifier); QCOMPARE(entryView->selectionModel()->selectedRows().size(), 2); MessageBox::setNextAnswer(QMessageBox::No); @@ -681,7 +822,7 @@ void TestGui::testDeleteEntry() groupView, Qt::LeftButton); QCOMPARE(groupView->currentGroup()->name(), m_db->metadata()->recycleBin()->name()); - clickIndex(entryView->model()->index(0, 0), entryView, Qt::LeftButton); + clickIndex(entryView->model()->index(0, 1), entryView, Qt::LeftButton); MessageBox::setNextAnswer(QMessageBox::No); QTest::mouseClick(entryDeleteWidget, Qt::LeftButton); QCOMPARE(entryView->model()->rowCount(), 3); @@ -692,8 +833,8 @@ void TestGui::testDeleteEntry() QCOMPARE(entryView->model()->rowCount(), 2); QCOMPARE(m_db->metadata()->recycleBin()->entries().size(), 2); - clickIndex(entryView->model()->index(0, 0), entryView, Qt::LeftButton); - clickIndex(entryView->model()->index(1, 0), entryView, Qt::LeftButton, Qt::ControlModifier); + clickIndex(entryView->model()->index(0, 1), entryView, Qt::LeftButton); + clickIndex(entryView->model()->index(1, 1), entryView, Qt::LeftButton, Qt::ControlModifier); MessageBox::setNextAnswer(QMessageBox::Yes); QTest::mouseClick(entryDeleteWidget, Qt::LeftButton); QCOMPARE(entryView->model()->rowCount(), 0); @@ -858,11 +999,12 @@ void TestGui::testDatabaseSettings() triggerAction("actionChangeDatabaseSettings"); QWidget* dbSettingsWidget = m_dbWidget->findChild<QWidget*>("databaseSettingsWidget"); QSpinBox* transformRoundsSpinBox = dbSettingsWidget->findChild<QSpinBox*>("transformRoundsSpinBox"); - transformRoundsSpinBox->setValue(100); + QVERIFY(transformRoundsSpinBox != nullptr); + transformRoundsSpinBox->setValue(123456); QTest::keyClick(transformRoundsSpinBox, Qt::Key_Enter); // wait for modified timer QTRY_COMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("Save*")); - QCOMPARE(m_db->transformRounds(), Q_UINT64_C(100)); + QCOMPARE(m_db->kdf()->rounds(), 123456); triggerAction("actionDatabaseSave"); QCOMPARE(m_tabWidget->tabText(m_tabWidget->currentIndex()), QString("Save")); @@ -912,6 +1054,43 @@ void TestGui::testDatabaseLocking() QCOMPARE(m_tabWidget->tabText(0).remove('&'), origDbName); } +void TestGui::testDragAndDropKdbxFiles() +{ + const int openedDatabasesCount = m_tabWidget->count(); + + const QString badDatabaseFilePath(QString(KEEPASSX_TEST_DATA_DIR).append("/NotDatabase.notkdbx")); + QMimeData badMimeData; + badMimeData.setUrls({QUrl::fromLocalFile(badDatabaseFilePath)}); + QDragEnterEvent badDragEvent(QPoint(1, 1), Qt::LinkAction, &badMimeData, Qt::LeftButton, Qt::NoModifier); + qApp->notify(m_mainWindow, &badDragEvent); + QCOMPARE(badDragEvent.isAccepted(), false); + + QDropEvent badDropEvent(QPoint(1, 1), Qt::LinkAction, &badMimeData, Qt::LeftButton, Qt::NoModifier); + qApp->notify(m_mainWindow, &badDropEvent); + QCOMPARE(badDropEvent.isAccepted(), false); + + QCOMPARE(m_tabWidget->count(), openedDatabasesCount); + + const QString goodDatabaseFilePath(QString(KEEPASSX_TEST_DATA_DIR).append("/NewDatabase.kdbx")); + QMimeData goodMimeData; + goodMimeData.setUrls({QUrl::fromLocalFile(goodDatabaseFilePath)}); + QDragEnterEvent goodDragEvent(QPoint(1, 1), Qt::LinkAction, &goodMimeData, Qt::LeftButton, Qt::NoModifier); + qApp->notify(m_mainWindow, &goodDragEvent); + QCOMPARE(goodDragEvent.isAccepted(), true); + + QDropEvent goodDropEvent(QPoint(1, 1), Qt::LinkAction, &goodMimeData, Qt::LeftButton, Qt::NoModifier); + qApp->notify(m_mainWindow, &goodDropEvent); + QCOMPARE(goodDropEvent.isAccepted(), true); + + QCOMPARE(m_tabWidget->count(), openedDatabasesCount + 1); + + MessageBox::setNextAnswer(QMessageBox::No); + triggerAction("actionDatabaseClose"); + Tools::wait(100); + + QCOMPARE(m_tabWidget->count(), openedDatabasesCount); +} + void TestGui::cleanupTestCase() { delete m_mainWindow; @@ -981,7 +1160,7 @@ void TestGui::dragAndDropGroup(const QModelIndex& sourceIndex, const QModelIndex QVERIFY(sourceIndex.isValid()); QVERIFY(targetIndex.isValid()); - GroupModel* groupModel = qobject_cast<GroupModel*>(m_dbWidget->findChild<GroupView*>("groupView")->model()); + auto groupModel = qobject_cast<GroupModel*>(m_dbWidget->findChild<GroupView*>("groupView")->model()); QMimeData mimeData; QByteArray encoded; |