Add support for multiple URLs in an entry
* Fixes #398 The new Browser Integration entry settings page has a list view with any additional URL's. These URL's are added to the entry attributes with KP2A_URL_<counter>, which means those are directly compatible with Keepass2Android.
This commit is contained in:
committed by
Jonathan White
parent
e50261a99c
commit
f726d7501f
@@ -89,7 +89,7 @@ endmacro(add_unit_test)
|
||||
|
||||
set(TEST_LIBRARIES
|
||||
keepassx_core
|
||||
${keepasshttp_LIB}
|
||||
${keepassxcbrowser_LIB}
|
||||
${autotype_LIB}
|
||||
Qt5::Core
|
||||
Qt5::Concurrent
|
||||
|
||||
@@ -245,6 +245,40 @@ void TestBrowser::testSearchEntriesWithPort()
|
||||
QCOMPARE(result[0]->url(), QString("http://127.0.0.1:443"));
|
||||
}
|
||||
|
||||
void TestBrowser::testSearchEntriesWithAdditionalURLs()
|
||||
{
|
||||
auto db = QSharedPointer<Database>::create();
|
||||
auto* root = db->rootGroup();
|
||||
|
||||
QList<Entry*> entries;
|
||||
QList<QString> urls;
|
||||
urls.push_back("https://github.com/");
|
||||
urls.push_back("https://www.example.com");
|
||||
urls.push_back("http://domain.com");
|
||||
|
||||
for (int i = 0; i < urls.length(); ++i) {
|
||||
auto entry = new Entry();
|
||||
entry->setGroup(root);
|
||||
entry->beginUpdate();
|
||||
entry->setUrl(urls[i]);
|
||||
entry->setUsername(QString("User %1").arg(i));
|
||||
entry->endUpdate();
|
||||
entries.push_back(entry);
|
||||
}
|
||||
|
||||
// Add an additional URL to the first entry
|
||||
entries.first()->attributes()->set(BrowserService::ADDITIONAL_URL, "https://keepassxc.org");
|
||||
|
||||
auto result = m_browserService->searchEntries(db, "github.com", "https://github.com"); // db, hostname, url
|
||||
QCOMPARE(result.length(), 1);
|
||||
QCOMPARE(result[0]->url(), QString("https://github.com/"));
|
||||
|
||||
// Search the additional URL. It should return the same entry
|
||||
auto additionalResult = m_browserService->searchEntries(db, "keepassxc.org", "https://keepassxc.org");
|
||||
QCOMPARE(additionalResult.length(), 1);
|
||||
QCOMPARE(additionalResult[0]->url(), QString("https://github.com/"));
|
||||
}
|
||||
|
||||
void TestBrowser::testSortEntries()
|
||||
{
|
||||
auto db = QSharedPointer<Database>::create();
|
||||
|
||||
@@ -42,6 +42,7 @@ private slots:
|
||||
void testSortPriority();
|
||||
void testSearchEntries();
|
||||
void testSearchEntriesWithPort();
|
||||
void testSearchEntriesWithAdditionalURLs();
|
||||
void testSortEntries();
|
||||
void testGetDatabaseGroups();
|
||||
|
||||
|
||||
@@ -549,8 +549,7 @@ void TestCli::testCreate()
|
||||
m_stderrFile->reset();
|
||||
m_stdoutFile->reset();
|
||||
|
||||
QCOMPARE(m_stdoutFile->readLine(),
|
||||
QByteArray("Enter password to encrypt database (optional): \n"));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Enter password to encrypt database (optional): \n"));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Successfully created new database.\n"));
|
||||
|
||||
Utils::Test::setNextPassword("a");
|
||||
@@ -578,8 +577,7 @@ void TestCli::testCreate()
|
||||
m_stdoutFile->seek(pos);
|
||||
m_stderrFile->seek(errPos);
|
||||
|
||||
QCOMPARE(m_stdoutFile->readLine(),
|
||||
QByteArray("Enter password to encrypt database (optional): \n"));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Enter password to encrypt database (optional): \n"));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Successfully created new database.\n"));
|
||||
|
||||
Utils::Test::setNextPassword("a");
|
||||
@@ -596,8 +594,7 @@ void TestCli::testCreate()
|
||||
m_stdoutFile->seek(pos);
|
||||
m_stderrFile->seek(errPos);
|
||||
|
||||
QCOMPARE(m_stdoutFile->readLine(),
|
||||
QByteArray("Enter password to encrypt database (optional): \n"));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Enter password to encrypt database (optional): \n"));
|
||||
QCOMPARE(m_stdoutFile->readLine(), QByteArray("Successfully created new database.\n"));
|
||||
|
||||
Utils::Test::setNextPassword("a");
|
||||
@@ -1041,8 +1038,7 @@ void TestCli::testImport()
|
||||
importCmd.execute({"import", "-q", m_xmlFile->fileName(), databaseFilenameQuiet});
|
||||
m_stdoutFile->seek(pos);
|
||||
|
||||
QCOMPARE(m_stdoutFile->readAll(),
|
||||
QByteArray("Enter password to encrypt database (optional): \n"));
|
||||
QCOMPARE(m_stdoutFile->readAll(), QByteArray("Enter password to encrypt database (optional): \n"));
|
||||
|
||||
Utils::Test::setNextPassword("a");
|
||||
auto dbQuiet = QSharedPointer<Database>(Utils::unlockDatabase(databaseFilenameQuiet, true, "", "", Utils::DEVNULL));
|
||||
|
||||
@@ -124,7 +124,7 @@ void TestEntry::testClone()
|
||||
QVERIFY(entryCloneResetTime->timeInfo().creationTime() != entryOrg->timeInfo().creationTime());
|
||||
|
||||
// Date back history of original entry
|
||||
Entry * firstHistoryItem = entryOrg->historyItems()[0];
|
||||
Entry* firstHistoryItem = entryOrg->historyItems()[0];
|
||||
TimeInfo entryOrgHistoryTimeInfo = firstHistoryItem->timeInfo();
|
||||
QDateTime datedBackEntryOrgModificationTime = entryOrgHistoryTimeInfo.lastModificationTime().addMSecs(-10);
|
||||
entryOrgHistoryTimeInfo.setLastModificationTime(datedBackEntryOrgModificationTime);
|
||||
@@ -140,9 +140,8 @@ void TestEntry::testClone()
|
||||
// Timeinfo of history items should not be modified
|
||||
QList<Entry*> entryOrgHistory = entryOrg->historyItems(), clonedHistory = entryCloneHistory->historyItems();
|
||||
auto entryOrgHistoryItem = entryOrgHistory.constBegin();
|
||||
for(auto entryCloneHistoryItem = clonedHistory.constBegin()
|
||||
;entryCloneHistoryItem != clonedHistory.constEnd()
|
||||
;++entryCloneHistoryItem, ++entryOrgHistoryItem) {
|
||||
for (auto entryCloneHistoryItem = clonedHistory.constBegin(); entryCloneHistoryItem != clonedHistory.constEnd();
|
||||
++entryCloneHistoryItem, ++entryOrgHistoryItem) {
|
||||
QCOMPARE((*entryOrgHistoryItem)->timeInfo(), (*entryCloneHistoryItem)->timeInfo());
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
#include <QDebug>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QLineEdit>
|
||||
#include <QListView>
|
||||
#include <QPlainTextEdit>
|
||||
#include <QPushButton>
|
||||
#include <QTableView>
|
||||
#include <QToolBar>
|
||||
@@ -128,6 +130,9 @@ void TestGuiBrowser::cleanupTestCase()
|
||||
|
||||
void TestGuiBrowser::testEntrySettings()
|
||||
{
|
||||
// Enable the Browser Integration
|
||||
config()->set("Browser/Enabled", true);
|
||||
|
||||
auto* toolBar = m_mainWindow->findChild<QToolBar*>("toolBar");
|
||||
auto* entryView = m_dbWidget->findChild<EntryView*>("entryView");
|
||||
|
||||
@@ -146,7 +151,7 @@ void TestGuiBrowser::testEntrySettings()
|
||||
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
|
||||
|
||||
// Switch to Properties page and select all rows from the custom data table
|
||||
editEntryWidget->setCurrentPage(4);
|
||||
editEntryWidget->setCurrentPage(5);
|
||||
auto customDataTableView = editEntryWidget->findChild<QTableView*>("customDataTable");
|
||||
QVERIFY(customDataTableView);
|
||||
QTest::mouseClick(customDataTableView, Qt::LeftButton);
|
||||
@@ -171,6 +176,56 @@ void TestGuiBrowser::testEntrySettings()
|
||||
QCOMPARE(entry->customData()->size(), 0);
|
||||
}
|
||||
|
||||
void TestGuiBrowser::testAdditionalURLs()
|
||||
{
|
||||
auto* toolBar = m_mainWindow->findChild<QToolBar*>("toolBar");
|
||||
auto* entryView = m_dbWidget->findChild<EntryView*>("entryView");
|
||||
|
||||
entryView->setFocus();
|
||||
QVERIFY(entryView->hasFocus());
|
||||
|
||||
// Select the first entry in the database
|
||||
QModelIndex entryItem = entryView->model()->index(0, 1);
|
||||
clickIndex(entryItem, entryView, Qt::LeftButton);
|
||||
|
||||
auto* entryEditAction = m_mainWindow->findChild<QAction*>("actionEntryEdit");
|
||||
QWidget* entryEditWidget = toolBar->widgetForAction(entryEditAction);
|
||||
QTest::mouseClick(entryEditWidget, Qt::LeftButton);
|
||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::Mode::EditMode);
|
||||
auto* editEntryWidget = m_dbWidget->findChild<EditEntryWidget*>("editEntryWidget");
|
||||
|
||||
// Switch to Browser Integration page and add three URL's
|
||||
editEntryWidget->setCurrentPage(4);
|
||||
auto* addURLButton = editEntryWidget->findChild<QPushButton*>("addURLButton");
|
||||
QVERIFY(addURLButton);
|
||||
|
||||
auto* urlList = editEntryWidget->findChild<QListView*>("additionalURLsView");
|
||||
QVERIFY(urlList);
|
||||
|
||||
QStringList testURLs = {"https://example1.com", "https://example2.com", "https://example3.com"};
|
||||
|
||||
for (const auto& url : testURLs) {
|
||||
QTest::mouseClick(addURLButton, Qt::LeftButton);
|
||||
QApplication::processEvents();
|
||||
QTest::keyClicks(urlList->focusWidget(), url);
|
||||
QTest::keyClick(urlList->focusWidget(), Qt::Key_Enter);
|
||||
}
|
||||
|
||||
// Check the values from attributesEdit
|
||||
editEntryWidget->setCurrentPage(1);
|
||||
auto* attributesView = editEntryWidget->findChild<QListView*>("attributesView");
|
||||
auto* attrTextEdit = editEntryWidget->findChild<QPlainTextEdit*>("attributesEdit");
|
||||
|
||||
// Go top of the list
|
||||
attributesView->setFocus();
|
||||
QTest::keyClick(attributesView->focusWidget(), Qt::Key_PageUp);
|
||||
|
||||
for (const auto& url : testURLs) {
|
||||
QCOMPARE(attrTextEdit->toPlainText(), url);
|
||||
QTest::keyClick(attributesView->focusWidget(), Qt::Key_Down);
|
||||
}
|
||||
}
|
||||
|
||||
void TestGuiBrowser::triggerAction(const QString& name)
|
||||
{
|
||||
auto* action = m_mainWindow->findChild<QAction*>(name);
|
||||
|
||||
@@ -44,6 +44,7 @@ private slots:
|
||||
void cleanupTestCase();
|
||||
|
||||
void testEntrySettings();
|
||||
void testAdditionalURLs();
|
||||
|
||||
private:
|
||||
void triggerAction(const QString& name);
|
||||
|
||||
Reference in New Issue
Block a user