`undo-redo.cy.js:15` is flaky and never asserted undo/redo: re-query the swapping preview iframe
### Overview The Cypress test `Undo/Redo functionality › Performs a basic interaction with Undo/Redo` (`web/modules/contrib/canvas/ui/tests/e2e/undo-redo.cy.js:15`) fails intermittently on CI, timing out while querying the preview iframe after an undo: ``` Timed out retrying after 4000ms: Expected to find element: [data-test-canvas-content-initialized="true"][data-canvas-swap-active="true"], but never found it. ``` Example job: https://git.drupalcode.org/project/canvas/-/jobs/10056816 There are two test-side problems: 1. **The undo/redo assertions never ran.** After inserting/undoing/redoing, the test asserted the hero count with `cy.getIframeBody().find(selector, (heroes) => expect(heroes.length).to.equal(N))`. `.find()`'s second argument is an options object, not a callback, so the callback never executed — the counts (4 → 3 → 4) were never actually checked. The test only verified that *some* hero existed, so it would have passed even if undo/redo did nothing. 2. **The iframe query raced the preview re-render.** Each insert/undo/redo re-renders the preview asynchronously (~6s observed) and swaps the preview iframe. During the swap there is a brief window with no `data-canvas-swap-active` iframe, and the freshly-swapped iframe trails the layout change by a few seconds — so querying it with the default 4s timeout caught the swap gap (the timeout above) or a stale frame. ### Proposed resolution - Add a `waitForElementCountInIframe()` test command that re-queries the *currently active* preview iframe on every retry and resolves once the count settles, so it rides through the iframe swap instead of reading a single mid-render frame. - Use it to assert the hero count 4 → 3 → 4 across insert/undo/redo, so the assertions now genuinely run. The test is now both correct (undo/redo are actually verified) and stable. Validated locally with 5/5 clean runs. ### User interface changes None.
issue