Skip to content

test(wasm-sdk): fix flaky tokenPaymentInfo document balance assertions#3771

Merged
shumkov merged 2 commits into
v3.1-devfrom
claude/quizzical-nobel-2774e2
Jun 2, 2026
Merged

test(wasm-sdk): fix flaky tokenPaymentInfo document balance assertions#3771
shumkov merged 2 commits into
v3.1-devfrom
claude/quizzical-nobel-2774e2

Conversation

@QuantumExplorer
Copy link
Copy Markdown
Member

@QuantumExplorer QuantumExplorer commented May 31, 2026

Issue being fixed or feature implemented

The nightly Tests workflow (Packages functional tests / Run functional testsRun WASM SDK functional tests) has been failing intermittently for several scheduled runs, e.g. run 26697658517.

The failures are in the tokenPaymentInfo document flow tests in packages/wasm-sdk/tests/functional/transitions/documents.spec.ts. They are flaky, not deterministic — different nightly runs fail on different lines with different stale values:

  • 2026-05-30: line 592 expected 911n to equal 916n, line 619 expected 916n to equal 917n
  • 2026-05-29: line 539 expected 45n to equal 41n, line 619 expected 905n to equal 917n

These tests pass on push-triggered runs only because the changed-package gating skips the WASM SDK functional suite there; the scheduled run exercises everything.

What was done?

Root cause: each balance check was a single proof-verified getIdentityTokenBalances read taken immediately after a document state transition. That balance proof can be served by a node whose view briefly lags the block that committed the transition, so an immediate read intermittently returns a stale balance. The existing waitForPlatform() sleep sat after the assertions, so it never protected them.

Replaced the immediate expect(await getSingleTokenBalance(...)).to.equal(x) assertions with a new expectTokenBalance(...) helper that polls the balance until it converges to the expected value (500ms interval, 30s timeout) before asserting. On a clean read it returns immediately; under lag it waits instead of failing.

How Has This Been Tested?

Change is test-only and mechanical (assertion sites rewritten to the polling helper; the expected values are unchanged). The expected balances were already correct — the suite passes on most runs — so converging on them removes the read-after-write race. Verified the full diff; no production code is touched.

Breaking Changes

None.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests
    • Improved reliability of token-balance checks in document/payment-flow tests by switching to a polling-based verification to handle timing variations after state transitions.
    • Updated test assertions and expected post-transition token amounts for all involved parties (seller, buyer, third-party) to reflect finalized balances.

The tokenPaymentInfo document-flow tests asserted on a single proof-verified
token-balance read taken immediately after a state transition. Those reads can
be served by a node whose view briefly lags the block that committed the
transition, so the nightly functional run failed intermittently on different
lines with stale balances. Replace the immediate assertions with a polling
helper that retries until the balance converges (or times out).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@QuantumExplorer QuantumExplorer requested a review from shumkov as a code owner May 31, 2026 04:50
@github-actions github-actions Bot added this to the v3.1.0 milestone May 31, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 31, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6021212d-8f16-45ea-8d73-b4e4f7ce23e7

📥 Commits

Reviewing files that changed from the base of the PR and between beced7f and 96dc5f6.

📒 Files selected for processing (1)
  • packages/wasm-sdk/tests/functional/transitions/documents.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/wasm-sdk/tests/functional/transitions/documents.spec.ts

📝 Walkthrough

Walkthrough

Adds a polling helper expectTokenBalance(...) that repeatedly reads identity token balances until they match an expected bigint, and replaces immediate token-balance assertions across document create/replace/transfer/delete/price/purchase tests with polling-based checks.

Changes

Token Balance Polling in Document Tests

Layer / File(s) Summary
Polling helper for token balance verification
packages/wasm-sdk/tests/functional/transitions/documents.spec.ts
Introduces expectTokenBalance helper that repeatedly reads identity token balances at intervals until the expected value is observed or timeout expires.
Update token balance assertions to use polling
packages/wasm-sdk/tests/functional/transitions/documents.spec.ts
Replaces twelve sets of immediate token-balance assertions with expectTokenBalance(...) calls across document creation, replacement, transfer, deletion, pricing, and purchase flows for seller, buyer, and third-party identities.

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • shumkov

"I hop and wait by platform gates,
Polling balances, counting paces,
Seller, buyer, third friend too —
Proofs align, the numbers true 🐇✨"

🚥 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 title clearly and specifically describes the main change: fixing flaky token balance assertions in WASM SDK tests by replacing immediate assertions with a polling helper.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/quizzical-nobel-2774e2

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.

@thepastaclaw
Copy link
Copy Markdown
Collaborator

thepastaclaw commented May 31, 2026

✅ Review complete (commit 96dc5f6)

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.

🧹 Nitpick comments (1)
packages/wasm-sdk/tests/functional/transitions/documents.spec.ts (1)

36-49: ⚡ Quick win

Consider enhancing timeout error message for easier debugging.

The helper correctly polls until the balance converges or timeout expires. However, when a timeout occurs, the subsequent expect(actual).to.equal(expected) assertion doesn't indicate that polling happened or how long it took. This can make debugging flaky tests more difficult, especially if getSingleTokenBalance returns undefined.

♻️ Proposed enhancement with descriptive timeout error
 const expectTokenBalance = async (
   identityId: string,
   tokenId: string,
   expected: bigint,
   { timeoutMs = 30000, intervalMs = 500 } = {},
 ) => {
   const deadline = Date.now() + timeoutMs;
+  const startTime = Date.now();
   let actual = await getSingleTokenBalance(identityId, tokenId);
   while (actual !== expected && Date.now() < deadline) {
     await new Promise((resolve) => { setTimeout(resolve, intervalMs); });
     actual = await getSingleTokenBalance(identityId, tokenId);
   }
-  expect(actual).to.equal(expected);
+  expect(actual).to.equal(
+    expected,
+    `Token balance did not converge after ${Date.now() - startTime}ms (expected: ${expected}, actual: ${actual})`,
+  );
 };
🤖 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 `@packages/wasm-sdk/tests/functional/transitions/documents.spec.ts` around
lines 36 - 49, The expectTokenBalance helper currently retries via
getSingleTokenBalance but on timeout the plain expect(actual).to.equal(expected)
offers no context; update expectTokenBalance to throw or assert with a
descriptive message when the deadline is exceeded (include identityId, tokenId,
expected, actual, timeoutMs and elapsed time) so test failures show that polling
timed out and the last observed value and duration; keep the polling loop and
only replace the final expect call with an assertion that includes this
contextual message (referencing expectTokenBalance and getSingleTokenBalance to
locate the change).
🤖 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.

Nitpick comments:
In `@packages/wasm-sdk/tests/functional/transitions/documents.spec.ts`:
- Around line 36-49: The expectTokenBalance helper currently retries via
getSingleTokenBalance but on timeout the plain expect(actual).to.equal(expected)
offers no context; update expectTokenBalance to throw or assert with a
descriptive message when the deadline is exceeded (include identityId, tokenId,
expected, actual, timeoutMs and elapsed time) so test failures show that polling
timed out and the last observed value and duration; keep the polling loop and
only replace the final expect call with an assertion that includes this
contextual message (referencing expectTokenBalance and getSingleTokenBalance to
locate the change).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 29bc5a1c-7199-4daf-92e5-aa6ea126e3c2

📥 Commits

Reviewing files that changed from the base of the PR and between 40f11b2 and beced7f.

📒 Files selected for processing (1)
  • packages/wasm-sdk/tests/functional/transitions/documents.spec.ts

Copy link
Copy Markdown
Collaborator

@thepastaclaw thepastaclaw left a comment

Choose a reason for hiding this comment

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

Code Review

Test-only change replaces immediate token-balance assertions with a 30s/500ms polling helper to address a documented read-after-write race in token balance proofs. Both agents found no in-scope defects. CodeRabbit's nitpick about the unhelpful timeout failure message is valid but low-priority and does not block.

💬 1 nitpick(s)

Comment thread packages/wasm-sdk/tests/functional/transitions/documents.spec.ts
Comment thread packages/wasm-sdk/tests/functional/transitions/documents.spec.ts
@shumkov shumkov self-assigned this Jun 1, 2026
A timeout in the balance-convergence poll is the most likely failure mode,
but it previously surfaced as a bare equality mismatch with no context.
Attach the identity, token, expected value, elapsed time, and last read to
the assertion message so a flaky CI failure is triageable from the log.

Addresses CodeRabbit/thepastaclaw review nitpick on #3771; polling logic
unchanged.

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

@thepastaclaw thepastaclaw left a comment

Choose a reason for hiding this comment

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

Code Review

Latest delta is a one-commit, test-only follow-up that adds triage context to the expectTokenBalance timeout assertion in packages/wasm-sdk/tests/functional/transitions/documents.spec.ts. The prior nitpick from beced7f is FIXED in substance: timeout failures now include identityId, tokenId, expected value, elapsed ms, and last observed value. No new in-scope defects were identified at HEAD 96dc5f6; both Claude and Codex agree.

Copy link
Copy Markdown
Collaborator

@shumkov shumkov left a comment

Choose a reason for hiding this comment

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

Kept the polling helper (mirrors the platform test suite's waitForBalanceToChange) over a larger waitForPlatform sleep — the SDK already waits for ST execution, so the flake is a post-commit cross-node read lag that polling rides out without paying a fixed wait on every read. Nitpick about timeout triage context addressed in 96dc5f6. Approving.

@shumkov shumkov merged commit ebac70c into v3.1-dev Jun 2, 2026
20 checks passed
@shumkov shumkov deleted the claude/quizzical-nobel-2774e2 branch June 2, 2026 10:46
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