UNPKG

dte-signer-sv

Version:

Sign Digital Tax Documents (DTE) for El Salvador's Ministry of Finance

165 lines 6.71 kB
import { signDTE } from "../index"; import { readFileSync } from "fs"; import path from "path"; // Use process.cwd() and relative path for Jest compatibility const tempDir = path.join(process.cwd(), "temp"); describe("signDTE", () => { const validCertificatePath = path.join(tempDir, "88888888888888.crt"); const validCertificateXML = readFileSync(validCertificatePath, "utf8"); const validPassword = "newpassword123"; const testDTE = { identificacion: { version: 1, ambiente: "00", tipoDte: "01", numeroControl: "DTE-01-00000001-000000000000001", codigoGeneracion: "TEST-CODE-001" } }; describe("with certificate file path", () => { it("should sign DTE successfully with valid inputs", async () => { const result = await signDTE({ dte: testDTE, privatePassword: validPassword, certificate: validCertificatePath, loadCertificateFromPath: true }); expect(typeof result).toBe("string"); expect(result.split(".")).toHaveLength(3); // JWT has 3 parts }); it("should throw error for invalid password", async () => { await expect(signDTE({ dte: testDTE, privatePassword: "wrongpassword", certificate: validCertificatePath, loadCertificateFromPath: true })).rejects.toThrow("Invalid private password"); }); it("should throw error for non-existent certificate file", async () => { await expect(signDTE({ dte: testDTE, privatePassword: validPassword, certificate: "./non-existent.crt", loadCertificateFromPath: true })).rejects.toThrow(); }); }); describe("with certificate XML content", () => { it("should sign DTE successfully with valid inputs", async () => { const result = await signDTE({ dte: testDTE, privatePassword: validPassword, certificate: validCertificateXML }); expect(typeof result).toBe("string"); expect(result.split(".")).toHaveLength(3); }); it("should work without loadCertificateFromPath flag", async () => { const result = await signDTE({ dte: testDTE, privatePassword: validPassword, certificate: validCertificateXML, loadCertificateFromPath: false }); expect(typeof result).toBe("string"); expect(result.split(".")).toHaveLength(3); }); it("should throw error for invalid XML", async () => { await expect(signDTE({ dte: testDTE, privatePassword: validPassword, certificate: "<invalid>not a certificate</invalid>" })).rejects.toThrow(); }); }); describe("DTE variations", () => { it("should sign empty object", async () => { const result = await signDTE({ dte: {}, privatePassword: validPassword, certificate: validCertificateXML }); expect(typeof result).toBe("string"); const parts = result.split("."); expect(parts).toHaveLength(3); // Decode payload to verify const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString()); expect(payload).toEqual({}); }); it("should sign complex nested object", async () => { const complexDTE = { nivel1: { nivel2: { nivel3: { datos: ["a", "b", "c"], numero: 123.45, booleano: true, nulo: null } } }, fecha: new Date().toISOString() }; const result = await signDTE({ dte: complexDTE, privatePassword: validPassword, certificate: validCertificateXML }); expect(typeof result).toBe("string"); const parts = result.split("."); expect(parts).toHaveLength(3); }); it("should handle special characters in DTE", async () => { const specialDTE = { texto: "Ñoño's café © 2024", simbolos: "!@#$%^&*()_+-=[]{}|;':\",./<>?" }; const result = await signDTE({ dte: specialDTE, privatePassword: validPassword, certificate: validCertificateXML }); expect(typeof result).toBe("string"); expect(result.split(".")).toHaveLength(3); }); }); describe("JWT structure validation", () => { it("should create valid JWT structure", async () => { const result = await signDTE({ dte: testDTE, privatePassword: validPassword, certificate: validCertificateXML }); const [header, payload, signature] = result.split("."); // Validate header const decodedHeader = JSON.parse(Buffer.from(header, "base64url").toString()); expect(decodedHeader.alg).toBe("RS512"); // Validate payload const decodedPayload = JSON.parse(Buffer.from(payload, "base64url").toString()); expect(decodedPayload).toEqual(testDTE); // Validate signature exists and has content expect(signature).toBeDefined(); expect(signature.length).toBeGreaterThan(0); }); it("should produce different signatures for different DTEs", async () => { const dte1 = { id: 1 }; const dte2 = { id: 2 }; const result1 = await signDTE({ dte: dte1, privatePassword: validPassword, certificate: validCertificateXML }); const result2 = await signDTE({ dte: dte2, privatePassword: validPassword, certificate: validCertificateXML }); expect(result1).not.toBe(result2); // But headers should be the same const header1 = result1.split(".")[0]; const header2 = result2.split(".")[0]; expect(header1).toBe(header2); }); }); }); //# sourceMappingURL=signer.test.js.map