|
| 1 | +--- |
| 2 | +phase: 1040-companion-notification-center |
| 3 | +plan: 01 |
| 4 | +subsystem: testing |
| 5 | +tags: [matlab, notification-center, eventstore, test-double, pure-logic, tdd] |
| 6 | + |
| 7 | +requires: |
| 8 | + - phase: 1032-ack-events |
| 9 | + provides: EventStore.acknowledgeEvent + Event.AckedAt (unacked filter key) |
| 10 | +provides: |
| 11 | + - StubEventStore test double (getEvents/numEvents/acknowledgeEvent + ThrowOnGet_/ThrowOnAck_) |
| 12 | + - NotificationCenterPane class shell + 7 static pure-logic helpers (filter/sort/diff/badge) |
| 13 | + - Flat headless test pinning all helper + stub semantics |
| 14 | +affects: [1040-02-notification-pane, 1040-03-companion-integration, 1040-04-companion-tests-verify] |
| 15 | + |
| 16 | +tech-stack: |
| 17 | + added: [] |
| 18 | + patterns: |
| 19 | + - "Interface-first TDD: static pure-logic helpers as the contract before any UI" |
| 20 | + - "Stub-with-failure-switches test double (ThrowOnGet_/ThrowOnAck_) modeled on CaptureNotificationService" |
| 21 | + |
| 22 | +key-files: |
| 23 | + created: |
| 24 | + - tests/StubEventStore.m |
| 25 | + - libs/FastSenseCompanion/NotificationCenterPane.m |
| 26 | + - tests/test_notification_center_pane.m |
| 27 | + modified: [] |
| 28 | + |
| 29 | +key-decisions: |
| 30 | + - "Event fixtures use the real 6-arg constructor Event(start,end,sensor,label,thresholdValue,direction); the planning docs' 4-arg shorthand does not construct (direction is required + validated against {'upper','lower'})" |
| 31 | + - "filterUnacked_ treats both empty AND all-NaN AckedAt as unacked, mirroring Event.computeDisplayState" |
| 32 | + - "diffIds_ is order-insensitive via sort(ids(:)) with {} guards so identical sets in any order report no change (no badge flicker)" |
| 33 | + |
| 34 | +patterns-established: |
| 35 | + - "NotificationCenterPane.<helper> static call surface — the pane's pure logic is callable + testable without a uifigure" |
| 36 | + |
| 37 | +requirements-completed: [] |
| 38 | + |
| 39 | +duration: ~15 min |
| 40 | +completed: 2026-06-02 |
| 41 | +--- |
| 42 | + |
| 43 | +# Phase 1040 Plan 01: Test Foundation Summary |
| 44 | + |
| 45 | +**StubEventStore test double + the NotificationCenterPane pure-logic core (7 static helpers: unacked filter incl. NaN, newest-first sort, order-insensitive id-diff, severity/badge mapping), pinned by an 18-assertion headless flat test.** |
| 46 | + |
| 47 | +## Performance |
| 48 | + |
| 49 | +- **Duration:** ~15 min |
| 50 | +- **Completed:** 2026-06-02 |
| 51 | +- **Tasks:** 3 |
| 52 | +- **Files modified:** 3 (all created) |
| 53 | + |
| 54 | +## Accomplishments |
| 55 | +- `tests/StubEventStore.m` — fake EventStore handle with `ThrowOnGet_`/`ThrowOnAck_` switches that drive the stale-read and ack-race paths later plans need. |
| 56 | +- `libs/FastSenseCompanion/NotificationCenterPane.m` — class shell (events block + full private property declaration) plus 7 pure static helpers; no UI primitives instantiated. |
| 57 | +- `tests/test_notification_center_pane.m` — 18 headless assertions covering the stub round-trip + ack-race throw and all 7 helpers; runs green in milliseconds. |
| 58 | + |
| 59 | +## Task Commits |
| 60 | + |
| 61 | +1. **Task 1: StubEventStore test double** — `2b51ac88` (test) |
| 62 | +2. **Task 2: NotificationCenterPane static pure-logic helpers** — `3a05c8c6` (feat) |
| 63 | +3. **Task 3: flat pure-logic test** — `bd19fb85` (test) |
| 64 | + |
| 65 | +## Files Created/Modified |
| 66 | +- `tests/StubEventStore.m` — `classdef StubEventStore < handle`; getEvents/numEvents/acknowledgeEvent; records acked ids + mutates AckedAt. |
| 67 | +- `libs/FastSenseCompanion/NotificationCenterPane.m` — shell + filterUnacked_/sortNewestFirst_/maxSeverity_/idsOf_/diffIds_/badgeText_/badgeColor_. |
| 68 | +- `tests/test_notification_center_pane.m` — flat function test (`add_companion_path` + local `check`), prints "All 18 tests passed." |
| 69 | + |
| 70 | +## Decisions Made |
| 71 | +- See key-decisions frontmatter. The Event 6-arg constructor correction is the most consequential — Plans 02/04 build Event fixtures and must use the full signature. |
| 72 | + |
| 73 | +## Deviations from Plan |
| 74 | + |
| 75 | +### Auto-fixed Issues |
| 76 | + |
| 77 | +**1. [Rule 3 - Blocking] Event constructor requires 6 args, not the 4 shown in the plan** |
| 78 | +- **Found during:** Task 3 (writing the flat test) |
| 79 | +- **Issue:** The plan's `<interfaces>` block and Task 3 examples construct `Event(startTime, endTime, sensorName, thresholdLabel)` (4 args). The real `Event` constructor is `Event(startTime, endTime, sensorName, thresholdLabel, thresholdValue, direction)` and throws if `direction` is missing/not in `{'upper','lower'}` — the 4-arg form cannot construct. |
| 80 | +- **Fix:** Built all test fixtures with the full 6-arg signature (e.g. `Event(30, NaN, 'P-101', 'HighPressure', 100, 'upper')`). |
| 81 | +- **Files modified:** tests/test_notification_center_pane.m |
| 82 | +- **Verification:** Test runs green (18/18). |
| 83 | +- **Committed in:** bd19fb85 |
| 84 | + |
| 85 | +--- |
| 86 | + |
| 87 | +**Total deviations:** 1 auto-fixed (1 blocking). |
| 88 | +**Impact on plan:** No scope change — only the fixture construction syntax. Carries forward to Plans 02 + 04 (their Event fixtures need the same 6-arg form). |
| 89 | + |
| 90 | +## Issues Encountered |
| 91 | +None. (Note: the plan's strict "no UI primitives" grep matches doc-comment mentions of `uifigure`/`uitable` in the property block, but a call-syntax grep confirms **zero** actual UI primitive calls — pure logic only.) |
| 92 | + |
| 93 | +## Next Phase Readiness |
| 94 | +- Plan 02 can extend `NotificationCenterPane` with the attach/detach/refresh/ack lifecycle on top of the static helpers; `StubEventStore` is ready to drive the headless suite. |
| 95 | +- No blockers. |
| 96 | + |
| 97 | +--- |
| 98 | +*Phase: 1040-companion-notification-center* |
| 99 | +*Completed: 2026-06-02* |
0 commit comments