diff --git a/modules/express/test/unit/typedRoutes/acceptShare.ts b/modules/express/test/unit/typedRoutes/acceptShare.ts index 5758a3a4d8..a6fb41dac2 100644 --- a/modules/express/test/unit/typedRoutes/acceptShare.ts +++ b/modules/express/test/unit/typedRoutes/acceptShare.ts @@ -18,6 +18,23 @@ export function assertDecode(codec: t.Type, input: unknown): T { return result.right; } +/** + * Helper function to extract path parameter names from a route path + * Supports both Express-style (:param) and OpenAPI-style ({param}) notation + */ +function extractPathParams(path: string): string[] { + const colonParams = path.match(/:(\w+)/g)?.map((p) => p.slice(1)) || []; + const braceParams = path.match(/\{(\w+)\}/g)?.map((p) => p.slice(1, -1)) || []; + return [...colonParams, ...braceParams]; +} + +/** + * Helper function to get codec parameter names from a params object + */ +function getCodecParamNames(paramsCodec: Record): string[] { + return Object.keys(paramsCodec); +} + describe('AcceptShare codec tests', function () { describe('AcceptShareRequestParams', function () { it('should validate valid params', function () { @@ -102,6 +119,26 @@ describe('AcceptShare codec tests', function () { assert.ok(PostAcceptShare.response[200]); assert.ok(PostAcceptShare.response[400]); }); + + /** + * CRITICAL TEST: Validates that path parameter names match codec parameter names + * to prevent runtime validation errors. + */ + it('should have path parameter names matching codec parameter names', function () { + const pathParams = extractPathParams(PostAcceptShare.path); + const codecParams = getCodecParamNames(AcceptShareRequestParams); + + pathParams.sort(); + codecParams.sort(); + + assert.deepStrictEqual( + pathParams, + codecParams, + `Path parameters ${JSON.stringify(pathParams)} do not match codec parameters ${JSON.stringify( + codecParams + )}. ` + `This will cause runtime validation errors! Path: ${PostAcceptShare.path}` + ); + }); }); it('should handle empty strings for optional fields', function () { diff --git a/modules/express/test/unit/typedRoutes/coinSignTx.ts b/modules/express/test/unit/typedRoutes/coinSignTx.ts index b81faed62d..631228a145 100644 --- a/modules/express/test/unit/typedRoutes/coinSignTx.ts +++ b/modules/express/test/unit/typedRoutes/coinSignTx.ts @@ -13,6 +13,23 @@ import { } from '../../../src/typedRoutes/api/v2/coinSignTx'; import { assertDecode } from './common'; +/** + * Helper function to extract path parameter names from a route path + * Supports both Express-style (:param) and OpenAPI-style ({param}) notation + */ +function extractPathParams(path: string): string[] { + const colonParams = path.match(/:(\w+)/g)?.map((p) => p.slice(1)) || []; + const braceParams = path.match(/\{(\w+)\}/g)?.map((p) => p.slice(1, -1)) || []; + return [...colonParams, ...braceParams]; +} + +/** + * Helper function to get codec parameter names from a params object + */ +function getCodecParamNames(paramsCodec: Record): string[] { + return Object.keys(paramsCodec); +} + describe('CoinSignTx codec tests', function () { describe('CoinSignTxParams', function () { it('should validate params with required coin', function () { @@ -370,5 +387,24 @@ describe('CoinSignTx codec tests', function () { assert.ok(PostCoinSignTx.response[200]); assert.ok(PostCoinSignTx.response[400]); }); + + /** + * CRITICAL TEST: Validates that path parameter names match codec parameter names + * to prevent runtime validation errors. + */ + it('should have path parameter names matching codec parameter names', function () { + const pathParams = extractPathParams(PostCoinSignTx.path); + const codecParams = getCodecParamNames(CoinSignTxParams); + + pathParams.sort(); + codecParams.sort(); + + assert.deepStrictEqual( + pathParams, + codecParams, + `Path parameters ${JSON.stringify(pathParams)} do not match codec parameters ${JSON.stringify(codecParams)}. ` + + `This will cause runtime validation errors! Path: ${PostCoinSignTx.path}` + ); + }); }); }); diff --git a/modules/express/test/unit/typedRoutes/consolidateUnspents.ts b/modules/express/test/unit/typedRoutes/consolidateUnspents.ts index a1e5bbe9c2..9515a9f791 100644 --- a/modules/express/test/unit/typedRoutes/consolidateUnspents.ts +++ b/modules/express/test/unit/typedRoutes/consolidateUnspents.ts @@ -8,6 +8,23 @@ import { } from '../../../src/typedRoutes/api/v1/consolidateUnspents'; import { assertDecode } from './common'; +/** + * Helper function to extract path parameter names from a route path + * Supports both Express-style (:param) and OpenAPI-style ({param}) notation + */ +function extractPathParams(path: string): string[] { + const colonParams = path.match(/:(\w+)/g)?.map((p) => p.slice(1)) || []; + const braceParams = path.match(/\{(\w+)\}/g)?.map((p) => p.slice(1, -1)) || []; + return [...colonParams, ...braceParams]; +} + +/** + * Helper function to get codec parameter names from a params object + */ +function getCodecParamNames(paramsCodec: Record): string[] { + return Object.keys(paramsCodec); +} + describe('ConsolidateUnspents codec tests', function () { describe('ConsolidateUnspentsRequestParams', function () { it('should validate params with required id', function () { @@ -657,5 +674,24 @@ describe('ConsolidateUnspents codec tests', function () { assert.ok(PutConsolidateUnspents.response[200]); assert.ok(PutConsolidateUnspents.response[400]); }); + + /** + * CRITICAL TEST: Validates that path parameter names match codec parameter names + * to prevent runtime validation errors. + */ + it('should have path parameter names matching codec parameter names', function () { + const pathParams = extractPathParams(PutConsolidateUnspents.path); + const codecParams = getCodecParamNames(ConsolidateUnspentsRequestParams); + + pathParams.sort(); + codecParams.sort(); + + assert.deepStrictEqual( + pathParams, + codecParams, + `Path parameters ${JSON.stringify(pathParams)} do not match codec parameters ${JSON.stringify(codecParams)}. ` + + `This will cause runtime validation errors! Path: ${PutConsolidateUnspents.path}` + ); + }); }); }); diff --git a/modules/express/test/unit/typedRoutes/constructPendingApprovalTx.ts b/modules/express/test/unit/typedRoutes/constructPendingApprovalTx.ts index 21a59dd8d9..76fe2e8691 100644 --- a/modules/express/test/unit/typedRoutes/constructPendingApprovalTx.ts +++ b/modules/express/test/unit/typedRoutes/constructPendingApprovalTx.ts @@ -8,6 +8,23 @@ import { } from '../../../src/typedRoutes/api/v1/constructPendingApprovalTx'; import { assertDecode } from './common'; +/** + * Helper function to extract path parameter names from a route path + * Supports both Express-style (:param) and OpenAPI-style ({param}) notation + */ +function extractPathParams(path: string): string[] { + const colonParams = path.match(/:(\w+)/g)?.map((p) => p.slice(1)) || []; + const braceParams = path.match(/\{(\w+)\}/g)?.map((p) => p.slice(1, -1)) || []; + return [...colonParams, ...braceParams]; +} + +/** + * Helper function to get codec parameter names from a params object + */ +function getCodecParamNames(paramsCodec: Record): string[] { + return Object.keys(paramsCodec); +} + describe('ConstructPendingApprovalTx codec tests', function () { describe('ConstructPendingApprovalTxRequestParams', function () { it('should validate params with required id', function () { @@ -301,5 +318,24 @@ describe('ConstructPendingApprovalTx codec tests', function () { assert.ok(PutConstructPendingApprovalTx.response[200]); assert.ok(PutConstructPendingApprovalTx.response[400]); }); + + /** + * CRITICAL TEST: Validates that path parameter names match codec parameter names + * to prevent runtime validation errors. + */ + it('should have path parameter names matching codec parameter names', function () { + const pathParams = extractPathParams(PutConstructPendingApprovalTx.path); + const codecParams = getCodecParamNames(ConstructPendingApprovalTxRequestParams); + + pathParams.sort(); + codecParams.sort(); + + assert.deepStrictEqual( + pathParams, + codecParams, + `Path parameters ${JSON.stringify(pathParams)} do not match codec parameters ${JSON.stringify(codecParams)}. ` + + `This will cause runtime validation errors! Path: ${PutConstructPendingApprovalTx.path}` + ); + }); }); }); diff --git a/modules/express/test/unit/typedRoutes/fanoutUnspents.ts b/modules/express/test/unit/typedRoutes/fanoutUnspents.ts index f1436f312f..95f3c28d85 100644 --- a/modules/express/test/unit/typedRoutes/fanoutUnspents.ts +++ b/modules/express/test/unit/typedRoutes/fanoutUnspents.ts @@ -8,6 +8,23 @@ import { } from '../../../src/typedRoutes/api/v1/fanoutUnspents'; import { assertDecode } from './common'; +/** + * Helper function to extract path parameter names from a route path + * Supports both Express-style (:param) and OpenAPI-style ({param}) notation + */ +function extractPathParams(path: string): string[] { + const colonParams = path.match(/:(\w+)/g)?.map((p) => p.slice(1)) || []; + const braceParams = path.match(/\{(\w+)\}/g)?.map((p) => p.slice(1, -1)) || []; + return [...colonParams, ...braceParams]; +} + +/** + * Helper function to get codec parameter names from a params object + */ +function getCodecParamNames(paramsCodec: Record): string[] { + return Object.keys(paramsCodec); +} + describe('FanoutUnspents codec tests', function () { describe('FanoutUnspentsRequestParams', function () { it('should validate params with required id', function () { @@ -390,5 +407,24 @@ describe('FanoutUnspents codec tests', function () { assert.ok(PutFanoutUnspents.response[200]); assert.ok(PutFanoutUnspents.response[400]); }); + + /** + * CRITICAL TEST: Validates that path parameter names match codec parameter names + * to prevent runtime validation errors. + */ + it('should have path parameter names matching codec parameter names', function () { + const pathParams = extractPathParams(PutFanoutUnspents.path); + const codecParams = getCodecParamNames(FanoutUnspentsRequestParams); + + pathParams.sort(); + codecParams.sort(); + + assert.deepStrictEqual( + pathParams, + codecParams, + `Path parameters ${JSON.stringify(pathParams)} do not match codec parameters ${JSON.stringify(codecParams)}. ` + + `This will cause runtime validation errors! Path: ${PutFanoutUnspents.path}` + ); + }); }); }); diff --git a/modules/express/test/unit/typedRoutes/pendingApproval.ts b/modules/express/test/unit/typedRoutes/pendingApproval.ts index 6d70e5defe..ba03066fea 100644 --- a/modules/express/test/unit/typedRoutes/pendingApproval.ts +++ b/modules/express/test/unit/typedRoutes/pendingApproval.ts @@ -6,9 +6,23 @@ import { PutPendingApproval, } from '../../../src/typedRoutes/api/v1/pendingApproval'; import { assertDecode } from './common'; + +/** + * Helper function to extract path parameter names from a route path + * Supports both Express-style (:param) and OpenAPI-style ({param}) notation + */ +function extractPathParams(path: string): string[] { + const colonParams = path.match(/:(\w+)/g)?.map((p) => p.slice(1)) || []; + const braceParams = path.match(/\{(\w+)\}/g)?.map((p) => p.slice(1, -1)) || []; + return [...colonParams, ...braceParams]; +} + /** - * Helper function to test io-ts codec decoding + * Helper function to get codec parameter names from a params object */ +function getCodecParamNames(paramsCodec: Record): string[] { + return Object.keys(paramsCodec); +} describe('PendingApproval codec tests', function () { describe('pendingApprovalRequestParams', function () { @@ -203,5 +217,24 @@ describe('PendingApproval codec tests', function () { assert.ok(PutPendingApproval.response[200]); assert.ok(PutPendingApproval.response[400]); }); + + /** + * CRITICAL TEST: Validates that path parameter names match codec parameter names + * to prevent runtime validation errors. + */ + it('should have path parameter names matching codec parameter names', function () { + const pathParams = extractPathParams(PutPendingApproval.path); + const codecParams = getCodecParamNames(pendingApprovalRequestParams); + + pathParams.sort(); + codecParams.sort(); + + assert.deepStrictEqual( + pathParams, + codecParams, + `Path parameters ${JSON.stringify(pathParams)} do not match codec parameters ${JSON.stringify(codecParams)}. ` + + `This will cause runtime validation errors! Path: ${PutPendingApproval.path}` + ); + }); }); }); diff --git a/modules/express/test/unit/typedRoutes/signTransaction.ts b/modules/express/test/unit/typedRoutes/signTransaction.ts index 634073c5d5..edb2df5304 100644 --- a/modules/express/test/unit/typedRoutes/signTransaction.ts +++ b/modules/express/test/unit/typedRoutes/signTransaction.ts @@ -7,6 +7,23 @@ import { } from '../../../src/typedRoutes/api/v1/signTransaction'; import { assertDecode } from './common'; +/** + * Helper function to extract path parameter names from a route path + * Supports both Express-style (:param) and OpenAPI-style ({param}) notation + */ +function extractPathParams(path: string): string[] { + const colonParams = path.match(/:(\w+)/g)?.map((p) => p.slice(1)) || []; + const braceParams = path.match(/\{(\w+)\}/g)?.map((p) => p.slice(1, -1)) || []; + return [...colonParams, ...braceParams]; +} + +/** + * Helper function to get codec parameter names from a params object + */ +function getCodecParamNames(paramsCodec: Record): string[] { + return Object.keys(paramsCodec); +} + describe('SignTransaction codec tests', function () { describe('signTransactionRequestParams', function () { it('should validate valid params', function () { @@ -334,5 +351,24 @@ describe('SignTransaction codec tests', function () { assert.ok(PostSignTransaction.response[200]); assert.ok(PostSignTransaction.response[400]); }); + + /** + * CRITICAL TEST: Validates that path parameter names match codec parameter names + * to prevent runtime validation errors. + */ + it('should have path parameter names matching codec parameter names', function () { + const pathParams = extractPathParams(PostSignTransaction.path); + const codecParams = getCodecParamNames(signTransactionRequestParams); + + pathParams.sort(); + codecParams.sort(); + + assert.deepStrictEqual( + pathParams, + codecParams, + `Path parameters ${JSON.stringify(pathParams)} do not match codec parameters ${JSON.stringify(codecParams)}. ` + + `This will cause runtime validation errors! Path: ${PostSignTransaction.path}` + ); + }); }); }); diff --git a/modules/express/test/unit/typedRoutes/walletRecoverToken.ts b/modules/express/test/unit/typedRoutes/walletRecoverToken.ts index 30de0a0ab9..6b04d9a2d5 100644 --- a/modules/express/test/unit/typedRoutes/walletRecoverToken.ts +++ b/modules/express/test/unit/typedRoutes/walletRecoverToken.ts @@ -8,6 +8,23 @@ import { } from '../../../src/typedRoutes/api/v2/walletRecoverToken'; import { assertDecode } from './common'; +/** + * Helper function to extract path parameter names from a route path + * Supports both Express-style (:param) and OpenAPI-style ({param}) notation + */ +function extractPathParams(path: string): string[] { + const colonParams = path.match(/:(\w+)/g)?.map((p) => p.slice(1)) || []; + const braceParams = path.match(/\{(\w+)\}/g)?.map((p) => p.slice(1, -1)) || []; + return [...colonParams, ...braceParams]; +} + +/** + * Helper function to get codec parameter names from a params object + */ +function getCodecParamNames(paramsCodec: Record): string[] { + return Object.keys(paramsCodec); +} + describe('WalletRecoverToken codec tests', function () { describe('RecoverTokenParams', function () { it('should validate params with required coin and id', function () { @@ -580,5 +597,24 @@ describe('WalletRecoverToken codec tests', function () { assert.ok(PostWalletRecoverToken.response[200]); assert.ok(PostWalletRecoverToken.response[400]); }); + + /** + * CRITICAL TEST: Validates that path parameter names match codec parameter names + * to prevent runtime validation errors. + */ + it('should have path parameter names matching codec parameter names', function () { + const pathParams = extractPathParams(PostWalletRecoverToken.path); + const codecParams = getCodecParamNames(RecoverTokenParams); + + pathParams.sort(); + codecParams.sort(); + + assert.deepStrictEqual( + pathParams, + codecParams, + `Path parameters ${JSON.stringify(pathParams)} do not match codec parameters ${JSON.stringify(codecParams)}. ` + + `This will cause runtime validation errors! Path: ${PostWalletRecoverToken.path}` + ); + }); }); }); diff --git a/modules/express/test/unit/typedRoutes/walletSignTx.ts b/modules/express/test/unit/typedRoutes/walletSignTx.ts index cf29792e6d..8f2e76ca51 100644 --- a/modules/express/test/unit/typedRoutes/walletSignTx.ts +++ b/modules/express/test/unit/typedRoutes/walletSignTx.ts @@ -13,6 +13,23 @@ import { } from '../../../src/typedRoutes/api/v2/walletSignTx'; import { assertDecode } from './common'; +/** + * Helper function to extract path parameter names from a route path + * Supports both Express-style (:param) and OpenAPI-style ({param}) notation + */ +function extractPathParams(path: string): string[] { + const colonParams = path.match(/:(\w+)/g)?.map((p) => p.slice(1)) || []; + const braceParams = path.match(/\{(\w+)\}/g)?.map((p) => p.slice(1, -1)) || []; + return [...colonParams, ...braceParams]; +} + +/** + * Helper function to get codec parameter names from a params object + */ +function getCodecParamNames(paramsCodec: Record): string[] { + return Object.keys(paramsCodec); +} + describe('WalletSignTx codec tests', function () { describe('WalletSignTxParams', function () { it('should validate params with required coin and id', function () { @@ -679,5 +696,24 @@ describe('WalletSignTx codec tests', function () { assert.ok(PostWalletSignTx.response[200]); assert.ok(PostWalletSignTx.response[400]); }); + + /** + * CRITICAL TEST: Validates that path parameter names match codec parameter names + * to prevent runtime validation errors. + */ + it('should have path parameter names matching codec parameter names', function () { + const pathParams = extractPathParams(PostWalletSignTx.path); + const codecParams = getCodecParamNames(WalletSignTxParams); + + pathParams.sort(); + codecParams.sort(); + + assert.deepStrictEqual( + pathParams, + codecParams, + `Path parameters ${JSON.stringify(pathParams)} do not match codec parameters ${JSON.stringify(codecParams)}. ` + + `This will cause runtime validation errors! Path: ${PostWalletSignTx.path}` + ); + }); }); }); diff --git a/modules/express/test/unit/typedRoutes/walletTxSignTSS.ts b/modules/express/test/unit/typedRoutes/walletTxSignTSS.ts index 604a6ba4f9..d8f22d75b9 100644 --- a/modules/express/test/unit/typedRoutes/walletTxSignTSS.ts +++ b/modules/express/test/unit/typedRoutes/walletTxSignTSS.ts @@ -13,6 +13,23 @@ import { } from '../../../src/typedRoutes/api/v2/walletTxSignTSS'; import { assertDecode } from './common'; +/** + * Helper function to extract path parameter names from a route path + * Supports both Express-style (:param) and OpenAPI-style ({param}) notation + */ +function extractPathParams(path: string): string[] { + const colonParams = path.match(/:(\w+)/g)?.map((p) => p.slice(1)) || []; + const braceParams = path.match(/\{(\w+)\}/g)?.map((p) => p.slice(1, -1)) || []; + return [...colonParams, ...braceParams]; +} + +/** + * Helper function to get codec parameter names from a params object + */ +function getCodecParamNames(paramsCodec: Record): string[] { + return Object.keys(paramsCodec); +} + describe('WalletTxSignTSS codec tests', function () { describe('WalletTxSignTSSParams', function () { it('should validate params with required coin and id', function () { @@ -690,5 +707,24 @@ describe('WalletTxSignTSS codec tests', function () { assert.ok(PostWalletTxSignTSS.response[200]); assert.ok(PostWalletTxSignTSS.response[400]); }); + + /** + * CRITICAL TEST: Validates that path parameter names match codec parameter names + * to prevent runtime validation errors. + */ + it('should have path parameter names matching codec parameter names', function () { + const pathParams = extractPathParams(PostWalletTxSignTSS.path); + const codecParams = getCodecParamNames(WalletTxSignTSSParams); + + pathParams.sort(); + codecParams.sort(); + + assert.deepStrictEqual( + pathParams, + codecParams, + `Path parameters ${JSON.stringify(pathParams)} do not match codec parameters ${JSON.stringify(codecParams)}. ` + + `This will cause runtime validation errors! Path: ${PostWalletTxSignTSS.path}` + ); + }); }); });