Skip to content

[Fix] Flaky Neon, Email Delivery, and Other Tests#1235

Merged
nams1570 merged 4 commits intodevfrom
fix-neon-register-flaky-tests
Mar 10, 2026
Merged

[Fix] Flaky Neon, Email Delivery, and Other Tests#1235
nams1570 merged 4 commits intodevfrom
fix-neon-register-flaky-tests

Conversation

@nams1570
Copy link
Copy Markdown
Collaborator

@nams1570 nams1570 commented Mar 10, 2026

Summary of Changes

Just bumped up polling, removed unnecessary wait checks in tests that don't need them. Minor changes, not an exhaustive list of flaky test fixes

Note that importing a function into a file B that was exported from a test file A causes vitest to see all the tests in test file A as being under file B. This messes up CI and makes it harder to track failing tests.

Summary by CodeRabbit

  • Tests
    • Increased wait timeouts, polling and retry limits across end-to-end tests to improve reliability for email delivery and sign-in code flows.
    • Replaced several fixed waits with polling-based checks and clearer timeout errors for email delivery verification.
  • Refactor
    • Extracted and centralized integration provisioning helpers for reuse across tests.

Copilot AI review requested due to automatic review settings March 10, 2026 17:45
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 10, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
stack-auth-hosted-components Ready Ready Preview, Comment Mar 10, 2026 8:44pm
stack-backend Ready Ready Preview, Comment Mar 10, 2026 8:44pm
stack-dashboard Ready Ready Preview, Comment Mar 10, 2026 8:44pm
stack-demo Ready Ready Preview, Comment Mar 10, 2026 8:44pm
stack-docs Ready Ready Preview, Comment Mar 10, 2026 8:44pm

@nams1570 nams1570 requested a review from N2D4 March 10, 2026 17:45
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 10, 2026

📝 Walkthrough

Walkthrough

Increased polling and retry windows for e2e email/OTP flows, replaced several fixed waits with polling, added outboxEmails to OTP failure payloads, extracted integration provisioning helpers into new modules, and updated tests to import/use those helpers and pass noWaitForEmail where appropriate.

Changes

