apacuana-sdk-core 0.2.0 → 0.3.0
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/README.md +64 -15
- package/coverage/clover.xml +145 -111
- package/coverage/coverage-final.json +6 -6
- package/coverage/lcov-report/index.html +30 -30
- package/coverage/lcov-report/src/api/certs.js.html +73 -28
- package/coverage/lcov-report/src/api/index.html +31 -31
- package/coverage/lcov-report/src/api/revocations.js.html +1 -1
- package/coverage/lcov-report/src/api/signatures.js.html +186 -159
- package/coverage/lcov-report/src/api/users.js.html +24 -63
- 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 +1 -1
- package/coverage/lcov-report/src/index.js.html +1 -1
- package/coverage/lcov-report/src/utils/constant.js.html +4 -4
- package/coverage/lcov-report/src/utils/helpers.js.html +101 -50
- package/coverage/lcov-report/src/utils/httpClient.js.html +1 -1
- package/coverage/lcov-report/src/utils/index.html +19 -19
- package/coverage/lcov.info +277 -205
- package/dist/index.js +136 -242
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +136 -242
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/api/certs.js +25 -10
- package/src/api/signatures.js +106 -97
- package/src/api/users.js +16 -29
- package/src/utils/helpers.js +17 -0
- package/tests/api/certs.test.js +58 -74
- package/tests/api/signatures.test.js +18 -73
- package/tests/api/users.test.js +10 -10
package/tests/api/certs.test.js
CHANGED
|
@@ -1,128 +1,112 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { getConfig } from "../../src/config";
|
|
1
|
+
import { getConfig } from "../../src/config/index";
|
|
3
2
|
import { httpRequest } from "../../src/utils/httpClient";
|
|
3
|
+
import helpers from "../../src/utils/helpers";
|
|
4
4
|
import { ApacuanaAPIError } from "../../src/errors";
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
STATUS_CERTIFICATE,
|
|
8
|
-
} from "../../src/utils/constant";
|
|
5
|
+
import { generateCert, getCertStatus } from "../../src/api/certs";
|
|
6
|
+
import { INTEGRATION_TYPE } from "../../src/utils/constant";
|
|
9
7
|
|
|
8
|
+
jest.mock("../../src/config/index");
|
|
10
9
|
jest.mock("../../src/utils/httpClient");
|
|
11
|
-
jest.mock("../../src/
|
|
10
|
+
jest.mock("../../src/utils/helpers");
|
|
12
11
|
|
|
13
|
-
describe("API
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
afterEach(() => {
|
|
12
|
+
describe("Certificate API - certs.js", () => {
|
|
13
|
+
beforeEach(() => {
|
|
17
14
|
jest.clearAllMocks();
|
|
18
15
|
});
|
|
19
16
|
|
|
20
17
|
describe("generateCert", () => {
|
|
21
|
-
it("
|
|
22
|
-
const mockResponse = { cert: "new-cert", success: true };
|
|
23
|
-
httpRequest.mockResolvedValue(mockResponse);
|
|
18
|
+
it("should generate a certificate for ONBOARDING integration", async () => {
|
|
24
19
|
getConfig.mockReturnValue({
|
|
25
20
|
integrationType: INTEGRATION_TYPE.ONBOARDING,
|
|
26
21
|
});
|
|
22
|
+
helpers.encryptedCsr.mockReturnValue("encrypted-csr");
|
|
23
|
+
httpRequest.mockResolvedValue({ cert: "new-cert", success: true });
|
|
27
24
|
|
|
28
|
-
const result = await generateCert(
|
|
25
|
+
const result = await generateCert("some-csr");
|
|
29
26
|
|
|
30
|
-
expect(
|
|
27
|
+
expect(helpers.validateCsr).toHaveBeenCalledWith("some-csr");
|
|
28
|
+
expect(helpers.encryptedCsr).toHaveBeenCalledWith("some-csr");
|
|
31
29
|
expect(httpRequest).toHaveBeenCalledWith(
|
|
32
30
|
"services/api/register/certificate",
|
|
33
|
-
|
|
31
|
+
"encrypted-csr",
|
|
34
32
|
"POST"
|
|
35
33
|
);
|
|
34
|
+
expect(result).toEqual({ cert: "new-cert", success: true });
|
|
36
35
|
});
|
|
37
36
|
|
|
38
|
-
it("
|
|
37
|
+
it("should throw an error if API response does not contain a certificate", async () => {
|
|
39
38
|
getConfig.mockReturnValue({
|
|
40
39
|
integrationType: INTEGRATION_TYPE.ONBOARDING,
|
|
41
40
|
});
|
|
42
|
-
|
|
41
|
+
helpers.encryptedCsr.mockReturnValue("encrypted-csr");
|
|
42
|
+
httpRequest.mockResolvedValue({ success: false });
|
|
43
|
+
|
|
44
|
+
await expect(generateCert("some-csr")).rejects.toThrow(
|
|
43
45
|
new ApacuanaAPIError(
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
"
|
|
46
|
+
"The API response does not contain the certificate.",
|
|
47
|
+
undefined,
|
|
48
|
+
"INVALID_API_RESPONSE"
|
|
47
49
|
)
|
|
48
50
|
);
|
|
49
51
|
});
|
|
50
52
|
|
|
51
|
-
it("
|
|
53
|
+
it("should throw an error for ONPREMISE", async () => {
|
|
52
54
|
getConfig.mockReturnValue({
|
|
53
|
-
integrationType: INTEGRATION_TYPE.
|
|
55
|
+
integrationType: INTEGRATION_TYPE.ONPREMISE,
|
|
54
56
|
});
|
|
55
|
-
|
|
57
|
+
|
|
58
|
+
await expect(generateCert("some-csr")).rejects.toThrow(
|
|
56
59
|
new ApacuanaAPIError(
|
|
57
|
-
"
|
|
58
|
-
|
|
59
|
-
"
|
|
60
|
+
"Certificate generation is not supported for integration type: ONPREMISE",
|
|
61
|
+
501,
|
|
62
|
+
"NOT_IMPLEMENTED"
|
|
60
63
|
)
|
|
61
64
|
);
|
|
62
65
|
});
|
|
63
66
|
|
|
64
|
-
it("
|
|
65
|
-
getConfig.mockReturnValue({
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
await expect(generateCert("csr-invalido")).rejects.toThrow(
|
|
69
|
-
new ApacuanaAPIError(
|
|
70
|
-
"El CSR debe estar codificado en formato base64 válido.",
|
|
71
|
-
400,
|
|
72
|
-
"INVALID_CSR_ENCODING"
|
|
73
|
-
)
|
|
67
|
+
it("should throw an error if integration type is not supported", async () => {
|
|
68
|
+
getConfig.mockReturnValue({ integrationType: "INVALID_TYPE" });
|
|
69
|
+
await expect(generateCert("some-csr")).rejects.toThrow(
|
|
70
|
+
"Unsupported integration type: INVALID_TYPE"
|
|
74
71
|
);
|
|
75
72
|
});
|
|
76
73
|
|
|
77
|
-
it("
|
|
78
|
-
getConfig.mockReturnValue({
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
});
|
|
74
|
+
it("should re-throw ApacuanaAPIError if httpRequest fails", async () => {
|
|
75
|
+
getConfig.mockReturnValue({
|
|
76
|
+
integrationType: INTEGRATION_TYPE.ONBOARDING,
|
|
77
|
+
});
|
|
78
|
+
const apiError = new ApacuanaAPIError("API Error", 500, "API_ERROR");
|
|
79
|
+
httpRequest.mockRejectedValue(apiError);
|
|
84
80
|
|
|
85
|
-
|
|
86
|
-
getConfig.mockReturnValue({ integrationType: "UNSUPPORTED_TYPE" });
|
|
87
|
-
await expect(generateCert(validBase64Csr)).rejects.toThrow(
|
|
88
|
-
new ApacuanaAPIError(
|
|
89
|
-
"Tipo de integración no soportado: UNSUPPORTED_TYPE",
|
|
90
|
-
400,
|
|
91
|
-
"UNSUPPORTED_INTEGRATION_TYPE"
|
|
92
|
-
)
|
|
93
|
-
);
|
|
81
|
+
await expect(generateCert("some-csr")).rejects.toThrow(apiError);
|
|
94
82
|
});
|
|
95
83
|
|
|
96
|
-
it("
|
|
97
|
-
httpRequest.mockResolvedValue({ success: true }); // No 'cert' property
|
|
84
|
+
it("should throw a generic error if something else fails", async () => {
|
|
98
85
|
getConfig.mockReturnValue({
|
|
99
86
|
integrationType: INTEGRATION_TYPE.ONBOARDING,
|
|
100
87
|
});
|
|
88
|
+
const genericError = new Error("Something failed");
|
|
89
|
+
httpRequest.mockRejectedValue(genericError);
|
|
101
90
|
|
|
102
|
-
await expect(generateCert(
|
|
103
|
-
|
|
104
|
-
"La respuesta de la API no contiene el certificado.",
|
|
105
|
-
undefined,
|
|
106
|
-
"INVALID_API_RESPONSE"
|
|
107
|
-
)
|
|
91
|
+
await expect(generateCert("some-csr")).rejects.toThrow(
|
|
92
|
+
"Certificate generation failed: Something failed"
|
|
108
93
|
);
|
|
109
94
|
});
|
|
110
95
|
});
|
|
111
96
|
|
|
112
97
|
describe("getCertStatus", () => {
|
|
113
|
-
it("
|
|
114
|
-
const mockUserData = {
|
|
115
|
-
cert: "some-cert-data",
|
|
116
|
-
verificationstatus: { id: 1 }, // VERIFICATION_STATUS.APPROVED
|
|
117
|
-
certificationId: "some-cert-id",
|
|
118
|
-
approvedUser: true,
|
|
119
|
-
};
|
|
98
|
+
it("should return the certificate status from helpers", () => {
|
|
99
|
+
const mockUserData = { certStatus: "VALID" };
|
|
120
100
|
getConfig.mockReturnValue({ userData: mockUserData });
|
|
101
|
+
helpers.getCertificateStatus.mockReturnValue("VALID");
|
|
102
|
+
|
|
121
103
|
const result = getCertStatus(true);
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
104
|
+
|
|
105
|
+
expect(helpers.getCertificateStatus).toHaveBeenCalledWith(
|
|
106
|
+
mockUserData,
|
|
107
|
+
true
|
|
108
|
+
);
|
|
109
|
+
expect(result).toEqual({ status: "VALID", success: true });
|
|
126
110
|
});
|
|
127
111
|
});
|
|
128
|
-
});
|
|
112
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getConfig } from "../../src/config";
|
|
2
2
|
import { httpRequest } from "../../src/utils/httpClient";
|
|
3
3
|
import { ApacuanaAPIError } from "../../src/errors";
|
|
4
|
-
import { addSigner, getDocs } from "../../src/api/signatures";
|
|
4
|
+
import { addSigner, getDocs, getDigest, signDocument } from "../../src/api/signatures";
|
|
5
5
|
import helpers from "../../src/utils/helpers";
|
|
6
6
|
import { INTEGRATION_TYPE } from "../../src/utils/constant";
|
|
7
7
|
|
|
@@ -13,6 +13,7 @@ jest.mock("../../src/utils/helpers", () => ({
|
|
|
13
13
|
validateSignOnPremiseData: jest.fn(),
|
|
14
14
|
signDigest: jest.fn(),
|
|
15
15
|
validateGetDocsData: jest.fn(),
|
|
16
|
+
validateGetDigestData: jest.fn(),
|
|
16
17
|
}));
|
|
17
18
|
|
|
18
19
|
describe("API - Signatures", () => {
|
|
@@ -38,18 +39,19 @@ describe("API - Signatures", () => {
|
|
|
38
39
|
);
|
|
39
40
|
});
|
|
40
41
|
|
|
41
|
-
it("should
|
|
42
|
+
it("should throw not implemented for ONPREMISE integration", async () => {
|
|
42
43
|
getConfig.mockReturnValue({
|
|
43
44
|
integrationType: INTEGRATION_TYPE.ONPREMISE,
|
|
44
45
|
});
|
|
45
46
|
const signerData = { name: "John Doe" };
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
await expect(addSigner(signerData)).rejects.toThrow(
|
|
49
|
+
new ApacuanaAPIError(
|
|
50
|
+
"Adding signers is not supported for integration type: ONPREMISE",
|
|
51
|
+
501,
|
|
52
|
+
"NOT_IMPLEMENTED"
|
|
53
|
+
)
|
|
54
|
+
);
|
|
53
55
|
});
|
|
54
56
|
|
|
55
57
|
it("should throw an error for unsupported integration type", async () => {
|
|
@@ -57,7 +59,7 @@ describe("API - Signatures", () => {
|
|
|
57
59
|
const signerData = { name: "test" };
|
|
58
60
|
await expect(addSigner(signerData)).rejects.toThrow(
|
|
59
61
|
new ApacuanaAPIError(
|
|
60
|
-
"
|
|
62
|
+
"Unsupported integration type: UNSUPPORTED",
|
|
61
63
|
400,
|
|
62
64
|
"UNSUPPORTED_INTEGRATION_TYPE"
|
|
63
65
|
)
|
|
@@ -67,70 +69,13 @@ describe("API - Signatures", () => {
|
|
|
67
69
|
it("should throw an error if signerData is invalid", async () => {
|
|
68
70
|
await expect(addSigner(null)).rejects.toThrow(
|
|
69
71
|
new ApacuanaAPIError(
|
|
70
|
-
"
|
|
71
|
-
400,
|
|
72
|
-
"INVALID_PARAMETER"
|
|
73
|
-
)
|
|
74
|
-
);
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
/*
|
|
79
|
-
describe("signDocument", () => {
|
|
80
|
-
const onBoardingData = {
|
|
81
|
-
documentData: { id: "doc1" },
|
|
82
|
-
signatureData: { id: "sig1" },
|
|
83
|
-
};
|
|
84
|
-
const onPremiseData = {
|
|
85
|
-
signature: { id: "sig1", positions: [] },
|
|
86
|
-
cert: "my-cert",
|
|
87
|
-
privateKey: "my-key",
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
it("should call signDocumentOnBoarding for ONBOARDING integration", async () => {
|
|
91
|
-
getConfig.mockReturnValue({ integrationType: INTEGRATION_TYPE.ONBOARDING });
|
|
92
|
-
const mockResponse = {
|
|
93
|
-
success: true,
|
|
94
|
-
id: "signed-doc-id",
|
|
95
|
-
message: "Firmado",
|
|
96
|
-
};
|
|
97
|
-
httpRequest.mockResolvedValue(mockResponse);
|
|
98
|
-
|
|
99
|
-
const result = await signDocument(onBoardingData);
|
|
100
|
-
|
|
101
|
-
expect(httpRequest).toHaveBeenCalledWith(
|
|
102
|
-
"/docs/sign",
|
|
103
|
-
onBoardingData,
|
|
104
|
-
"POST"
|
|
105
|
-
);
|
|
106
|
-
expect(result).toEqual(mockResponse);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it("should throw TypeError for ONPREMISE integration due to implementation issue", async () => {
|
|
110
|
-
getConfig.mockReturnValue({
|
|
111
|
-
integrationType: INTEGRATION_TYPE.ONPREMISE,
|
|
112
|
-
});
|
|
113
|
-
httpRequest
|
|
114
|
-
.mockResolvedValueOnce({ data: { digest: "test-digest" } })
|
|
115
|
-
.mockResolvedValueOnce({ data: "signed-response" });
|
|
116
|
-
helpers.signDigest.mockResolvedValue("signed-digest");
|
|
117
|
-
|
|
118
|
-
await expect(signDocument(onPremiseData)).rejects.toThrow(
|
|
119
|
-
"Fallo en la firma del documento (on-premise): Cannot read properties of undefined (reading 'map')"
|
|
120
|
-
);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it("should throw an error if data is invalid", async () => {
|
|
124
|
-
await expect(signDocument({})).rejects.toThrow(
|
|
125
|
-
new ApacuanaAPIError(
|
|
126
|
-
"El parámetro 'data' es requerido y debe ser un objeto no vacío.",
|
|
72
|
+
"Signer data (signerData) is required and must be a non-empty object.",
|
|
127
73
|
400,
|
|
128
74
|
"INVALID_PARAMETER"
|
|
129
75
|
)
|
|
130
76
|
);
|
|
131
77
|
});
|
|
132
78
|
});
|
|
133
|
-
*/
|
|
134
79
|
|
|
135
80
|
describe("getDocs", () => {
|
|
136
81
|
const paginationData = { page: 1, size: 10 };
|
|
@@ -153,7 +98,7 @@ describe("API - Signatures", () => {
|
|
|
153
98
|
);
|
|
154
99
|
});
|
|
155
100
|
|
|
156
|
-
it("should throw an error for ONPREMISE integration
|
|
101
|
+
it("should throw an error for ONPREMISE integration", async () => {
|
|
157
102
|
getConfig.mockReturnValue({
|
|
158
103
|
integrationType: INTEGRATION_TYPE.ONPREMISE,
|
|
159
104
|
customerId: "test-customer",
|
|
@@ -161,13 +106,13 @@ describe("API - Signatures", () => {
|
|
|
161
106
|
httpRequest.mockResolvedValue({ docs: [] });
|
|
162
107
|
|
|
163
108
|
await expect(getDocs(paginationData)).rejects.toThrow(
|
|
164
|
-
"
|
|
109
|
+
"Document retrieval is not supported for integration type: ONBOARDING"
|
|
165
110
|
);
|
|
166
111
|
});
|
|
167
112
|
|
|
168
113
|
it("should throw an error if page or size are missing", async () => {
|
|
169
114
|
const validationError = new ApacuanaAPIError(
|
|
170
|
-
"
|
|
115
|
+
"Parameters 'page' and 'size' are required.",
|
|
171
116
|
400,
|
|
172
117
|
"INVALID_PARAMETER"
|
|
173
118
|
);
|
|
@@ -180,7 +125,7 @@ describe("API - Signatures", () => {
|
|
|
180
125
|
|
|
181
126
|
it("should throw an error if status is invalid", async () => {
|
|
182
127
|
const validationError = new ApacuanaAPIError(
|
|
183
|
-
"
|
|
128
|
+
"Parameter 'status' is not valid.",
|
|
184
129
|
400,
|
|
185
130
|
"INVALID_PARAMETER"
|
|
186
131
|
);
|
|
@@ -193,13 +138,13 @@ describe("API - Signatures", () => {
|
|
|
193
138
|
);
|
|
194
139
|
});
|
|
195
140
|
|
|
196
|
-
it("should throw an error for non-on-premise integrations", async () => {
|
|
141
|
+
it("should throw an error for non-on-premise integrations when customerId is missing", async () => {
|
|
197
142
|
getConfig.mockReturnValue({
|
|
198
143
|
integrationType: INTEGRATION_TYPE.ONBOARDING,
|
|
199
144
|
});
|
|
200
145
|
await expect(getDocs(paginationData)).rejects.toThrow(
|
|
201
146
|
new ApacuanaAPIError(
|
|
202
|
-
"
|
|
147
|
+
"'customerId' is not configured. Please configure the SDK.",
|
|
203
148
|
400,
|
|
204
149
|
"CONFIGURATION_ERROR"
|
|
205
150
|
)
|
package/tests/api/users.test.js
CHANGED
|
@@ -67,34 +67,34 @@ describe("getCustomer", () => {
|
|
|
67
67
|
});
|
|
68
68
|
});
|
|
69
69
|
|
|
70
|
-
test("
|
|
70
|
+
test("should throw an error if configuration is incomplete", async () => {
|
|
71
71
|
getConfig.mockReturnValue({
|
|
72
72
|
verificationId: "mock-verify-id",
|
|
73
73
|
customerId: null,
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
await expect(getCustomer()).rejects.toThrow(
|
|
77
|
-
"
|
|
77
|
+
"Both 'verificationId' and 'customerId' must be configured."
|
|
78
78
|
);
|
|
79
79
|
expect(httpRequest).not.toHaveBeenCalled();
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
-
test("
|
|
82
|
+
test("should throw ApacuanaAPIError if backend does not return sessionid or entry", async () => {
|
|
83
83
|
httpRequest.mockResolvedValueOnce({
|
|
84
84
|
success: true,
|
|
85
|
-
message: "
|
|
85
|
+
message: "Backend error, token could not be generated.",
|
|
86
86
|
entry: { userId: "mock-user" },
|
|
87
87
|
});
|
|
88
88
|
|
|
89
89
|
await expect(getCustomer()).rejects.toThrow(
|
|
90
|
-
"
|
|
90
|
+
"The API response does not contain the user."
|
|
91
91
|
);
|
|
92
92
|
expect(httpRequest).toHaveBeenCalledTimes(1);
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
test("
|
|
95
|
+
test("should rethrow ApacuanaAPIError if httpClient request fails", async () => {
|
|
96
96
|
const apiError = new ApacuanaAPIError(
|
|
97
|
-
"
|
|
97
|
+
"Authentication error",
|
|
98
98
|
401,
|
|
99
99
|
"AUTH_ERROR"
|
|
100
100
|
);
|
|
@@ -104,12 +104,12 @@ describe("getCustomer", () => {
|
|
|
104
104
|
expect(httpRequest).toHaveBeenCalledTimes(1);
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
test("
|
|
108
|
-
const genericError = new Error("
|
|
107
|
+
test("should throw ApacuanaAPIError on unexpected error", async () => {
|
|
108
|
+
const genericError = new Error("Network or unknown error");
|
|
109
109
|
httpRequest.mockRejectedValueOnce(genericError);
|
|
110
110
|
|
|
111
111
|
await expect(getCustomer()).rejects.toThrow(
|
|
112
|
-
"
|
|
112
|
+
"Unexpected failure getting token: Network or unknown error"
|
|
113
113
|
);
|
|
114
114
|
expect(httpRequest).toHaveBeenCalledTimes(1);
|
|
115
115
|
});
|