apacuana-sdk-core 1.26.0 → 1.26.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env +8 -0
- package/README.md +69 -0
- package/coverage/clover.xml +192 -147
- package/coverage/coverage-final.json +4 -4
- package/coverage/lcov-report/index.html +27 -27
- package/coverage/lcov-report/src/api/certs.js.html +1 -1
- package/coverage/lcov-report/src/api/faceLiveness.js.html +1 -1
- package/coverage/lcov-report/src/api/index.html +18 -18
- package/coverage/lcov-report/src/api/revocations.js.html +1 -1
- package/coverage/lcov-report/src/api/signatures.js.html +413 -11
- package/coverage/lcov-report/src/api/users.js.html +1 -1
- package/coverage/lcov-report/src/config/index.html +1 -1
- package/coverage/lcov-report/src/config/index.js.html +1 -1
- package/coverage/lcov-report/src/errors/index.html +1 -1
- package/coverage/lcov-report/src/errors/index.js.html +8 -8
- package/coverage/lcov-report/src/index.html +15 -15
- package/coverage/lcov-report/src/index.js.html +41 -8
- package/coverage/lcov-report/src/success/index.html +1 -1
- package/coverage/lcov-report/src/success/index.js.html +5 -5
- package/coverage/lcov-report/src/utils/constant.js.html +1 -1
- package/coverage/lcov-report/src/utils/helpers.js.html +1 -1
- package/coverage/lcov-report/src/utils/httpClient.js.html +1 -1
- package/coverage/lcov-report/src/utils/index.html +1 -1
- package/coverage/lcov.info +343 -253
- package/dist/api/signatures.d.ts +5 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +290 -93
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +290 -93
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/api/signatures.js +136 -2
- package/src/index.js +11 -0
- package/tests/api/signatures.test.js +166 -2
- package/tests/integration/createAndLockDocument.test.js +93 -0
- package/coverage/lcov-report/api/index.html +0 -131
- package/coverage/lcov-report/api/signatures.js.html +0 -1093
- package/coverage/lcov-report/api/users.js.html +0 -292
- package/coverage/lcov-report/certs.js.html +0 -175
- package/coverage/lcov-report/config/index.html +0 -116
- package/coverage/lcov-report/config/index.js.html +0 -208
- package/coverage/lcov-report/errors/index.html +0 -116
- package/coverage/lcov-report/errors/index.js.html +0 -148
- package/coverage/lcov-report/utils/constant.js.html +0 -145
- package/coverage/lcov-report/utils/httpClient.js.html +0 -646
- package/coverage/lcov-report/utils/index.html +0 -131
package/package.json
CHANGED
package/src/api/signatures.js
CHANGED
|
@@ -240,12 +240,10 @@ const deleteSignatureVariantOnPremise = async () => {
|
|
|
240
240
|
|
|
241
241
|
const addMemberOnBoarding = async (memberData) => {
|
|
242
242
|
const payload = helpers.validateAddMemberData(memberData);
|
|
243
|
-
// Transform documentId to docid for API compatibility
|
|
244
243
|
const apiPayload = {
|
|
245
244
|
docid: payload.documentId,
|
|
246
245
|
kinddoc: payload.typedoc,
|
|
247
246
|
doc: payload.doc,
|
|
248
|
-
signature: payload.signature,
|
|
249
247
|
};
|
|
250
248
|
try {
|
|
251
249
|
const response = await httpRequest(
|
|
@@ -272,6 +270,64 @@ const addMemberOnPremise = async () => {
|
|
|
272
270
|
);
|
|
273
271
|
};
|
|
274
272
|
|
|
273
|
+
const createDocumentOnBoarding = async (documentData) => {
|
|
274
|
+
const formData = new FormData();
|
|
275
|
+
formData.append("name", documentData.name);
|
|
276
|
+
formData.append("reference", documentData.reference);
|
|
277
|
+
try {
|
|
278
|
+
const response = await httpRequest(
|
|
279
|
+
"services/api/documents",
|
|
280
|
+
formData,
|
|
281
|
+
"POST"
|
|
282
|
+
);
|
|
283
|
+
return new ApacuanaSuccess({
|
|
284
|
+
msg: response.msg,
|
|
285
|
+
id: response.id,
|
|
286
|
+
});
|
|
287
|
+
} catch (error) {
|
|
288
|
+
if (error instanceof ApacuanaAPIError) {
|
|
289
|
+
throw error;
|
|
290
|
+
}
|
|
291
|
+
throw new ApacuanaAPIError(
|
|
292
|
+
`Failed to create document: ${error.message || "Unknown error"}`
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
const createDocumentOnPremise = async () => {
|
|
298
|
+
throw new ApacuanaAPIError(
|
|
299
|
+
"Creating documents is not supported for integration type: ONPREMISE",
|
|
300
|
+
501,
|
|
301
|
+
"NOT_IMPLEMENTED"
|
|
302
|
+
);
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const lockDocumentOnBoarding = async (documentId) => {
|
|
306
|
+
try {
|
|
307
|
+
const response = await httpRequest(
|
|
308
|
+
`services/api/documents/lock/${documentId}`,
|
|
309
|
+
{},
|
|
310
|
+
"PUT"
|
|
311
|
+
);
|
|
312
|
+
return new ApacuanaSuccess(response);
|
|
313
|
+
} catch (error) {
|
|
314
|
+
if (error instanceof ApacuanaAPIError) {
|
|
315
|
+
throw error;
|
|
316
|
+
}
|
|
317
|
+
throw new ApacuanaAPIError(
|
|
318
|
+
`Failed to lock document: ${error.message || "Unknown error"}`
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const lockDocumentOnPremise = async () => {
|
|
324
|
+
throw new ApacuanaAPIError(
|
|
325
|
+
"Locking documents is not supported for integration type: ONPREMISE",
|
|
326
|
+
501,
|
|
327
|
+
"NOT_IMPLEMENTED"
|
|
328
|
+
);
|
|
329
|
+
};
|
|
330
|
+
|
|
275
331
|
// =================================================================
|
|
276
332
|
// Exported Functions
|
|
277
333
|
// =================================================================
|
|
@@ -506,3 +562,81 @@ export const addMember = async (memberData) => {
|
|
|
506
562
|
"UNSUPPORTED_INTEGRATION_TYPE"
|
|
507
563
|
);
|
|
508
564
|
};
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Crea un nuevo documento para ser firmado.
|
|
568
|
+
* @param {object} documentData - Datos del documento a crear.
|
|
569
|
+
* @param {string} documentData.name - Nombre del documento.
|
|
570
|
+
* @param {string} documentData.reference - Referencia del documento.
|
|
571
|
+
* @returns {Promise<object>} Una promesa que resuelve a un objeto con `{ msg, id }` del documento creado.
|
|
572
|
+
* @throws {ApacuanaAPIError} Si los datos son inválidos, la llamada a la API falla, o el tipo de integración no es soportado.
|
|
573
|
+
*/
|
|
574
|
+
export const createDocument = async (documentData) => {
|
|
575
|
+
if (
|
|
576
|
+
!documentData ||
|
|
577
|
+
typeof documentData !== "object" ||
|
|
578
|
+
Object.keys(documentData).length === 0
|
|
579
|
+
) {
|
|
580
|
+
throw new ApacuanaAPIError(
|
|
581
|
+
"Document data (documentData) is required and must be a non-empty object.",
|
|
582
|
+
400,
|
|
583
|
+
"INVALID_PARAMETER"
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
if (!documentData.name || !documentData.reference) {
|
|
588
|
+
throw new ApacuanaAPIError(
|
|
589
|
+
"Fields 'name' and 'reference' are required.",
|
|
590
|
+
400,
|
|
591
|
+
"INVALID_PARAMETER"
|
|
592
|
+
);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
const { integrationType } = getConfig();
|
|
596
|
+
|
|
597
|
+
if (integrationType === INTEGRATION_TYPE.ONBOARDING) {
|
|
598
|
+
return createDocumentOnBoarding(documentData);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
if (integrationType === INTEGRATION_TYPE.ONPREMISE) {
|
|
602
|
+
return createDocumentOnPremise();
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
throw new ApacuanaAPIError(
|
|
606
|
+
`Unsupported integration type: ${integrationType}`,
|
|
607
|
+
400,
|
|
608
|
+
"UNSUPPORTED_INTEGRATION_TYPE"
|
|
609
|
+
);
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Bloquea un documento para evitar modificaciones.
|
|
614
|
+
* @param {string} documentId - ID (UUID) del documento a bloquear.
|
|
615
|
+
* @returns {Promise<object>} Una promesa que resuelve al response de la API.
|
|
616
|
+
* @throws {ApacuanaAPIError} Si el documentId es inválido, la llamada a la API falla, o el tipo de integración no es soportado.
|
|
617
|
+
*/
|
|
618
|
+
export const lockDocument = async (documentId) => {
|
|
619
|
+
if (!documentId || typeof documentId !== "string") {
|
|
620
|
+
throw new ApacuanaAPIError(
|
|
621
|
+
"Field 'documentId' is required and must be a string.",
|
|
622
|
+
400,
|
|
623
|
+
"INVALID_PARAMETER"
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
const { integrationType } = getConfig();
|
|
628
|
+
|
|
629
|
+
if (integrationType === INTEGRATION_TYPE.ONBOARDING) {
|
|
630
|
+
return lockDocumentOnBoarding(documentId);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
if (integrationType === INTEGRATION_TYPE.ONPREMISE) {
|
|
634
|
+
return lockDocumentOnPremise();
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
throw new ApacuanaAPIError(
|
|
638
|
+
`Unsupported integration type: ${integrationType}`,
|
|
639
|
+
400,
|
|
640
|
+
"UNSUPPORTED_INTEGRATION_TYPE"
|
|
641
|
+
);
|
|
642
|
+
};
|
package/src/index.js
CHANGED
|
@@ -10,10 +10,12 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
addSigner,
|
|
12
12
|
addMember,
|
|
13
|
+
createDocument,
|
|
13
14
|
deleteSignatureVariant,
|
|
14
15
|
getDigest,
|
|
15
16
|
getDocs,
|
|
16
17
|
getSignatureVariant,
|
|
18
|
+
lockDocument,
|
|
17
19
|
signDocument,
|
|
18
20
|
uploadSignatureVariant,
|
|
19
21
|
} from "./api/signatures";
|
|
@@ -161,6 +163,15 @@ const apacuana = {
|
|
|
161
163
|
return sendFaceLiveness(data);
|
|
162
164
|
},
|
|
163
165
|
|
|
166
|
+
createDocument: (data) => {
|
|
167
|
+
checkSdk(false);
|
|
168
|
+
return createDocument(data);
|
|
169
|
+
},
|
|
170
|
+
lockDocument: (documentId) => {
|
|
171
|
+
checkSdk(false);
|
|
172
|
+
return lockDocument(documentId);
|
|
173
|
+
},
|
|
174
|
+
|
|
164
175
|
close: () => close(),
|
|
165
176
|
getConfig,
|
|
166
177
|
};
|
|
@@ -5,12 +5,14 @@ import ApacuanaSuccess from "../../src/success";
|
|
|
5
5
|
import {
|
|
6
6
|
addSigner,
|
|
7
7
|
addMember,
|
|
8
|
+
createDocument,
|
|
9
|
+
deleteSignatureVariant,
|
|
8
10
|
getDocs,
|
|
9
11
|
getDigest,
|
|
12
|
+
getSignatureVariant,
|
|
13
|
+
lockDocument,
|
|
10
14
|
signDocument,
|
|
11
15
|
uploadSignatureVariant,
|
|
12
|
-
getSignatureVariant,
|
|
13
|
-
deleteSignatureVariant,
|
|
14
16
|
} from "../../src/api/signatures";
|
|
15
17
|
import helpers from "../../src/utils/helpers";
|
|
16
18
|
import { INTEGRATION_TYPE } from "../../src/utils/constant";
|
|
@@ -622,4 +624,166 @@ describe("API - Signatures", () => {
|
|
|
622
624
|
);
|
|
623
625
|
});
|
|
624
626
|
});
|
|
627
|
+
|
|
628
|
+
describe("createDocument", () => {
|
|
629
|
+
it("should create a document for ONBOARDING integration", async () => {
|
|
630
|
+
getConfig.mockReturnValue({
|
|
631
|
+
integrationType: INTEGRATION_TYPE.ONBOARDING,
|
|
632
|
+
});
|
|
633
|
+
const documentData = { name: "prueba", reference: "prueba" };
|
|
634
|
+
const mockResponse = {
|
|
635
|
+
msg: "Documento creado",
|
|
636
|
+
id: "ef3344bb-d114-46b5-8356-90ec113cbbbd",
|
|
637
|
+
};
|
|
638
|
+
httpRequest.mockResolvedValue(mockResponse);
|
|
639
|
+
|
|
640
|
+
const result = await createDocument(documentData);
|
|
641
|
+
|
|
642
|
+
expect(httpRequest).toHaveBeenCalledWith(
|
|
643
|
+
"services/api/documents",
|
|
644
|
+
expect.any(FormData),
|
|
645
|
+
"POST"
|
|
646
|
+
);
|
|
647
|
+
expect(result).toBeInstanceOf(ApacuanaSuccess);
|
|
648
|
+
expect(result.data).toEqual(mockResponse);
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
it("should throw not implemented for ONPREMISE integration", async () => {
|
|
652
|
+
getConfig.mockReturnValue({
|
|
653
|
+
integrationType: INTEGRATION_TYPE.ONPREMISE,
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
await expect(
|
|
657
|
+
createDocument({ name: "x", reference: "y" })
|
|
658
|
+
).rejects.toThrow(
|
|
659
|
+
new ApacuanaAPIError(
|
|
660
|
+
"Creating documents is not supported for integration type: ONPREMISE",
|
|
661
|
+
501,
|
|
662
|
+
"NOT_IMPLEMENTED"
|
|
663
|
+
)
|
|
664
|
+
);
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
it("should throw an error for unsupported integration type", async () => {
|
|
668
|
+
getConfig.mockReturnValue({ integrationType: "UNSUPPORTED" });
|
|
669
|
+
await expect(
|
|
670
|
+
createDocument({ name: "x", reference: "y" })
|
|
671
|
+
).rejects.toThrow(
|
|
672
|
+
new ApacuanaAPIError(
|
|
673
|
+
"Unsupported integration type: UNSUPPORTED",
|
|
674
|
+
400,
|
|
675
|
+
"UNSUPPORTED_INTEGRATION_TYPE"
|
|
676
|
+
)
|
|
677
|
+
);
|
|
678
|
+
});
|
|
679
|
+
|
|
680
|
+
it("should throw an error if documentData is invalid", async () => {
|
|
681
|
+
await expect(createDocument(null)).rejects.toThrow(
|
|
682
|
+
new ApacuanaAPIError(
|
|
683
|
+
"Document data (documentData) is required and must be a non-empty object.",
|
|
684
|
+
400,
|
|
685
|
+
"INVALID_PARAMETER"
|
|
686
|
+
)
|
|
687
|
+
);
|
|
688
|
+
});
|
|
689
|
+
|
|
690
|
+
it("should throw an error if name or reference is missing", async () => {
|
|
691
|
+
await expect(createDocument({ name: "x" })).rejects.toThrow(
|
|
692
|
+
new ApacuanaAPIError(
|
|
693
|
+
"Fields 'name' and 'reference' are required.",
|
|
694
|
+
400,
|
|
695
|
+
"INVALID_PARAMETER"
|
|
696
|
+
)
|
|
697
|
+
);
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
it("should wrap non-ApacuanaAPIError from httpRequest as ApacuanaAPIError", async () => {
|
|
701
|
+
getConfig.mockReturnValue({
|
|
702
|
+
integrationType: INTEGRATION_TYPE.ONBOARDING,
|
|
703
|
+
});
|
|
704
|
+
httpRequest.mockRejectedValue(new Error("Network error"));
|
|
705
|
+
|
|
706
|
+
await expect(
|
|
707
|
+
createDocument({ name: "x", reference: "y" })
|
|
708
|
+
).rejects.toThrow(
|
|
709
|
+
new ApacuanaAPIError("Failed to create document: Network error")
|
|
710
|
+
);
|
|
711
|
+
});
|
|
712
|
+
});
|
|
713
|
+
|
|
714
|
+
describe("lockDocument", () => {
|
|
715
|
+
it("should lock a document for ONBOARDING integration", async () => {
|
|
716
|
+
getConfig.mockReturnValue({
|
|
717
|
+
integrationType: INTEGRATION_TYPE.ONBOARDING,
|
|
718
|
+
});
|
|
719
|
+
const documentId = "ccb318a8-e8ff-4a17-ba20-10acbcd96785";
|
|
720
|
+
const mockResponse = { success: true, locked: true };
|
|
721
|
+
httpRequest.mockResolvedValue(mockResponse);
|
|
722
|
+
|
|
723
|
+
const result = await lockDocument(documentId);
|
|
724
|
+
|
|
725
|
+
expect(httpRequest).toHaveBeenCalledWith(
|
|
726
|
+
`services/api/documents/lock/${documentId}`,
|
|
727
|
+
{},
|
|
728
|
+
"PUT"
|
|
729
|
+
);
|
|
730
|
+
expect(result).toBeInstanceOf(ApacuanaSuccess);
|
|
731
|
+
expect(result.data).toEqual(mockResponse);
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
it("should throw not implemented for ONPREMISE integration", async () => {
|
|
735
|
+
getConfig.mockReturnValue({
|
|
736
|
+
integrationType: INTEGRATION_TYPE.ONPREMISE,
|
|
737
|
+
});
|
|
738
|
+
|
|
739
|
+
await expect(lockDocument("ccb318a8-e8ff-4a17-ba20-10acbcd96785")).rejects.toThrow(
|
|
740
|
+
new ApacuanaAPIError(
|
|
741
|
+
"Locking documents is not supported for integration type: ONPREMISE",
|
|
742
|
+
501,
|
|
743
|
+
"NOT_IMPLEMENTED"
|
|
744
|
+
)
|
|
745
|
+
);
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
it("should throw an error for unsupported integration type", async () => {
|
|
749
|
+
getConfig.mockReturnValue({ integrationType: "UNSUPPORTED" });
|
|
750
|
+
await expect(lockDocument("ccb318a8-e8ff-4a17-ba20-10acbcd96785")).rejects.toThrow(
|
|
751
|
+
new ApacuanaAPIError(
|
|
752
|
+
"Unsupported integration type: UNSUPPORTED",
|
|
753
|
+
400,
|
|
754
|
+
"UNSUPPORTED_INTEGRATION_TYPE"
|
|
755
|
+
)
|
|
756
|
+
);
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
it("should throw an error if documentId is missing or not a string", async () => {
|
|
760
|
+
await expect(lockDocument(null)).rejects.toThrow(
|
|
761
|
+
new ApacuanaAPIError(
|
|
762
|
+
"Field 'documentId' is required and must be a string.",
|
|
763
|
+
400,
|
|
764
|
+
"INVALID_PARAMETER"
|
|
765
|
+
)
|
|
766
|
+
);
|
|
767
|
+
await expect(lockDocument(123)).rejects.toThrow(
|
|
768
|
+
new ApacuanaAPIError(
|
|
769
|
+
"Field 'documentId' is required and must be a string.",
|
|
770
|
+
400,
|
|
771
|
+
"INVALID_PARAMETER"
|
|
772
|
+
)
|
|
773
|
+
);
|
|
774
|
+
});
|
|
775
|
+
|
|
776
|
+
it("should wrap non-ApacuanaAPIError from httpRequest as ApacuanaAPIError", async () => {
|
|
777
|
+
getConfig.mockReturnValue({
|
|
778
|
+
integrationType: INTEGRATION_TYPE.ONBOARDING,
|
|
779
|
+
});
|
|
780
|
+
httpRequest.mockRejectedValue(new Error("Network error"));
|
|
781
|
+
|
|
782
|
+
await expect(
|
|
783
|
+
lockDocument("ccb318a8-e8ff-4a17-ba20-10acbcd96785")
|
|
784
|
+
).rejects.toThrow(
|
|
785
|
+
new ApacuanaAPIError("Failed to lock document: Network error")
|
|
786
|
+
);
|
|
787
|
+
});
|
|
788
|
+
});
|
|
625
789
|
});
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration tests for createDocument → lockDocument flow
|
|
3
|
+
*
|
|
4
|
+
* Requires environment variables (copy .env.example to .env and fill in):
|
|
5
|
+
* APACUANA_API_URL=https://api.dev.apacuana.3dlinkweb.com
|
|
6
|
+
* APACUANA_SECRET_KEY=your-secret-key
|
|
7
|
+
* APACUANA_API_KEY=your-api-key
|
|
8
|
+
* APACUANA_VERIFICATION_ID=your-verification-id
|
|
9
|
+
* APACUANA_INTEGRATION_TYPE=ONBOARDING
|
|
10
|
+
*
|
|
11
|
+
* Note: APACUANA_DOCUMENT_REFERENCE is provided by the backend team for this
|
|
12
|
+
* sandbox environment; it's a reference id the document will be linked to.
|
|
13
|
+
*
|
|
14
|
+
* Run with: NODE_ENV=test npm test -- --testPathPatterns="integration/createAndLockDocument.test.js"
|
|
15
|
+
*/
|
|
16
|
+
import { readFileSync } from "fs";
|
|
17
|
+
import { resolve } from "path";
|
|
18
|
+
|
|
19
|
+
const envPath = resolve(process.cwd(), ".env");
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const envContent = readFileSync(envPath, "utf-8");
|
|
23
|
+
envContent.split("\n").forEach(line => {
|
|
24
|
+
const [key, ...valueParts] = line.split("=");
|
|
25
|
+
if (key && key.trim() && !key.startsWith("#")) {
|
|
26
|
+
process.env[key.trim()] = valueParts.join("=").replace(/"/g, "").trim();
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
} catch (err) {
|
|
30
|
+
// .env file not found, continue without it
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
import apacuana from "../../src/index.js";
|
|
34
|
+
|
|
35
|
+
const requiredEnvVars = [
|
|
36
|
+
"APACUANA_API_URL",
|
|
37
|
+
"APACUANA_SECRET_KEY",
|
|
38
|
+
"APACUANA_API_KEY",
|
|
39
|
+
"APACUANA_VERIFICATION_ID",
|
|
40
|
+
"APACUANA_INTEGRATION_TYPE",
|
|
41
|
+
"APACUANA_DOCUMENT_REFERENCE",
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const missingVars = requiredEnvVars.filter(v => !process.env[v]);
|
|
45
|
+
if (missingVars.length > 0) {
|
|
46
|
+
test.skip("createDocument then lockDocument integration", () => {});
|
|
47
|
+
throw new Error(
|
|
48
|
+
`\n⚠️ Missing environment variables: ${missingVars.join(", ")}\n` +
|
|
49
|
+
"Create a .env file based on .env.example.\n"
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
describe("createDocument → lockDocument - Integration", () => {
|
|
54
|
+
beforeAll(async () => {
|
|
55
|
+
await apacuana.init({
|
|
56
|
+
apiUrl: process.env.APACUANA_API_URL,
|
|
57
|
+
secretKey: process.env.APACUANA_SECRET_KEY,
|
|
58
|
+
apiKey: process.env.APACUANA_API_KEY,
|
|
59
|
+
verificationId: process.env.APACUANA_VERIFICATION_ID,
|
|
60
|
+
integrationType: process.env.APACUANA_INTEGRATION_TYPE,
|
|
61
|
+
// customerId omitted: init() would set Authorization: Bearer which the
|
|
62
|
+
// backend rejects on this endpoint with 404 "Cliente no encontrado".
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
afterAll(() => {
|
|
67
|
+
apacuana.close();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("should create a document and then lock it using the returned id", async () => {
|
|
71
|
+
const timestamp = Date.now();
|
|
72
|
+
const documentData = {
|
|
73
|
+
name: `integration-test-${timestamp}`,
|
|
74
|
+
reference: process.env.APACUANA_DOCUMENT_REFERENCE,
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const createResult = await apacuana.createDocument(documentData);
|
|
78
|
+
|
|
79
|
+
expect(createResult).toBeDefined();
|
|
80
|
+
expect(createResult.success).toBe(true);
|
|
81
|
+
expect(createResult.data).toBeDefined();
|
|
82
|
+
expect(createResult.data.id).toBeDefined();
|
|
83
|
+
expect(typeof createResult.data.id).toBe("string");
|
|
84
|
+
|
|
85
|
+
const documentId = createResult.data.id;
|
|
86
|
+
|
|
87
|
+
const lockResult = await apacuana.lockDocument(documentId);
|
|
88
|
+
|
|
89
|
+
expect(lockResult).toBeDefined();
|
|
90
|
+
expect(lockResult.success).toBe(true);
|
|
91
|
+
expect(lockResult.data).toBeDefined();
|
|
92
|
+
});
|
|
93
|
+
});
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
<!doctype html>
|
|
3
|
-
<html lang="en">
|
|
4
|
-
|
|
5
|
-
<head>
|
|
6
|
-
<title>Code coverage report for api</title>
|
|
7
|
-
<meta charset="utf-8" />
|
|
8
|
-
<link rel="stylesheet" href="../prettify.css" />
|
|
9
|
-
<link rel="stylesheet" href="../base.css" />
|
|
10
|
-
<link rel="shortcut icon" type="image/x-icon" href="../favicon.png" />
|
|
11
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
12
|
-
<style type='text/css'>
|
|
13
|
-
.coverage-summary .sorter {
|
|
14
|
-
background-image: url(../sort-arrow-sprite.png);
|
|
15
|
-
}
|
|
16
|
-
</style>
|
|
17
|
-
</head>
|
|
18
|
-
|
|
19
|
-
<body>
|
|
20
|
-
<div class='wrapper'>
|
|
21
|
-
<div class='pad1'>
|
|
22
|
-
<h1><a href="../index.html">All files</a> api</h1>
|
|
23
|
-
<div class='clearfix'>
|
|
24
|
-
|
|
25
|
-
<div class='fl pad1y space-right2'>
|
|
26
|
-
<span class="strong">57.29% </span>
|
|
27
|
-
<span class="quiet">Statements</span>
|
|
28
|
-
<span class='fraction'>55/96</span>
|
|
29
|
-
</div>
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<div class='fl pad1y space-right2'>
|
|
33
|
-
<span class="strong">50.98% </span>
|
|
34
|
-
<span class="quiet">Branches</span>
|
|
35
|
-
<span class='fraction'>26/51</span>
|
|
36
|
-
</div>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
<div class='fl pad1y space-right2'>
|
|
40
|
-
<span class="strong">50% </span>
|
|
41
|
-
<span class="quiet">Functions</span>
|
|
42
|
-
<span class='fraction'>7/14</span>
|
|
43
|
-
</div>
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
<div class='fl pad1y space-right2'>
|
|
47
|
-
<span class="strong">57.29% </span>
|
|
48
|
-
<span class="quiet">Lines</span>
|
|
49
|
-
<span class='fraction'>55/96</span>
|
|
50
|
-
</div>
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
</div>
|
|
54
|
-
<p class="quiet">
|
|
55
|
-
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
|
|
56
|
-
</p>
|
|
57
|
-
<template id="filterTemplate">
|
|
58
|
-
<div class="quiet">
|
|
59
|
-
Filter:
|
|
60
|
-
<input type="search" id="fileSearch">
|
|
61
|
-
</div>
|
|
62
|
-
</template>
|
|
63
|
-
</div>
|
|
64
|
-
<div class='status-line medium'></div>
|
|
65
|
-
<div class="pad1">
|
|
66
|
-
<table class="coverage-summary">
|
|
67
|
-
<thead>
|
|
68
|
-
<tr>
|
|
69
|
-
<th data-col="file" data-fmt="html" data-html="true" class="file">File</th>
|
|
70
|
-
<th data-col="pic" data-type="number" data-fmt="html" data-html="true" class="pic"></th>
|
|
71
|
-
<th data-col="statements" data-type="number" data-fmt="pct" class="pct">Statements</th>
|
|
72
|
-
<th data-col="statements_raw" data-type="number" data-fmt="html" class="abs"></th>
|
|
73
|
-
<th data-col="branches" data-type="number" data-fmt="pct" class="pct">Branches</th>
|
|
74
|
-
<th data-col="branches_raw" data-type="number" data-fmt="html" class="abs"></th>
|
|
75
|
-
<th data-col="functions" data-type="number" data-fmt="pct" class="pct">Functions</th>
|
|
76
|
-
<th data-col="functions_raw" data-type="number" data-fmt="html" class="abs"></th>
|
|
77
|
-
<th data-col="lines" data-type="number" data-fmt="pct" class="pct">Lines</th>
|
|
78
|
-
<th data-col="lines_raw" data-type="number" data-fmt="html" class="abs"></th>
|
|
79
|
-
</tr>
|
|
80
|
-
</thead>
|
|
81
|
-
<tbody><tr>
|
|
82
|
-
<td class="file medium" data-value="signatures.js"><a href="signatures.js.html">signatures.js</a></td>
|
|
83
|
-
<td data-value="50.6" class="pic medium">
|
|
84
|
-
<div class="chart"><div class="cover-fill" style="width: 50%"></div><div class="cover-empty" style="width: 50%"></div></div>
|
|
85
|
-
</td>
|
|
86
|
-
<td data-value="50.6" class="pct medium">50.6%</td>
|
|
87
|
-
<td data-value="83" class="abs medium">42/83</td>
|
|
88
|
-
<td data-value="38.46" class="pct low">38.46%</td>
|
|
89
|
-
<td data-value="39" class="abs low">15/39</td>
|
|
90
|
-
<td data-value="46.15" class="pct low">46.15%</td>
|
|
91
|
-
<td data-value="13" class="abs low">6/13</td>
|
|
92
|
-
<td data-value="50.6" class="pct medium">50.6%</td>
|
|
93
|
-
<td data-value="83" class="abs medium">42/83</td>
|
|
94
|
-
</tr>
|
|
95
|
-
|
|
96
|
-
<tr>
|
|
97
|
-
<td class="file high" data-value="users.js"><a href="users.js.html">users.js</a></td>
|
|
98
|
-
<td data-value="100" class="pic high">
|
|
99
|
-
<div class="chart"><div class="cover-fill cover-full" style="width: 100%"></div><div class="cover-empty" style="width: 0%"></div></div>
|
|
100
|
-
</td>
|
|
101
|
-
<td data-value="100" class="pct high">100%</td>
|
|
102
|
-
<td data-value="13" class="abs high">13/13</td>
|
|
103
|
-
<td data-value="91.66" class="pct high">91.66%</td>
|
|
104
|
-
<td data-value="12" class="abs high">11/12</td>
|
|
105
|
-
<td data-value="100" class="pct high">100%</td>
|
|
106
|
-
<td data-value="1" class="abs high">1/1</td>
|
|
107
|
-
<td data-value="100" class="pct high">100%</td>
|
|
108
|
-
<td data-value="13" class="abs high">13/13</td>
|
|
109
|
-
</tr>
|
|
110
|
-
|
|
111
|
-
</tbody>
|
|
112
|
-
</table>
|
|
113
|
-
</div>
|
|
114
|
-
<div class='push'></div><!-- for sticky footer -->
|
|
115
|
-
</div><!-- /wrapper -->
|
|
116
|
-
<div class='footer quiet pad2 space-top1 center small'>
|
|
117
|
-
Code coverage generated by
|
|
118
|
-
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
119
|
-
at 2025-08-26T16:18:42.585Z
|
|
120
|
-
</div>
|
|
121
|
-
<script src="../prettify.js"></script>
|
|
122
|
-
<script>
|
|
123
|
-
window.onload = function () {
|
|
124
|
-
prettyPrint();
|
|
125
|
-
};
|
|
126
|
-
</script>
|
|
127
|
-
<script src="../sorter.js"></script>
|
|
128
|
-
<script src="../block-navigation.js"></script>
|
|
129
|
-
</body>
|
|
130
|
-
</html>
|
|
131
|
-
|