aboutsummaryrefslogtreecommitdiffstats
path: root/docs/superpowers/plans/2026-08-03-post-0.1.0-usability-closed.md
diff options
context:
space:
mode:
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.md44
1 files changed, 44 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 221b3b2..ed88693 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
@@ -4893,3 +4893,47 @@ 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.
+
+## 36. `test_mainwindow` cannot reach the worker
+
+**Done 2026-08-14, unreleased.** See
+`specs/2026-08-14-mainwindow-worker-fixture-design.md`.
+
+**Observed:** twice in one session (0.8.0), a defect could not be given a
+regression test because `MainWindow` in tests had no notmuch database, so its
+`NotmuchWorker` never emitted `threadLoaded`. One of those, the guard in
+`onThreadLoaded()` against a queued load repainting a pane a multi-row selection
+had just blanked, is now covered: the reproduction written here fails when that
+handler is disabled.
+
+**Shipped as `WorkerBackedWindow` in `test_mainwindow.cpp`, opt-in per test,
+with NO production change.** `wireWorker()` already built the worker from
+`m_config.notmuchConfig()`, an ordinary config key, so a written
+`qtmaildir.conf` pointing at the fixture exercises the shipping path. The entry
+had read as bigger than it was since 2026-08-04 because it assumed a hook was
+needed.
+
+**Three traps found while writing it, each of which had made an earlier version
+of the test worthless. All three are worth knowing before touching this area.**
+
+The worker is **unreachable by `findChild`**. `wireWorker()` creates it
+parentless and immediately moves it to its own thread, so it is not in the
+window's object hierarchy. The tests wait with `QTRY_VERIFY_WITH_TIMEOUT` on
+observable state instead, which is the better assertion anyway.
+
+**`rowCount()` on a thread row is 0 until the thread is expanded**, because
+children are populated by the expansion. `hasChildren()` is the correct
+pre-expansion question, falling back to `summary.totalCount > 1`, and it is also
+what proves two messages threaded rather than arriving as two rows. An assertion
+on `rowCount` fails against correct code.
+
+**`currentThreadId()` reports intent, not content.** It is assigned
+synchronously in the selection handler at `src/mainwindow.cpp:2387`, before any
+worker round-trip, so a test asserting on it passed with `onThreadLoaded()`
+disabled entirely. `MessageView::showingPlaceholder()` is what the user sees.
+The test asserts the pane IS blank before the click, so the assertion after it
+means something.
+
+**Item 66 did not reproduce**, which is recorded in that item rather than
+worked around here. The test was not widened until it failed; the negative
+result and what it narrows to are in item 66's own entry.