Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'tests/gui/TestGui.cpp')
-rw-r--r--tests/gui/TestGui.cpp209
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;