Skip to content

fix: get E2E Tests fully green (wallet-lifecycle, theme-toggle, visual regression baselines) - #338

Merged
prodbycorne merged 5 commits into
SmartDropLabs:mainfrom
praizehimm:debug/e2e-artifact-diagnostics
Sep 7, 2026
Merged

fix: get E2E Tests fully green (wallet-lifecycle, theme-toggle, visual regression baselines)#338
prodbycorne merged 5 commits into
SmartDropLabs:mainfrom
praizehimm:debug/e2e-artifact-diagnostics

Conversation

@praizehimm

@praizehimm praizehimm commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Summary

#335 fixed the crash that was blocking this job entirely (a broken
next-intl rewrite 404ing every route under next start), which let
Playwright run to completion for the first time ever on this repo. That
surfaced 4 more pre-existing, dormant failures. This PR root-causes and
fixes all of them using real diagnostics pulled from actual CI runs
(trace.zip, error-context.md, and the real Linux/Chromium screenshots) --
this Mac can't run Playwright at all (ERROR: Playwright does not support chromium on mac13), so nothing here was guessed blind.

Result: E2E Tests is fully green -- all 15 tests pass. (Run:
https://github.com/SmartDropLabs/smartdrop-frontend/actions/runs/34145838859)

1. Diagnostics were silently broken (needed this to see anything)

.github/workflows/e2e.yml uploaded playwright-report/ on failure, but
e2e/playwright.config.ts doesn't configure the html reporter, so that
directory was never written -- every failed run uploaded an empty
artifact. Pointed it at test-results/ instead, which is where traces
and DOM snapshots actually land.

2. wallet-lifecycle.spec.ts: floating connect button not found on "/"

error-context.md showed the real cause: OnboardingOverlay opens a Chakra
Modal on a first-ever visit to "/", which aria-hiddens the rest of the
page for focus-trapping (correct modal behavior) -- that removed the
connect button from the accessibility tree entirely. / is the only
route this suite visits fresh. Seeded the "already onboarded" localStorage
flag before navigating, matching the returning-user baseline every other
spec implicitly gets.

3. farm.spec.ts: countdown locator strict-mode violation

Two elements legitimately show the same locked position's countdown
(FarmPoolRow and EarningRow each render it independently) -- not a
bug. Scoped the locator with .first(), matching the pattern already
used two lines below for unlockBtn.

4. visual-regression.spec.ts "theme toggle persists across reloads"

Traced the actual click+reload sequence via trace.zip: the toggle
worked correctly every time. The test's own setup was the bug --
page.addInitScript(() => localStorage.setItem(..., "light")) re-runs on
every navigation in that page, including the page.reload() used to
test persistence, silently overwriting the just-set "dark" value back to
"light" right before the check read it. Switched to page.evaluate() +
one explicit reload for the one-time seed.

5. visual-regression.spec.ts (3 tests): missing baselines + dev-overlay noise

This repo never had baseline screenshots committed, so toHaveScreenshot()
always failed by design on a first run. Pulled real Chromium renders from
actual CI runs (not generated locally -- pixel output isn't portable
across platforms) for all 4 needed baselines. Along the way found two
more issues these tests never got far enough to hit before:

  • Next.js's dev-mode error/issues badge (<nextjs-portal>, this suite
    runs pnpm dev) animates inside what's likely a shadow root the
    existing animation-disabling script can't reach, making it
    non-deterministic pixel-to-pixel. mask didn't visibly cover it (the
    custom element's own layout box doesn't necessarily bound its shadow
    content), so hidden it outright via display: none before each
    screenshot instead.
  • expect(consoleErrors).toEqual([]) was tripping on two benign, dev/
    test-only sources: Next's own <HotReload> hydration-mismatch warning
    (framework-internal, never ships to production) and the browser's own
    "Failed to load resource: 404" log for the routes these specs
    intentionally navigate to because they don't exist. Filtered both by
    pattern rather than weakening the check generally.

Verified

… dir

The failure-artifact upload step pointed at playwright-report/, but
e2e/playwright.config.ts doesn't configure the html reporter, so that
directory is never written -- every failed E2E run has been uploading an
empty artifact. test-results/ is where traces, error-context.md (a DOM/
accessibility snapshot at the moment of failure), and screenshots
actually land regardless of which reporter is configured. Needed this to
get real diagnostics on the remaining E2E failures.
@netlify

netlify Bot commented Sep 7, 2026

Copy link
Copy Markdown

Deploy Preview for spiffy-melomakarona-eb1e8a ready!

Name Link
🔨 Latest commit 1aba1e3
🔍 Latest deploy log https://app.netlify.com/projects/spiffy-melomakarona-eb1e8a/deploys/6a9eede5b2e1be00084e7972
😎 Deploy Preview https://deploy-preview-338--spiffy-melomakarona-eb1e8a.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Sep 7, 2026

Copy link
Copy Markdown

Deploy Preview for smart-drop ready!

