Skip to content

test(dashnote): add Playwright e2e suite (smoke, auth, notes, settings) + CI#81

Merged
thephez merged 9 commits into
mainfrom
test/e2e
May 13, 2026
Merged

test(dashnote): add Playwright e2e suite (smoke, auth, notes, settings) + CI#81
thephez merged 9 commits into
mainfrom
test/e2e

Conversation

@thephez
Copy link
Copy Markdown
Collaborator

@thephez thephez commented May 13, 2026

Summary

  • New Playwright e2e suite under example-apps/dashnote/test/e2e/ covering every user-facing operation against real Dash Platform testnet. No SDK mocks.
  • Four specs (smoke, auth, notes, settings) plus a shared fixtures.ts mirroring the dashmint-lab setup.
  • Two projects per run: chromium-desktop (Desktop Chrome) and chromium-mobile (Pixel 7) — same specs cover responsive layout regressions.
  • New dashnote-e2e.yml GitHub Actions workflow with a read-only / read-write split mirroring the existing test-tutorials.yml pattern: smoke + settings run on every PR/push touching example-apps/dashnote/**; auth + notes are workflow_dispatch-only to avoid burning testnet credits on routine runs.

Coverage

smoke.spec.ts (no auth): SDK boot, tab navigation, theme toggle, login-modal open/close + input validation + WIF preview, mobile hamburger drawer, dashnote-lite.html loads.

auth.spec.ts (auth-gated, serial): mnemonic login + logout via IdentityCard menu, remember-me persistence across reload, forget-this-device via SettingsPanel AND via LoginModal, switch-identity, Settings tab reachable from both nav button and menu, identity ID displayed after login.

notes.spec.ts (auth-gated, serial): create/edit/delete round-trip, search filter (uses persistent [e2e-fixture] notes seeded once), discard-changes confirmation dismissal, mobile list↔editor transitions, two-context concurrent saves (verifies revision bumping across sessions).

settings.spec.ts (mixed): readonly sign-in prompt, copy identity ID / contract ID to clipboard, clear local cache (with localStorage assertion), "Use this ID" enable/disable state, DPNS name renders once resolved.

Notable design choices

  • Mobile + desktop in one suite: specs use viewport-agnostic locators where possible; mobile-only behaviors are guarded inline with test.skip(testInfo.project.name !== "chromium-mobile", …) rather than in a separate file.
  • Test data hygiene: transient notes use [e2e] title prefix and are cleaned up in afterEach. Two persistent [e2e-fixture] notes back the search test so we don't write + delete throwaway notes every run.
  • Connection gate via .conn-dot.connected instead of text — the readonly IdentityCard renders the "Connected" label twice, breaking strict-mode locators.
  • Mobile cleanup gotcha: cleanupE2eNotes calls returnToList at the top of each loop iteration because the list pane is display: none whenever a note is selected, which would otherwise make candidate scans silently return 0 and leak orphans.

CI workflow

  • e2e-read-only (smoke + settings): runs on every push/PR to main that touches example-apps/dashnote/** or the workflow itself. ~20 min budget.
  • e2e-read-write (auth + notes): workflow_dispatch only, 60 min budget, concurrency group prevents parallel runs that would conflict on the shared testnet identity.
  • Both jobs cache Playwright browsers keyed on the @playwright/test version, upload playwright-report/ and test-results/ artifacts on failure (14-day retention).

Summary by CodeRabbit

  • Tests
    • Added comprehensive end-to-end test coverage for the Dashnote example app, including authentication flows, note management, settings functionality, and responsive design validation across desktop and mobile.
    • Added automated test execution via GitHub Actions with read-only and read-write test suites.

Review Change Stack

thephez and others added 6 commits May 13, 2026 11:27
Scaffolds dashnote's first Playwright suite: config with chromium-desktop+ chromium-mobile projects, shared fixtures with a pre-connected page and mobile-aware navButton helper, and a smoke spec covering boot/connect, tab navigation, theme toggle, login-modal open/close/validation, mobile hamburger drawer, and the dashnote-lite.html static page.

No mnemonic required — read-only flows only. Runs against real testnet, same posture as dashmint-lab.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds an `auth.spec.ts` covering login, logout via the IdentityCard menu,
switch-identity, remember-me persistence, and forget-this-device via
both the Settings panel and the LoginModal — all gated on
PLATFORM_MNEMONIC and run serially against real testnet under both
desktop and mobile projects. Adds an `openIdentityMenu` fixture helper
that handles the mobile drawer dance, mirroring `navButton`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… fixtures

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

Warning

Rate limit exceeded

@thephez has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 26 minutes and 22 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0089f732-feb3-43fb-b2c5-22798007c0ec

📥 Commits

Reviewing files that changed from the base of the PR and between 473b0d3 and aeed628.

📒 Files selected for processing (4)
  • .github/workflows/dashnote-e2e.yml
  • example-apps/dashnote/test/e2e/auth.spec.ts
  • example-apps/dashnote/test/e2e/fixtures.ts
  • example-apps/dashnote/test/e2e/settings.spec.ts
📝 Walkthrough

Walkthrough

This PR introduces comprehensive Playwright E2E testing infrastructure for the Dashnote example app. It adds a GitHub Actions workflow for automated test execution, Playwright configuration, shared test fixtures and helpers, and test suites covering app boot, identity/authentication, notes CRUD operations, and Settings UI interactions.

Changes

Dashnote E2E Testing Suite and CI/CD Workflow

Layer / File(s) Summary
GitHub Actions workflow and CI configuration
.github/workflows/dashnote-e2e.yml
Configures GitHub Actions to run Playwright E2E tests on pushes and PRs affecting the dashnote app, plus manual dispatch with test-suite selection. Defines e2e-read-only job (smoke and settings tests, cached Playwright browsers) and e2e-read-write job (auth and notes tests, manual dispatch only, separate concurrency). Both upload test reports and traces on failure.
Playwright test runner configuration and npm scripts
example-apps/dashnote/playwright.config.ts, example-apps/dashnote/package.json
Defines Playwright config for test discovery, CI-driven execution parameters, two test projects (Desktop Chrome, Pixel 7 mobile), Vite dev server startup, and trace/clipboard settings. Adds test:e2e and test:e2e:ui npm scripts.
Test suite documentation and guidance
example-apps/dashnote/CLAUDE.md
Documents the Playwright E2E commands, auto-starting Vite server on port 5181, fixture patterns, real testnet targeting, and conditional skipping of auth-gated tests when PLATFORM_MNEMONIC is missing.
Shared test fixtures and UI interaction helpers
example-apps/dashnote/test/e2e/fixtures.ts
Exports custom test fixture ensuring app connectivity before specs, environment-driven helpers for responsive/mobile-aware navigation, mnemonic login with remember-me support, note creation/editing/deletion, list navigation, cleanup routines, and search fixture seeding with deterministic test data constants.
Smoke tests for basic app functionality
example-apps/dashnote/test/e2e/smoke.spec.ts
Tests app boot (connected indicator, page title), tab navigation, theme toggling, login modal open/close/input gating, advanced-settings field visibility, mobile drawer state transitions, and lite HTML page loading.
Authentication and identity management tests
example-apps/dashnote/test/e2e/auth.spec.ts
Tests mnemonic login/logout, remember-me persistence across reloads, forget-this-device flows from Settings and LoginModal, identity switching, Settings tab navigation paths, and identity ID display validation. Uses serial execution with per-test localStorage reset.
Notes CRUD, search, and cross-context sync tests
example-apps/dashnote/test/e2e/notes.spec.ts
Tests note create-edit-delete round-trip, search filtering with fixture seeding, discard-confirmation dialogs, mobile list↔editor navigation, and concurrent cross-context edits with sync verification via page reload. Uses serial execution with per-test cleanup of E2E-prefixed notes.
Settings UI and functionality tests
example-apps/dashnote/test/e2e/settings.spec.ts
Tests Settings UI: copying identity and contract IDs to clipboard, clearing local cache via localStorage verification, enable/disable state of "use this id" button based on contract input, DPNS name resolution display, and readonly-mode sign-in prompt verification.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • dashpay/platform-tutorials#80: This PR exercises the identity-card menu and Settings UI behaviors that were introduced by the settings-split refactoring in PR #80.

Poem

🐰 A rabbit hops through Dashnote, testing every page,
Login flows and note creation—all within the stage.
From smoke to auth to settings bright, the E2E suite's complete,
With fixtures ready, browsers cached, no test shall skip a beat! 🎭✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title directly and precisely summarizes the main change: adding a Playwright end-to-end test suite (smoke, auth, notes, settings) for dashnote plus the CI workflow to run it.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/e2e

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (4)
.github/workflows/dashnote-e2e.yml (2)

100-102: Cross-branch workflow dispatches will queue serially.

The fixed concurrency group dashnote-e2e-read-write (without github.ref) combined with cancel-in-progress: false means all read-write test runs share a single queue, regardless of which branch or PR triggered them. This is intentional to prevent concurrent writes to the testnet, but it means a manual dispatch from branch A followed by one from branch B will run serially (potential 60+ minute wait).

Consider documenting this behavior in the workflow description or in example-apps/dashnote/CLAUDE.md to set expectations for contributors using workflow_dispatch.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/dashnote-e2e.yml around lines 100 - 102, The workflow uses
a fixed concurrency group "dashnote-e2e-read-write" with cancel-in-progress:
false, causing cross-branch workflow_dispatch runs to queue serially; update the
docs to explain this behavior (add a short note in the workflow description and
in example-apps/dashnote/CLAUDE.md) stating that manual dispatches from
different branches will run one-by-one and may incur long waits, and optionally
mention the mitigation: either include github.ref in the concurrency group name
to isolate queues per branch or keep the single group to enforce serialized
testnet writes.

58-58: ⚡ Quick win

Consider pinning actions/cache to a commit SHA for consistency.

While using @v4 is acceptable, pinning to a specific commit SHA (like actions/checkout and actions/setup-node) improves supply-chain security and ensures reproducible builds.

📌 Example pinned version

Check the actions/cache releases for the latest v4 commit SHA:

-      uses: actions/cache@v4
+      uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0

Apply the same pattern at line 120.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/dashnote-e2e.yml at line 58, Replace the floating tag
"uses: actions/cache@v4" with a pinned commit SHA reference (e.g., "uses:
actions/cache@<commit-sha>") by looking up the latest v4 release commit SHA in
the actions/cache GitHub releases and substituting it; ensure the same pinning
pattern is applied to other GitHub Action uses in this workflow (notably the
entries that currently use tags like actions/checkout and actions/setup-node) so
all actions are committed to specific SHAs for reproducible, secure runs.
example-apps/dashnote/test/e2e/fixtures.ts (2)

302-309: ⚡ Quick win

Consider logging or distinguishing error types in the cleanup try-catch.

The catch block silently continues on any error, which could mask selector changes, UI regressions, or actual bugs. If all candidates fail to load within the 5-second timeout, targetTitle remains null and cleanup exits early at line 318, leaving notes behind despite the safety counter.

Since cleanup is best-effort, consider adding a console.warn or debug log when a candidate fails to help with debugging test flakiness.

🔍 Proposed improvement
       try {
         canonical = await page
           .getByLabel("Title")
           .inputValue({ timeout: 5_000 });
       } catch {
+        console.warn(`[cleanupE2eNotes] Failed to read title for candidate ${i}, skipping`);
         continue;
       }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@example-apps/dashnote/test/e2e/fixtures.ts` around lines 302 - 309, The catch
block around page.getByLabel("Title").inputValue in the cleanup loop currently
swallows all errors; change it to log a warning/debug message including the
error and some context (e.g., the candidate index or the selector "Title")
before continuing so transient timeouts vs real selector/UI regressions can be
distinguished—update the try-catch in the cleanup loop that assigns canonical to
call console.warn or a test logger with the error and candidate info when an
exception occurs.

284-286: ⚡ Quick win

Consider logging when the safety counter is exhausted.

The safety counter caps cleanup at 20 notes to prevent runaway loops. If tests consistently leave more than 20 e2e notes, they'll accumulate over time without any signal. Adding a warning when safety reaches 0 would improve observability.

📊 Proposed logging
   let safety = 20;
   while (safety > 0) {
     safety -= 1;
     // ... existing logic ...
   }
+  if (safety === 0) {
+    console.warn('[cleanupE2eNotes] Safety limit reached; some e2e notes may remain');
+  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@example-apps/dashnote/test/e2e/fixtures.ts` around lines 284 - 286, The loop
using the safety counter (variable safety in the while (safety > 0) { ... safety
-= 1 }) should log a warning when the counter reaches 0 so test authors know
cleanup capped out; update the loop to detect when safety would become 0 (after
decrement or before breaking) and emit a clear warning message (e.g., via
console.warn or the existing test logger) that includes context such as the
remaining notes count or which cleanup routine ran, referencing the safety
variable and the surrounding cleanup logic in fixtures.ts.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@example-apps/dashnote/test/e2e/auth.spec.ts`:
- Around line 33-46: The test comment should explain why "Connected" appears
twice after logout: update the comment in the "login with a mnemonic, then
logout via the IdentityCard menu" test to state that IdentityCard renders
"Connected" in two places — the eyebrow label and the status text next to the
connection indicator — so the expect for two occurrences is correct; locate the
comment near the test (references: test name and IdentityCard component) and
replace the existing single-occurrence explanation with a brief note mentioning
both the eyebrow label and the inline status text.

In `@example-apps/dashnote/test/e2e/settings.spec.ts`:
- Around line 40-57: The file-level test.beforeEach (which calls loginViaModal)
is applying to all tests including the readonly suite; move the mnemonic-gated
setup into its own describe block so readonly tests run without auth. Create a
new test.describe(...) for the auth-required specs, and relocate
test.skip(!HAS_MNEMONIC, ...), test.describe.configure({ mode: "serial" }) and
the test.beforeEach(...) (which clears localStorage, reloads, waits for
".conn-dot.connected", and calls loginViaModal) into that describe block,
leaving the readonly tests at top-level unchanged.

---

Nitpick comments:
In @.github/workflows/dashnote-e2e.yml:
- Around line 100-102: The workflow uses a fixed concurrency group
"dashnote-e2e-read-write" with cancel-in-progress: false, causing cross-branch
workflow_dispatch runs to queue serially; update the docs to explain this
behavior (add a short note in the workflow description and in
example-apps/dashnote/CLAUDE.md) stating that manual dispatches from different
branches will run one-by-one and may incur long waits, and optionally mention
the mitigation: either include github.ref in the concurrency group name to
isolate queues per branch or keep the single group to enforce serialized testnet
writes.
- Line 58: Replace the floating tag "uses: actions/cache@v4" with a pinned
commit SHA reference (e.g., "uses: actions/cache@<commit-sha>") by looking up
the latest v4 release commit SHA in the actions/cache GitHub releases and
substituting it; ensure the same pinning pattern is applied to other GitHub
Action uses in this workflow (notably the entries that currently use tags like
actions/checkout and actions/setup-node) so all actions are committed to
specific SHAs for reproducible, secure runs.

In `@example-apps/dashnote/test/e2e/fixtures.ts`:
- Around line 302-309: The catch block around
page.getByLabel("Title").inputValue in the cleanup loop currently swallows all
errors; change it to log a warning/debug message including the error and some
context (e.g., the candidate index or the selector "Title") before continuing so
transient timeouts vs real selector/UI regressions can be distinguished—update
the try-catch in the cleanup loop that assigns canonical to call console.warn or
a test logger with the error and candidate info when an exception occurs.
- Around line 284-286: The loop using the safety counter (variable safety in the
while (safety > 0) { ... safety -= 1 }) should log a warning when the counter
reaches 0 so test authors know cleanup capped out; update the loop to detect
when safety would become 0 (after decrement or before breaking) and emit a clear
warning message (e.g., via console.warn or the existing test logger) that
includes context such as the remaining notes count or which cleanup routine ran,
referencing the safety variable and the surrounding cleanup logic in
fixtures.ts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b93f2f77-4b2e-4298-aaed-59391a1fb3fd

📥 Commits

Reviewing files that changed from the base of the PR and between a7f935e and 473b0d3.

📒 Files selected for processing (9)
  • .github/workflows/dashnote-e2e.yml
  • example-apps/dashnote/CLAUDE.md
  • example-apps/dashnote/package.json
  • example-apps/dashnote/playwright.config.ts
  • example-apps/dashnote/test/e2e/auth.spec.ts
  • example-apps/dashnote/test/e2e/fixtures.ts
  • example-apps/dashnote/test/e2e/notes.spec.ts
  • example-apps/dashnote/test/e2e/settings.spec.ts
  • example-apps/dashnote/test/e2e/smoke.spec.ts

Comment thread example-apps/dashnote/test/e2e/auth.spec.ts
Comment thread example-apps/dashnote/test/e2e/settings.spec.ts Outdated
thephez and others added 3 commits May 13, 2026 16:21
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… SHAs

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@thephez thephez merged commit f600894 into main May 13, 2026
5 checks passed
@thephez thephez deleted the test/e2e branch May 13, 2026 20:41
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.

1 participant