MWPW-191474-Firefly-caraousal test cases#70
Conversation
|
Hello, I'm the AEM Code Sync Bot and I will run some actions to deploy your branch and validate page speed.
|
08243e6 to
141896d
Compare
141896d to
2499b7a
Compare
| }); | ||
|
|
||
| it('handles carousel with exactly 2 items', async () => { | ||
| const block = body.querySelector('#carousel-basic'); |
There was a problem hiding this comment.
This uses #carousel-basic which has 4 items, not 2. The test name says "exactly 2 items" but never exercises the 2-item boundary. Use #carousel-mixed-media (which has 2 items) or add a dedicated #carousel-two-items fixture. This matters because createMoveHandler gates on itemCount <= 1 — the 2-item case is the minimum for navigation and circular ordering with only 2 cards is a known edge case.
| const handler = sinon.spy(); | ||
| viewport.addEventListener('mouseenter', handler); | ||
| viewport.dispatchEvent(new Event('mouseenter')); | ||
| expect(handler.called).to.be.true; |
There was a problem hiding this comment.
This test only proves dispatchEvent triggers a listener you added yourself — it does not test carousel behavior. The actual auto-scroll stop handler is registered by setupAutoScroll with { once: true }. To test it properly: mock IntersectionObserver to start auto-scroll, verify the interval is active, then dispatch mouseenter and assert no further slides advance.
| expect(cards.length).to.be.greaterThan(0); | ||
| }); | ||
|
|
||
| it('first card exists after initialization', async () => { |
There was a problem hiding this comment.
5 duplicate tests that inflate the count without adding coverage:
| Duplicate | Identical to |
|---|---|
| "first card exists after initialization" (L47) | "converts carousel items to firefly-carousel-cards" (L38) |
| "gracefully handles carousel with no items" (L400) | "handles empty carousel gracefully" (L56) |
| "initializes all carousel features without errors" (L674) | "carousel initializes without errors" (L65) |
| "applies aria-label to navigation buttons" (L267) | "navigation buttons are properly labeled" (L169) |
| "renders without errors" (L390) | "carousel initializes without errors" (L65) |
~41 lines of pure duplication. Remove these and invest the effort in the uncovered branches (touch swipe, IntersectionObserver auto-scroll, prompt pill click → window.open, parseSlideItem null paths).
|
|
||
| const videoContainer = block.querySelector('.video-container'); | ||
| if (videoContainer) { | ||
| expect(videoContainer).to.exist; |
There was a problem hiding this comment.
if (x) expect(x).to.exist is a no-op — the assertion only runs when it's guaranteed to pass. This pattern appears in 3 tests:
- Here (L669):
if (videoContainer) { expect(videoContainer).to.exist; } - L278:
if (nextBtn) { expect(nextBtn.title).to.exist; } - L289:
if (pills.length > 0) { expect(firstPill.getAttribute('aria-label')).to.exist; }
If the element is expected, assert unconditionally — let the test fail when it's missing. If it genuinely might not exist, the test verifies nothing and should be removed.
| clock.tick(100); | ||
|
|
||
| const cards = block.querySelectorAll('.firefly-carousel-card'); | ||
| expect(cards.length).to.be.greaterThan(0); |
There was a problem hiding this comment.
greaterThan(0) is too weak — #carousel-basic has exactly 4 items, so use .to.equal(4). This same pattern appears 14+ times across the file. With greaterThan(0), a regression that silently drops 3 of 4 cards still passes. Use exact counts wherever the fixture is known.
| }); | ||
|
|
||
| it('handles video source attributes in video slides', async () => { | ||
| const block = body.querySelector('#carousel-with-videos'); |
There was a problem hiding this comment.
Silent early return — if the fixture is missing, this test passes without running any assertions. Since you authored the mock HTML and #carousel-with-videos exists in it, replace with expect(block).to.exist; so a broken fixture fails loudly. Same pattern at L104, L159, L318, L328, L663.
| await init(block); | ||
| clock.tick(100); | ||
|
|
||
| const dir = block.getAttribute('dir') || document.documentElement.getAttribute('dir'); |
There was a problem hiding this comment.
This doesn't test RTL behavior. The source computes RTL via document.dir === 'rtl' (not a dir attribute on the block element) — dir shouldn't be checked on element DOM, only page DOM. This test just asserts the mock's own attribute exists, which always passes.
Fix: Set document.dir = 'rtl' before init, then verify the track transform uses a negative axis multiplier (i.e. translate3d offset is positive instead of negative). Reset document.dir in cleanup.
| expect(viewport).to.exist; | ||
| expect(track).to.exist; | ||
|
|
||
| window.dispatchEvent(new Event('resize')); |
There was a problem hiding this comment.
The source uses ResizeObserver on the viewport (see observeResize), not a window resize listener — this event doesn't trigger the actual responsive code path. The assertion just re-checks that the viewport still exists, which it always will.
Fix: Mock ResizeObserver and trigger the callback manually, then verify controls.reposition() recalculates the track transform. Or resize the viewport element's dimensions and flush the observer.
| }); | ||
| }); | ||
|
|
||
| describe('Branch Coverage - Enhanced Tests', () => { |
There was a problem hiding this comment.
Despite the name, several important source branches remain uncovered:
| Source path | Gap |
|---|---|
setupSwipe (touch events) |
No touch tests at all |
setupAutoScroll (IntersectionObserver) |
No IO mock — only verified setInterval was called |
parseSlideItem null returns |
Not tested for < 3 children, missing media, or missing deeplink |
createPromptPill click → window.open |
Not tested |
ensureVideoSource setting src from dataset |
Not tested |
waitForTrackTransition fallback timer vs transitionend |
Not tested |
createMoveHandler returning false (itemCount ≤ 1) |
Single-slide test early-returns before asserting |
setupArrowKeyNavigation focus guard (!el.contains(activeElement)) |
Not tested |
setMediaControlTabOrder with .pause-play-wrapper |
Mock has no pause-play-wrapper elements |
These are the branches that actually catch regressions. Consider replacing the duplicate/tautological tests with coverage for these paths.
|
|
||
| it('carousel initializes without errors', async () => { | ||
| const block = body.querySelector('#carousel-basic'); | ||
| expect(() => { |
There was a problem hiding this comment.
init is async — wrapping it in a sync callback means any rejection becomes an unhandled promise rejection, not a synchronous throw. This assertion would pass even if init rejected. Happens to work here because init doesn't actually await anything internally, but it's conceptually wrong.
Fix: Just await init(block) directly — if it throws, Mocha catches it and fails the test. No expect().not.to.throw() wrapper needed.
| await init(block); | ||
|
|
||
| const track = block.querySelector('.firefly-carousel-track'); | ||
| let errorThrown = false; |
There was a problem hiding this comment.
Manual try/catch reimplements what expect(...).not.to.throw() already does, but loses the error message on failure. And since init is async, a rejected promise wouldn't be caught here anyway — it'd become an unhandled rejection and the test would still pass.
Fix: Remove the try/catch scaffolding. Just await init(block) and run the assertions directly — WTR/Mocha will fail the test if anything throws.
|
@hkhatana26 Please check why the UT github action is failing? |
Resolves: MWPW-191474
Test URLs:
Dev Validation-

http://127.0.0.1:5502/coverage/lcov-report/blocks/firefly-carousel/index.html