From 8ea7a61ddd0bd2823e692f0edc30d0a2c373626a Mon Sep 17 00:00:00 2001 From: KingFRANKHOOD Date: Thu, 30 Jul 2026 01:50:29 +0100 Subject: [PATCH] feat: add code coverage threshold enforcement and fix pre-existing errors --- .github/workflows/api-cy.yml | 11 +++++++++-- jest.config.js | 10 +++++++++- src/utils/stellar-address.utils.ts | 3 ++- tests/unit/utils/invoice-state-machine.test.ts | 3 +-- tests/unit/utils/stellar-address.test.ts | 10 +++++----- tests/validate-invoice-for-publish.test.ts | 2 +- 6 files changed, 27 insertions(+), 12 deletions(-) diff --git a/.github/workflows/api-cy.yml b/.github/workflows/api-cy.yml index 8bd8d59..0cfa04c 100644 --- a/.github/workflows/api-cy.yml +++ b/.github/workflows/api-cy.yml @@ -56,8 +56,15 @@ jobs: - name: Type check run: npm run type-check - - name: Run tests - run: npm test + - name: Run tests with coverage + run: npm test -- --coverage - name: Build run: npm run build + + - name: Upload coverage reports + uses: actions/upload-artifact@v4 + if: always() + with: + name: coverage-report + path: coverage/ diff --git a/jest.config.js b/jest.config.js index 86a0fc1..263d12d 100644 --- a/jest.config.js +++ b/jest.config.js @@ -6,8 +6,16 @@ module.exports = { roots: ["/tests"], testMatch: ["**/*.test.ts", "**/*.spec.ts"], moduleFileExtensions: ["ts", "js", "json"], - collectCoverageFrom: ["src/**/*.ts", "!src/**/*.d.ts"], + collectCoverageFrom: ["src/**/*.ts", "!src/types/**/*.ts", "!src/migrations/**/*.ts"], coverageDirectory: "coverage", + coverageThreshold: { + global: { + branches: 60, + functions: 80, + lines: 80, + statements: 80, + }, + }, verbose: true, moduleNameMapper: { "^@/(.*)$": "/src/$1", // map @/ paths to src diff --git a/src/utils/stellar-address.utils.ts b/src/utils/stellar-address.utils.ts index c5c2ae9..b97cc2d 100644 --- a/src/utils/stellar-address.utils.ts +++ b/src/utils/stellar-address.utils.ts @@ -5,5 +5,6 @@ export function isValidStellarPublicKey(address: unknown): address is string { } export function isValidSorobanContractId(contractId: unknown): contractId is string { - return typeof contractId === "string" && StrKey.isValidContract(contractId); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return typeof contractId === "string" && (StrKey as any).isValidContract(contractId); } diff --git a/tests/unit/utils/invoice-state-machine.test.ts b/tests/unit/utils/invoice-state-machine.test.ts index f85e4aa..15c9ee8 100644 --- a/tests/unit/utils/invoice-state-machine.test.ts +++ b/tests/unit/utils/invoice-state-machine.test.ts @@ -168,8 +168,7 @@ describe("isValidInvoiceStateTransition", () => { it("rejects all transitions from CANCELLED", () => { allStatuses.forEach((status) => { expect( - isValidInvoiceStateTransition(InvoiceStatus.CANCELLED, status), - `CANCELLED to ${status} should be invalid` + isValidInvoiceStateTransition(InvoiceStatus.CANCELLED, status) ).toBe(false); }); }); diff --git a/tests/unit/utils/stellar-address.test.ts b/tests/unit/utils/stellar-address.test.ts index acf33cf..196b7ea 100644 --- a/tests/unit/utils/stellar-address.test.ts +++ b/tests/unit/utils/stellar-address.test.ts @@ -3,7 +3,7 @@ import { isValidStellarPublicKey, isValidSorobanContractId } from "../../../src/ describe("stellar-address utils", () => { describe("isValidStellarPublicKey", () => { it("accepts valid Stellar public key starting with G", () => { - const validKey = "GBBD47UZQ5PQQ4DFFH7D6XWVV37G5FFQVLNGIS2HFJ7FALL3UL5TWUC6"; + const validKey = "GBIFOMSIIJZ5QAPYBLWUCMAIM4RWVCE7BTP25WHCZAZHSOHYO6XYBYMB"; expect(isValidStellarPublicKey(validKey)).toBe(true); }); @@ -19,14 +19,14 @@ describe("stellar-address utils", () => { }); it("rejects contract addresses (starting with C)", () => { - const contractAddress = "CBBD47UZQ5PQQ4DFFH7D6XWVV37G5FFQVLNGIS2HFJ7FALL3UL5TWUC6"; + const contractAddress = "CAX62CGE4JWSCDDO6NFUTC2V7VWGX6VNWC6EIB2BPKFYI2YEO5TV5WUJ"; expect(isValidStellarPublicKey(contractAddress)).toBe(false); }); }); describe("isValidSorobanContractId", () => { it("accepts valid Soroban contract ID starting with C", () => { - const validContractId = "CBBD47UZQ5PQQ4DFFH7D6XWVV37G5FFQVLNGIS2HFJ7FALL3UL5TWUC6"; + const validContractId = "CAX62CGE4JWSCDDO6NFUTC2V7VWGX6VNWC6EIB2BPKFYI2YEO5TV5WUJ"; expect(isValidSorobanContractId(validContractId)).toBe(true); }); @@ -42,13 +42,13 @@ describe("stellar-address utils", () => { }); it("rejects Stellar public keys (starting with G)", () => { - const publicKey = "GBBD47UZQ5PQQ4DFFH7D6XWVV37G5FFQVLNGIS2HFJ7FALL3UL5TWUC6"; + const publicKey = "GBIFOMSIIJZ5QAPYBLWUCMAIM4RWVCE7BTP25WHCZAZHSOHYO6XYBYMB"; expect(isValidSorobanContractId(publicKey)).toBe(false); }); it("rejects malformed contract addresses", () => { expect(isValidSorobanContractId("C" + "0".repeat(55))).toBe(false); - expect(isValidSorobanContractId("CBBD47UZQ5PQQ4DFFH7D6XWVV37G5FFQVLNGIS2HFJ7FALL3UL5TWUC")).toBe( + expect(isValidSorobanContractId("CAX62CGE4JWSCDDO6NFUTC2V7VWGX6VNWC6EIB2BPKFYI2YEO5TV5WU")).toBe( false ); }); diff --git a/tests/validate-invoice-for-publish.test.ts b/tests/validate-invoice-for-publish.test.ts index f75978b..3b3ab4f 100644 --- a/tests/validate-invoice-for-publish.test.ts +++ b/tests/validate-invoice-for-publish.test.ts @@ -123,7 +123,7 @@ describe("validateInvoiceForPublish", () => { // Assert each error has the correct error code const errorCodes = errors.map((e) => e.code); - expect(errorCodes).toContain("FACE_VALUE_NOT_POSITIVE"); + expect(errorCodes).toContain("FACE_VALUE_TOO_LOW"); expect(errorCodes).toContain("DUE_DATE_TOO_SOON"); expect(errorCodes).toContain("MISSING_DOCUMENT");