Skip to content

test: add test suite for listMyTransactions (GET /api/transactions/me) - #1954

Merged
K1NGD4VID merged 13 commits into
LabsCrypt:mainfrom
Jubilee-001:main
Oct 9, 2026
Merged

K1NGD4VID merged 13 commits into
LabsCrypt:mainfrom
Jubilee-001:main

Conversation

@Jubilee-001

@Jubilee-001 Jubilee-001 commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Closes #1853

listMyTransactions (GET /api/transactions/me) was the only controller in src/controllers with zero test coverage — no test file referenced transactionController, transactionRoutes, or listMyTransactions. This PR adds route-level coverage following the existing conventions in remittanceRoutes.test.ts: supertest against the real Express app, requireJwtAuth exercised with real JWTs, and jest.unstable_mockModule for the DB pool, cache, and external services. The mock DB is an in-memory simulation of transaction_submissions honoring the controller's exact query shape ($1 = owner, $2 = limit + 1, optional $3 = cursor), so tests assert both HTTP responses and the emitted SQL parameters.

Acceptance criteria

  • Unauthenticated request (401) — missing Authorization header and invalid token
  • Page of results with default limit — 20 rows, camelCase field mapping, full page_info shape, WHERE submitted_by = $1 + limit + 1 probe asserted in SQL
  • Cursor-based pagination across two pages — 3-page walk asserting next_cursor/has_previous/has_next transitions, exact params ([wallet, limit+1, cursor]), no duplicate or skipped rows
  • Invalid/malformed cursor — abc, 0, -1, "" treated as absent: no cursor clause, first-page semantics, no error
  • Limit clamp at MAX_LIMIT (500) — limit=10000 → page_info.limit 500, 500 rows, 501 probe param; plus default-limit fallback for abc/0/-5
  • Rows of a different submitted_by never returned — other-user rows seeded with higher IDs (would surface first if the filter were dropped) asserted absent, on both the first page and cursor pages, with the SQL ownership clause asserted

Test plan

  • npm test (targeted suite): 13/13 passing
  • npx eslint src/__tests__/transactionRoutes.test.ts: cleans
  • tsc --noEmit: no new errors for this file (pre-existing errors in unrelated files unchanged)
  • Work landed as 8 small, atomic commits; each intermediate state was run and green before the next commit

Jubilee-001 and others added 9 commits September 29, 2026 18:54
listMyTransactions had no test coverage; every other controller does.
Start route-level tests with supertest against the real app, mocking the
DB pool, cache, and external services. First cases pin down the JWT gate:
401 without an Authorization header, 401 for an invalid token, and 200
with a valid JWT whose publicKey scopes the query.

Refs LabsCrypt#1853
With no query params the endpoint should return the first 20 rows
(DEFAULT_LIMIT) ordered newest-first, expose snake_case DB columns as
camelCase fields, and report page_info with limit 20, count 20, a
next_cursor for the following page, and has_next true because the
controller deliberately probes limit + 1 rows.

Refs LabsCrypt#1853
Walking GET /api/transactions/me with the returned next_cursor must
yield every row exactly once in newest-first order. Each page carries
has_previous/has_next flags and a next_cursor built from the last row's
id; the SQL appends AND id < $3 with the cursor as the third parameter.

Refs LabsCrypt#1853
Non-numeric, zero, negative, and empty cursor values are all treated as
absent: the query gets no cursor clause, page_info reports
has_previous=false and next_cursor=null, and the response is the full
first page rather than an error or a partial leak.

Refs LabsCrypt#1853
A client-supplied limit of 10000 must not translate into an unbounded
fetch: page_info reports the clamped limit 500, only 500 rows come back,
and the SQL probe parameter shows limit + 1 (501) proving the clamp
happened before the query was built.

Refs LabsCrypt#1853
…rams

Non-numeric, zero, and negative limit values fall back to the
DEFAULT_LIMIT of 20 instead of erroring or producing a zero-row page.

Refs LabsCrypt#1853
The endpoint must filter on the authenticated wallet's publicKey.
Another user's rows are seeded with higher ids so they would surface
first under newest-first ordering if the ownership filter were dropped;
the response contains only the caller's rows and the SQL binds the
authenticated wallet as the $1 ownership parameter.

Refs LabsCrypt#1853
Cursor-filtered requests must retain the submitted_by ownership clause
alongside the AND id < $3 predicate, so paging cannot widen the result
set beyond the authenticated wallet's own transactions.

Refs LabsCrypt#1853
test: add coverage for GET /api/transactions/me
@Jubilee-001

Copy link
Copy Markdown
Contributor Author

The failing RemitLend CI / backend check is due to 8 pre-existing lint errors already on main (in auditLogService.ts, auditLogService.pagination.test.ts, and idempotency.namespace.test.ts) — unrelated to this PR's change. My changed file (transactionRoutes.test.ts) has 0 lint errors/warnings. Flagging in case these should be cleaned up separately.

@Jubilee-001 Jubilee-001 reopened this Sep 29, 2026
@K1NGD4VID
K1NGD4VID merged commit 03c17ea into LabsCrypt:main Oct 9, 2026
14 checks passed
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.

[test] No test coverage for GET /api/transactions/me

2 participants