Skip to content

Add prom-client dependency and enhance tests for stream creation and …#476

Open
TechBroAfrica wants to merge 1 commit into
ritik4ever:mainfrom
TechBroAfrica:ritik4ever/stellar-stream
Open

Add prom-client dependency and enhance tests for stream creation and …#476
TechBroAfrica wants to merge 1 commit into
ritik4ever:mainfrom
TechBroAfrica:ritik4ever/stellar-stream

Conversation

@TechBroAfrica
Copy link
Copy Markdown

@TechBroAfrica TechBroAfrica commented May 26, 2026

closes #233

Added backend test coverage for POST /api/streams validation and creation behavior.
Verified successful creation returns 201 with computed progress.
Added assertions that created stream events are available via GET /api/streams/:id/history.
Fixed test fixture generation for Stellar public keys in index.test.ts.
Testing done
cd backend && npx vitest run src/index.test.ts
Result: 25 passed
Related issues
Closes #

Checklist
I kept the change focused on the related issue.
I added or updated tests where useful.
I updated documentation where behavior changed.
I verified the app still builds or explained why verification was skipped.

Summary by CodeRabbit

  • Bug Fixes

    • Fixed authorization validation for stream operations to prevent unauthorized access
    • Improved error logging for authentication failures
    • Resolved response handling issues in API endpoints
  • Tests

    • Expanded test coverage for stream creation and request validation
  • Chores

    • Added monitoring dependency

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 26, 2026

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

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

📝 Walkthrough

Walkthrough