Cohort / File(s) Summary
OTP & backend helpers
apps/e2e/tests/backend/backend-helpers.ts
Increased OTP sign-in code retry loop from 30 → 40 and include outboxEmails (result of getOutboxEmails()) in error payload when code not found.
Outbox / email polling tests
apps/e2e/tests/backend/endpoints/api/v1/emails/outbox-api.test.ts, apps/e2e/tests/js/email.test.ts, apps/e2e/tests/helpers.ts
Replaced several fixed waits with polling loops; increased iteration caps (e.g., 20 → 50) and wait intervals (25ms → 100ms, slow template 500ms → 2000ms); mailbox retry limit 25 → 30; added timeout errors when outbox/email not sent within new limits.
Integration provisioning helpers (new)
apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/provision-helpers.ts, apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/provision-helpers.ts
Added provisionProject() helper modules that POST to respective provisioning endpoints using niceBackendFetch with test project payload and Basic auth header.
Integration tests — import updates
apps/e2e/tests/backend/endpoints/api/v1/integrations/*/projects/provision.test.ts, apps/e2e/tests/backend/endpoints/api/v1/integrations/*/projects/transfer.test.ts, apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/webhooks.test.ts
Removed in-file provisionProject() implementations and now import provisionProject from new provision-helpers modules; call sites unchanged.
Signup/no-wait adjustments in tests
apps/e2e/tests/backend/endpoints/api/v1/auth/passkey/register.test.ts, apps/e2e/tests/backend/endpoints/api/v1/integrations/*/projects/provision.test.ts
Updated test signups to pass { noWaitForEmail: true } to Auth.Password.signUpWithEmail() in several test cases.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • BilalG1
  • N2D4

Poem

🐇 "I hopped through tests both near and far,

I nudged the waits and tuned each timer star.
Helpers moved into neat little packs,
Polling patience fixed the flaky cracks.
Hokey mailboxes—now steady as a jar!"

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main focus of this PR—fixing flaky tests across multiple test suites by adjusting polling/retry thresholds and removing unnecessary waits.
Description check ✅ Passed The PR description covers the main changes (bumped polling, removed unnecessary waits) and mentions a critical Vitest issue affecting test attribution, but lacks structured detail matching the template format.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-neon-register-flaky-tests

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.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 10, 2026

Greptile Summary

This PR targets test flakiness in the e2e suite by bumping polling retry counts, increasing inter-poll delays, replacing fixed sleeps with adaptive polling loops, and refactoring provisionProject out of .test.ts files into dedicated provision-helpers.ts modules.

Key changes:

  • backend-helpers.ts / helpers.ts: retry limits increased (30→40 and 25→30) for sign-in code and mailbox polling.
  • outbox-api.test.ts: retry ceiling raised (20→50), per-poll waits increased (25ms→100ms), slowTemplate busy-wait increased (500ms→2000ms), and the post-unpause fixed wait raised (7s→10s). The final fixed wait after unpause still risks a race condition in slow CI environments.
  • email.test.ts: the hard-coded 10 s sleep is replaced with a 40-iteration polling loop (up to 20 s); the loop lacks an explicit timeout error, which could produce confusing failure messages.
  • provision-helpers.ts (neon + custom): correctly separates the shared provisionProject helper from the test file, fixing an anti-pattern where other test files imported from .test.ts modules.
  • register.test.ts / provision.test.ts: noWaitForEmail: true is added where email delivery is not exercised, appropriately skipping unnecessary waits.

Confidence Score: 4/5

  • Safe to merge — all changes are confined to the e2e test suite and do not affect production code.
  • Every change is in test files. The refactoring (helper extraction), retry bumps, and noWaitForEmail additions are all clearly correct and reduce flakiness. Two minor style concerns remain: the polling loop in email.test.ts lacks an explicit timeout error, and the post-unpause fixed wait in outbox-api.test.ts could still race on slow machines. Neither is a blocker.
  • apps/e2e/tests/js/email.test.ts and apps/e2e/tests/backend/endpoints/api/v1/emails/outbox-api.test.ts — both contain the polling / wait patterns worth hardening.

Important Files Changed

Filename Overview
apps/e2e/tests/js/email.test.ts Replaces a fixed 10 s wait with a polling loop; the loop lacks an explicit timeout error and uses any typing.
apps/e2e/tests/backend/endpoints/api/v1/emails/outbox-api.test.ts Increased retry counts (20→50), inter-poll waits (25ms→100ms), slow-template busy-wait (500ms→2000ms), and final unpause wait (7s→10s); the post-unpause fixed wait remains potentially flaky.
apps/e2e/tests/backend/backend-helpers.ts Bumped sign-in code message retry limit from 30 to 40 — safe, targeted fix for flakiness.
apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/provision-helpers.ts New helper file extracting provisionProject from the test file — correct refactor to avoid importing from .test.ts files.
apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/provision-helpers.ts New helper file extracting provisionProject from the test file — mirrors the Neon equivalent, clean separation of concerns.
apps/e2e/tests/backend/endpoints/api/v1/auth/passkey/register.test.ts Added noWaitForEmail: true to two signUpWithEmail calls where email delivery is irrelevant to the test.
apps/e2e/tests/helpers.ts Bumped maxRetries in waitForMessagesWithSubjectCount from 25 to 30 — straightforward flakiness reduction.
apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/provision.test.ts Removed inlined provisionProject and imports it from the new helper; added noWaitForEmail: true for the writability sign-up check.
apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/transfer.test.ts Import path updated from provision.test to provision-helpers — no logic change.
apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/webhooks.test.ts Import path updated from provision.test to provision-helpers — no logic change.
apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/transfer.test.ts Import path updated from provision.test to provision-helpers — no logic change.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Test: email.test.ts\nshould provide delivery statistics] --> B[sendEmail to user]
    B --> C{Poll loop\ni < 40 × 500 ms}
    C -->|stats.hour.sent >= 1| D[Assert capacity.penalty_factor\nAssert rate_per_second ≈ 2.7778\nAssert stats snapshot]
    C -->|exhausted — no explicit error| D

    E[Test: outbox-api.test.ts\npause/cancel email] --> F[Send email with\nslowTemplate 2000ms busy-wait]
    F --> G{Poll loop\ni < 50 × 100 ms}
    G -->|email found & PATCH paused| H[Assert paused state]
    G -->|exhausted| I[Assertions fail\nwith pauseSucceeded check]
    H --> J[Unpause email]
    J --> K[await wait 10 000ms fixed]
    K --> L[Assert status === sent]

    M[Import refactor] --> N[provision.test.ts\nno longer exports helper]
    N --> O[provision-helpers.ts\nneon + custom]
    O --> P[transfer.test.ts\nwebhooks.test.ts\nprovision.test.ts]
Loading

Last reviewed commit: 95a600a

Comment thread apps/e2e/tests/js/email.test.ts Outdated
Comment thread apps/e2e/tests/backend/endpoints/api/v1/emails/outbox-api.test.ts Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to reduce flakiness in the e2e suite by replacing fixed sleeps with polling, increasing retry budgets, and extracting shared “provision project” helpers for Neon/custom integration tests.

Changes:

  • Replaced a fixed wait in the email delivery stats test with polling, and loosened assertions around capacity rate precision.
  • Increased mailbox/email polling retries and timeouts in several backend e2e tests.
  • Extracted duplicated provisionProject helpers into dedicated *-helpers.ts modules and updated imports.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
apps/e2e/tests/js/email.test.ts Switches from fixed sleep to polling for delivery stats; adjusts assertions/snapshot scope.
apps/e2e/tests/helpers.ts Increases mailbox polling retry count.
apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/webhooks.test.ts Updates provisionProject import to shared helper module.
apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/transfer.test.ts Updates provisionProject import to shared helper module.
apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/provision.test.ts Uses shared helper; skips verification email wait during signup for reduced flakiness.
apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/provision-helpers.ts New shared helper for Neon project provisioning test setup.
apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/transfer.test.ts Updates provisionProject import to shared helper module.
apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/provision.test.ts Uses shared helper for custom project provisioning.
apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/provision-helpers.ts New shared helper for custom project provisioning test setup.
apps/e2e/tests/backend/endpoints/api/v1/emails/outbox-api.test.ts Increases polling budgets and extends slow-render template delay to reduce timing flakiness.
apps/e2e/tests/backend/endpoints/api/v1/auth/passkey/register.test.ts Skips verification email wait during signup to avoid mailbox timing dependency.
apps/e2e/tests/backend/backend-helpers.ts Increases OTP sign-in email polling attempts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/e2e/tests/js/email.test.ts Outdated
Comment thread apps/e2e/tests/backend/endpoints/api/v1/emails/outbox-api.test.ts
Comment thread apps/e2e/tests/backend/endpoints/api/v1/auth/passkey/register.test.ts Outdated
Comment thread apps/e2e/tests/backend/endpoints/api/v1/auth/passkey/register.test.ts Outdated
Copy link
Copy Markdown
Contributor

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/provision.test.ts (1)

120-120: ⚠️ Potential issue | 🟡 Minor

Test description refers to "neon" but this tests the custom integration endpoint.

The test description says "should fail if the neon client details are missing" but this file tests /api/v1/integrations/custom/projects/provision. This appears to be a copy-paste error from the Neon integration tests.

📝 Suggested fix
-it("should fail if the neon client details are missing", async ({ expect }) => {
+it("should fail if the client details are missing", async ({ expect }) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/provision.test.ts`
at line 120, The test title mistakenly references "neon" while testing the
custom integration endpoint; update the test's description string in the it(...)
call (currently `it("should fail if the neon client details are missing", ...)`)
to accurately describe the behavior for the custom integration (e.g., `should
fail if the custom integration client details are missing`), and scan nearby
tests in the same file for similar copy-paste titles to rename consistently.
🧹 Nitpick comments (1)
apps/e2e/tests/js/email.test.ts (1)

190-195: Consider adding a timeout error for explicit failure.

The polling loop exits silently if the email is never delivered within 40 iterations. While subsequent assertions will fail, an explicit timeout error would provide clearer diagnostics.

Also, consider adding a brief comment for the any type usage per coding guidelines.

💡 Suggested improvement
-  let info: any;
-  for (let i = 0; i < 40; i++) {
-    info = await serverApp.getEmailDeliveryStats();
-    if (info.stats.hour.sent >= 1) break;
-    await wait(500);
-  }
+  // Using `any` because getEmailDeliveryStats return type is complex and we're testing its structure
+  let info: any;
+  let delivered = false;
+  for (let i = 0; i < 40; i++) {
+    info = await serverApp.getEmailDeliveryStats();
+    if (info.stats.hour.sent >= 1) {
+      delivered = true;
+      break;
+    }
+    await wait(500);
+  }
+  expect(delivered).toBe(true);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/e2e/tests/js/email.test.ts` around lines 190 - 195, The polling loop
using info and serverApp.getEmailDeliveryStats() should throw a clear timeout
error if no emails are observed after the 40 iterations: after the loop, check
whether info?.stats?.hour?.sent >= 1 and if not, throw a descriptive error
(e.g., "Timed out waiting for email delivery after X ms/iterations") so test
failures are explicit; also add a brief inline comment explaining the use of the
any type for info (e.g., "info typed as any because response shape varies in E2E
test") or replace any with an appropriate type/interface to satisfy coding
guidelines.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/provision.test.ts`:
- Line 120: The test title mistakenly references "neon" while testing the custom
integration endpoint; update the test's description string in the it(...) call
(currently `it("should fail if the neon client details are missing", ...)`) to
accurately describe the behavior for the custom integration (e.g., `should fail
if the custom integration client details are missing`), and scan nearby tests in
the same file for similar copy-paste titles to rename consistently.

---

Nitpick comments:
In `@apps/e2e/tests/js/email.test.ts`:
- Around line 190-195: The polling loop using info and
serverApp.getEmailDeliveryStats() should throw a clear timeout error if no
emails are observed after the 40 iterations: after the loop, check whether
info?.stats?.hour?.sent >= 1 and if not, throw a descriptive error (e.g., "Timed
out waiting for email delivery after X ms/iterations") so test failures are
explicit; also add a brief inline comment explaining the use of the any type for
info (e.g., "info typed as any because response shape varies in E2E test") or
replace any with an appropriate type/interface to satisfy coding guidelines.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6ab4e177-fa1c-46bc-bdfa-55261ee9cfdb

📥 Commits

Reviewing files that changed from the base of the PR and between b701fdf and 95a600a.

📒 Files selected for processing (12)
  • apps/e2e/tests/backend/backend-helpers.ts
  • apps/e2e/tests/backend/endpoints/api/v1/auth/passkey/register.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/emails/outbox-api.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/provision-helpers.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/provision.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/transfer.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/provision-helpers.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/provision.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/transfer.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/webhooks.test.ts
  • apps/e2e/tests/helpers.ts
  • apps/e2e/tests/js/email.test.ts

Comment thread apps/e2e/tests/js/email.test.ts
Comment thread apps/e2e/tests/js/email.test.ts Outdated
Because provisionProject used to be exported from provision.test.ts, when the test failed in provision.test.ts, CI registered it as coming from webhooks.test.ts. This is obviously bad so we extract it to a shared helper.

The neon flaky test in provision.test.ts doesn't actually need to verify the email. Plus, there's a flag in the signUpWithEmail function that exists for precisely the purpose of skipping the check. This e2e test isn't related to sign up emails at all and they aren't part of the critical path.
Same issue with it checking if email has arrived when other tests in our test suite already do that. We also bump up number of retries to make any other tests that depend on this more robust
Bumping up number of attempts. Since it's polling with early exit, if it finds it early it exits. So the average case shouldn't change.
for email test switching to a polling approach is the right fix, like the todo says.
for outbox api it's dicier due to a race condition. We
Copy link
Copy Markdown
Contributor

@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: 1

🧹 Nitpick comments (2)
apps/e2e/tests/backend/endpoints/api/v1/emails/outbox-api.test.ts (2)

940-953: Fail fast on terminal non-sent states after unpausing.

This loop waits the full 25 seconds even if the email has already settled into a terminal state like skipped, or if the refetch itself stops succeeding. That makes CI slower and hides the actual regression behind a timeout.

♻️ Suggested shape
       // Poll until the email is sent (since we unpaused it)
       for (let i = 0; ; i++) {
         const finalGetResponse = await niceBackendFetch(`/api/v1/emails/outbox/${emailId}`, {
           method: "GET",
           accessType: "server",
         });
-        if (finalGetResponse.body.status === "sent") break;
+        if (finalGetResponse.status !== 200) {
+          throw new StackAssertionError("Failed to refetch email after unpause", {
+            response: finalGetResponse,
+          });
+        }
+        if (finalGetResponse.body.status === "sent") break;
+        if (finalGetResponse.body.status === "skipped") {
+          throw new StackAssertionError("Email reached a terminal state after unpause", {
+            response: finalGetResponse.body,
+          });
+        }
         if (i >= 50) {
           throw new StackAssertionError(`Timed out waiting for email to be sent after unpause`, {
-            status: finalGetResponse.body.status,
+            response: finalGetResponse.body,
           });
         }
         await wait(500);
       }
As per coding guidelines, "Fail early, fail loud. Fail fast with an error instead of silently continuing."
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/e2e/tests/backend/endpoints/api/v1/emails/outbox-api.test.ts` around
lines 940 - 953, The polling loop that checks finalGetResponse.body.status after
unpausing should fail fast on terminal non-"sent" states or on a failed refetch
instead of waiting the full retry window; update the loop around the
niceBackendFetch call (the for loop using emailId, finalGetResponse, wait) to
immediately throw a StackAssertionError when the fetch fails or when
finalGetResponse.body.status is a terminal state (e.g., "skipped", "failed",
"cancelled" — include the status in the error), and keep the existing timeout
fallback only for non-terminal transient states.

887-916: Throw an explicit timeout error from these pause loops.

If the email never becomes pausable, both tests fall through to a generic expect(pauseSucceeded).toBe(true) failure and lose the last outbox state. Please use the same StackAssertionError + outboxEmails pattern you already added around Line 673 so these flakes stay debuggable.

♻️ Suggested shape
       for (let i = 0; i < 50; i++) {
         const listResponse = await niceBackendFetch("/api/v1/emails/outbox", {
           method: "GET",
           accessType: "server",
         });
         const emails = listResponse.body.items.filter((e: any) => e.to?.user_id === userId);

         if (emails.length > 0) {
           emailId = emails[0].id;
           // Try to pause it
           const pauseResponse = await niceBackendFetch(`/api/v1/emails/outbox/${emailId}`, {
             method: "PATCH",
             accessType: "server",
             body: {
               is_paused: true,
             },
           });

           if (pauseResponse.status === 200 && pauseResponse.body.status === "paused") {
             pauseSucceeded = true;
             break;
           }
         }

         await wait(100);
       }

-      expect(emailId).not.toBeNull();
-      expect(pauseSucceeded).toBe(true);
+      if (!pauseSucceeded || emailId == null) {
+        throw new StackAssertionError("Timeout waiting to pause email", {
+          outboxEmails: await getOutboxEmails(),
+          userId,
+        });
+      }
As per coding guidelines, "Fail early, fail loud. Fail fast with an error instead of silently continuing."

Also applies to: 1008-1037

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/e2e/tests/backend/endpoints/api/v1/emails/outbox-api.test.ts` around
lines 887 - 916, The pause loop that polls /api/v1/emails/outbox (using
niceBackendFetch) must throw an explicit timeout StackAssertionError with the
current outboxEmails snapshot if it never finds a pausable email; replace the
final generic expect(pauseSucceeded).toBe(true) failure with the same pattern
used around Line 673 (create and throw new StackAssertionError with a
descriptive message and include outboxEmails), and do the same for the second
loop (lines 1008-1037) so tests fail fast and include the last observed outbox
state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/e2e/tests/js/email.test.ts`:
- Around line 190-198: The polling loop currently only waits for
info.stats.hour.sent to become 1 but later asserts day/week/month counters too,
causing flakiness; update the loop that calls serverApp.getEmailDeliveryStats()
to break only when all asserted counters match (e.g., info.stats.hour.sent === 1
&& info.stats.day.sent === 1 && info.stats.week.sent === 1 &&
info.stats.month.sent === 1), keep the existing timeout/throw behavior, and
return the final info value from the loop so the subsequent assertions use the
polled result (removing the implicit any).

---

Nitpick comments:
In `@apps/e2e/tests/backend/endpoints/api/v1/emails/outbox-api.test.ts`:
- Around line 940-953: The polling loop that checks finalGetResponse.body.status
after unpausing should fail fast on terminal non-"sent" states or on a failed
refetch instead of waiting the full retry window; update the loop around the
niceBackendFetch call (the for loop using emailId, finalGetResponse, wait) to
immediately throw a StackAssertionError when the fetch fails or when
finalGetResponse.body.status is a terminal state (e.g., "skipped", "failed",
"cancelled" — include the status in the error), and keep the existing timeout
fallback only for non-terminal transient states.
- Around line 887-916: The pause loop that polls /api/v1/emails/outbox (using
niceBackendFetch) must throw an explicit timeout StackAssertionError with the
current outboxEmails snapshot if it never finds a pausable email; replace the
final generic expect(pauseSucceeded).toBe(true) failure with the same pattern
used around Line 673 (create and throw new StackAssertionError with a
descriptive message and include outboxEmails), and do the same for the second
loop (lines 1008-1037) so tests fail fast and include the last observed outbox
state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d94d47a5-75ad-4484-900d-24ca344ef31d

📥 Commits

Reviewing files that changed from the base of the PR and between 95a600a and 9230513.

📒 Files selected for processing (12)
  • apps/e2e/tests/backend/backend-helpers.ts
  • apps/e2e/tests/backend/endpoints/api/v1/auth/passkey/register.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/emails/outbox-api.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/provision-helpers.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/provision.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/transfer.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/provision-helpers.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/provision.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/transfer.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/webhooks.test.ts
  • apps/e2e/tests/helpers.ts
  • apps/e2e/tests/js/email.test.ts
🚧 Files skipped from review as they are similar to previous changes (7)
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/transfer.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/provision.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/custom/projects/provision-helpers.ts
  • apps/e2e/tests/helpers.ts
  • apps/e2e/tests/backend/backend-helpers.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/transfer.test.ts
  • apps/e2e/tests/backend/endpoints/api/v1/integrations/neon/projects/provision-helpers.ts

Comment thread apps/e2e/tests/js/email.test.ts
@nams1570 nams1570 merged commit aeb5f77 into dev Mar 10, 2026
41 checks passed
@nams1570 nams1570 deleted the fix-neon-register-flaky-tests branch March 10, 2026 21:02
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.

3 participants