@xenterprises/fastify-xplaid 1.0.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.
@@ -0,0 +1,563 @@
1
+ /**
2
+ * xPlaid Tests
3
+ *
4
+ * Tests for the Plaid Fastify plugin
5
+ */
6
+
7
+ import { describe, test, beforeEach, afterEach, mock } from "node:test";
8
+ import assert from "node:assert";
9
+ import Fastify from "fastify";
10
+ import xPlaid, { ENVIRONMENTS, PRODUCTS, COUNTRY_CODES } from "../src/xPlaid.js";
11
+
12
+ // Mock the plaid module
13
+ const mockPlaidApi = {
14
+ linkTokenCreate: mock.fn(),
15
+ linkTokenGet: mock.fn(),
16
+ itemPublicTokenExchange: mock.fn(),
17
+ accountsGet: mock.fn(),
18
+ accountsBalanceGet: mock.fn(),
19
+ transactionsSync: mock.fn(),
20
+ transactionsGet: mock.fn(),
21
+ transactionsRefresh: mock.fn(),
22
+ identityGet: mock.fn(),
23
+ authGet: mock.fn(),
24
+ investmentsHoldingsGet: mock.fn(),
25
+ investmentsTransactionsGet: mock.fn(),
26
+ liabilitiesGet: mock.fn(),
27
+ itemGet: mock.fn(),
28
+ itemRemove: mock.fn(),
29
+ institutionsGetById: mock.fn(),
30
+ institutionsSearch: mock.fn(),
31
+ itemWebhookUpdate: mock.fn(),
32
+ webhookVerificationKeyGet: mock.fn(),
33
+ };
34
+
35
+ // Store original module for restoration
36
+ let originalPlaidModule;
37
+
38
+ describe("xPlaid Plugin", () => {
39
+ let fastify;
40
+
41
+ beforeEach(async () => {
42
+ fastify = Fastify();
43
+ // Reset all mocks
44
+ Object.values(mockPlaidApi).forEach((fn) => fn.mock.resetCalls());
45
+ });
46
+
47
+ afterEach(async () => {
48
+ await fastify.close();
49
+ });
50
+
51
+ describe("Plugin Registration", () => {
52
+ test("should register successfully with valid credentials", async () => {
53
+ await fastify.register(xPlaid, {
54
+ clientId: "test_client_id",
55
+ secret: "test_secret",
56
+ environment: "sandbox",
57
+ });
58
+ await fastify.ready();
59
+
60
+ assert.ok(fastify.xplaid, "xplaid should exist");
61
+ assert.ok(fastify.xplaid.link, "xplaid.link should exist");
62
+ assert.ok(fastify.xplaid.accounts, "xplaid.accounts should exist");
63
+ assert.ok(fastify.xplaid.transactions, "xplaid.transactions should exist");
64
+ assert.ok(fastify.xplaid.identity, "xplaid.identity should exist");
65
+ assert.ok(fastify.xplaid.auth, "xplaid.auth should exist");
66
+ assert.ok(fastify.xplaid.investments, "xplaid.investments should exist");
67
+ assert.ok(fastify.xplaid.liabilities, "xplaid.liabilities should exist");
68
+ assert.ok(fastify.xplaid.items, "xplaid.items should exist");
69
+ assert.ok(fastify.xplaid.webhooks, "xplaid.webhooks should exist");
70
+ assert.ok(fastify.xplaid.config, "xplaid.config should exist");
71
+ });
72
+
73
+ test("should throw error without clientId", async () => {
74
+ await assert.rejects(
75
+ async () => {
76
+ await fastify.register(xPlaid, {
77
+ secret: "test_secret",
78
+ environment: "sandbox",
79
+ });
80
+ await fastify.ready();
81
+ },
82
+ { message: "xPlaid: clientId is required" }
83
+ );
84
+ });
85
+
86
+ test("should throw error without secret", async () => {
87
+ await assert.rejects(
88
+ async () => {
89
+ await fastify.register(xPlaid, {
90
+ clientId: "test_client_id",
91
+ environment: "sandbox",
92
+ });
93
+ await fastify.ready();
94
+ },
95
+ { message: "xPlaid: secret is required" }
96
+ );
97
+ });
98
+
99
+ test("should default invalid environment to sandbox", async () => {
100
+ await fastify.register(xPlaid, {
101
+ clientId: "test_client_id",
102
+ secret: "test_secret",
103
+ environment: "invalid",
104
+ });
105
+ await fastify.ready();
106
+
107
+ // Invalid environments should fall back to sandbox
108
+ assert.strictEqual(fastify.xplaid.config.environment, "sandbox");
109
+ });
110
+
111
+ test("should skip registration when active is false", async () => {
112
+ await fastify.register(xPlaid, {
113
+ clientId: "test_client_id",
114
+ secret: "test_secret",
115
+ environment: "sandbox",
116
+ active: false,
117
+ });
118
+ await fastify.ready();
119
+
120
+ assert.ok(!fastify.xplaid, "xplaid should not exist");
121
+ });
122
+
123
+ test("should default to sandbox environment", async () => {
124
+ await fastify.register(xPlaid, {
125
+ clientId: "test_client_id",
126
+ secret: "test_secret",
127
+ });
128
+ await fastify.ready();
129
+
130
+ assert.strictEqual(fastify.xplaid.config.environment, "sandbox");
131
+ });
132
+
133
+ test("should expose constants", async () => {
134
+ await fastify.register(xPlaid, {
135
+ clientId: "test_client_id",
136
+ secret: "test_secret",
137
+ environment: "sandbox",
138
+ });
139
+ await fastify.ready();
140
+
141
+ assert.ok(fastify.xplaid.constants, "constants should exist");
142
+ assert.ok(fastify.xplaid.constants.ENVIRONMENTS, "ENVIRONMENTS should exist");
143
+ assert.ok(fastify.xplaid.constants.PRODUCTS, "PRODUCTS should exist");
144
+ assert.ok(fastify.xplaid.constants.COUNTRY_CODES, "COUNTRY_CODES should exist");
145
+ });
146
+
147
+ test("should mask clientId in config", async () => {
148
+ await fastify.register(xPlaid, {
149
+ clientId: "test_client_id_12345",
150
+ secret: "test_secret",
151
+ environment: "sandbox",
152
+ });
153
+ await fastify.ready();
154
+
155
+ assert.ok(fastify.xplaid.config.clientId.includes("***"), "clientId should be masked");
156
+ assert.ok(!fastify.xplaid.config.clientId.includes("test_client_id_12345"), "full clientId should not be exposed");
157
+ });
158
+ });
159
+
160
+ describe("Exported Constants", () => {
161
+ test("should export ENVIRONMENTS constant", () => {
162
+ assert.strictEqual(ENVIRONMENTS.SANDBOX, "sandbox");
163
+ assert.strictEqual(ENVIRONMENTS.DEVELOPMENT, "development");
164
+ assert.strictEqual(ENVIRONMENTS.PRODUCTION, "production");
165
+ });
166
+
167
+ test("should export PRODUCTS constant", () => {
168
+ assert.strictEqual(PRODUCTS.AUTH, "auth");
169
+ assert.strictEqual(PRODUCTS.TRANSACTIONS, "transactions");
170
+ assert.strictEqual(PRODUCTS.IDENTITY, "identity");
171
+ assert.strictEqual(PRODUCTS.INVESTMENTS, "investments");
172
+ assert.strictEqual(PRODUCTS.LIABILITIES, "liabilities");
173
+ assert.strictEqual(PRODUCTS.ASSETS, "assets");
174
+ });
175
+
176
+ test("should export COUNTRY_CODES constant", () => {
177
+ assert.strictEqual(COUNTRY_CODES.US, "US");
178
+ assert.strictEqual(COUNTRY_CODES.CA, "CA");
179
+ assert.strictEqual(COUNTRY_CODES.GB, "GB");
180
+ assert.strictEqual(COUNTRY_CODES.IE, "IE");
181
+ assert.strictEqual(COUNTRY_CODES.FR, "FR");
182
+ assert.strictEqual(COUNTRY_CODES.ES, "ES");
183
+ assert.strictEqual(COUNTRY_CODES.NL, "NL");
184
+ });
185
+ });
186
+
187
+ describe("Plugin Constants", () => {
188
+ test("should expose ENVIRONMENTS in plugin", async () => {
189
+ await fastify.register(xPlaid, {
190
+ clientId: "test_client_id",
191
+ secret: "test_secret",
192
+ environment: "sandbox",
193
+ });
194
+ await fastify.ready();
195
+
196
+ const { ENVIRONMENTS } = fastify.xplaid.constants;
197
+ assert.strictEqual(ENVIRONMENTS.SANDBOX, "sandbox");
198
+ assert.strictEqual(ENVIRONMENTS.DEVELOPMENT, "development");
199
+ assert.strictEqual(ENVIRONMENTS.PRODUCTION, "production");
200
+ });
201
+
202
+ test("should expose PRODUCTS in plugin", async () => {
203
+ await fastify.register(xPlaid, {
204
+ clientId: "test_client_id",
205
+ secret: "test_secret",
206
+ environment: "sandbox",
207
+ });
208
+ await fastify.ready();
209
+
210
+ const { PRODUCTS } = fastify.xplaid.constants;
211
+ assert.strictEqual(PRODUCTS.AUTH, "auth");
212
+ assert.strictEqual(PRODUCTS.TRANSACTIONS, "transactions");
213
+ assert.strictEqual(PRODUCTS.IDENTITY, "identity");
214
+ assert.strictEqual(PRODUCTS.INVESTMENTS, "investments");
215
+ assert.strictEqual(PRODUCTS.LIABILITIES, "liabilities");
216
+ });
217
+
218
+ test("should expose COUNTRY_CODES in plugin", async () => {
219
+ await fastify.register(xPlaid, {
220
+ clientId: "test_client_id",
221
+ secret: "test_secret",
222
+ environment: "sandbox",
223
+ });
224
+ await fastify.ready();
225
+
226
+ const { COUNTRY_CODES } = fastify.xplaid.constants;
227
+ assert.strictEqual(COUNTRY_CODES.US, "US");
228
+ assert.strictEqual(COUNTRY_CODES.CA, "CA");
229
+ assert.strictEqual(COUNTRY_CODES.GB, "GB");
230
+ });
231
+ });
232
+
233
+ describe("Raw Client Access", () => {
234
+ test("should expose raw Plaid client", async () => {
235
+ await fastify.register(xPlaid, {
236
+ clientId: "test_client_id",
237
+ secret: "test_secret",
238
+ environment: "sandbox",
239
+ });
240
+ await fastify.ready();
241
+
242
+ assert.ok(fastify.xplaid.raw, "raw client should exist");
243
+ assert.ok(typeof fastify.xplaid.raw === "object", "raw client should be an object");
244
+ });
245
+ });
246
+ });
247
+
248
+ describe("Link Service", () => {
249
+ let fastify;
250
+
251
+ beforeEach(async () => {
252
+ fastify = Fastify();
253
+ });
254
+
255
+ afterEach(async () => {
256
+ await fastify.close();
257
+ });
258
+
259
+ test("should have createToken method", async () => {
260
+ await fastify.register(xPlaid, {
261
+ clientId: "test_client_id",
262
+ secret: "test_secret",
263
+ environment: "sandbox",
264
+ });
265
+ await fastify.ready();
266
+
267
+ assert.ok(typeof fastify.xplaid.link.createToken === "function");
268
+ });
269
+
270
+ test("should have getToken method", async () => {
271
+ await fastify.register(xPlaid, {
272
+ clientId: "test_client_id",
273
+ secret: "test_secret",
274
+ environment: "sandbox",
275
+ });
276
+ await fastify.ready();
277
+
278
+ assert.ok(typeof fastify.xplaid.link.getToken === "function");
279
+ });
280
+
281
+ test("should have exchangePublicToken method", async () => {
282
+ await fastify.register(xPlaid, {
283
+ clientId: "test_client_id",
284
+ secret: "test_secret",
285
+ environment: "sandbox",
286
+ });
287
+ await fastify.ready();
288
+
289
+ assert.ok(typeof fastify.xplaid.link.exchangePublicToken === "function");
290
+ });
291
+ });
292
+
293
+ describe("Accounts Service", () => {
294
+ let fastify;
295
+
296
+ beforeEach(async () => {
297
+ fastify = Fastify();
298
+ });
299
+
300
+ afterEach(async () => {
301
+ await fastify.close();
302
+ });
303
+
304
+ test("should have get method", async () => {
305
+ await fastify.register(xPlaid, {
306
+ clientId: "test_client_id",
307
+ secret: "test_secret",
308
+ environment: "sandbox",
309
+ });
310
+ await fastify.ready();
311
+
312
+ assert.ok(typeof fastify.xplaid.accounts.get === "function");
313
+ });
314
+
315
+ test("should have getBalance method", async () => {
316
+ await fastify.register(xPlaid, {
317
+ clientId: "test_client_id",
318
+ secret: "test_secret",
319
+ environment: "sandbox",
320
+ });
321
+ await fastify.ready();
322
+
323
+ assert.ok(typeof fastify.xplaid.accounts.getBalance === "function");
324
+ });
325
+ });
326
+
327
+ describe("Transactions Service", () => {
328
+ let fastify;
329
+
330
+ beforeEach(async () => {
331
+ fastify = Fastify();
332
+ });
333
+
334
+ afterEach(async () => {
335
+ await fastify.close();
336
+ });
337
+
338
+ test("should have sync method", async () => {
339
+ await fastify.register(xPlaid, {
340
+ clientId: "test_client_id",
341
+ secret: "test_secret",
342
+ environment: "sandbox",
343
+ });
344
+ await fastify.ready();
345
+
346
+ assert.ok(typeof fastify.xplaid.transactions.sync === "function");
347
+ });
348
+
349
+ test("should have get method", async () => {
350
+ await fastify.register(xPlaid, {
351
+ clientId: "test_client_id",
352
+ secret: "test_secret",
353
+ environment: "sandbox",
354
+ });
355
+ await fastify.ready();
356
+
357
+ assert.ok(typeof fastify.xplaid.transactions.get === "function");
358
+ });
359
+
360
+ test("should have refresh method", async () => {
361
+ await fastify.register(xPlaid, {
362
+ clientId: "test_client_id",
363
+ secret: "test_secret",
364
+ environment: "sandbox",
365
+ });
366
+ await fastify.ready();
367
+
368
+ assert.ok(typeof fastify.xplaid.transactions.refresh === "function");
369
+ });
370
+ });
371
+
372
+ describe("Identity Service", () => {
373
+ let fastify;
374
+
375
+ beforeEach(async () => {
376
+ fastify = Fastify();
377
+ });
378
+
379
+ afterEach(async () => {
380
+ await fastify.close();
381
+ });
382
+
383
+ test("should have get method", async () => {
384
+ await fastify.register(xPlaid, {
385
+ clientId: "test_client_id",
386
+ secret: "test_secret",
387
+ environment: "sandbox",
388
+ });
389
+ await fastify.ready();
390
+
391
+ assert.ok(typeof fastify.xplaid.identity.get === "function");
392
+ });
393
+ });
394
+
395
+ describe("Auth Service", () => {
396
+ let fastify;
397
+
398
+ beforeEach(async () => {
399
+ fastify = Fastify();
400
+ });
401
+
402
+ afterEach(async () => {
403
+ await fastify.close();
404
+ });
405
+
406
+ test("should have get method", async () => {
407
+ await fastify.register(xPlaid, {
408
+ clientId: "test_client_id",
409
+ secret: "test_secret",
410
+ environment: "sandbox",
411
+ });
412
+ await fastify.ready();
413
+
414
+ assert.ok(typeof fastify.xplaid.auth.get === "function");
415
+ });
416
+ });
417
+
418
+ describe("Investments Service", () => {
419
+ let fastify;
420
+
421
+ beforeEach(async () => {
422
+ fastify = Fastify();
423
+ });
424
+
425
+ afterEach(async () => {
426
+ await fastify.close();
427
+ });
428
+
429
+ test("should have getHoldings method", async () => {
430
+ await fastify.register(xPlaid, {
431
+ clientId: "test_client_id",
432
+ secret: "test_secret",
433
+ environment: "sandbox",
434
+ });
435
+ await fastify.ready();
436
+
437
+ assert.ok(typeof fastify.xplaid.investments.getHoldings === "function");
438
+ });
439
+
440
+ test("should have getTransactions method", async () => {
441
+ await fastify.register(xPlaid, {
442
+ clientId: "test_client_id",
443
+ secret: "test_secret",
444
+ environment: "sandbox",
445
+ });
446
+ await fastify.ready();
447
+
448
+ assert.ok(typeof fastify.xplaid.investments.getTransactions === "function");
449
+ });
450
+ });
451
+
452
+ describe("Liabilities Service", () => {
453
+ let fastify;
454
+
455
+ beforeEach(async () => {
456
+ fastify = Fastify();
457
+ });
458
+
459
+ afterEach(async () => {
460
+ await fastify.close();
461
+ });
462
+
463
+ test("should have get method", async () => {
464
+ await fastify.register(xPlaid, {
465
+ clientId: "test_client_id",
466
+ secret: "test_secret",
467
+ environment: "sandbox",
468
+ });
469
+ await fastify.ready();
470
+
471
+ assert.ok(typeof fastify.xplaid.liabilities.get === "function");
472
+ });
473
+ });
474
+
475
+ describe("Items Service", () => {
476
+ let fastify;
477
+
478
+ beforeEach(async () => {
479
+ fastify = Fastify();
480
+ });
481
+
482
+ afterEach(async () => {
483
+ await fastify.close();
484
+ });
485
+
486
+ test("should have get method", async () => {
487
+ await fastify.register(xPlaid, {
488
+ clientId: "test_client_id",
489
+ secret: "test_secret",
490
+ environment: "sandbox",
491
+ });
492
+ await fastify.ready();
493
+
494
+ assert.ok(typeof fastify.xplaid.items.get === "function");
495
+ });
496
+
497
+ test("should have remove method", async () => {
498
+ await fastify.register(xPlaid, {
499
+ clientId: "test_client_id",
500
+ secret: "test_secret",
501
+ environment: "sandbox",
502
+ });
503
+ await fastify.ready();
504
+
505
+ assert.ok(typeof fastify.xplaid.items.remove === "function");
506
+ });
507
+
508
+ test("should have getInstitution method", async () => {
509
+ await fastify.register(xPlaid, {
510
+ clientId: "test_client_id",
511
+ secret: "test_secret",
512
+ environment: "sandbox",
513
+ });
514
+ await fastify.ready();
515
+
516
+ assert.ok(typeof fastify.xplaid.items.getInstitution === "function");
517
+ });
518
+
519
+ test("should have searchInstitutions method", async () => {
520
+ await fastify.register(xPlaid, {
521
+ clientId: "test_client_id",
522
+ secret: "test_secret",
523
+ environment: "sandbox",
524
+ });
525
+ await fastify.ready();
526
+
527
+ assert.ok(typeof fastify.xplaid.items.searchInstitutions === "function");
528
+ });
529
+ });
530
+
531
+ describe("Webhooks Service", () => {
532
+ let fastify;
533
+
534
+ beforeEach(async () => {
535
+ fastify = Fastify();
536
+ });
537
+
538
+ afterEach(async () => {
539
+ await fastify.close();
540
+ });
541
+
542
+ test("should have update method", async () => {
543
+ await fastify.register(xPlaid, {
544
+ clientId: "test_client_id",
545
+ secret: "test_secret",
546
+ environment: "sandbox",
547
+ });
548
+ await fastify.ready();
549
+
550
+ assert.ok(typeof fastify.xplaid.webhooks.update === "function");
551
+ });
552
+
553
+ test("should have getVerificationKey method", async () => {
554
+ await fastify.register(xPlaid, {
555
+ clientId: "test_client_id",
556
+ secret: "test_secret",
557
+ environment: "sandbox",
558
+ });
559
+ await fastify.ready();
560
+
561
+ assert.ok(typeof fastify.xplaid.webhooks.getVerificationKey === "function");
562
+ });
563
+ });