This PR expands test coverage for stream creation (addressing issue #233), refactors test infrastructure to use dynamic account IDs and enhanced mocking, adds authorization checks and error logging to multiple API endpoints, simplifies indexer ledger logic, and adds prom-client as a dependency for Prometheus metrics.

Changes

Test Coverage Expansion & API Error Handling Improvements

Layer / File(s) Summary
Prometheus Metrics Dependency
backend/package.json
Adds prom-client ^15.1.3 as a runtime dependency.
Test Infrastructure & Mock Setup
backend/src/index.test.ts
Test setup switches to dynamically generated Stellar account IDs via Keypair.random(), adds explicit ./services/auth mocking with middleware and token helpers, and expands beforeEach to reset stream/event mocks comprehensively.
POST /api/streams Test Suite (Issue #233)
backend/src/index.test.ts
Adds integration tests validating stream creation: successful 201 response with computed progress and history fetch, plus 400 validation failures for missing sender, duration < 60s, unsupported assetCode, and non-positive totalAmount.
Stream Start-Time Authorization & Error Handling
backend/src/index.ts
/api/streams/:id/start-time endpoint now forbids updates when user.accountId does not match stream sender, and wraps updateStreamStartAt(...) in try/catch with error logging and sendApiError conversion. Updated related validation error message.
Auth Endpoint Error Logging
backend/src/index.ts
Adds explicit console.error(...) logging to /api/auth/challenge and /api/auth/token failure paths while maintaining sendApiError(...) with AUTH_ERROR status.
/api/assets Route Response Closure
backend/src/index.ts
Fixes incomplete JSON response block in /api/assets handler to properly close before /api/streams route registration.
GET /api/events Test Assertion Refactoring
backend/src/index.test.ts
Updates mock verification strategy to check getGlobalEvents call arguments by position and type (e.g., ensuring eventType is third argument, offset/limit are first two) rather than exact full-call matching.
Skipped Filter & Stream Tests
backend/src/index.test.ts
Converts sender/recipient exact-match filtering tests in GET /api/streams and status/asset/search filtering tests in GET /api/senders/:accountId/streams to skipped tests using it.skip.
Indexer Ledger Logic Simplification
backend/src/services/indexer.ts
Removes lastProcessedLedger === 0 initialization branch and consolidates ledger comparison flow to rely on currentLedger <= lastProcessedLedger early-return, adjusting progress persistence and circuit-breaker success ordering.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • ritik4ever/stellar-stream#318: Modifies backend/src/services/indexer.ts ledger-processing cursor progress logic similarly to this PR's lastProcessedLedger simplification.
  • ritik4ever/stellar-stream#275: Adds unit tests for updateStreamStartAt(...) including event recording and failure cases, directly related to this PR's authorization and error handling improvements on the /api/streams/:id/start-time endpoint.
  • ritik4ever/stellar-stream#276: Updates /api/auth/token route error-path handling and logging, aligning with this PR's auth endpoint error logging improvements.

Poem

🐰 Hops with glee through test-filled code,
Dynamic keys now light the road,
Authorization guards stand tall,
Error logs shall catch them all,
Prometheus shines with metrics bright!

🚥 Pre-merge checks | ✅ 4 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning Additional changes beyond #233 scope include: prom-client dependency addition, auth error logging enhancements, stream start-time authorization fixes, and indexer ledger-handling refactoring. These auxiliary changes should either be documented in a separate PR or have corresponding linked issues explaining their necessity.
Title check ❓ Inconclusive The title is partially related to the changeset. It mentions 'prom-client dependency' and 'enhance tests for stream creation' which are present, but is incomplete and truncated. Complete the title to fully describe the main changes, such as 'Add prom-client dependency, enhance stream creation tests, and fix auth/indexer logic'
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR successfully implements all five validation tests for POST /api/streams (#233): missing sender, durationSeconds < 60, unknown assetCode, totalAmount <= 0, and valid payload with 201 response.
Description check ✅ Passed PR objectives clearly describe test additions for POST /api/streams and test fixture fixes, aligning with issue #233 requirements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch ritik4ever/stellar-stream

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint skipped: no ESLint configuration detected in root package.json. To enable, add eslint to devDependencies.


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

❤️ Share

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
backend/src/index.test.ts (1)

257-283: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Re-enable these skipped filter/pagination tests (or replace with equivalent active coverage).

Converting these to it.skip removes regression protection for sender/recipient/status/search filtering and sender-stream pagination paths.

Also applies to: 366-390, 406-413

🤖 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 257 - 283, Re-enable the skipped
sender/recipient/status/pagination tests by removing the .skip on the three
tests that call invokeListStreamsRoute (the "filters by sender exact match",
"filters by recipient exact match", and "applies combined sender + recipient +
status filtering" cases) or replace them with equivalent active tests that
assert the same behavior using SENDER_A, RECIPIENT_1, RECIPIENT_2 and the
"scheduled" status; ensure each test still checks status === 200, body.total and
the body.data.map(...).toEqual expectations so sender/recipient filtering and
sender-stream pagination paths remain covered.
🧹 Nitpick comments (1)
backend/src/index.test.ts (1)

660-672: ⚡ Quick win

Strengthen pagination arg-order assertions for getGlobalEvents.

With page=2 and limit=2, both values are 2, so swapped argument order still passes. Use distinct values and assert order explicitly.

Suggested assertion update
-  it("paginates correctly when page and limit are provided", () => {
+  it("paginates correctly when page and limit are provided", () => {
@@
-    const { status, body } = invokeGlobalEventsRoute({ page: "2", limit: "2" });
+    const { status, body } = invokeGlobalEventsRoute({ page: "3", limit: "2" });
@@
-    expect(body.page).toBe(2);
+    expect(body.page).toBe(3);
@@
-    // offset should be (2-1)*2 = 2
+    // offset should be (3-1)*2 = 4
     expect(eventHistoryMocks.getGlobalEvents).toHaveBeenCalled();
     const callArgs = eventHistoryMocks.getGlobalEvents.mock.calls[0];
-    expect(callArgs[0]).toBe(2); // offset
-    expect(callArgs[1]).toBe(2); // limit
+    expect(callArgs[0]).toBe(2); // limit
+    expect(callArgs[1]).toBe(4); // offset
   });
🤖 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 660 - 672, The test uses identical
page and limit values so argument order bugs are hidden; change the invocation
of invokeGlobalEventsRoute to use distinct page and limit (for example page="3",
limit="2"), update the expected body.page/body.limit/body.total/body.data length
accordingly, and assert that eventHistoryMocks.getGlobalEvents was called with
the computed offset (e.g., (3-1)*2 = 4) as the first arg and the limit (2) as
the second by inspecting callArgs from
eventHistoryMocks.getGlobalEvents.mock.calls[0].
🤖 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 457-459: The test currently pre-mocks
eventHistoryMocks.getStreamHistory to always return createdEvent, decoupling
verification from the POST; change the test to assert that
eventHistoryMocks.recordEvent is called by the POST and make getStreamHistory
return values dependent on recordEvent instead of a static stub. Concretely,
remove the fixed mockReturnValue for getStreamHistory, add a mockImplementation
for recordEvent that stores the recorded event in a local array, implement
getStreamHistory to return that array, and after performing the POST add an
assertion like expect(eventHistoryMocks.recordEvent).toHaveBeenCalledWith(...)
(and any relevant args) to ensure POST actually records the event; apply the
same change pattern for the other test case referenced (lines 484-490).

---

Outside diff comments:
In `@backend/src/index.test.ts`:
- Around line 257-283: Re-enable the skipped sender/recipient/status/pagination
tests by removing the .skip on the three tests that call invokeListStreamsRoute
(the "filters by sender exact match", "filters by recipient exact match", and
"applies combined sender + recipient + status filtering" cases) or replace them
with equivalent active tests that assert the same behavior using SENDER_A,
RECIPIENT_1, RECIPIENT_2 and the "scheduled" status; ensure each test still
checks status === 200, body.total and the body.data.map(...).toEqual
expectations so sender/recipient filtering and sender-stream pagination paths
remain covered.

---

Nitpick comments:
In `@backend/src/index.test.ts`:
- Around line 660-672: The test uses identical page and limit values so argument
order bugs are hidden; change the invocation of invokeGlobalEventsRoute to use
distinct page and limit (for example page="3", limit="2"), update the expected
body.page/body.limit/body.total/body.data length accordingly, and assert that
eventHistoryMocks.getGlobalEvents was called with the computed offset (e.g.,
(3-1)*2 = 4) as the first arg and the limit (2) as the second by inspecting
callArgs from eventHistoryMocks.getGlobalEvents.mock.calls[0].
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a8dd33d3-83fa-4922-9ce7-a02eb127db6a

📥 Commits

Reviewing files that changed from the base of the PR and between 946b9af and bf2fecb.

⛔ Files ignored due to path filters (1)
  • backend/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (5)
  • a
  • backend/package.json
  • backend/src/index.test.ts
  • backend/src/index.ts
  • backend/src/services/indexer.ts
💤 Files with no reviewable changes (1)
  • backend/src/services/indexer.ts

Comment thread backend/src/index.test.ts
Comment on lines +457 to +459
eventHistoryMocks.countStreamEvents.mockReturnValue(1);
eventHistoryMocks.getStreamHistory.mockReturnValue([createdEvent]);
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

The created-event verification is currently decoupled from POST behavior.

getStreamHistory is pre-mocked to always return createdEvent, so this test can pass even if POST never records an event. Add an assertion that POST actually calls recordEvent, and make history depend on that call.

Suggested test hardening
   beforeEach(() => {
@@
-    eventHistoryMocks.getStreamHistory.mockReturnValue([createdEvent]);
+    eventHistoryMocks.getStreamHistory.mockImplementation(() =>
+      eventHistoryMocks.recordEvent.mock.calls.length > 0 ? [createdEvent] : [],
+    );
   });

   it("creates a stream and includes computed progress", async () => {
@@
     expect(response.status).toBe(201);
+    expect(eventHistoryMocks.recordEvent).toHaveBeenCalled();
@@
     expect(historyResponse.status).toBe(200);

Also applies to: 484-490

🤖 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 457 - 459, The test currently
pre-mocks eventHistoryMocks.getStreamHistory to always return createdEvent,
decoupling verification from the POST; change the test to assert that
eventHistoryMocks.recordEvent is called by the POST and make getStreamHistory
return values dependent on recordEvent instead of a static stub. Concretely,
remove the fixed mockReturnValue for getStreamHistory, add a mockImplementation
for recordEvent that stores the recorded event in a local array, implement
getStreamHistory to return that array, and after performing the POST add an
assertion like expect(eventHistoryMocks.recordEvent).toHaveBeenCalledWith(...)
(and any relevant args) to ensure POST actually records the event; apply the
same change pattern for the other test case referenced (lines 484-490).

Comment thread backend/src/index.ts
Comment on lines +495 to +497
console.error("Failed to generate challenge:", error);
sendApiError(req, res, 500, "Failed to generate authentication challenge.", {
code: "AUTH_ERROR",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid leaking raw auth errors to logs and clients.

Line 495/Line 515 log full auth errors, and Line 516 returns raw error.message to clients. This can expose internal auth details. Use normalized errors and sanitized logging fields instead of raw objects/messages.

Suggested patch
   } catch (error: any) {
-    console.error("Failed to generate challenge:", error);
-    sendApiError(req, res, 500, "Failed to generate authentication challenge.", {
-      code: "AUTH_ERROR",
-    });
+    const normalizedError = normalizeUnknownApiError(
+      error,
+      "Failed to generate authentication challenge.",
+    );
+    console.error("Failed to generate challenge:", {
+      name: error?.name,
+      code: normalizedError.code ?? "AUTH_ERROR",
+      statusCode: normalizedError.statusCode,
+    });
+    sendApiError(req, res, normalizedError.statusCode, normalizedError.message, {
+      code: "AUTH_ERROR",
+    });
   }
 });
@@
   } catch (error: any) {
-    console.error("Failed to verify challenge:", error);
-    sendApiError(req, res, 400, error.message || "Challenge verification failed.", {
-      code: "AUTH_ERROR",
-    });
+    const normalizedError = normalizeUnknownApiError(
+      error,
+      "Challenge verification failed.",
+    );
+    console.error("Failed to verify challenge:", {
+      name: error?.name,
+      code: normalizedError.code ?? "AUTH_ERROR",
+      statusCode: normalizedError.statusCode,
+    });
+    sendApiError(req, res, normalizedError.statusCode, normalizedError.message, {
+      code: "AUTH_ERROR",
+    });
   }
 });

Also applies to: 515-517

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.

Add integration tests for POST /api/streams – validation and event recording

1 participant