Add CI functional tests and fix messagesoverlay handler bug#4132
Add CI functional tests and fix messagesoverlay handler bug#4132bobrippling merged 10 commits intoespruino:masterfrom
Conversation
- Add functional-tests job to GitHub Actions workflow - Runs app tests for apps with test.json - Smart detection: only tests changed apps on PRs, all on master push - Pins EspruinoWebIDE to specific commit for stability - Enhance bin/runapptests.js test runner - Fix syntax bug on line 479 (exitCode → exit) - Add uncaught error detection (Uncaught, ERROR:, ASSERT, stack traces) - Add 60-second per-test timeout to prevent infinite loop hangs - Add summary table with pass/fail/timeout counts - Add docs/testing.md with test.json format documentation - Fix calendar app bug when no events (menu was malformed array/object hybrid)
- calendar: Make "No events" a non-selectable label (undefined) - runapptests: Remove handleConsoleOutput duplication - CI: Only run all tests on push to master, not feature branches Feature branch pushes now test only changed apps since master
The show() function was registering a remove:cleanup callback on every call to setLCDOverlay(). During showMessage(), show() is called twice (via drawBorder and drawMessage). When the second call replaced the first overlay with the same ID, Espruino triggered the first overlay's remove callback, causing premature handler restoration. Fix: Track overlay state with overlayShowing flag and only register the remove callback on the first show() call. Also enhanced assertArray in test runner to treat arrays containing only undefined/null values as empty.
- Fix messagesoverlay premature cleanup on overlay update - Add regression test for overlay update scenario - Fix error detection false positives in test runner (ASSERT vs assertArray) - Fix triple evaluation in assertArray with IIFE pattern - Add timeout cleanup with emu.stopIdle() - Fix calendar duplicate event labels overwriting menu items - Fix CI workflow error suppression (separate git/grep) - Update docs and ChangeLog
bobrippling
left a comment
There was a problem hiding this comment.
Thanks for the big test improvement and the fix! And I also appreciate you being upfront about using an AI, that explains some of the more verbose changes. I've left a few comments but will let @gfwilliams have a look, with this being both a central app change and change to infrastructure
|
This looks good to me - it's nice to have the test harness start to be used, and right now it doesn't seem to add a bunch of time to the execution of the tests (12s?). To fix the build you need to update the version in the messagesoverlay And please can you move the But otherwise, if you can take a look at the stuff @bobrippling suggested it'd be great to get this merged |
Show message with proper back navigation instead of blocking alert when there are no calendar events.
Distinguishes between truly empty arrays and arrays containing only null/undefined values (e.g., sparse arrays from backgrounded handlers).
- Fix bashism in nodejs.yml (== to =) - Use regex for Uncaught detection in test runner - Combine error detection into single uncaughtError variable - Use isTimeout flag instead of string matching - Remove unicode and header/divider lines from summary output - Move docs/testing.md to TESTING.md, trim API sections - Link TESTING.md from README.md - Bump messagesoverlay version to 0.12
- Remove allNullish assertion (unnecessary, undefinedOrEmpty works) - Replace .filter() calls with truthy checks (Espruino lacks filter)
|
@bobrippling @gfwilliams this is ready for review again. Thank you for your patience. |
|
Looks great to me - thanks for your time working on this! I'm happy to merge if you are @bobrippling ? |
|
Certainly am - thanks @elijahr! |
|
Looks like a problem with the tests - @elijahr do you see the same? |
|
@bobrippling looks like the test checks for memory leaks, and is failing due to memory usage going down on the second run, so I guess a good thing! Here's a fix: #4152 |
|
Thanks - just merged that! |
|
Nice, yes thank you! |
|
What could cause this to fail initially but succeed when re-running? Happened e.g. with this one: https://github.com/espruino/BangleApps/actions/runs/21783161416 |
I wonder if it just ran over the watch's free flash and a compact was triggered or similar |
## Problem Tests occasionally fail with: ``` Uncaught SyntaxError: Got [ERASED] expected EOF ``` Reported in espruino#4132 by @thyttan: tests fail initially but succeed on re-run. Example: https://github.com/espruino/BangleApps/actions/runs/21783161416/attempts/1 ## Cause The test runner sends commands without waiting for the emulator to finish processing. When one test ends and the next begins, `factoryReset()` can be called while the previous test's commands are still being processed, corrupting the input stream. ## Solution - Track emulator ready state (has it output a response?) - Add `waitForResponse()` to poll until command completes - Add `safeFactoryReset()` that ensures previous commands finished - Wait after each test step (`cmd`, `emit`, `load`, etc.) - Wait after app upload and reset in test setup ## Testing - All functional tests pass locally and in CI - Full test suite (all 4 apps): https://github.com/elijahr/BangleApps/actions/runs/21789313739 - No significant increase in test duration
|
@thyttan @bobrippling I think what might be going on is a race condition around |
Summary
This PR adds automated functional testing to CI and fixes a bug in messagesoverlay discovered during test development.
CI Functional Tests
functional-testsjob to GitHub Actions workflowtest.jsontest.jsonTest Runner Enhancements (
bin/runapptests.js)--idflag to run tests for specific app(s)undefinedOrEmptyassertion for arrays (handles[undefined]edge case)Bug Fix: messagesoverlay Handler Restoration
Problem: Event handlers were being prematurely restored while a message overlay was still being displayed.
Root cause: The
show()function registered aremove:cleanupcallback on every call tosetLCDOverlay(). DuringshowMessage(),show()is called twice (viadrawBorder()anddrawMessage()). When the second call replaced the first overlay with the same ID, Espruino triggered the first overlay's remove callback, causing premature handler restoration.Fix: Track overlay state with
overlayShowingflag and only register the remove callback on the firstshow()call.Documentation
docs/testing.mdwith comprehensive testing guideapps/messagesoverlay/ChangeLogfor version 0.12Files Changed
.github/workflows/nodejs.yml- Add functional-tests jobbin/runapptests.js- Test runner enhancementsapps/messagesoverlay/lib.js- Bug fix for premature cleanupapps/messagesoverlay/test.json- Clean up test fileapps/messagesoverlay/ChangeLog- Version 0.12apps/calendar/calendar.js- Fix non-selectable "No events" menu itemdocs/testing.md- Testing documentationTest plan
🤖 Generated with Claude Code