From bf84711c31dfe400a4ff95382a85b23e184eb23a Mon Sep 17 00:00:00 2001 From: Real Dev Vortex Date: Wed, 30 Sep 2026 00:23:57 +0100 Subject: [PATCH 1/7] fix: [Testing] RemittanceNFT update_metadata_uri is entirely unte (#1149) --- backend/src/__tests__/adminDisputePagination.test.ts | 2 +- .../src/__tests__/adminGovernanceController.test.ts | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/src/__tests__/adminDisputePagination.test.ts b/backend/src/__tests__/adminDisputePagination.test.ts index 6d86bcd96..acef773ea 100644 --- a/backend/src/__tests__/adminDisputePagination.test.ts +++ b/backend/src/__tests__/adminDisputePagination.test.ts @@ -215,4 +215,4 @@ describe('listLoanDisputes pagination', () => { ); expect(dataCall?.[0]).toContain('ORDER BY created_at DESC'); }); -}); +}) diff --git a/backend/src/__tests__/adminGovernanceController.test.ts b/backend/src/__tests__/adminGovernanceController.test.ts index 2d7b582a4..7f2a3c3ba 100644 --- a/backend/src/__tests__/adminGovernanceController.test.ts +++ b/backend/src/__tests__/adminGovernanceController.test.ts @@ -1,10 +1,9 @@ -import { jest, describe, it, expect, beforeEach, afterEach } from '@jest/globals'; -import type { Request, Response } from 'express'; +import { jest, describe, it, expect, beforeEach, afterEach } from '@jest/globals';import type { Request, Response } from 'express'; type MockQueryResult = { rows: Record[]; rowCount: number }; const mockQuery: jest.MockedFunction< - (sql: string, params?: unknown[]) => Promise +(sql: string, params?: unknown[]) => Promise > = jest.fn(); jest.unstable_mockModule('../db/connection.js', () => ({ @@ -36,6 +35,7 @@ describe('adminGovernanceController - getPendingGovernance', () => { delete process.env.GOVERNANCE_CURRENT_ADMIN; delete process.env.MULTISIG_GOVERNANCE_CONTRACT_ID; delete process.env.GOVERNANCE_THRESHOLD; + delete process.env.GOVERNANCE_SIGNERS; }); it('filters signers so signers from older pending proposals are not mixed in', async () => { @@ -43,7 +43,7 @@ describe('adminGovernanceController - getPendingGovernance', () => { const res = createMockResponse(); // Database returns rows from multiple proposals (ordered by proposal_id DESC) - mockQuery.mockResolvedValueOnce({ + mockQuery.mockResolvedOnce({ rows: [ { proposal_id: 'prop-2', @@ -106,7 +106,7 @@ describe('adminGovernanceController - getPendingGovernance', () => { const req = {} as Request; const res = createMockResponse(); - mockQuery.mockResolvedValueOnce({ + mockQuery.mockResolvedOnce({ rows: [], rowCount: 0, }); @@ -115,7 +115,7 @@ describe('adminGovernanceController - getPendingGovernance', () => { await flushAsync(); expect(res.json).toHaveBeenCalledWith( - expect.objectContaining({ + expect.objectContaining( { pendingProposal: null, signers: [ { address: 'GSIGNER_1', approved: false }, From 5192bc6b42b0e306963479f9d8a82cd42b14a614 Mon Sep 17 00:00:00 2001 From: Real Dev Vortex Date: Mon, 5 Oct 2026 15:28:43 +0000 Subject: [PATCH 2/7] fix: fix linting errors --- backend/package-lock.json | 24 +------------------ .../src/__tests__/remittanceFilters.test.ts | 7 +++--- .../auditLogService.pagination.test.ts | 8 ++----- backend/src/services/auditLogService.ts | 3 +-- .../src/tests/idempotency.namespace.test.ts | 21 +++++++--------- 5 files changed, 16 insertions(+), 47 deletions(-) diff --git a/backend/package-lock.json b/backend/package-lock.json index 3c0980142..87648331d 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -60,7 +60,7 @@ "typescript": "^5.9.3" }, "engines": { - "node": ">=18" + "node": ">=22" } }, "node_modules/@apidevtools/json-schema-ref-parser": { @@ -116,7 +116,6 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "license": "MIT", - "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -715,7 +714,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" @@ -728,7 +726,6 @@ "dev": true, "license": "MIT", "optional": true, - "peer": true, "dependencies": { "tslib": "^2.4.0" } @@ -2075,7 +2072,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.1.tgz", "integrity": "sha512-gLyJlPHPZYdAk1JENA9LeHejZe1Ti77/pTeFm/nMXmQH/HFZlcS/O2XJB+L8fkbrNSqhdtlvjBVjxwUYanNH5Q==", "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=8.0.0" } @@ -2097,7 +2093,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.10.0.tgz", "integrity": "sha512-/wNZ8twnEQQA4HoHu22+vcsdru6pWPWxW+7w+FlxT6Id7PE/WIbZmVKkte+PF72e0F2dnImFeHD2syyE1Mw6MQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, @@ -2113,7 +2108,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.220.0.tgz", "integrity": "sha512-xQx3E2WxP1mDvKzxLxX+CTCtNLa560YJZ3087qYHerl2YmiKpv7AH+dAy7vmx+eVrZ5BwhfWUAVoKOoxCNHcpw==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@opentelemetry/api-logs": "0.220.0", "import-in-the-middle": "^3.0.0", @@ -2164,7 +2158,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.10.0.tgz", "integrity": "sha512-GuYQQT7QD2EeO8lcZLRQzcbOyhqAzL+6WWTKTU9mSUBYBazkEDl+VrQcXQhbB08OWM9anD1aHleVadzulpOaUQ==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@opentelemetry/core": "2.10.0", "@opentelemetry/resources": "2.10.0", @@ -2525,7 +2518,6 @@ "resolved": "https://registry.npmjs.org/@redis/client/-/client-5.12.1.tgz", "integrity": "sha512-7aPGWeqA3uFm43o19umzdl16CEjK/JQGtSXVPevplTaOU3VJA/rseBC1QvYUz9lLDIMBimc4SW/zrW4S89BaCA==", "license": "MIT", - "peer": true, "dependencies": { "cluster-key-slot": "1.1.2" }, @@ -3075,7 +3067,6 @@ "integrity": "sha512-OScDchr2fwuUmWdf4kZ9h7PcJiYDVInhJizG/biAq3cAvqwYktuy/TYGGdZNMtNTFUP7rnb0NU4TUdm82kt4Rg==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } @@ -3092,7 +3083,6 @@ "integrity": "sha512-fKVHpikPdg4GKks3JuLEhvwSyvwzF23hnabPy6DD8ljVbC7+6J5dQzdv4arV6jqq57djnMgs1HKBxX4P8aBI3A==", "devOptional": true, "license": "MIT", - "peer": true, "dependencies": { "@types/node": "*", "pg-protocol": "*", @@ -3241,7 +3231,6 @@ "integrity": "sha512-fHq2VC1kpyYfvEcbiMjOpySY4WS7voEp89yAThrHRX5sm9j2lzYppCb2umFMEed4fWcyeLjHxrz0mpjNBaBxMQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.68.0", "@typescript-eslint/types": "8.68.0", @@ -3808,7 +3797,6 @@ "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -4398,7 +4386,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.11.12", "caniuse-lite": "^1.0.30001809", @@ -5508,7 +5495,6 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -5565,7 +5551,6 @@ "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", - "peer": true, "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -5996,7 +5981,6 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "license": "MIT", - "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", @@ -6040,7 +6024,6 @@ "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.7.0.tgz", "integrity": "sha512-hOwV7WOxXfjRpAM1DSJWZDXx3GhplwD8IfwuwvogD8i1Qnkgosw/H45s4ZnFAUHDAhPjlY9hLBvJhKmGMyY26g==", "license": "MIT", - "peer": true, "dependencies": { "debug": "^4.4.3", "ip-address": "^10.2.0" @@ -7576,7 +7559,6 @@ "integrity": "sha512-HeFeOUEKh5gjnp1rjuSCse8Dhj0Y3KA8lsZ3azr4Wnq1nCxwMBu35MDc9mp8iblZxmeAz6wV4P241tyUB7J2Ew==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@jest/core": "30.5.0", "@jest/types": "30.5.0", @@ -9525,7 +9507,6 @@ "resolved": "https://registry.npmjs.org/pg/-/pg-8.23.0.tgz", "integrity": "sha512-Ip2EQCngowJLGOfCwkFhPXU7/ljlhn6Rxlmy4XYfL2Y+vyRM59+8uR2xqRWKdYmbXmxCFOAmKxBuSUCdF34qLg==", "license": "MIT", - "peer": true, "dependencies": { "pg-connection-string": "^2.14.0", "pg-pool": "^3.14.0", @@ -9773,7 +9754,6 @@ "integrity": "sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -11445,7 +11425,6 @@ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -11715,7 +11694,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/backend/src/__tests__/remittanceFilters.test.ts b/backend/src/__tests__/remittanceFilters.test.ts index 080c3b124..aadc6172c 100644 --- a/backend/src/__tests__/remittanceFilters.test.ts +++ b/backend/src/__tests__/remittanceFilters.test.ts @@ -37,9 +37,10 @@ jest.unstable_mockModule('../services/notificationService.js', () => ({ })); jest.unstable_mockModule('../utils/stellarEnvelope.js', () => ({ - parseAndValidateSignedEnvelope: jest - .fn() - .mockReturnValue({ source: 'GCWEPACYJLN7S3ZUXSVMXZBFKYXSHRGZ6O326HDDPDKBKZPXD45XNHC3', signatureCount: 1 }), + parseAndValidateSignedEnvelope: jest.fn().mockReturnValue({ + source: 'GCWEPACYJLN7S3ZUXSVMXZBFKYXSHRGZ6O326HDDPDKBKZPXD45XNHC3', + signatureCount: 1, + }), })); const mockQuery = jest.fn(); diff --git a/backend/src/services/__tests__/auditLogService.pagination.test.ts b/backend/src/services/__tests__/auditLogService.pagination.test.ts index d89cc90a1..60645ecbb 100644 --- a/backend/src/services/__tests__/auditLogService.pagination.test.ts +++ b/backend/src/services/__tests__/auditLogService.pagination.test.ts @@ -100,9 +100,7 @@ describe('getAuditLogs keyset pagination and totals (#1808)', () => { it('omits the count query unless withTotal is set', async () => { await getAuditLogs({ limit: 2 }); - const countCalls = mockQuery.mock.calls.filter(([text]) => - String(text).includes('COUNT(*)'), - ); + const countCalls = mockQuery.mock.calls.filter(([text]) => String(text).includes('COUNT(*)')); expect(countCalls).toHaveLength(0); }); @@ -122,9 +120,7 @@ describe('getAuditLogs keyset pagination and totals (#1808)', () => { limit: 2, }); - const countCall = mockQuery.mock.calls.find(([text]) => - String(text).includes('COUNT(*)'), - ); + const countCall = mockQuery.mock.calls.find(([text]) => String(text).includes('COUNT(*)')); const countSql = String(countCall?.[0]); const countValues = (countCall?.[1] as unknown[]) ?? []; diff --git a/backend/src/services/auditLogService.ts b/backend/src/services/auditLogService.ts index 1fcfc8d72..a7dfd33bb 100644 --- a/backend/src/services/auditLogService.ts +++ b/backend/src/services/auditLogService.ts @@ -24,8 +24,7 @@ export function encodeCursor(row: Record | undefined): string | const id = row.id; const createdAt = row.created_at; if (id === undefined || id === null || !createdAt) return null; - const createdAtIso = - createdAt instanceof Date ? createdAt.toISOString() : String(createdAt); + const createdAtIso = createdAt instanceof Date ? createdAt.toISOString() : String(createdAt); return `${createdAtIso}${CURSOR_SEPARATOR}${String(id)}`; } diff --git a/backend/src/tests/idempotency.namespace.test.ts b/backend/src/tests/idempotency.namespace.test.ts index aedb3af73..3b58d4ed1 100644 --- a/backend/src/tests/idempotency.namespace.test.ts +++ b/backend/src/tests/idempotency.namespace.test.ts @@ -1,5 +1,9 @@ import { Request, Response, NextFunction } from 'express'; -import { idempotencyMiddleware, computeFingerprint, namespacedKey } from '../middleware/idempotency.js'; +import { + idempotencyMiddleware, + computeFingerprint, + namespacedKey, +} from '../middleware/idempotency.js'; import { cacheService } from '../services/cacheService.js'; import { jest } from '@jest/globals'; @@ -33,8 +37,7 @@ describe('idempotencyMiddleware key namespacing (#1809)', () => { return request; }; - const cacheKeysRead = () => - asMock(cacheService.get).mock.calls.map(([key]) => String(key)); + const cacheKeysRead = () => asMock(cacheService.get).mock.calls.map(([key]) => String(key)); beforeEach(() => { req = buildRequest(ALICE); @@ -75,11 +78,7 @@ describe('idempotencyMiddleware key namespacing (#1809)', () => { jest.clearAllMocks(); asMock(cacheService.setNotExists).mockResolvedValue(true); - await idempotencyMiddleware( - buildRequest(BOB) as Request, - res as Response, - next, - ); + await idempotencyMiddleware(buildRequest(BOB) as Request, res as Response, next); const bobKey = cacheKeysRead()[0]; expect(aliceKey).not.toBe(bobKey); @@ -173,11 +172,7 @@ describe('idempotencyMiddleware key namespacing (#1809)', () => { jest.clearAllMocks(); asMock(cacheService.setNotExists).mockResolvedValue(true); - await idempotencyMiddleware( - buildRequest(undefined) as Request, - res as Response, - next, - ); + await idempotencyMiddleware(buildRequest(undefined) as Request, res as Response, next); expect(cacheKeysRead()[0]).toBe(first); expect(first).toContain('anon'); From 71d2b216c56f4c0a987bd48317b973e7c73fe351 Mon Sep 17 00:00:00 2001 From: Bello Qudus Folohunsho Date: Mon, 5 Oct 2026 20:56:35 +0100 Subject: [PATCH 3/7] fix: fix formatting of some files --- backend/src/__tests__/adminDisputePagination.test.ts | 2 +- backend/src/__tests__/adminGovernanceController.test.ts | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/backend/src/__tests__/adminDisputePagination.test.ts b/backend/src/__tests__/adminDisputePagination.test.ts index acef773ea..6d86bcd96 100644 --- a/backend/src/__tests__/adminDisputePagination.test.ts +++ b/backend/src/__tests__/adminDisputePagination.test.ts @@ -215,4 +215,4 @@ describe('listLoanDisputes pagination', () => { ); expect(dataCall?.[0]).toContain('ORDER BY created_at DESC'); }); -}) +}); diff --git a/backend/src/__tests__/adminGovernanceController.test.ts b/backend/src/__tests__/adminGovernanceController.test.ts index 7f2a3c3ba..87f05df47 100644 --- a/backend/src/__tests__/adminGovernanceController.test.ts +++ b/backend/src/__tests__/adminGovernanceController.test.ts @@ -1,9 +1,10 @@ -import { jest, describe, it, expect, beforeEach, afterEach } from '@jest/globals';import type { Request, Response } from 'express'; +import { jest, describe, it, expect, beforeEach, afterEach } from '@jest/globals'; +import type { Request, Response } from 'express'; type MockQueryResult = { rows: Record[]; rowCount: number }; const mockQuery: jest.MockedFunction< -(sql: string, params?: unknown[]) => Promise + (sql: string, params?: unknown[]) => Promise > = jest.fn(); jest.unstable_mockModule('../db/connection.js', () => ({ @@ -115,7 +116,7 @@ describe('adminGovernanceController - getPendingGovernance', () => { await flushAsync(); expect(res.json).toHaveBeenCalledWith( - expect.objectContaining( { + expect.objectContaining({ pendingProposal: null, signers: [ { address: 'GSIGNER_1', approved: false }, From 009c1692b967b27329613f2428987a8c542f01a3 Mon Sep 17 00:00:00 2001 From: Real Dev Vortex Date: Tue, 6 Oct 2026 09:50:13 +0100 Subject: [PATCH 4/7] fix: Add project badges to README Added project badges for license, frontend, backend, and smart contracts. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9246562be..4b3426168 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # RemitLend +123 + [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC) [![Frontend: Next.js](https://img.shields.io/badge/Frontend-Next.js-black?logo=next.js)](https://nextjs.org/) [![Backend: Express](https://img.shields.io/badge/Backend-Express.js-white?logo=express)](https://expressjs.com/) From 1b5becf9326a9beef0d7b1192f56369ee7945d35 Mon Sep 17 00:00:00 2001 From: Real Dev Vortex Date: Tue, 6 Oct 2026 10:00:47 +0100 Subject: [PATCH 5/7] refractor: Refactor adminGovernanceController tests Refactor test to use mockResolvedValueOnce for query and remove redundant assertions. --- .../adminGovernanceController.test.ts | 56 +------------------ 1 file changed, 2 insertions(+), 54 deletions(-) diff --git a/backend/src/__tests__/adminGovernanceController.test.ts b/backend/src/__tests__/adminGovernanceController.test.ts index 87f05df47..28db080bd 100644 --- a/backend/src/__tests__/adminGovernanceController.test.ts +++ b/backend/src/__tests__/adminGovernanceController.test.ts @@ -44,7 +44,7 @@ describe('adminGovernanceController - getPendingGovernance', () => { const res = createMockResponse(); // Database returns rows from multiple proposals (ordered by proposal_id DESC) - mockQuery.mockResolvedOnce({ + mockQuery.mockResolvedValueOnce({ rows: [ { proposal_id: 'prop-2', @@ -74,56 +74,4 @@ describe('adminGovernanceController - getPendingGovernance', () => { executable_at: null, expires_at: null, signer_address: 'GSIGNER_PROP1_ONLY', - approved: true, - }, - ], - rowCount: 3, - }); - - getPendingGovernance(req, res, () => {}); - await flushAsync(); - - expect(res.json).toHaveBeenCalledTimes(1); - const responseData = (res.json as jest.Mock).mock.calls[0]?.[0] as Record; - - expect(responseData.pendingProposal).toBeDefined(); - expect(responseData.pendingProposal.id).toBe('prop-2'); - expect(responseData.pendingProposal.proposedAdmin).toBe('GNEW_ADMIN_2'); - - // Crucial check: only prop-2 signers should be included, NOT prop-1 signer - const signers = responseData.pendingProposal.signers; - expect(signers).toHaveLength(2); - expect(signers).toEqual([ - { address: 'GSIGNER_PROP2_APPROVED', approved: true }, - { address: 'GSIGNER_PROP2_PENDING', approved: false }, - ]); - expect(signers.some((s: { address: string }) => s.address === 'GSIGNER_PROP1_ONLY')).toBe( - false, - ); - }); - - it('returns fallback signers from env when no pending proposal exists', async () => { - process.env.GOVERNANCE_SIGNERS = 'GSIGNER_1, GSIGNER_2'; - const req = {} as Request; - const res = createMockResponse(); - - mockQuery.mockResolvedOnce({ - rows: [], - rowCount: 0, - }); - - getPendingGovernance(req, res, () => {}); - await flushAsync(); - - expect(res.json).toHaveBeenCalledWith( - expect.objectContaining({ - pendingProposal: null, - signers: [ - { address: 'GSIGNER_1', approved: false }, - { address: 'GSIGNER_2', approved: false }, - ], - threshold: 2, - }), - ); - }); -}); + approved](#) From 9faa8ae456e96d002cadd9a466996e800392e753 Mon Sep 17 00:00:00 2001 From: Real Dev Vortex Date: Tue, 6 Oct 2026 10:06:53 +0100 Subject: [PATCH 6/7] refractor: Refactor adminGovernanceController tests for signers Update test to ensure signers from older proposals are filtered out and fallback signers are returned when no pending proposals exist. --- .../adminGovernanceController.test.ts | 60 ++++++++++++++++++- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/backend/src/__tests__/adminGovernanceController.test.ts b/backend/src/__tests__/adminGovernanceController.test.ts index 28db080bd..22ac767d9 100644 --- a/backend/src/__tests__/adminGovernanceController.test.ts +++ b/backend/src/__tests__/adminGovernanceController.test.ts @@ -43,7 +43,6 @@ describe('adminGovernanceController - getPendingGovernance', () => { const req = {} as Request; const res = createMockResponse(); - // Database returns rows from multiple proposals (ordered by proposal_id DESC) mockQuery.mockResolvedValueOnce({ rows: [ { @@ -67,11 +66,66 @@ describe('adminGovernanceController - getPendingGovernance', () => { approved: false, }, { - proposal_id: 'prop-1', // Older proposal + proposal_id: 'prop-1', proposed_admin: 'GOLD_ADMIN_1', approval_count: 2, threshold: 2, executable_at: null, expires_at: null, signer_address: 'GSIGNER_PROP1_ONLY', - approved](#) + approved: true, + }, + ], + rowCount: 3, + }); + + getPendingGovernance(req, res, () => {}); + await flushAsync(); + + expect(res.json).toHaveBeenCalledTimes(1); + + const responseData = (res.json as jest.Mock).mock.calls[0]?.[0] as Record; + + expect(responseData.pendingProposal).toBeDefined(); + expect(responseData.pendingProposal.id).toBe('prop-2'); + expect(responseData.pendingProposal.proposedAdmin).toBe('GNEW_ADMIN_2'); + + const signers = responseData.pendingProposal.signers; + + expect(signers).toHaveLength(2); + expect(signers).toEqual([ + { address: 'GSIGNER_PROP2_APPROVED', approved: true }, + { address: 'GSIGNER_PROP2_PENDING', approved: false }, + ]); + + expect( + signers.some((s: { address: string }) => s.address === 'GSIGNER_PROP1_ONLY'), + ).toBe(false); + }); + + it('returns fallback signers from env when no pending proposal exists', async () => { + process.env.GOVERNANCE_SIGNERS = 'GSIGNER_1, GSIGNER_2'; + + const req = {} as Request; + const res = createMockResponse(); + + mockQuery.mockResolvedValueOnce({ + rows: [], + rowCount: 0, + }); + + getPendingGovernance(req, res, () => {}); + await flushAsync(); + + expect(res.json).toHaveBeenCalledWith( + expect.objectContaining({ + pendingProposal: null, + signers: [ + { address: 'GSIGNER_1', approved: false }, + { address: 'GSIGNER_2', approved: false }, + ], + threshold: 2, + }), + ); + }); +}); From 70b6c000b0f88ea51104c34a2e9a5fbbe80fab0b Mon Sep 17 00:00:00 2001 From: Bello Qudus Folohunsho Date: Tue, 6 Oct 2026 10:58:51 +0100 Subject: [PATCH 7/7] fix: fix formatting of some files --- backend/src/__tests__/adminGovernanceController.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/__tests__/adminGovernanceController.test.ts b/backend/src/__tests__/adminGovernanceController.test.ts index 22ac767d9..4dfef9230 100644 --- a/backend/src/__tests__/adminGovernanceController.test.ts +++ b/backend/src/__tests__/adminGovernanceController.test.ts @@ -98,9 +98,9 @@ describe('adminGovernanceController - getPendingGovernance', () => { { address: 'GSIGNER_PROP2_PENDING', approved: false }, ]); - expect( - signers.some((s: { address: string }) => s.address === 'GSIGNER_PROP1_ONLY'), - ).toBe(false); + expect(signers.some((s: { address: string }) => s.address === 'GSIGNER_PROP1_ONLY')).toBe( + false, + ); }); it('returns fallback signers from env when no pending proposal exists', async () => {