2 changed files with 186 additions and 1 deletions
@ -0,0 +1,178 @@
|
||||
/* Проверяем время жизни уведомления и первую активность без ввода в настоящую desktop-сессию. */ |
||||
#include "../src/message_notification.h" |
||||
#include "../src/user_activity_monitor.h" |
||||
#include "../../../lib/debug_config.h" |
||||
|
||||
#include <QtTest> |
||||
#include <QLineEdit> |
||||
#include <QPushButton> |
||||
#include <QScreen> |
||||
#include <QMouseEvent> |
||||
|
||||
#ifdef UTUN_TEST_ACTIVITY_DBUS |
||||
#include <QDBusConnection> |
||||
#include <QDBusContext> |
||||
#include <QDBusMessage> |
||||
#endif |
||||
|
||||
class FakeSystemActivity : public UserActivityMonitor { |
||||
public: |
||||
FakeSystemActivity() { clock.start(); } |
||||
QElapsedTimer clock; |
||||
qint64 lastInput = -5000; |
||||
bool available = true; |
||||
protected: |
||||
qint64 systemIdleTime() override { return available ? clock.elapsed() - lastInput : -1; } |
||||
}; |
||||
|
||||
#ifdef UTUN_TEST_ACTIVITY_DBUS |
||||
class FakeGnomeIdle : public QObject, protected QDBusContext { |
||||
Q_OBJECT |
||||
Q_CLASSINFO("D-Bus Interface", "org.gnome.Mutter.IdleMonitor") |
||||
public: |
||||
FakeGnomeIdle() { clock.start(); } |
||||
QElapsedTimer clock; |
||||
qint64 lastInput = -5000; |
||||
int delayMs = 0; |
||||
int requests = 0; |
||||
public slots: |
||||
qulonglong GetIdletime() { |
||||
++requests; |
||||
const qulonglong idle = clock.elapsed() - lastInput; |
||||
if (delayMs) { |
||||
const QDBusMessage reply = message().createReply(QVariant::fromValue(idle)); |
||||
setDelayedReply(true); |
||||
QTimer::singleShot(delayMs, this, [reply] { QDBusConnection::sessionBus().send(reply); }); |
||||
} |
||||
return idle; |
||||
} |
||||
}; |
||||
#endif |
||||
|
||||
class MessageNotificationTest : public QObject { |
||||
Q_OBJECT |
||||
private slots: |
||||
void initTestCase() { |
||||
debug_config_init(); |
||||
debug_set_level(DEBUG_LEVEL_DEBUG); |
||||
qunsetenv("XDG_SESSION_TYPE"); |
||||
} |
||||
|
||||
void firstSystemActivityAndCancellation() { |
||||
FakeSystemActivity activity; |
||||
QSignalSpy spy(&activity, &UserActivityMonitor::activity); |
||||
activity.start(); |
||||
QTest::qWait(600); |
||||
QCOMPARE(spy.size(), 0); // Старый ввод до начала наблюдения не считается активностью.
|
||||
activity.lastInput = activity.clock.elapsed(); |
||||
QTRY_COMPARE_WITH_TIMEOUT(spy.size(), 1, 700); |
||||
QTest::qWait(300); |
||||
QCOMPARE(spy.size(), 1); |
||||
activity.start(); |
||||
activity.stop(); |
||||
activity.lastInput = activity.clock.elapsed(); |
||||
QTest::qWait(400); |
||||
QCOMPARE(spy.size(), 1); |
||||
activity.start(); |
||||
QTest::qWait(20); |
||||
activity.lastInput = activity.clock.elapsed(); |
||||
QTRY_COMPARE_WITH_TIMEOUT(spy.size(), 2, 700); |
||||
} |
||||
|
||||
void localFallbackDoesNotConsumeInput() { |
||||
FakeSystemActivity activity; |
||||
activity.available = false; |
||||
QSignalSpy spy(&activity, &UserActivityMonitor::activity); |
||||
QLineEdit input; |
||||
input.show(); |
||||
activity.start(); |
||||
QTest::keyClick(&input, Qt::Key_A); |
||||
QTest::keyClick(&input, Qt::Key_B); |
||||
QCOMPARE(input.text(), QString("ab")); |
||||
QCOMPARE(spy.size(), 1); |
||||
} |
||||
|
||||
void waitsForActivityThenExpiresWithoutExtension() { |
||||
QWidget hiddenParent; |
||||
QLineEdit otherWindow; |
||||
otherWindow.show(); |
||||
QApplication::setActiveWindow(&otherWindow); |
||||
MessageNotification notification(&hiddenParent); |
||||
notification.showMessage("42", "Alice", "Test channel", {}); |
||||
QVERIFY(notification.isVisible()); |
||||
QCOMPARE(QApplication::activeWindow(), &otherWindow); |
||||
QTest::qWait(10200); |
||||
QVERIFY(notification.isVisible()); // Без активности автоматического таймера нет.
|
||||
QElapsedTimer elapsed; |
||||
elapsed.start(); |
||||
QTest::keyClick(&otherWindow, Qt::Key_A); |
||||
QTest::qWait(5500); |
||||
QVERIFY(notification.isVisible()); |
||||
QTest::keyClick(&otherWindow, Qt::Key_B); |
||||
QTRY_VERIFY_WITH_TIMEOUT(!notification.isVisible(), 6000); |
||||
QVERIFY(elapsed.elapsed() >= 10000); |
||||
QVERIFY(elapsed.elapsed() < 12000); |
||||
QCOMPARE(otherWindow.text(), QString("ab")); |
||||
} |
||||
|
||||
void replacementCancelsOldCountdownAndOpensLatestChat() { |
||||
QLineEdit otherWindow; |
||||
otherWindow.show(); |
||||
MessageNotification notification; |
||||
QSignalSpy activated(¬ification, &MessageNotification::activated); |
||||
notification.showMessage("42", "Alice", "First channel", {}); |
||||
QTest::keyClick(&otherWindow, Qt::Key_A); |
||||
QTest::qWait(100); |
||||
notification.showMessage("dm:7", "Bob", "Direct messages", QRect(-10, -10, 20, 20)); |
||||
QTest::qWait(10200); |
||||
QVERIFY(notification.isVisible()); // Прежний таймер не закрывает новое уведомление.
|
||||
const QRect area = notification.screen()->availableGeometry(); |
||||
QVERIFY(area.contains(notification.geometry())); |
||||
QTest::mouseClick(¬ification, Qt::LeftButton, Qt::NoModifier, QPoint(30, notification.height() - 15)); |
||||
QVERIFY(!notification.isVisible()); |
||||
QCOMPARE(activated.size(), 1); |
||||
QCOMPARE(activated[0][0].toString(), QString("dm:7")); |
||||
notification.showMessage("43", "Charlie", "Third channel", {}); |
||||
auto* closeButton = notification.findChild<QPushButton*>("notificationCloseButton"); |
||||
QVERIFY(closeButton); |
||||
QTest::mouseClick(closeButton, Qt::LeftButton); |
||||
QVERIFY(!notification.isVisible()); |
||||
QCOMPARE(activated.size(), 1); |
||||
} |
||||
|
||||
#ifdef UTUN_TEST_ACTIVITY_DBUS |
||||
void gnomeIdleAndStaleReplies() { |
||||
auto bus = QDBusConnection::sessionBus(); |
||||
QVERIFY(bus.registerService("org.gnome.Mutter.IdleMonitor")); |
||||
FakeGnomeIdle idle; |
||||
QVERIFY(bus.registerObject("/org/gnome/Mutter/IdleMonitor/Core", &idle, QDBusConnection::ExportAllSlots)); |
||||
qputenv("XDG_SESSION_TYPE", "wayland"); |
||||
UserActivityMonitor activity; |
||||
QSignalSpy spy(&activity, &UserActivityMonitor::activity); |
||||
activity.start(); |
||||
QTRY_VERIFY_WITH_TIMEOUT(idle.requests >= 2, 1000); |
||||
QCOMPARE(spy.size(), 0); |
||||
idle.lastInput = idle.clock.elapsed(); |
||||
QTRY_COMPARE_WITH_TIMEOUT(spy.size(), 1, 1000); |
||||
|
||||
idle.delayMs = 300; |
||||
activity.start(); |
||||
QTest::qWait(20); |
||||
idle.lastInput = idle.clock.elapsed(); |
||||
const int before = idle.requests; |
||||
QTRY_VERIFY_WITH_TIMEOUT(idle.requests > before, 1000); |
||||
activity.stop(); |
||||
idle.lastInput = idle.clock.elapsed() - 5000; |
||||
activity.start(); |
||||
QTest::qWait(800); |
||||
QCOMPARE(spy.size(), 1); // Ответ об активности прежнего наблюдения должен быть отброшен.
|
||||
activity.stop(); |
||||
qunsetenv("XDG_SESSION_TYPE"); |
||||
bus.unregisterObject("/org/gnome/Mutter/IdleMonitor/Core"); |
||||
bus.unregisterService("org.gnome.Mutter.IdleMonitor"); |
||||
} |
||||
#endif |
||||
}; |
||||
|
||||
QTEST_MAIN(MessageNotificationTest) |
||||
#include "test_message_notification.moc" |
||||
Loading…
Reference in new issue