aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_mainwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_mainwindow.cpp')
-rw-r--r--tests/test_mainwindow.cpp93
1 files changed, 87 insertions, 6 deletions
diff --git a/tests/test_mainwindow.cpp b/tests/test_mainwindow.cpp
index 57eb763..6bfa925 100644
--- a/tests/test_mainwindow.cpp
+++ b/tests/test_mainwindow.cpp
@@ -18,18 +18,27 @@
#include <QtTest>
+#include <QAction>
+#include <QDir>
+#include <QSettings>
+#include <QTemporaryDir>
+
+#include "config.h"
#include "keymap.h"
#include "mainwindow.h"
-/// MainWindow is mostly wiring and needs a live QApplication plus a real
-/// database, so it is verified manually in Task 13. Two things do not need
-/// either, and both are the kind of drift a comment alone does not prevent.
+/// MainWindow is mostly wiring, and the parts that need a real database are
+/// still verified manually. What is checked here is the action registry: the
+/// bindings a user configures reach the QActions the menus and the keyboard
+/// both read from, and no action is left unreachable.
class TestMainWindow : public QObject
{
Q_OBJECT
private slots:
void everyKnownActionIsRegistered();
void everyRegisteredActionIsKnown();
+ void everyActionHasAShortcut();
+ void configuredBindingReachesTheAction();
void cidPrefixesAreBangFree();
void cidPrefixesAreDistinctPerMessage();
};
@@ -39,8 +48,14 @@ void TestMainWindow::everyKnownActionIsRegistered()
// KeyMap::knownActions() is what loadOverrides() validates config bindings
// against. An action listed there but never registered means a user can
// bind a key in qtmaildir.conf, get no warning, and have it do nothing.
+ //
+ // registeredActionNames() is now derived from the QActions themselves, so
+ // this compares against what the window really installed.
+ const Config config;
+ MainWindow window(config);
+
const QStringList known = KeyMap::knownActions();
- const QStringList registered = MainWindow::registeredActionNames();
+ const QStringList registered = window.registeredActionNames();
for (const QString &action : known) {
QVERIFY2(registered.contains(action),
@@ -53,8 +68,11 @@ void TestMainWindow::everyRegisteredActionIsKnown()
{
// The reverse drift: an action MainWindow implements but KeyMap rejects.
// The user would get "unknown action" for a binding that is really there.
+ const Config config;
+ MainWindow window(config);
+
const QStringList known = KeyMap::knownActions();
- const QStringList registered = MainWindow::registeredActionNames();
+ const QStringList registered = window.registeredActionNames();
for (const QString &action : registered) {
QVERIFY2(known.contains(action),
@@ -63,6 +81,57 @@ void TestMainWindow::everyRegisteredActionIsKnown()
}
}
+void TestMainWindow::everyActionHasAShortcut()
+{
+ // An action with no binding is unreachable from the keyboard. Every one
+ // of them carries a default, so an empty shortcut means the default table
+ // and the action list have drifted apart.
+ const Config config;
+ MainWindow window(config);
+
+ for (const QString &name : window.registeredActionNames()) {
+ const QAction *action = window.findChild<QAction *>(name);
+ QVERIFY2(action, qPrintable(QStringLiteral("no QAction named '%1'").arg(name)));
+ QVERIFY2(!action->shortcut().isEmpty(),
+ qPrintable(QStringLiteral("action '%1' has no shortcut").arg(name)));
+ }
+}
+
+void TestMainWindow::configuredBindingReachesTheAction()
+{
+ // The whole point of [keys]: a user's override must end up on the QAction,
+ // which is what both the keyboard and the menus read.
+ QTemporaryDir dir;
+ const QString path = dir.filePath(QStringLiteral("qtmaildir.conf"));
+ {
+ QSettings s(path, QSettings::IniFormat);
+ s.beginGroup(QStringLiteral("keys"));
+ s.setValue(QStringLiteral("Ctrl+Alt+A"), QStringLiteral("archive"));
+ s.endGroup();
+ }
+
+ // MainWindow reads its keymap from Config::defaultPath(), so point that
+ // at the temporary file for this test.
+ const QString previous = qEnvironmentVariable("XDG_CONFIG_HOME");
+ QVERIFY(QDir().mkpath(dir.filePath(QStringLiteral("qtmaildir"))));
+ QVERIFY(QFile::copy(path, dir.filePath(QStringLiteral("qtmaildir/qtmaildir.conf"))));
+ qputenv("XDG_CONFIG_HOME", dir.path().toUtf8());
+
+ {
+ const Config config;
+ MainWindow window(config);
+ const QAction *archive =
+ window.findChild<QAction *>(QStringLiteral("archive"));
+ QVERIFY(archive);
+ QCOMPARE(archive->shortcut(), QKeySequence(QStringLiteral("Ctrl+Alt+A")));
+ }
+
+ if (previous.isEmpty())
+ qunsetenv("XDG_CONFIG_HOME");
+ else
+ qputenv("XDG_CONFIG_HOME", previous.toUtf8());
+}
+
void TestMainWindow::cidPrefixesAreBangFree()
{
// MainWindow is the only producer of cidPrefix in the application. The
@@ -89,5 +158,17 @@ void TestMainWindow::cidPrefixesAreDistinctPerMessage()
}
}
-QTEST_MAIN(TestMainWindow)
+// Constructing a MainWindow needs a QApplication and a platform plugin. The
+// test has no display under ctest, so it runs offscreen unless the caller
+// asked for something else.
+int main(int argc, char *argv[])
+{
+ qputenv("QT_QPA_PLATFORM", qgetenv("QT_QPA_PLATFORM").isEmpty()
+ ? QByteArray("offscreen")
+ : qgetenv("QT_QPA_PLATFORM"));
+ QApplication app(argc, argv);
+ TestMainWindow test;
+ return QTest::qExec(&test, argc, argv);
+}
+
#include "test_mainwindow.moc"