Name Link
🔨 Latest commit 1aba1e3
🔍 Latest deploy log https://app.netlify.com/projects/smart-drop/deploys/6a9eede527c49a00083b653e
😎 Deploy Preview https://deploy-preview-338--smart-drop.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Root-caused both remaining E2E failures from SmartDropLabs#335 using real CI trace/DOM
diagnostics (via the test-results upload fix in SmartDropLabs#338), instead of guessing.

- wallet-lifecycle.spec.ts: "/" is the only route this suite visits fresh.
  On a first-ever visit, OnboardingOverlay (src/components/
  OnboardingOverlay) opens a Chakra Modal, which marks the rest of the page
  aria-hidden for focus-trapping. That's correct accessible-modal behavior,
  not a bug -- but it removed the floating connect button from the
  accessibility tree entirely, so getByRole couldn't find it at all
  ("element(s) not found", not just "not visible"). Confirmed via the
  captured error-context.md DOM snapshot, which showed the onboarding
  dialog open and blocking. Seeded the same "smartdrop_onboarded" flag the
  overlay itself writes on dismiss, so this test starts at the returning-
  user baseline every other spec in the suite implicitly gets by never
  visiting "/".

- visual-regression.spec.ts "theme toggle persists across reloads": traced
  the actual click+reload sequence via the captured trace.zip. The toggle
  click worked correctly every time (localStorage read "dark" immediately
  after, on the first check, no retries needed) -- the bug was in the test
  itself. It seeded the "light" baseline via page.addInitScript(), which
  Playwright re-runs on *every* navigation in that page, including the
  page.reload() the test uses to check persistence. So the seed script was
  silently overwriting the just-set "dark" value back to "light" right
  before the app re-hydrated and the persistence check read it. Switched
  to page.evaluate() + one explicit reload for the one-time seed, which
  doesn't re-fire on the later reload.

- Added the 3 baseline screenshots these tests need (404-page-light,
  leaderboard-credits, leaderboard-stake) -- this repo has never had any
  committed, so toHaveScreenshot() always failed on its first run
  regardless of app correctness. Pulled the actual PNGs Chromium rendered
  on the real ubuntu-latest CI runner (via the same test-results artifact)
  rather than generating them locally, since pixel output isn't portable
  across platforms and this Mac can't run Playwright's Chromium at all
  (unsupported OS). The 4th (404-page-dark) still has no baseline -- the
  toggle-persistence test never reached that screenshot line before this
  fix, so no actual.png existed yet to pull. It'll get generated (and
  fail once, by Playwright's normal first-run behavior) on this branch's
  next CI run; will follow up with it once that run lands.

Both bugs were latent and pre-existing -- neither test had ever run to
completion in CI before SmartDropLabs#335 fixed the Lighthouse crash that was gating
this whole job.
The 3 baselines added in the previous commit were pixel-accurate everywhere
except one region: Next.js's dev-mode error/issues badge (<nextjs-portal>,
bottom-left -- this suite runs against `pnpm dev`, not a production build).
Confirmed via a real CI diff (leaderboard-stake-diff.png from run
34143853333): every pixel outside that badge matched the committed
baseline exactly; only the badge itself differed between two separate CI
runs of the same deterministic page state.

The animation-disabling <style> this spec already injects into
document.head doesn't reach whatever's animating inside the badge (it
likely lives in a shadow root), so its pixels aren't reproducible run to
run -- unsuitable for a pixel-diff baseline regardless of how the
baseline is generated. Masking it with Playwright's `mask` option (paints
over the region before comparing, in both the actual screenshot and the
stored baseline) is the standard fix for exactly this class of known-
dynamic, out-of-scope-of-the-test UI element.

This invalidates the 3 baselines just committed -- they were captured
without masking, so the masked region's paint differs from what a masked
comparison now expects. Removing them here; a follow-up commit will add
freshly-generated masked baselines (all 4 now, including 404-page-dark,
which the previous run reached for the first time after the
wallet-lifecycle/theme-toggle fixes).
Two follow-ups after the masked run (34144631276) still failed:

1. Playwright's `mask` option didn't visibly cover <nextjs-portal> --
   the actual.png still showed the badge unmasked. A custom element's own
   layout box doesn't necessarily bound whatever's rendered in its shadow
   root, so masking by locator bounding-rect isn't reliable here. Hiding
   it outright (display: none via page.evaluate, before each screenshot)
   sidesteps that entirely -- confirmed simpler and doesn't depend on
   Playwright correctly computing a box for shadow-DOM content.

2. Once tests ran far enough to reach `expect(consoleErrors).toEqual([])`
   for the first time (previously blocked earlier by the theme-toggle bug
   fixed last commit), it failed for reasons that turned out to be
   pre-existing and unrelated to anything under test:
   - Next's own dev-only <HotReload> hydration-mismatch warning (from its
     dev-mode error-overlay machinery re-hydrating oddly under automation
     -- framework-internal, never ships in the production build).
   - The browser's own "Failed to load resource: 404" log, logged
     automatically for the routes these specs *intentionally* navigate to
     because they don't exist -- that's the point of a 404-page test, not
     an app defect.
   Filtered both out of trackConsoleErrors() by pattern rather than
   weakening the assertion generally, so it still catches anything else.
All 4 baselines this suite needs, pulled from a real CI run (34145325691)
with the dev-overlay-hide fix applied -- confirmed clean (no dev-only
badge) by inspecting each image directly before committing. Same
rationale as the earlier baseline commits: this repo has never had any
committed, Playwright always fails toHaveScreenshot() on a first run
regardless of app correctness, and pixel output isn't portable across
platforms so these have to come from the actual ubuntu-latest runner
CI uses, not generated locally.
@praizehimm praizehimm changed the title fix: upload actual Playwright failure diagnostics (empty artifact bug) fix: get E2E Tests fully green (wallet-lifecycle, theme-toggle, visual regression baselines) Sep 7, 2026
@prodbycorne
prodbycorne merged commit 3d0b1ba into SmartDropLabs:main Sep 7, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants