Skip to content

Add validation tests for create stream – duration minimum and amount … - #658

Open
nanaabdul1172 wants to merge 2 commits into
ritik4ever:mainfrom
nanaabdul1172:Validation-tests
Open

Add validation tests for create stream – duration minimum and amount …#658
nanaabdul1172 wants to merge 2 commits into
ritik4ever:mainfrom
nanaabdul1172:Validation-tests

Conversation

@nanaabdul1172

@nanaabdul1172 nanaabdul1172 commented Jul 25, 2026

Copy link
Copy Markdown

closes #316
✅ Boundary Tests Added
Duration Validation (lines 621-660):

durationSeconds = 59 → Returns 400 with "durationSeconds must be at least 60 seconds"
durationSeconds = 60 → Returns 201 (boundary passes) ✓
Amount Precision Validation (lines 663-743):

totalAmount = 0.0000001 (1 stroop) → Returns 201 (valid minimum) ✓
totalAmount = 0 → Returns 400 with "Amount must be greater than zero"
totalAmount = 100.12345678 (8 decimals) → Returns 400 with "Amount cannot have more than 7 decimal places"
totalAmount = 100.1234567 (7 decimals) → Returns 201 (maximum precision accepted) ✓
✅ Acceptance Criteria Met
✅ Duration boundary (59 vs 60) is tested explicitly
✅ Stroop-level minimum amount (0.0000001) is accepted
✅ More than 7 decimal places is rejected with clear message
✅ Zero amount is rejected with appropriate error
Additional Work
Fixed a syntax error in
index.ts
where duplicate code was preventing compilation
Tests are well-organized under nested describe blocks for easy maintenance
All tests follow the existing pattern with proper assertions for status codes, error codes, and error messages

Summary by CodeRabbit

  • New Features

    • Added stricter validation for stream duration and payment amounts, including support for the minimum valid values and precise decimal handling.
  • Bug Fixes

    • Improved recipient stream filtering by status, sender, asset, and asset code.
    • Corrected validation responses for invalid durations, zero amounts, and overly precise amounts.
  • Documentation

    • Added documentation covering stream validation boundary cases and expected API responses.

@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown

@nanaabdul1172 is attempting to deploy a commit to the ritik4ever's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Jul 25, 2026

Copy link
Copy Markdown

@nanaabdul1172 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (1)
  • backend/package-lock.json is excluded by !**/package-lock.json

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a78adc24-c9a1-4038-84f9-da85a5d3ffff

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR adds boundary tests and documentation for POST /api/streams duration and amount validation, and updates recipient stream filtering expressions while preserving their matching behavior.

Changes

Stream validation coverage

Layer / File(s) Summary
Boundary validation tests and documentation
backend/src/index.test.ts, BOUNDARY_TESTS_SUMMARY.md
Tests and documents duration limits, minimum positive amounts, zero rejection, and Stellar precision limits for POST /api/streams.

Recipient stream filtering

Layer / File(s) Summary
Recipient filter expression update
backend/src/index.ts
Restructures status, sender, asset, and assetCode filtering expressions while retaining existing comparison and case-handling behavior.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: alexatsejames-alt

🚥 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 is concise and reflects the main change: adding validation tests for create stream duration and amount boundaries.
Linked Issues check ✅ Passed The boundary tests cover all requested cases: 59/60 seconds, stroop-level minimum amount, zero rejection, and >7 decimal precision rejection.
Out of Scope Changes check ✅ Passed The code changes align with the test-boundary work, and the extra index.ts compilation fix appears ancillary to making the suite build.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

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

Inline comments:
In `@backend/src/index.test.ts`:
- Around line 663-742: The totalAmountSchema decimal-place check is bypassed by
scientific notation, allowing sub-stroop values such as 0.00000001. Replace the
string-based precision check with stroop-scale/decimal-safe validation, add a
rejection test in backend/src/index.test.ts for that sub-stroop value, and
update BOUNDARY_TESTS_SUMMARY.md at lines 36-40 to reflect coverage only after
the new case is included.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a95ca4be-b2e7-4f49-bd75-3c1c0d4467a8

📥 Commits

Reviewing files that changed from the base of the PR and between b3d32c1 and b036bb1.

⛔ Files ignored due to path filters (2)
  • backend/package-lock.json is excluded by !**/package-lock.json
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (3)
  • BOUNDARY_TESTS_SUMMARY.md
  • backend/src/index.test.ts
  • backend/src/index.ts

Comment thread backend/src/index.test.ts
Comment on lines +663 to +742
it("returns 201 when totalAmount is 0.0000001 (1 stroop - minimum valid)", async () => {
const response = await request(app)
.post("/api/streams")
.set("Authorization", "Bearer mock_token")
.send({
sender: SENDER_A,
recipient: RECIPIENT_1,
assetCode: "USDC",
totalAmount: 0.0000001,
durationSeconds: 120,
});

expect(response.status).toBe(201);
expect(response.body.data).toMatchObject({
totalAmount: 0.0000001,
});
});

it("returns 400 when totalAmount is 0", async () => {
const response = await request(app)
.post("/api/streams")
.set("Authorization", "Bearer mock_token")
.send({
sender: SENDER_A,
recipient: RECIPIENT_1,
assetCode: "USDC",
totalAmount: 0,
durationSeconds: 120,
});

expect(response.status).toBe(400);
expect(response.body.code).toBe("VALIDATION_ERROR");
expect(response.body.error).toContain("Amount must be greater than zero");
expect(response.body.details).toEqual(
expect.arrayContaining([
expect.objectContaining({ field: "totalAmount" }),
]),
);
});

it("returns 400 when totalAmount has more than 7 decimal places", async () => {
const response = await request(app)
.post("/api/streams")
.set("Authorization", "Bearer mock_token")
.send({
sender: SENDER_A,
recipient: RECIPIENT_1,
assetCode: "USDC",
totalAmount: 100.12345678, // 8 decimal places
durationSeconds: 120,
});

expect(response.status).toBe(400);
expect(response.body.code).toBe("VALIDATION_ERROR");
expect(response.body.error).toContain("Amount cannot have more than 7 decimal places");
expect(response.body.details).toEqual(
expect.arrayContaining([
expect.objectContaining({ field: "totalAmount" }),
]),
);
});

it("returns 201 when totalAmount has exactly 7 decimal places", async () => {
const response = await request(app)
.post("/api/streams")
.set("Authorization", "Bearer mock_token")
.send({
sender: SENDER_A,
recipient: RECIPIENT_1,
assetCode: "USDC",
totalAmount: 100.1234567, // exactly 7 decimal places
durationSeconds: 120,
});

expect(response.status).toBe(201);
expect(response.body.data).toMatchObject({
totalAmount: 100.1234567,
});
});
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

What does JavaScript Number.prototype.toString()return for0.00000001, and when does it use exponential notation?

💡 Result:

For the number 0.00000001 (which is 10⁻⁸), JavaScript's Number.prototype.toString returns the string "1e-8" [1][2]. Exponential (scientific) notation is used by Number.prototype.toString when the radix is 10 and the absolute value of the number is either greater than or equal to 10²¹ or strictly less than 10⁻⁶ [1][3]. Specifically, the ECMAScript specification defines this behavior based on the exponent n in the number's representation [4][5]. When formatting a number in base 10, if the number cannot be represented without exceeding the range -5 to 21 for the exponent n, the engine switches to exponential notation [4][5]. In summary: - Result for 0.00000001: "1e-8" [1][2] - Threshold for exponential notation: magnitude < 10⁻⁶ or ≥ 10²¹ [1][3]

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Locate relevant files"
git ls-files | rg '(^|/)schemas\.ts$|(@|^|/)index\.test\.ts$|BOUNDARY_TESTS_SUMMARY\.md$|backend/src/validation' || true

echo
echo "Search decimal validation symbols"
rg -n "Amount cannot have more than 7 decimal places|decimal places|totalAmountSchema|totalAmount" backend/src validation BOUNDARY_TESTS_SUMMARY.md 2>/dev/null || true

echo
echo "Candidate schema/test summary"
for f in backend/src/validation/schemas.ts backend/src/index.test.ts BOUNDARY_TESTS_SUMMARY.md; do
  if [ -f "$f" ]; then
    echo "===== $f ====="
    wc -l "$f"
    if [ "$f" = "backend/src/validation/schemas.ts" ]; then
      ast-grep outline "$f" --match totalAmountSchema --view expanded || true
      sed -n '1,220p' "$f" | cat -n
    elif [ "$f" = "backend/src/index.test.ts" ]; then
      sed -n '620,760p' "$f" | cat -n
    elif [ "$f" = "BOUNDARY_TESTS_SUMMARY.md" ]; then
      sed -n '1,80p' "$f" | cat -n
    fi
  fi
done

Repository: ritik4ever/stellar-stream

Length of output: 34506


🏁 Script executed:

#!/bin/bash
set -euo pipefail

node - <<'JS'
const values = [0.00000001, 0.0000001, 100.12345678, 100.1234567, 0, 100];
for (const v of values) {
  const parts = String(v).split(".");
  const decimalStr = parts[1];
  console.log(JSON.stringify({ value: v, string: String(v), decimalStr, passes: !decimalStr || decimalStr.length <= 7 }));
}
JS

echo
echo "Relevant schema/validation tests"
sed -n '34,44p' backend/src/validation/schemas.ts | cat -n
sed -n '236,248p' backend/src/validation/schemas.test.ts | cat -n
sed -n '296,312p' backend/src/validation/schemas.test.ts | cat -n

Repository: ritik4ever/stellar-stream

Length of output: 2371


Cover the scientific-notation precision bypass.

totalAmountSchema counts decimal places with value.toString().split(".")[1]; 0.00000001 becomes 1e-8, which has no fractional substring and passes the “no more than 7 decimal places” check. Add a sub-stroop rejection case and switch the schema to stroop-scale/decimal-safe validation; update BOUNDARY_TESTS_SUMMARY.md where it claims >7 decimal precision is fully rejected until that case is covered.

📍 Affects 2 files
  • backend/src/index.test.ts#L663-L742 (this comment)
  • BOUNDARY_TESTS_SUMMARY.md#L36-L40
🤖 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 `@backend/src/index.test.ts` around lines 663 - 742, The totalAmountSchema
decimal-place check is bypassed by scientific notation, allowing sub-stroop
values such as 0.00000001. Replace the string-based precision check with
stroop-scale/decimal-safe validation, add a rejection test in
backend/src/index.test.ts for that sub-stroop value, and update
BOUNDARY_TESTS_SUMMARY.md at lines 36-40 to reflect coverage only after the new
case is included.

@ritik4ever

Copy link
Copy Markdown
Owner

Hi @nanaabdul1172,

This PR could not be merged because it has merge conflicts with the target branch.

Please resolve the merge conflicts, push the updated changes, and the PR can be reviewed and merged.

Thank you!

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.

Title: Add validation tests for create stream – duration minimum and amount precision

2 participants