@xenterprises/fastify-xsignwell 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,539 @@
1
+ /**
2
+ * xSignwell Tests
3
+ *
4
+ * Test suite for the xSignwell plugin.
5
+ */
6
+
7
+ import { test, describe, beforeEach, afterEach, mock } from "node:test";
8
+ import assert from "node:assert";
9
+ import Fastify from "fastify";
10
+ import xSignwell from "../src/xSignwell.js";
11
+
12
+ // Mock fetch globally
13
+ const originalFetch = global.fetch;
14
+
15
+ function mockFetch(responses = {}) {
16
+ global.fetch = mock.fn(async (url, options) => {
17
+ const path = new URL(url).pathname;
18
+
19
+ // Find matching response
20
+ for (const [pattern, response] of Object.entries(responses)) {
21
+ if (path.includes(pattern)) {
22
+ return {
23
+ ok: response.ok !== false,
24
+ status: response.status || 200,
25
+ text: async () => JSON.stringify(response.data || {}),
26
+ json: async () => response.data || {},
27
+ };
28
+ }
29
+ }
30
+
31
+ // Default success response
32
+ return {
33
+ ok: true,
34
+ status: 200,
35
+ text: async () => JSON.stringify({ success: true }),
36
+ json: async () => ({ success: true }),
37
+ };
38
+ });
39
+ }
40
+
41
+ function restoreFetch() {
42
+ global.fetch = originalFetch;
43
+ }
44
+
45
+ describe("xSignwell Plugin", () => {
46
+ let fastify;
47
+
48
+ beforeEach(async () => {
49
+ fastify = Fastify({ logger: false });
50
+ mockFetch({
51
+ "/me": { data: { email: "test@example.com", name: "Test User" } },
52
+ });
53
+ });
54
+
55
+ afterEach(async () => {
56
+ restoreFetch();
57
+ await fastify.close();
58
+ });
59
+
60
+ describe("Plugin Registration", () => {
61
+ test("should register successfully with valid API key", async () => {
62
+ await fastify.register(xSignwell, {
63
+ apiKey: "test_api_key",
64
+ });
65
+ await fastify.ready();
66
+
67
+ assert.ok(fastify.xsignwell, "xsignwell should exist");
68
+ assert.ok(fastify.xsignwell.documents, "xsignwell.documents should exist");
69
+ assert.ok(fastify.xsignwell.templates, "xsignwell.templates should exist");
70
+ assert.ok(fastify.xsignwell.webhooks, "xsignwell.webhooks should exist");
71
+ assert.ok(fastify.xsignwell.bulkSend, "xsignwell.bulkSend should exist");
72
+ assert.ok(fastify.xsignwell.me, "xsignwell.me should exist");
73
+ assert.ok(fastify.xsignwell.config, "xsignwell.config should exist");
74
+ });
75
+
76
+ test("should throw error without API key", async () => {
77
+ await assert.rejects(
78
+ async () => {
79
+ await fastify.register(xSignwell, {});
80
+ await fastify.ready();
81
+ },
82
+ /apiKey is required/
83
+ );
84
+ });
85
+
86
+ test("should skip registration when active is false", async () => {
87
+ await fastify.register(xSignwell, {
88
+ apiKey: "test_api_key",
89
+ active: false,
90
+ });
91
+ await fastify.ready();
92
+
93
+ assert.ok(!fastify.xsignwell, "xsignwell should not exist");
94
+ });
95
+
96
+ test("should store test mode configuration", async () => {
97
+ await fastify.register(xSignwell, {
98
+ apiKey: "test_api_key",
99
+ testMode: true,
100
+ });
101
+ await fastify.ready();
102
+
103
+ assert.strictEqual(fastify.xsignwell.config.testMode, true);
104
+ });
105
+ });
106
+
107
+ describe("Account Info", () => {
108
+ test("should get account info", async () => {
109
+ await fastify.register(xSignwell, {
110
+ apiKey: "test_api_key",
111
+ });
112
+ await fastify.ready();
113
+
114
+ const account = await fastify.xsignwell.me();
115
+ assert.strictEqual(account.email, "test@example.com");
116
+ });
117
+ });
118
+ });
119
+
120
+ describe("Documents Service", () => {
121
+ let fastify;
122
+
123
+ beforeEach(async () => {
124
+ fastify = Fastify({ logger: false });
125
+ });
126
+
127
+ afterEach(async () => {
128
+ restoreFetch();
129
+ await fastify.close();
130
+ });
131
+
132
+ test("should create a document", async () => {
133
+ mockFetch({
134
+ "/documents": {
135
+ data: {
136
+ id: "doc_123",
137
+ name: "Test Document",
138
+ status: "draft",
139
+ },
140
+ },
141
+ });
142
+
143
+ await fastify.register(xSignwell, { apiKey: "test_key" });
144
+ await fastify.ready();
145
+
146
+ const doc = await fastify.xsignwell.documents.create({
147
+ name: "Test Document",
148
+ recipients: [
149
+ { email: "john@example.com", name: "John Doe" },
150
+ ],
151
+ files: [
152
+ { name: "test.pdf", url: "https://example.com/test.pdf" },
153
+ ],
154
+ });
155
+
156
+ assert.strictEqual(doc.id, "doc_123");
157
+ assert.strictEqual(doc.name, "Test Document");
158
+ });
159
+
160
+ test("should create document from template", async () => {
161
+ mockFetch({
162
+ "/document_templates/tpl_123/documents": {
163
+ data: {
164
+ id: "doc_456",
165
+ template_id: "tpl_123",
166
+ status: "pending",
167
+ },
168
+ },
169
+ });
170
+
171
+ await fastify.register(xSignwell, { apiKey: "test_key" });
172
+ await fastify.ready();
173
+
174
+ const doc = await fastify.xsignwell.documents.createFromTemplate("tpl_123", {
175
+ recipients: [
176
+ { id: "signer_1", email: "john@example.com", name: "John Doe" },
177
+ ],
178
+ fields: {
179
+ name: "John Doe",
180
+ date: "2025-01-01",
181
+ },
182
+ });
183
+
184
+ assert.strictEqual(doc.id, "doc_456");
185
+ assert.strictEqual(doc.template_id, "tpl_123");
186
+ });
187
+
188
+ test("should get a document", async () => {
189
+ mockFetch({
190
+ "/documents/doc_123": {
191
+ data: {
192
+ id: "doc_123",
193
+ name: "Test Document",
194
+ status: "completed",
195
+ recipients: [
196
+ { id: "r_1", email: "john@example.com", status: "signed" },
197
+ ],
198
+ },
199
+ },
200
+ });
201
+
202
+ await fastify.register(xSignwell, { apiKey: "test_key" });
203
+ await fastify.ready();
204
+
205
+ const doc = await fastify.xsignwell.documents.get("doc_123");
206
+
207
+ assert.strictEqual(doc.id, "doc_123");
208
+ assert.strictEqual(doc.status, "completed");
209
+ });
210
+
211
+ test("should send a document", async () => {
212
+ mockFetch({
213
+ "/documents/doc_123/send": {
214
+ data: { id: "doc_123", status: "pending" },
215
+ },
216
+ });
217
+
218
+ await fastify.register(xSignwell, { apiKey: "test_key" });
219
+ await fastify.ready();
220
+
221
+ const result = await fastify.xsignwell.documents.send("doc_123");
222
+
223
+ assert.strictEqual(result.status, "pending");
224
+ });
225
+
226
+ test("should send reminder", async () => {
227
+ mockFetch({
228
+ "/documents/doc_123/remind": {
229
+ data: { success: true },
230
+ },
231
+ });
232
+
233
+ await fastify.register(xSignwell, { apiKey: "test_key" });
234
+ await fastify.ready();
235
+
236
+ const result = await fastify.xsignwell.documents.remind("doc_123");
237
+
238
+ assert.ok(result.success);
239
+ });
240
+
241
+ test("should delete a document", async () => {
242
+ mockFetch({
243
+ "/documents/doc_123": {
244
+ data: { success: true },
245
+ },
246
+ });
247
+
248
+ await fastify.register(xSignwell, { apiKey: "test_key" });
249
+ await fastify.ready();
250
+
251
+ const result = await fastify.xsignwell.documents.remove("doc_123");
252
+
253
+ assert.ok(result.success);
254
+ });
255
+
256
+ test("should get completed PDF", async () => {
257
+ mockFetch({
258
+ "/documents/doc_123/completed_pdf": {
259
+ data: {
260
+ file_url: "https://signwell.com/documents/doc_123.pdf",
261
+ },
262
+ },
263
+ });
264
+
265
+ await fastify.register(xSignwell, { apiKey: "test_key" });
266
+ await fastify.ready();
267
+
268
+ const result = await fastify.xsignwell.documents.getCompletedPdf("doc_123");
269
+
270
+ assert.ok(result.file_url);
271
+ });
272
+ });
273
+
274
+ describe("Templates Service", () => {
275
+ let fastify;
276
+
277
+ beforeEach(async () => {
278
+ fastify = Fastify({ logger: false });
279
+ });
280
+
281
+ afterEach(async () => {
282
+ restoreFetch();
283
+ await fastify.close();
284
+ });
285
+
286
+ test("should get a template", async () => {
287
+ mockFetch({
288
+ "/document_templates/tpl_123": {
289
+ data: {
290
+ id: "tpl_123",
291
+ name: "NDA Template",
292
+ fields: [
293
+ { name: "company_name", type: "text" },
294
+ ],
295
+ },
296
+ },
297
+ });
298
+
299
+ await fastify.register(xSignwell, { apiKey: "test_key" });
300
+ await fastify.ready();
301
+
302
+ const template = await fastify.xsignwell.templates.get("tpl_123");
303
+
304
+ assert.strictEqual(template.id, "tpl_123");
305
+ assert.strictEqual(template.name, "NDA Template");
306
+ });
307
+
308
+ test("should list templates", async () => {
309
+ mockFetch({
310
+ "/document_templates": {
311
+ data: {
312
+ templates: [
313
+ { id: "tpl_1", name: "Template 1" },
314
+ { id: "tpl_2", name: "Template 2" },
315
+ ],
316
+ },
317
+ },
318
+ });
319
+
320
+ await fastify.register(xSignwell, { apiKey: "test_key" });
321
+ await fastify.ready();
322
+
323
+ const result = await fastify.xsignwell.templates.list();
324
+
325
+ assert.strictEqual(result.templates.length, 2);
326
+ });
327
+
328
+ test("should create a template", async () => {
329
+ mockFetch({
330
+ "/document_templates": {
331
+ data: {
332
+ id: "tpl_new",
333
+ name: "New Template",
334
+ },
335
+ },
336
+ });
337
+
338
+ await fastify.register(xSignwell, { apiKey: "test_key" });
339
+ await fastify.ready();
340
+
341
+ const template = await fastify.xsignwell.templates.create({
342
+ name: "New Template",
343
+ files: [{ name: "doc.pdf", url: "https://example.com/doc.pdf" }],
344
+ });
345
+
346
+ assert.strictEqual(template.id, "tpl_new");
347
+ });
348
+
349
+ test("should delete a template", async () => {
350
+ mockFetch({
351
+ "/document_templates/tpl_123": {
352
+ data: { success: true },
353
+ },
354
+ });
355
+
356
+ await fastify.register(xSignwell, { apiKey: "test_key" });
357
+ await fastify.ready();
358
+
359
+ const result = await fastify.xsignwell.templates.remove("tpl_123");
360
+
361
+ assert.ok(result.success);
362
+ });
363
+ });
364
+
365
+ describe("Webhooks Service", () => {
366
+ let fastify;
367
+
368
+ beforeEach(async () => {
369
+ fastify = Fastify({ logger: false });
370
+ });
371
+
372
+ afterEach(async () => {
373
+ restoreFetch();
374
+ await fastify.close();
375
+ });
376
+
377
+ test("should list webhooks", async () => {
378
+ mockFetch({
379
+ "/hooks": {
380
+ data: {
381
+ hooks: [
382
+ { id: "hook_1", callback_url: "https://example.com/webhook" },
383
+ ],
384
+ },
385
+ },
386
+ });
387
+
388
+ await fastify.register(xSignwell, { apiKey: "test_key" });
389
+ await fastify.ready();
390
+
391
+ const result = await fastify.xsignwell.webhooks.list();
392
+
393
+ assert.ok(result.hooks);
394
+ });
395
+
396
+ test("should create a webhook", async () => {
397
+ mockFetch({
398
+ "/hooks": {
399
+ data: {
400
+ id: "hook_new",
401
+ callback_url: "https://example.com/webhook",
402
+ },
403
+ },
404
+ });
405
+
406
+ await fastify.register(xSignwell, { apiKey: "test_key" });
407
+ await fastify.ready();
408
+
409
+ const webhook = await fastify.xsignwell.webhooks.create({
410
+ callbackUrl: "https://example.com/webhook",
411
+ });
412
+
413
+ assert.strictEqual(webhook.id, "hook_new");
414
+ });
415
+
416
+ test("should delete a webhook", async () => {
417
+ mockFetch({
418
+ "/hooks/hook_123": {
419
+ data: { success: true },
420
+ },
421
+ });
422
+
423
+ await fastify.register(xSignwell, { apiKey: "test_key" });
424
+ await fastify.ready();
425
+
426
+ const result = await fastify.xsignwell.webhooks.remove("hook_123");
427
+
428
+ assert.ok(result.success);
429
+ });
430
+
431
+ test("should parse webhook event", async () => {
432
+ await fastify.register(xSignwell, { apiKey: "test_key" });
433
+ await fastify.ready();
434
+
435
+ const payload = {
436
+ event: "document.completed",
437
+ document: {
438
+ id: "doc_123",
439
+ name: "Test Document",
440
+ },
441
+ timestamp: "2025-01-01T00:00:00Z",
442
+ };
443
+
444
+ const event = fastify.xsignwell.webhooks.parseEvent(payload);
445
+
446
+ assert.strictEqual(event.event, "document.completed");
447
+ assert.strictEqual(event.documentId, "doc_123");
448
+ assert.ok(event.document);
449
+ });
450
+
451
+ test("should have event type constants", async () => {
452
+ await fastify.register(xSignwell, { apiKey: "test_key" });
453
+ await fastify.ready();
454
+
455
+ const events = fastify.xsignwell.webhooks.events;
456
+
457
+ assert.strictEqual(events.DOCUMENT_COMPLETED, "document.completed");
458
+ assert.strictEqual(events.DOCUMENT_SIGNED, "document.signed");
459
+ assert.strictEqual(events.DOCUMENT_DECLINED, "document.declined");
460
+ });
461
+ });
462
+
463
+ describe("Bulk Send Service", () => {
464
+ let fastify;
465
+
466
+ beforeEach(async () => {
467
+ fastify = Fastify({ logger: false });
468
+ });
469
+
470
+ afterEach(async () => {
471
+ restoreFetch();
472
+ await fastify.close();
473
+ });
474
+
475
+ test("should create a bulk send", async () => {
476
+ mockFetch({
477
+ "/bulk_sends": {
478
+ data: {
479
+ id: "bulk_123",
480
+ status: "processing",
481
+ document_count: 2,
482
+ },
483
+ },
484
+ });
485
+
486
+ await fastify.register(xSignwell, { apiKey: "test_key" });
487
+ await fastify.ready();
488
+
489
+ const bulkSend = await fastify.xsignwell.bulkSend.create({
490
+ templateId: "tpl_123",
491
+ recipients: [
492
+ { email: "john@example.com", name: "John" },
493
+ { email: "jane@example.com", name: "Jane" },
494
+ ],
495
+ });
496
+
497
+ assert.strictEqual(bulkSend.id, "bulk_123");
498
+ assert.strictEqual(bulkSend.document_count, 2);
499
+ });
500
+
501
+ test("should list bulk sends", async () => {
502
+ mockFetch({
503
+ "/bulk_sends": {
504
+ data: {
505
+ bulk_sends: [
506
+ { id: "bulk_1", status: "completed" },
507
+ ],
508
+ },
509
+ },
510
+ });
511
+
512
+ await fastify.register(xSignwell, { apiKey: "test_key" });
513
+ await fastify.ready();
514
+
515
+ const result = await fastify.xsignwell.bulkSend.list();
516
+
517
+ assert.ok(result.bulk_sends);
518
+ });
519
+
520
+ test("should get bulk send documents", async () => {
521
+ mockFetch({
522
+ "/bulk_sends/bulk_123/documents": {
523
+ data: {
524
+ documents: [
525
+ { id: "doc_1", status: "pending" },
526
+ { id: "doc_2", status: "completed" },
527
+ ],
528
+ },
529
+ },
530
+ });
531
+
532
+ await fastify.register(xSignwell, { apiKey: "test_key" });
533
+ await fastify.ready();
534
+
535
+ const result = await fastify.xsignwell.bulkSend.getDocuments("bulk_123");
536
+
537
+ assert.strictEqual(result.documents.length, 2);
538
+ });
539
+ });