feat(next): multi-wallet login flow with two-step UI and Synpress E2E#96
feat(next): multi-wallet login flow with two-step UI and Synpress E2E#96gaboesquivel merged 6 commits intomainfrom
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThe PR consolidates the dashboard to the root path, integrates wallet authentication flows for MetaMask and Solana using Synpress, refactors the login UI with wallet options, redirects Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant LoginPage as Login Page
participant LoginActions as LoginActions
participant WalletOptions as WalletOptionsView
participant Connector as Wallet Connector
User->>LoginPage: Navigate to /login
LoginPage->>LoginActions: Render with initialError
LoginActions->>LoginActions: Show initial panel
User->>LoginActions: Click "Wallet Login"
LoginActions->>WalletOptions: showWalletOptions = true
WalletOptions->>WalletOptions: Render wallet options
User->>WalletOptions: Click "Connect MetaMask"
WalletOptions->>Connector: useConnect() for injected
Connector->>Connector: Connect to MetaMask
User->>Connector: Sign transaction
Connector->>LoginPage: Redirect with auth token
LoginPage->>User: Redirect to / (root)
sequenceDiagram
actor Test
participant Playwright as Playwright
participant Synpress as Synpress
participant MetaMask as MetaMask
participant App as Next.js App
Test->>Playwright: Load metamask.setup.ts
Playwright->>Synpress: Initialize Synpress helper
Synpress->>MetaMask: Get extension ID & context
Synpress->>MetaMask: Import seed phrase
MetaMask->>Synpress: Wallet initialized
Test->>App: Navigate to /login
App->>Test: Render login page
Test->>App: Click wallet login → Connect MetaMask
App->>MetaMask: Initiate connection
MetaMask->>Synpress: Handle connection request
Test->>MetaMask: Confirm signature
MetaMask->>App: Return signed message
App->>Test: Redirect to / with auth
Test->>Test: Assert URL/UI state
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In @.gitignore:
- Line 24: Update the .gitignore entry for the Synpress cache to use a trailing
slash by replacing or changing ".cache-synpress" to ".cache-synpress/" and add
Cypress artifact directories to ignore if applicable: "cypress/screenshots/",
"cypress/videos/", and "cypress/downloads/"; ensure you check synpress.json for
any custom Cypress output folders and add those paths as well so test artifacts
aren’t committed.
In @.gitleaks.toml:
- Line 13: The current allowlist entry
'''apps/next/e2e/wallet-setup/.*\.(ts|js|mjs)$''' is too broad and disables all
gitleaks rules for that directory; replace it with a targeted allowlist that
matches only the known, safe test secrets used by Synpress (e.g., explicit
regexes for the test seed phrase and test private key values) or remove the
allowlist entirely and instead add explicit exceptions for specific harmless
constants; update the .gitleaks.toml entry by removing the directory-wide regex
and adding narrowly scoped regex patterns that exactly match the test values you
intend to permit so real secrets remain detectable.
In `@apps/next/components/wallet-sign-in-buttons.tsx`:
- Line 60: The current onConnect handler in wallet-sign-in-buttons.tsx (and the
similar handler in wallet-options-view.tsx) silently no-ops when the injected
connector is undefined; update the UI to avoid a confusing button state by
disabling the "Connect MetaMask" button (e.g., add disabled={!injected}) and/or
show feedback when clicked with no injected wallet (e.g., show a tooltip or call
the existing connect error handler or a toast). Ensure you update the onConnect
callback associated with connect({ connector: injected }) to only call connect
when injected is defined (guard injected before invoking) and add the UI
disabled state so users cannot attempt to connect when no injected connector
exists.
🧹 Nitpick comments (7)
osv-scanner.toml (1)
6-27: AddignoreUntildates to these suppressions to ensure periodic reassessment.These vulnerabilities in transitive dev dependencies (axios, glob, ws, tsup from Synpress E2E tooling) are appropriately ignored for now, but without an expiry date they risk being forgotten indefinitely. Setting
ignoreUntilto a future date (e.g., 3–6 months out) ensures they are revisited and removed once upstream patches become available or the dependencies are upgraded.Example with `ignoreUntil`
[[IgnoredVulns]] id = "GHSA-43fc-jf86-j433" reason = "Transitive (axios) from Synpress E2E, dev only" ignoreUntil = "2026-08-01"Apply similarly to all 7 entries.
apps/next/components/wallet-sign-in-buttons.tsx (1)
45-61: Significant duplication withwallet-options-view.tsx.
WalletSignInButtons(lines 45–61) andWalletOptionsView(wallet-options-view.tsx lines 10–49) share nearly identical hook setup:useWallet('eip155'),useWallet('solana'),useChainId(),useConnect(),useWalletModal(), and the same injected-connector lookup. Consider extracting this shared wallet-connection logic into a custom hook (e.g.,useWalletConnectors) to keep both components DRY.apps/next/scripts/run-e2e-local.mjs (1)
130-143: Synpress build triggers unnecessarily when running non-wallet projects.The condition
!pwArgs.some(a => a.startsWith('--project='))means that passing any args without an explicit--project=flag (e.g.,--grep "magic-link") will trigger the Synpress build. This adds unnecessary build time when running only non-wallet specs.Consider tightening the condition, for example by also checking whether any wallet spec file is explicitly targeted:
♻️ Suggested refinement
const runWalletSpecs = - !pwArgs.some(a => a.startsWith('--project=')) || - pwArgs.some(a => a.includes('wallet-metamask') || a.includes('wallet-solana')) + pwArgs.some(a => a.includes('wallet-metamask') || a.includes('wallet-solana')) || + !pwArgs.some(a => a.startsWith('--project'))This reorders the check so the explicit wallet match is evaluated first, but the fundamental behavior is the same — you may want to skip the build entirely when a non-wallet
--projectis specified (regardless of=vs space separator).apps/next/components/login/login-actions.tsx (1)
42-70: Both view panels are always mounted — wallet hooks run even on initial view.Since both panels are rendered simultaneously (hidden via CSS), all wallet-related hooks in
WalletOptionsView(useConnect, useWallet, etc.) execute even when the user is on the initial login form. This is fine for a smooth transition UX, but worth noting for awareness — if those hooks trigger network requests or side effects, they'll fire immediately on mount.If this becomes a concern, lazy-mounting the wallet panel (e.g.,
{showWalletOptions && <WalletOptionsView ... />}) would defer those hooks, at the cost of losing the CSS transition.apps/next/e2e/wallet-auth.spec.ts (1)
18-33: Redundantpage.goto('/')afterwaitForURLalready confirmed navigation to/.Line 27 waits for the URL to be
/, then Line 29 navigates to/again. This is a no-op but adds unnecessary latency.♻️ Remove redundant navigation
await authHelpers.verifyMagicLink(page, token) await page.waitForURL(url => url.pathname === '/' || url.pathname === '', { timeout: 5000 }) - await page.goto('/') await expect(page.getByRole('heading', { name: /dashboard/i })).toBeVisible()apps/next/components/dashboard/dashboard-wallet-content.tsx (1)
139-165: UX: No explicit MetaMask connect button in the "Link wallet" section.When no wallet is connected (Line 140), the UI shows a Solana connect button but only a text hint for MetaMask ("or connect MetaMask for EVM"). Users may not know how to connect MetaMask without an explicit button. If MetaMask connection is handled via auto-injection from
wagmi, consider adding a brief tooltip or instruction.apps/next/e2e/wallet-solana-auth.spec.ts (1)
17-17: Consider a stricter URL assertion to avoid false positives.The regex
/\/(\?.*)?$/would also match URLs like/login/or/some-path/. Since you're verifying a redirect to root specifically, consider using the same pattern as inwallet-auth.spec.tsLine 27:- await expect(page).toHaveURL(/\/(\?.*)?$/) + await page.waitForURL(url => url.pathname === '/' || url.pathname === '', { timeout: 5000 })This explicitly validates the pathname rather than relying on a regex against the full URL.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.cursor/rules/frontend/e2e-playwright.mdc (1)
13-13:⚠️ Potential issue | 🟡 MinorStale project list — missing the two new wallet projects.
This line still describes only
authandchromiumprojects. It should also mentionwallet-metamaskandwallet-solanato match the updatedplaywright.config.ts.✏️ Suggested update
-- projects: auth first (`magic-link-auth.spec.ts`), chromium second (all other specs including `wallet-auth.spec.ts`, `link-wallet.spec.ts`, `link-email.spec.ts`) +- projects: auth first (`magic-link-auth.spec.ts`), wallet-metamask and wallet-solana (Synpress-based real-wallet specs), chromium last (all remaining specs; ignores auth and wallet specs)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.cursor/rules/frontend/e2e-playwright.mdc at line 13, Update the stale projects list line that currently mentions only "auth" and "chromium" to also include the two new wallet projects ("wallet-metamask" and "wallet-solana") so the documentation matches the updated playwright.config.ts; locate the line describing projects (the sentence starting with "projects: auth first...") and append or insert the wallet-metamask and wallet-solana entries in the same style/order as the existing projects.
🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.
In @.cursor/rules/frontend/e2e-playwright.mdc:
- Line 13: Update the stale projects list line that currently mentions only
"auth" and "chromium" to also include the two new wallet projects
("wallet-metamask" and "wallet-solana") so the documentation matches the updated
playwright.config.ts; locate the line describing projects (the sentence starting
with "projects: auth first...") and append or insert the wallet-metamask and
wallet-solana entries in the same style/order as the existing projects.
In @.github/workflows/next-e2e-test.yml:
- Around line 105-118: Add an id to the cache step (e.g., id: cache-synpress)
and guard the "Build Synpress wallet cache" step so it only runs when the cache
was missed; update its if condition to include &&
steps.cache-synpress.outputs.cache-hit != 'true' while keeping the existing
deployment and filter guards. Reference the step named "Cache Synpress wallet"
to add the id and the step named "Build Synpress wallet cache" to change the if
condition.
- Line 118: The CI step currently appends "|| true" to the xvfb-run
--auto-servernum pnpm --filter `@repo/next` synpress:phantom command which hides
Phantom setup failures; remove the "|| true" and instead handle failures
explicitly by capturing the command exit code (e.g., run the command, check $?
or use shell conditional), and if it fails either fail the job or echo a clear
warning message with the exit code and context (so the failure is visible in CI
logs) before deciding to continue; update the step that runs "xvfb-run
--auto-servernum pnpm --filter `@repo/next` synpress:phantom" accordingly.
In `@apps/docu/content/docs/testing/e2e-testing.mdx`:
- Around line 150-163: Replace the ambiguous parenthetical "(seed: standard test
phrase)" with an explicit reference to the Synpress/BIP-39 test mnemonic so
readers know it’s not a project secret; update the sentence near the wallet
setup filenames (e2e/wallet-setup/metamask.setup.ts,
e2e/wallet-setup/phantom.setup.ts) to say something like "(seed: the Synpress
default BIP-39 test mnemonic, e.g. the well-known 'test test test test test test
test test test test test junk')" so it clearly identifies the public test
phrase.
In `@apps/next/e2e/badges.spec.ts`:
- Around line 36-46: The test "should show both badges side by side on login
page" mixes locator styles: replace the inconsistent use of
page.locator('text=Signed Out') or page.getByText('Signed Out') so both
assertions use the same API; pick one (e.g., change page.locator('text=Signed
Out') to page.getByText('Signed Out') or vice versa) so the assertions in that
test consistently reference the same locator method.
In `@apps/next/scripts/run-e2e-local.mjs`:
- Line 140: The DISPLAY check is inconsistent: `const synpressNeedsXvfb =
process.platform === 'linux' && !env.DISPLAY` uses the merged `env` object while
later code checks `process.env.DISPLAY`, causing divergence if `.env.test`
defines DISPLAY; make the checks consistent by using the same source (preferably
`env.DISPLAY`) everywhere—update the later DISPLAY checks (the Playwright/xvfb
decision code that currently reads `process.env.DISPLAY`) to read `env.DISPLAY`
so both `synpressNeedsXvfb` and the Playwright run use the same environment
values.
- Around line 142-158: The used pattern of conditionally prefixing commands with
xvfb-run is duplicated across metamaskCmd/metamaskArgs, phantomCmd/phantomArgs
and the Playwright run invocation; create a small helper (e.g., wrapWithXvfb or
buildXvfbCommand) that takes the base command and args plus the boolean
synpressNeedsXvfb and returns the proper cmd and args tuple, then replace the
metamaskCmd/metamaskArgs, phantomCmd/phantomArgs and the Playwright spawnSync
call to use that helper (ensure spawnSync is still called with cwd, env, stdio
as before).
- Around line 128-138: pwArgs is being mutated with .push(), making flow hard to
follow; instead compute the final args immutably: keep the initial pwArgs
creation in the pwArgs variable (from userArgs/hasWorkers) and then derive a new
finalPwArgs (used later) by conditionally concatenating the extra project flags
when (!hasProjectArg && skipWalletE2E) is true. Reference pwArgs, hasProjectArg,
skipWalletE2E (and runWalletSpecs if helpful) and replace the in-place
pwArgs.push(...) with an immutable assignment that produces finalPwArgs without
mutating pwArgs.
In `@apps/next/scripts/run-e2e.mjs`:
- Around line 42-43: runWalletSpecs currently defaults to true when no --project
flag is passed (via the rest array), causing xvfb and --workers=1 to run
unnecessarily; change the logic so runWalletSpecs is true only if an explicit
indicator is present or wallet spec files exist: check for an explicit flag like
'--wallet' in rest or detect wallet tests by scanning the filesystem for wallet
spec patterns (e.g., using a glob for "*wallet*.spec.*") and set runWalletSpecs
based on that detection, leaving it false when neither an explicit flag nor
matching files are found; update any code that relies on runWalletSpecs (the
variable named runWalletSpecs and the subsequent xvfb/--workers handling) to use
this new condition.
🧹 Nitpick comments (7)
🤖 Fix all nitpicks with AI agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/next-e2e-test.yml: - Around line 105-118: Add an id to the cache step (e.g., id: cache-synpress) and guard the "Build Synpress wallet cache" step so it only runs when the cache was missed; update its if condition to include && steps.cache-synpress.outputs.cache-hit != 'true' while keeping the existing deployment and filter guards. Reference the step named "Cache Synpress wallet" to add the id and the step named "Build Synpress wallet cache" to change the if condition. - Line 118: The CI step currently appends "|| true" to the xvfb-run --auto-servernum pnpm --filter `@repo/next` synpress:phantom command which hides Phantom setup failures; remove the "|| true" and instead handle failures explicitly by capturing the command exit code (e.g., run the command, check $? or use shell conditional), and if it fails either fail the job or echo a clear warning message with the exit code and context (so the failure is visible in CI logs) before deciding to continue; update the step that runs "xvfb-run --auto-servernum pnpm --filter `@repo/next` synpress:phantom" accordingly. In `@apps/docu/content/docs/testing/e2e-testing.mdx`: - Around line 150-163: Replace the ambiguous parenthetical "(seed: standard test phrase)" with an explicit reference to the Synpress/BIP-39 test mnemonic so readers know it’s not a project secret; update the sentence near the wallet setup filenames (e2e/wallet-setup/metamask.setup.ts, e2e/wallet-setup/phantom.setup.ts) to say something like "(seed: the Synpress default BIP-39 test mnemonic, e.g. the well-known 'test test test test test test test test test test test junk')" so it clearly identifies the public test phrase. In `@apps/next/e2e/badges.spec.ts`: - Around line 36-46: The test "should show both badges side by side on login page" mixes locator styles: replace the inconsistent use of page.locator('text=Signed Out') or page.getByText('Signed Out') so both assertions use the same API; pick one (e.g., change page.locator('text=Signed Out') to page.getByText('Signed Out') or vice versa) so the assertions in that test consistently reference the same locator method. In `@apps/next/scripts/run-e2e-local.mjs`: - Around line 142-158: The used pattern of conditionally prefixing commands with xvfb-run is duplicated across metamaskCmd/metamaskArgs, phantomCmd/phantomArgs and the Playwright run invocation; create a small helper (e.g., wrapWithXvfb or buildXvfbCommand) that takes the base command and args plus the boolean synpressNeedsXvfb and returns the proper cmd and args tuple, then replace the metamaskCmd/metamaskArgs, phantomCmd/phantomArgs and the Playwright spawnSync call to use that helper (ensure spawnSync is still called with cwd, env, stdio as before). - Around line 128-138: pwArgs is being mutated with .push(), making flow hard to follow; instead compute the final args immutably: keep the initial pwArgs creation in the pwArgs variable (from userArgs/hasWorkers) and then derive a new finalPwArgs (used later) by conditionally concatenating the extra project flags when (!hasProjectArg && skipWalletE2E) is true. Reference pwArgs, hasProjectArg, skipWalletE2E (and runWalletSpecs if helpful) and replace the in-place pwArgs.push(...) with an immutable assignment that produces finalPwArgs without mutating pwArgs. In `@apps/next/scripts/run-e2e.mjs`: - Around line 42-43: runWalletSpecs currently defaults to true when no --project flag is passed (via the rest array), causing xvfb and --workers=1 to run unnecessarily; change the logic so runWalletSpecs is true only if an explicit indicator is present or wallet spec files exist: check for an explicit flag like '--wallet' in rest or detect wallet tests by scanning the filesystem for wallet spec patterns (e.g., using a glob for "*wallet*.spec.*") and set runWalletSpecs based on that detection, leaving it false when neither an explicit flag nor matching files are found; update any code that relies on runWalletSpecs (the variable named runWalletSpecs and the subsequent xvfb/--workers handling) to use this new condition.apps/next/e2e/badges.spec.ts (1)
36-46: Nit: inconsistent locator style for "Signed Out" within the same test group.Line 36 uses
page.locator('text=Signed Out')while line 46 usespage.getByText('Signed Out'). Both work, but picking one style consistently improves readability.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/next/e2e/badges.spec.ts` around lines 36 - 46, The test "should show both badges side by side on login page" mixes locator styles: replace the inconsistent use of page.locator('text=Signed Out') or page.getByText('Signed Out') so both assertions use the same API; pick one (e.g., change page.locator('text=Signed Out') to page.getByText('Signed Out') or vice versa) so the assertions in that test consistently reference the same locator method..github/workflows/next-e2e-test.yml (2)
105-118: Skip the wallet build when the cache is already warm.The cache step has no
id, so the build step (Line 117-118) runs unconditionally — even on a cache hit. Add anidand gate the build on a cache miss to save CI minutes.♻️ Proposed fix
- name: Cache Synpress wallet if: steps.filter.outputs.next == 'true' && steps.wait-app.outputs.deployment_url_app != '' && steps.wait-api.outputs.deployment_url_api != '' + id: synpress-cache uses: actions/cache@v4 with: path: apps/next/.cache-synpress key: synpress-${{ runner.os }}-${{ hashFiles('apps/next/e2e/wallet-setup/**') }} restore-keys: | synpress-${{ runner.os }}- - name: Build Synpress wallet cache - if: steps.filter.outputs.next == 'true' && steps.wait-app.outputs.deployment_url_app != '' && steps.wait-api.outputs.deployment_url_api != '' + if: steps.filter.outputs.next == 'true' && steps.wait-app.outputs.deployment_url_app != '' && steps.wait-api.outputs.deployment_url_api != '' && steps.synpress-cache.outputs.cache-hit != 'true' run: | xvfb-run --auto-servernum pnpm --filter `@repo/next` synpress:metamask xvfb-run --auto-servernum pnpm --filter `@repo/next` synpress:phantom || true🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/next-e2e-test.yml around lines 105 - 118, Add an id to the cache step (e.g., id: cache-synpress) and guard the "Build Synpress wallet cache" step so it only runs when the cache was missed; update its if condition to include && steps.cache-synpress.outputs.cache-hit != 'true' while keeping the existing deployment and filter guards. Reference the step named "Cache Synpress wallet" to add the id and the step named "Build Synpress wallet cache" to change the if condition.
118-118:|| truesilently swallows Phantom setup failures.If Phantom wallet support is experimental, consider at least logging a warning so failures are visible in CI output rather than silently ignored.
- xvfb-run --auto-servernum pnpm --filter `@repo/next` synpress:phantom || true + xvfb-run --auto-servernum pnpm --filter `@repo/next` synpress:phantom || echo "::warning::Phantom wallet cache build failed — skipping"🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/next-e2e-test.yml at line 118, The CI step currently appends "|| true" to the xvfb-run --auto-servernum pnpm --filter `@repo/next` synpress:phantom command which hides Phantom setup failures; remove the "|| true" and instead handle failures explicitly by capturing the command exit code (e.g., run the command, check $? or use shell conditional), and if it fails either fail the job or echo a clear warning message with the exit code and context (so the failure is visible in CI logs) before deciding to continue; update the step that runs "xvfb-run --auto-servernum pnpm --filter `@repo/next` synpress:phantom" accordingly.apps/docu/content/docs/testing/e2e-testing.mdx (1)
150-163: Minor: clarify "standard test phrase" reference.Line 161 mentions
(seed: standard test phrase)which is ambiguous. Consider specifying that this refers to the Synpress default test mnemonic (e.g., "the well-knowntest test test...BIP-39 mnemonic") so readers don't confuse it with a project-specific secret.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/docu/content/docs/testing/e2e-testing.mdx` around lines 150 - 163, Replace the ambiguous parenthetical "(seed: standard test phrase)" with an explicit reference to the Synpress/BIP-39 test mnemonic so readers know it’s not a project secret; update the sentence near the wallet setup filenames (e2e/wallet-setup/metamask.setup.ts, e2e/wallet-setup/phantom.setup.ts) to say something like "(seed: the Synpress default BIP-39 test mnemonic, e.g. the well-known 'test test test test test test test test test test test junk')" so it clearly identifies the public test phrase.apps/next/scripts/run-e2e-local.mjs (2)
142-158: Extract the xvfb-wrapping pattern into a helper to reduce duplication.The pattern of conditionally prepending
xvfb-run --auto-servernum --appears three times (MetaMask build, Phantom build, Playwright run). A small helper would reduce duplication and make it easier to adjust the xvfb flags in one place.Example helper
+function wrapXvfb(cmd, args, needsXvfb) { + return needsXvfb + ? ['xvfb-run', ['--auto-servernum', '--', cmd, ...args]] + : [cmd, args] +} + // then usage: - const metamaskCmd = synpressNeedsXvfb ? 'xvfb-run' : 'pnpm' - const metamaskArgs = synpressNeedsXvfb - ? ['--auto-servernum', '--', 'pnpm', 'synpress:metamask'] - : ['synpress:metamask'] + const [metamaskCmd, metamaskArgs] = wrapXvfb('pnpm', ['synpress:metamask'], synpressNeedsXvfb)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/next/scripts/run-e2e-local.mjs` around lines 142 - 158, The used pattern of conditionally prefixing commands with xvfb-run is duplicated across metamaskCmd/metamaskArgs, phantomCmd/phantomArgs and the Playwright run invocation; create a small helper (e.g., wrapWithXvfb or buildXvfbCommand) that takes the base command and args plus the boolean synpressNeedsXvfb and returns the proper cmd and args tuple, then replace the metamaskCmd/metamaskArgs, phantomCmd/phantomArgs and the Playwright spawnSync call to use that helper (ensure spawnSync is still called with cwd, env, stdio as before).
128-138: MutatingpwArgsin-place on Line 138 makes the data flow harder to follow.
pwArgsis built on Line 130, then conditionally mutated via.push()on Line 138, then read again on Lines 172-177 to producefinalPwArgs. Consider building the final args immutably to make the control flow clearer.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/next/scripts/run-e2e-local.mjs` around lines 128 - 138, pwArgs is being mutated with .push(), making flow hard to follow; instead compute the final args immutably: keep the initial pwArgs creation in the pwArgs variable (from userArgs/hasWorkers) and then derive a new finalPwArgs (used later) by conditionally concatenating the extra project flags when (!hasProjectArg && skipWalletE2E) is true. Reference pwArgs, hasProjectArg, skipWalletE2E (and runWalletSpecs if helpful) and replace the in-place pwArgs.push(...) with an immutable assignment that produces finalPwArgs without mutating pwArgs.apps/next/scripts/run-e2e.mjs (1)
42-43:runWalletSpecsdefaults totruewhen no--projectflag is passed — verify this is intentional.When a user runs the script without any
--project=argument,runWalletSpecsevaluates totrue(first disjunct). This means the xvfb wrapper and--workers=1default kick in even for plainpnpm run-e2e.mjsinvocations that may not involve wallet tests at all. If only the Playwright config'stestMatchdetermines which projects actually run, this is fine—but the xvfb overhead and single-worker default may slow down non-wallet runs unnecessarily.Consider gating on the presence of wallet spec files or an explicit flag rather than defaulting to
true.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/next/scripts/run-e2e.mjs` around lines 42 - 43, runWalletSpecs currently defaults to true when no --project flag is passed (via the rest array), causing xvfb and --workers=1 to run unnecessarily; change the logic so runWalletSpecs is true only if an explicit indicator is present or wallet spec files exist: check for an explicit flag like '--wallet' in rest or detect wallet tests by scanning the filesystem for wallet spec patterns (e.g., using a glob for "*wallet*.spec.*") and set runWalletSpecs based on that detection, leaving it false when neither an explicit flag nor matching files are found; update any code that relies on runWalletSpecs (the variable named runWalletSpecs and the subsequent xvfb/--workers handling) to use this new condition.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/docu/content/docs/testing/e2e-testing.mdx (1)
88-100:⚠️ Potential issue | 🟡 MinorSection header and intro at line 90 don't account for the new wallet-project specs.
Line 90 states: "Wallet-related specs run in the chromium project." However,
wallet-metamask-auth.spec.ts(line 99) andwallet-solana-auth.spec.ts(line 100) run in their own dedicated wallet-metamask and wallet-solana projects respectively, not in chromium. The current wording is misleading — onlywallet-auth.spec.ts,link-wallet.spec.ts, andlink-email.spec.tsrun in chromium.Consider updating the intro paragraph to clarify the project assignment, e.g.:
Proposed fix
-Wallet-related specs run in the **chromium** project (after the auth project). They use `authHelpers.sendMagicLink` and `authHelpers.verifyMagicLink` for per-test setup and do **not** use the `authenticatedPage` fixture. No browser extensions required. +Wallet UI specs (`wallet-auth`, `link-wallet`, `link-email`) run in the **chromium** project (after the auth project). They use `authHelpers.sendMagicLink` and `authHelpers.verifyMagicLink` for per-test setup and do **not** use the `authenticatedPage` fixture. Full wallet auth specs (`wallet-metamask-auth`, `wallet-solana-auth`) run in their own dedicated projects (**wallet-metamask**, **wallet-solana**) using injected mock providers. No browser extensions required.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/docu/content/docs/testing/e2e-testing.mdx` around lines 88 - 100, Update the intro paragraph to accurately state which specs run in which Playwright projects: note that wallet-auth.spec.ts, link-wallet.spec.ts, and link-email.spec.ts run in the chromium project, while wallet-metamask-auth.spec.ts runs in the wallet-metamask project and wallet-solana-auth.spec.ts runs in the wallet-solana project; revise the sentence that currently reads "Wallet-related specs run in the **chromium** project" to mention the three chromium specs explicitly and call out the separate wallet-metamask and wallet-solana projects for the EVM and Solana flows (also keep the note about using authHelpers.sendMagicLink/authHelpers.verifyMagicLink and not using the authenticatedPage fixture).
🤖 Fix all issues with AI agents
Verify each finding against the current code and only fix it if needed.
In @.cursor/rules/frontend/e2e-playwright.mdc:
- Line 13: The term "wallet specs" is ambiguous; update the references in the
doc that group the chromium project specs (wallet-auth.spec.ts,
link-wallet.spec.ts, link-email.spec.ts) and the separate wallet project specs
(wallet-metamask-auth.spec.ts, wallet-solana-auth.spec.ts) to use distinct
labels (e.g., "wallet UI specs" for the chromium magic-link tests and "wallet
auth specs" for the wallet-metamask/wallet-solana mock-auth tests) and add a
one-line clarifying note explaining the difference; ensure you change every
occurrence (the group around
wallet-auth.spec.ts/link-wallet.spec.ts/link-email.spec.ts and the mentions near
wallet-metamask-auth.spec.ts and wallet-solana-auth.spec.ts) and keep the
examples and project references (chromium vs wallet projects) consistent with
the new labels.
In @.github/scripts/wait-vercel-deployment.sh:
- Around line 54-57: Remove the unconditional 5-minute sleep and ensure START is
set before any wait so the timeout includes all elapsed time: delete the
echo/sleep lines or make the initial delay configurable (e.g., NEW_ARG or
INITIAL_DELAY) and default to 0, then set START=$(date +%s) before entering the
polling loop and compute TIMEOUT_SEC=$((TIMEOUT_MIN * 60)) as before; update any
references to the initial sleep to use the new variable (or remove them) so the
polling loop alone controls waits and the total duration is correctly bounded by
TIMEOUT_SEC.
In `@apps/docu/content/docs/testing/e2e-testing.mdx`:
- Around line 88-100: Update the intro paragraph to accurately state which specs
run in which Playwright projects: note that wallet-auth.spec.ts,
link-wallet.spec.ts, and link-email.spec.ts run in the chromium project, while
wallet-metamask-auth.spec.ts runs in the wallet-metamask project and
wallet-solana-auth.spec.ts runs in the wallet-solana project; revise the
sentence that currently reads "Wallet-related specs run in the **chromium**
project" to mention the three chromium specs explicitly and call out the
separate wallet-metamask and wallet-solana projects for the EVM and Solana flows
(also keep the note about using
authHelpers.sendMagicLink/authHelpers.verifyMagicLink and not using the
authenticatedPage fixture).
In `@apps/next/e2e/fixtures-solana-mock.ts`:
- Around line 24-54: The mock's event methods (mock.on, mock.off, mock.emit,
removeListener) are no-ops while connect() calls mock.emit('connect',
publicKey), so listeners never fire; implement a minimal event emitter in the
fixture: store handlers in a Map keyed by event name when
mock.on/removeListener/off are called, remove handlers appropriately, and invoke
those handlers with the provided args from mock.emit (ensure connect() triggers
the stored 'connect' handlers); update signaled symbols: mock.on, mock.off,
mock.removeListener, mock.emit, and connect to use this handler storage so tests
relying on window.solana.on('connect', ...) work.
In `@apps/next/e2e/wallet-metamask-auth.spec.ts`:
- Around line 12-15: Replace the direct DOM invocation evaluate(el =>
el.click()) with Playwright's native click() on the Playwright locators (e.g.,
use connectBtn.click() and signInBtn.click()) so actionability checks and
auto-waiting are preserved; if flakiness was the reason for using evaluate, add
an explicit wait for the mock wallet readiness (e.g., waitForSelector or
waitForFunction) before calling connectBtn.click() to ensure the wallet
injection timing is handled and avoid bypassing Playwright's checks.
In `@apps/next/package.json`:
- Around line 37-39: The synpress wallet setup scripts ("synpress:metamask",
"synpress:phantom", "synpress:build") and the setup files
(e2e/wallet-setup/metamask.setup.ts, phantom.setup.ts) are orphaned because
playwright.config.ts and the wallet tests still use mock fixtures
(fixtures-wallet-mock, fixtures-solana-mock); either integrate these setup files
into the test config or remove them and update package.json/docs. To fix: decide
which approach to keep; if keeping synpress, add references to the setup files
in playwright.config.ts (e.g., add projects or globalSetup entries that point to
e2e/wallet-setup/metamask.setup.ts and phantom.setup.ts and switch tests to use
those projects instead of fixtures-wallet-mock/fixtures-solana-mock), update
test invocations to call the corresponding npm scripts, and document usage in
the README; if removing, delete the two setup files and remove the three scripts
from package.json and any README mentions so there are no unused artifacts.
In `@apps/next/scripts/run-e2e-local.mjs`:
- Around line 128-146: The project default flags are appended after userArgs in
this script (see userArgs, pwArgs, finalPwArgs) which differs from run-e2e.mjs;
change the assembly so the project defaults are inserted before the user's
remaining args (i.e., build finalPwArgs as [...workers/projectArgs, ...userArgs]
like run-e2e.mjs) to make argument ordering consistent across scripts while
preserving the existing hasProjectArg and hasWorkers checks.
In `@package.json`:
- Around line 56-77: The top-level "overrides" object must be moved under the
existing "pnpm" object so pnpm v10 will apply them; move the entire overrides
block (the keys for eslint, `@eslint/js`, tmp, js-yaml, diff, bigint-buffer, tar,
`@isaacs/brace-expansion`, esbuild, path-to-regexp, undici, next, lodash,
lodash-es) into a new "overrides" property nested inside the existing "pnpm"
object (which already contains "onlyBuiltDependencies"), remove the top-level
"overrides" entry, and ensure there are no duplicate keys so pnpm.overrides is
the single source of truth.
- Line 46: Replace the "vercel": "latest" dependency with a pinned semantic
version to ensure reproducible builds; locate the "vercel" entry in package.json
and change its version string from "latest" to a specific release (for example
"29.10.0" or another vetted semver), or use a caret/tilde range if you intend
controlled updates (e.g., "^29.10.0"), and update lockfile by running your
package manager (pnpm install) to commit the deterministic version.
🧹 Nitpick comments (7)
🤖 Fix all nitpicks with AI agents
Verify each finding against the current code and only fix it if needed. In @.cursor/rules/frontend/e2e-playwright.mdc: - Line 13: The term "wallet specs" is ambiguous; update the references in the doc that group the chromium project specs (wallet-auth.spec.ts, link-wallet.spec.ts, link-email.spec.ts) and the separate wallet project specs (wallet-metamask-auth.spec.ts, wallet-solana-auth.spec.ts) to use distinct labels (e.g., "wallet UI specs" for the chromium magic-link tests and "wallet auth specs" for the wallet-metamask/wallet-solana mock-auth tests) and add a one-line clarifying note explaining the difference; ensure you change every occurrence (the group around wallet-auth.spec.ts/link-wallet.spec.ts/link-email.spec.ts and the mentions near wallet-metamask-auth.spec.ts and wallet-solana-auth.spec.ts) and keep the examples and project references (chromium vs wallet projects) consistent with the new labels. In @.github/scripts/wait-vercel-deployment.sh: - Around line 54-57: Remove the unconditional 5-minute sleep and ensure START is set before any wait so the timeout includes all elapsed time: delete the echo/sleep lines or make the initial delay configurable (e.g., NEW_ARG or INITIAL_DELAY) and default to 0, then set START=$(date +%s) before entering the polling loop and compute TIMEOUT_SEC=$((TIMEOUT_MIN * 60)) as before; update any references to the initial sleep to use the new variable (or remove them) so the polling loop alone controls waits and the total duration is correctly bounded by TIMEOUT_SEC. In `@apps/next/e2e/fixtures-solana-mock.ts`: - Around line 24-54: The mock's event methods (mock.on, mock.off, mock.emit, removeListener) are no-ops while connect() calls mock.emit('connect', publicKey), so listeners never fire; implement a minimal event emitter in the fixture: store handlers in a Map keyed by event name when mock.on/removeListener/off are called, remove handlers appropriately, and invoke those handlers with the provided args from mock.emit (ensure connect() triggers the stored 'connect' handlers); update signaled symbols: mock.on, mock.off, mock.removeListener, mock.emit, and connect to use this handler storage so tests relying on window.solana.on('connect', ...) work. In `@apps/next/e2e/wallet-metamask-auth.spec.ts`: - Around line 12-15: Replace the direct DOM invocation evaluate(el => el.click()) with Playwright's native click() on the Playwright locators (e.g., use connectBtn.click() and signInBtn.click()) so actionability checks and auto-waiting are preserved; if flakiness was the reason for using evaluate, add an explicit wait for the mock wallet readiness (e.g., waitForSelector or waitForFunction) before calling connectBtn.click() to ensure the wallet injection timing is handled and avoid bypassing Playwright's checks. In `@apps/next/package.json`: - Around line 37-39: The synpress wallet setup scripts ("synpress:metamask", "synpress:phantom", "synpress:build") and the setup files (e2e/wallet-setup/metamask.setup.ts, phantom.setup.ts) are orphaned because playwright.config.ts and the wallet tests still use mock fixtures (fixtures-wallet-mock, fixtures-solana-mock); either integrate these setup files into the test config or remove them and update package.json/docs. To fix: decide which approach to keep; if keeping synpress, add references to the setup files in playwright.config.ts (e.g., add projects or globalSetup entries that point to e2e/wallet-setup/metamask.setup.ts and phantom.setup.ts and switch tests to use those projects instead of fixtures-wallet-mock/fixtures-solana-mock), update test invocations to call the corresponding npm scripts, and document usage in the README; if removing, delete the two setup files and remove the three scripts from package.json and any README mentions so there are no unused artifacts. In `@apps/next/scripts/run-e2e-local.mjs`: - Around line 128-146: The project default flags are appended after userArgs in this script (see userArgs, pwArgs, finalPwArgs) which differs from run-e2e.mjs; change the assembly so the project defaults are inserted before the user's remaining args (i.e., build finalPwArgs as [...workers/projectArgs, ...userArgs] like run-e2e.mjs) to make argument ordering consistent across scripts while preserving the existing hasProjectArg and hasWorkers checks. In `@package.json`: - Line 46: Replace the "vercel": "latest" dependency with a pinned semantic version to ensure reproducible builds; locate the "vercel" entry in package.json and change its version string from "latest" to a specific release (for example "29.10.0" or another vetted semver), or use a caret/tilde range if you intend controlled updates (e.g., "^29.10.0"), and update lockfile by running your package manager (pnpm install) to commit the deterministic version..github/scripts/wait-vercel-deployment.sh (1)
54-57: Unconditional 5-minute sleep wastes CI time and isn't counted toward the timeout.Two concerns:
- Wasted time: The existing polling loop already handles "no deployment yet" gracefully. If Vercel happens to be ready in 2 minutes, you still wait 5. This adds ~5 min to every CI run unconditionally.
- Hidden total duration:
STARTis set after the sleep (line 56), so the 5-min delay is invisible to the 18-min timeout. Worst case is 23 minutes of wall-clock time, which may surprise maintainers and could hit CI job-level timeouts.Consider either making the initial delay configurable (e.g., a 4th argument) or simply removing it and relying on the poll loop, perhaps with a longer initial poll interval.
♻️ Option: make the initial delay configurable with a sensible default
PROJECT_NAME="${1:?project name required}" TIMEOUT_MIN="${2:-18}" [[ -n "${3:-}" ]] && OUTPUT_KEY="deployment_url_$3" || OUTPUT_KEY="deployment_url" -POLL_SEC=45 +INITIAL_DELAY="${4:-0}" +POLL_SEC=45 API_BASE="https://api.vercel.com"echo "::group::Waiting for Vercel deployment (${PROJECT_NAME} @ ${GITHUB_SHA})" -echo "Waiting 5min for Vercel to start build..." -sleep 300 +if [[ "$INITIAL_DELAY" -gt 0 ]]; then + echo "Waiting ${INITIAL_DELAY}s for Vercel to start build..." + sleep "$INITIAL_DELAY" +fi START=$(date +%s) TIMEOUT_SEC=$((TIMEOUT_MIN * 60))🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/scripts/wait-vercel-deployment.sh around lines 54 - 57, Remove the unconditional 5-minute sleep and ensure START is set before any wait so the timeout includes all elapsed time: delete the echo/sleep lines or make the initial delay configurable (e.g., NEW_ARG or INITIAL_DELAY) and default to 0, then set START=$(date +%s) before entering the polling loop and compute TIMEOUT_SEC=$((TIMEOUT_MIN * 60)) as before; update any references to the initial sleep to use the new variable (or remove them) so the polling loop alone controls waits and the total duration is correctly bounded by TIMEOUT_SEC.apps/next/e2e/wallet-metamask-auth.spec.ts (1)
12-15:evaluate(el => el.click())bypasses Playwright's actionability checks.Lines 12 and 15 use
evaluateto click instead of Playwright's native.click(). This skips auto-waiting for the element to be visible, enabled, and stable — which can mask real UI bugs (e.g., overlapping elements, disabled state not clearing). The Solana test (wallet-solana-auth.spec.ts) uses native.click()for equivalent steps.If this was done to work around flakiness with the mock wallet injection timing, consider adding an explicit wait instead.
Suggested change
- await connectBtn.evaluate((el: HTMLElement) => el.click()) + await connectBtn.click() const signInBtn = page.getByRole('button', { name: /sign in with ethereum/i }) await expect(signInBtn).toBeVisible({ timeout: 15_000 }) - await signInBtn.evaluate((el: HTMLElement) => el.click()) + await signInBtn.click()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/next/e2e/wallet-metamask-auth.spec.ts` around lines 12 - 15, Replace the direct DOM invocation evaluate(el => el.click()) with Playwright's native click() on the Playwright locators (e.g., use connectBtn.click() and signInBtn.click()) so actionability checks and auto-waiting are preserved; if flakiness was the reason for using evaluate, add an explicit wait for the mock wallet readiness (e.g., waitForSelector or waitForFunction) before calling connectBtn.click() to ensure the wallet injection timing is handled and avoid bypassing Playwright's checks.package.json (1)
46-46: Pinvercelto a specific version for reproducible builds.Using
"latest"means everypnpm installcan pull a different version, which can cause CI flakiness and makes builds non-reproducible.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@package.json` at line 46, Replace the "vercel": "latest" dependency with a pinned semantic version to ensure reproducible builds; locate the "vercel" entry in package.json and change its version string from "latest" to a specific release (for example "29.10.0" or another vetted semver), or use a caret/tilde range if you intend controlled updates (e.g., "^29.10.0"), and update lockfile by running your package manager (pnpm install) to commit the deterministic version.apps/next/e2e/fixtures-solana-mock.ts (1)
24-54: Event emitter methods are no-ops — verify the app doesn't rely onon('connect')events.
mock.on,mock.off, andmock.emitare all no-ops, butconnect()callsmock.emit('connect', publicKey). If the application code registers listeners viawindow.solana.on('connect', handler), those handlers will never fire. This is fine if the app only pollsisConnectedor awaits theconnect()promise, but could cause issues if it relies on event-driven connection detection.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/next/e2e/fixtures-solana-mock.ts` around lines 24 - 54, The mock's event methods (mock.on, mock.off, mock.emit, removeListener) are no-ops while connect() calls mock.emit('connect', publicKey), so listeners never fire; implement a minimal event emitter in the fixture: store handlers in a Map keyed by event name when mock.on/removeListener/off are called, remove handlers appropriately, and invoke those handlers with the provided args from mock.emit (ensure connect() triggers the stored 'connect' handlers); update signaled symbols: mock.on, mock.off, mock.removeListener, mock.emit, and connect to use this handler storage so tests relying on window.solana.on('connect', ...) work.apps/next/scripts/run-e2e-local.mjs (1)
128-146: Argument construction is correct, but project defaults are appended in a different position thanrun-e2e.mjs.In
run-e2e.mjs(line 46), project args are placed before the user's remaining args:[...workers, ...projectArgs, ...rest]Here, project defaults are appended after
userArgs(line 132–140). Playwright doesn't care about the ordering of--projectflags, so this is functionally equivalent — but the inconsistency between the two scripts could confuse a future maintainer. Consider aligning the argument assembly order for consistency.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/next/scripts/run-e2e-local.mjs` around lines 128 - 146, The project default flags are appended after userArgs in this script (see userArgs, pwArgs, finalPwArgs) which differs from run-e2e.mjs; change the assembly so the project defaults are inserted before the user's remaining args (i.e., build finalPwArgs as [...workers/projectArgs, ...userArgs] like run-e2e.mjs) to make argument ordering consistent across scripts while preserving the existing hasProjectArg and hasWorkers checks..cursor/rules/frontend/e2e-playwright.mdc (1)
13-13: The term "wallet specs" is overloaded — consider disambiguating.Line 13 groups
wallet-auth.spec.ts,link-wallet.spec.ts,link-email.spec.tsunder the chromium project and calls them out alongside "wallet specs." Lines 19 and 33 also use the label "wallet specs" for these chromium-project specs that authenticate via magic link. Meanwhile, Lines 27–28 introducewallet-metamask-auth.spec.tsandwallet-solana-auth.spec.tsas separate wallet-project specs with actual wallet mock auth.Both groups involve "wallets" but have fundamentally different auth mechanisms. A reader unfamiliar with the codebase could confuse them. Consider using distinct labels, e.g., "wallet UI specs" (chromium) vs. "wallet auth specs" (wallet-metamask/wallet-solana), or adding a brief clarifying note.
Also applies to: 19-19, 26-29
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.cursor/rules/frontend/e2e-playwright.mdc at line 13, The term "wallet specs" is ambiguous; update the references in the doc that group the chromium project specs (wallet-auth.spec.ts, link-wallet.spec.ts, link-email.spec.ts) and the separate wallet project specs (wallet-metamask-auth.spec.ts, wallet-solana-auth.spec.ts) to use distinct labels (e.g., "wallet UI specs" for the chromium magic-link tests and "wallet auth specs" for the wallet-metamask/wallet-solana mock-auth tests) and add a one-line clarifying note explaining the difference; ensure you change every occurrence (the group around wallet-auth.spec.ts/link-wallet.spec.ts/link-email.spec.ts and the mentions near wallet-metamask-auth.spec.ts and wallet-solana-auth.spec.ts) and keep the examples and project references (chromium vs wallet projects) consistent with the new labels.apps/next/package.json (1)
37-39: Synpress setup files and scripts are defined but not integrated into the test suite.The
synpress:metamask,synpress:phantom, andsynpress:buildscripts exist in package.json, and the corresponding setup files (e2e/wallet-setup/metamask.setup.tsande2e/wallet-setup/phantom.setup.ts) are fully implemented with synpress code. However, the wallet auth tests run with mock fixtures instead (fixtures-wallet-mockandfixtures-solana-mock), and the setup files are not referenced inplaywright.config.ts.Either document the purpose of these files and when they should be used, or remove them if they're no longer needed.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/next/package.json` around lines 37 - 39, The synpress wallet setup scripts ("synpress:metamask", "synpress:phantom", "synpress:build") and the setup files (e2e/wallet-setup/metamask.setup.ts, phantom.setup.ts) are orphaned because playwright.config.ts and the wallet tests still use mock fixtures (fixtures-wallet-mock, fixtures-solana-mock); either integrate these setup files into the test config or remove them and update package.json/docs. To fix: decide which approach to keep; if keeping synpress, add references to the setup files in playwright.config.ts (e.g., add projects or globalSetup entries that point to e2e/wallet-setup/metamask.setup.ts and phantom.setup.ts and switch tests to use those projects instead of fixtures-wallet-mock/fixtures-solana-mock), update test invocations to call the corresponding npm scripts, and document usage in the README; if removing, delete the two setup files and remove the three scripts from package.json and any README mentions so there are no unused artifacts.
- Add pnpm-workspace overrides for axios, glob, ws (Synpress), esbuild, lodash, lodash-es - Override vercel>@vercel/blob to 2.2.0 for patched undici in blob path - Override path-to-regexp to 6.3.0 - Remove undici override (breaks jsdom used by @repo/react tests) - Set audit-level=high (moderate undici vulns in @vercel/node until upstream fix) - Restore pnpm audit step in security workflow - Add osv-scanner ignores for undici (jsdom incompatible) and path-to-regexp - Update docs: README, scripts/README, security-check.mjs
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes & Improvements