diff options
| author | Danilo M. <danix@danix.xyz> | 2026-08-14 18:28:57 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-08-14 18:28:57 +0200 |
| commit | 854c850972b949b8124744c9af83d812ab98b208 (patch) | |
| tree | 60c0415e2ba9854966f39510401e44484efee73e /docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md | |
| parent | 86074f40121466798cdd64e07a00db2542543c52 (diff) | |
| download | qtmaildir-854c850972b949b8124744c9af83d812ab98b208.tar.gz qtmaildir-854c850972b949b8124744c9af83d812ab98b208.zip | |
docs: close item 84, spec item 36
Item 84's section moves to the closed file, recording that the fix was
a split rather than a suppression, and that its mutation check
reproduces the original hang at exit 124 rather than merely failing.
Item 36 is specced and no longer "on demand": item 66 needs it. Two
findings while writing it. The deliverable is a RED reproduction of 66,
with the fix deliberately excluded, since that defect has never been
isolated and designing a fix beside a hypothesis is how a wrong one gets
locked in. And the item is smaller than it has read since 2026-08-04:
wireWorker() already builds the worker from a config key, so a test
writes a config pointing at the fixture and nothing in src/ changes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md')
| -rw-r--r-- | docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md index cfa119b..221b3b2 100644 --- a/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md +++ b/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md @@ -4841,3 +4841,55 @@ blocked emit when the condition is disabled, and it did not hang, which is the outcome item 85's trap made worth checking for. The user hand tested all three surfaces with an empty query bar and with one, including the disjunction case the parenthesising exists for. + +## 84. A config problem blocks `test_mainwindow` on a modal nobody can dismiss + +**Done 2026-08-14, unreleased.** + +**Observed (2026-08-14):** a new test in `test_mainwindow` hung with no output +and was killed at the two-minute timeout. It had configured an account section +carrying only `sent=`, with no `maildir=`. + +**Cause (verified by attaching gdb to the hung process, not inferred).** + +``` +#7 QDialog::exec() +#9 MainWindow::showWarnings ... src/mainwindow.cpp:1670 +#10 MainWindow::MainWindow ... src/mainwindow.cpp:381 +``` + +`Config::load` handled the malformed account exactly as it should, recording +"Account 'one' has no maildir; ignoring it" and carrying on. `showWarnings()` +then put every collected problem in a `QMessageBox::warning`, modal, called from +the `MainWindow` CONSTRUCTOR. Under the offscreen platform nothing can dismiss +it, so the constructor never returned. + +**The application was never wrong here.** The modal is right for a person: a +config problem should interrupt startup rather than scroll past. The defect was +that a TEST could not dismiss it, and that the failure was a silent hang rather +than an error naming its cause. + +**Fixed by splitting the function rather than suppressing the dialog.** +Suppressing it under `QTEST_MAIN` was rejected in the entry before any code was +written, because that is exactly the path `test_mainwindow` exercises and a +suppressed dialog ships the startup warning untested. Instead `showWarnings()` +became two: `applyWarnings()`, which sets the status label and stays in the +constructor, and `configProblems()`, a getter. `main.cpp` raises the dialog +after `show()`, which also gives it a visible parent to sit on. + +The warnings/problems distinction is preserved exactly, including its comment: a +keybinding the user wrote and that is being ignored interrupts startup, a notice +such as "no sync command configured" does not. + +**Verified.** 23 of 23 tests passing. The warning path has its first test, +built from the config shape that caused the original hang. Mutation checked by +putting the modal back in the constructor: the test times out at exit 124 rather +than failing, reproducing the original symptom exactly, which is the strongest +form this check could take. The user hand tested both halves of the +distinction: `archive=NotAKey` under `[keys]` surfaces the dialog over the +window, and the same line under `[general]` correctly does not, since it is not +a keybinding and nothing is broken. + +**The consequence for item 36.** That item could not add fixture-backed tests +while a malformed config could hang the constructor. It can now, which is why +84 was done first. |
