diff --git a/CMakeLists.txt b/CMakeLists.txt index eb9ef37..bc3535b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,7 +78,7 @@ set(WIDGETS_UI_FILES settingsdialog/qtlanguageoptionpage.ui settingsdialog/qtenvoptionpage.ui paletteeditor/paletteeditor.ui) - +set(QT_TESTS buttonoverlay dialogs) set(CMAKE_MODULE_FILES cmake/modules/AndroidApk.cmake cmake/modules/QtConfig.cmake cmake/modules/QtGuiConfig.cmake cmake/modules/QtLinkage.cmake cmake/modules/QtWebViewProviderConfig.cmake cmake/modules/QtJsProviderConfig.cmake) @@ -160,6 +160,7 @@ if (DBUS_NOTIFICATIONS) list(APPEND SRC_FILES ${DBUS_NOTIFICATIONS_FILE_NAME}.cpp) list(APPEND DBUS_FILES dbus/org.freedesktop.Notifications.xml) list(APPEND META_PUBLIC_COMPILE_DEFINITIONS ${META_PROJECT_VARNAME}_SUPPORT_DBUS_NOTIFICATIONS) + list(APPEND QT_TESTS dbusnotification) message(STATUS "D-Bus notifications enabled") else () list(APPEND EXCLUDED_FILES ${DBUS_NOTIFICATIONS_FILE_NAME}.h ${DBUS_NOTIFICATIONS_FILE_NAME}.cpp) @@ -191,6 +192,6 @@ include(ConfigHeader) include(TestUtilities) set(QT_TEST_LIBRARIES ${CPP_UTILITIES_LIB} ${META_TARGET_NAME}) use_qt_module(LIBRARIES_VARIABLE "QT_TEST_LIBRARIES" PREFIX "${QT_PACKAGE_PREFIX}" MODULE "Test") -foreach (TEST buttonoverlay dialogs) +foreach (TEST ${QT_TESTS}) configure_test_target(TEST_NAME "${TEST}_tests" SRC_FILES "tests/${TEST}.cpp" LIBRARIES "${QT_TEST_LIBRARIES}") endforeach () diff --git a/tests/dbusnotification.cpp b/tests/dbusnotification.cpp new file mode 100644 index 0000000..235494b --- /dev/null +++ b/tests/dbusnotification.cpp @@ -0,0 +1,103 @@ +#include "../misc/dbusnotification.h" + +#include "resources/config.h" + +#include +#include + +using namespace QtUtilities; + +/*! + * \brief The DBusNotificationTests class tests the DBusNotification class. + */ +class DBusNotificationTests : public QObject { + Q_OBJECT + +private Q_SLOTS: + void smokeTest(); + void semiAutomaticTest(); +}; + +static void dummy(DBusNotification::Capabilities &&) +{ +} +const static auto callback = std::function(&dummy); + +/*! + * \brief Runs some basic functions of DBusNotification (c'tor, d'tor, some accessors, ...) but doesn't really check + * whether it works. + * \remarks This test should pass regardless whether DBus-notifications are actually available. Hence it avoids any checks + * which depend on that and just checks whether certain function don't lead to crashes. + */ +void DBusNotificationTests::smokeTest() +{ + DBusNotification::isAvailable(); + DBusNotification::queryCapabilities(callback); + DBusNotification n(QStringLiteral("Smoke test"), NotificationIcon::Warning, 100); + QVERIFY2(!n.isVisible(), "not immediately visible"); + QCOMPARE(n.title(), QStringLiteral("Smoke test")); + n.setApplicationName(QStringLiteral(APP_NAME " tests; " APP_VERSION)); + QCOMPARE(n.applicationName(), QStringLiteral(APP_NAME " tests; " APP_VERSION)); + n.show(QStringLiteral("Some message")); // will emit an error if not available + n.isVisible(); + n.hide(); + QCOMPARE(n.message(), QStringLiteral("Some message")); + n.update(QStringLiteral("Another message")); + n.hide(); + if (n.isVisible()) { + QSignalSpy closedSpy(&n, &DBusNotification::closed); + closedSpy.wait(); + } +} + +/*! + * \brief Runs a semi-automatic test to verify whether DBusNotification works for real. + * \remarks This test needs a daemon for D-Bus notifications running and requires manual user interaction. It is therefore + * skipped unless an environment variable is set. + */ +void DBusNotificationTests::semiAutomaticTest() +{ + const auto envValue = qEnvironmentVariable(PROJECT_VARNAME_UPPER "_ENABLE_SEMI_AUTOMATIC_NOTIFICATION_TESTS"); + auto envValueIsInt = false; + if (envValue.isEmpty() || (envValue.toInt(&envValueIsInt) == 0 && envValueIsInt)) { + QSKIP("Set the environment variable " PROJECT_VARNAME_UPPER "_ENABLE_SEMI_AUTOMATIC_NOTIFICATION_TESTS to run " + "the semi-automatic D-Bus notification test."); + } + + QVERIFY2(DBusNotification::isAvailable(), "D-Bus notifications are available"); + + DBusNotification n(QStringLiteral("Semi-automatic test"), NotificationIcon::Information, 10000); + QString clickedAction, error; + const auto actionConnection = connect(&n, &DBusNotification::actionInvoked, [&clickedAction] (const QString &actionName) { + clickedAction = actionName; + }); + const auto errorConnection = connect(&n, &DBusNotification::error, [&error] () { + error = QStringLiteral("error occurred (TODO: pass an error message here)"); + }); + n.setApplicationName(QStringLiteral(APP_NAME " tests; " APP_VERSION)); + n.show(QStringLiteral("Some message; will append more lines later")); + for (auto i = 1; i <= 10; ++i) { + n.update(QStringLiteral("Yet another line, should be displayed in the same notification as previous message (%1)").arg(i)); + QTest::qWait(100); + } + QCOMPARE(error, QString()); + n.setImage(QIcon::fromTheme(QStringLiteral("document-open")).pixmap(64).toImage()); + n.setTitle(n.title() + QStringLiteral(" - click action to continue")); + n.setActions(QStringList({QStringLiteral("fail"), QStringLiteral("Let test fail"), QStringLiteral("pass"), QStringLiteral("Let test pass")})); + QSignalSpy actionInvokedSpy(&n, &DBusNotification::actionInvoked); + n.update(QStringLiteral("Click on \"Let test pass\" to continue within 10 seconds")); + actionInvokedSpy.wait(10000); + QCOMPARE(clickedAction, QStringLiteral("pass")); + QSignalSpy closedSpy(&n, &DBusNotification::closed); + n.setTimeout(5000); + n.setActions(QStringList()); + n.update(QStringLiteral("Waiting for message to close (will close automatically in 5 seconds)")); + closedSpy.wait(8000); + + QCOMPARE(error, QString()); + disconnect(actionConnection); + disconnect(errorConnection); +} + +QTEST_MAIN(DBusNotificationTests) +#include "dbusnotification.moc"