@terreno/api 0.7.2 → 0.8.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.
Files changed (50) hide show
  1. package/dist/__tests__/{versionCheck.test.js → versionCheckPlugin.test.js} +2 -2
  2. package/dist/api.d.ts +4 -2
  3. package/dist/api.js +7 -2
  4. package/dist/consentApp.d.ts +33 -0
  5. package/dist/consentApp.js +484 -0
  6. package/dist/consentApp.test.d.ts +1 -0
  7. package/dist/consentApp.test.js +1132 -0
  8. package/dist/index.d.ts +6 -0
  9. package/dist/index.js +6 -0
  10. package/dist/models/consentForm.d.ts +2 -0
  11. package/dist/models/consentForm.js +115 -0
  12. package/dist/models/consentResponse.d.ts +2 -0
  13. package/dist/models/consentResponse.js +73 -0
  14. package/dist/models/versionConfig.d.ts +1 -1
  15. package/dist/openApiValidator.js +2 -0
  16. package/dist/populate.d.ts +1 -0
  17. package/dist/populate.js +53 -13
  18. package/dist/syncConsents.d.ts +67 -0
  19. package/dist/syncConsents.js +334 -0
  20. package/dist/syncConsents.test.d.ts +1 -0
  21. package/dist/syncConsents.test.js +249 -0
  22. package/dist/terrenoApp.js +6 -5
  23. package/dist/terrenoPlugin.d.ts +1 -1
  24. package/dist/types/consentForm.d.ts +32 -0
  25. package/dist/types/consentForm.js +2 -0
  26. package/dist/types/consentResponse.d.ts +23 -0
  27. package/dist/types/consentResponse.js +2 -0
  28. package/dist/vendor/wesleytodd-openapi/lib/generate-doc.js +1 -1
  29. package/dist/versionCheckPlugin.d.ts +2 -0
  30. package/dist/versionCheckPlugin.js +3 -6
  31. package/package.json +1 -1
  32. package/src/__tests__/{versionCheck.test.ts → versionCheckPlugin.test.ts} +2 -2
  33. package/src/api.ts +11 -4
  34. package/src/consentApp.test.ts +749 -0
  35. package/src/consentApp.ts +463 -0
  36. package/src/index.ts +6 -0
  37. package/src/models/consentForm.ts +123 -0
  38. package/src/models/consentResponse.ts +78 -0
  39. package/src/models/versionConfig.ts +1 -1
  40. package/src/openApiValidator.ts +2 -0
  41. package/src/populate.ts +33 -0
  42. package/src/syncConsents.test.ts +124 -0
  43. package/src/syncConsents.ts +263 -0
  44. package/src/terrenoApp.ts +6 -6
  45. package/src/terrenoPlugin.ts +1 -1
  46. package/src/types/consentForm.ts +41 -0
  47. package/src/types/consentResponse.ts +34 -0
  48. package/src/vendor/wesleytodd-openapi/lib/generate-doc.js +1 -1
  49. package/src/versionCheckPlugin.ts +5 -6
  50. /package/dist/__tests__/{versionCheck.test.d.ts → versionCheckPlugin.test.d.ts} +0 -0
@@ -0,0 +1,1132 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ var __read = (this && this.__read) || function (o, n) {
39
+ var m = typeof Symbol === "function" && o[Symbol.iterator];
40
+ if (!m) return o;
41
+ var i = m.call(o), r, ar = [], e;
42
+ try {
43
+ while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
44
+ }
45
+ catch (error) { e = { error: error }; }
46
+ finally {
47
+ try {
48
+ if (r && !r.done && (m = i["return"])) m.call(i);
49
+ }
50
+ finally { if (e) throw e.error; }
51
+ }
52
+ return ar;
53
+ };
54
+ var __importDefault = (this && this.__importDefault) || function (mod) {
55
+ return (mod && mod.__esModule) ? mod : { "default": mod };
56
+ };
57
+ Object.defineProperty(exports, "__esModule", { value: true });
58
+ var bun_test_1 = require("bun:test");
59
+ var supertest_1 = __importDefault(require("supertest"));
60
+ var consentApp_1 = require("./consentApp");
61
+ var consentForm_1 = require("./models/consentForm");
62
+ var consentResponse_1 = require("./models/consentResponse");
63
+ var terrenoApp_1 = require("./terrenoApp");
64
+ var tests_1 = require("./tests");
65
+ var buildApp = function (consentAppOptions) {
66
+ if (consentAppOptions === void 0) { consentAppOptions = {}; }
67
+ return new terrenoApp_1.TerrenoApp({
68
+ skipListen: true,
69
+ userModel: tests_1.UserModel,
70
+ })
71
+ .register(new consentApp_1.ConsentApp(consentAppOptions))
72
+ .build();
73
+ };
74
+ (0, bun_test_1.describe)("ConsentApp", function () {
75
+ var admin;
76
+ var notAdmin;
77
+ var adminAgent;
78
+ var userAgent;
79
+ (0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
80
+ var app;
81
+ var _a;
82
+ return __generator(this, function (_b) {
83
+ switch (_b.label) {
84
+ case 0: return [4 /*yield*/, (0, tests_1.setupDb)()];
85
+ case 1:
86
+ _a = __read.apply(void 0, [_b.sent(), 2]), admin = _a[0], notAdmin = _a[1];
87
+ return [4 /*yield*/, Promise.all([consentForm_1.ConsentForm.deleteMany({}), consentResponse_1.ConsentResponse.deleteMany({})])];
88
+ case 2:
89
+ _b.sent();
90
+ app = buildApp({ auditTrail: true });
91
+ return [4 /*yield*/, (0, tests_1.authAsUser)(app, "admin")];
92
+ case 3:
93
+ adminAgent = _b.sent();
94
+ return [4 /*yield*/, (0, tests_1.authAsUser)(app, "notAdmin")];
95
+ case 4:
96
+ userAgent = _b.sent();
97
+ return [2 /*return*/];
98
+ }
99
+ });
100
+ }); });
101
+ (0, bun_test_1.afterEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
102
+ return __generator(this, function (_a) {
103
+ switch (_a.label) {
104
+ case 0: return [4 /*yield*/, Promise.all([consentForm_1.ConsentForm.deleteMany({}), consentResponse_1.ConsentResponse.deleteMany({})])];
105
+ case 1:
106
+ _a.sent();
107
+ return [2 /*return*/];
108
+ }
109
+ });
110
+ }); });
111
+ (0, bun_test_1.describe)("GET /consent-forms (admin CRUD)", function () {
112
+ (0, bun_test_1.it)("returns empty list when no forms exist", function () { return __awaiter(void 0, void 0, void 0, function () {
113
+ var res;
114
+ return __generator(this, function (_a) {
115
+ switch (_a.label) {
116
+ case 0: return [4 /*yield*/, adminAgent.get("/consent-forms").expect(200)];
117
+ case 1:
118
+ res = _a.sent();
119
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(0);
120
+ return [2 /*return*/];
121
+ }
122
+ });
123
+ }); });
124
+ (0, bun_test_1.it)("lists consent forms for admins", function () { return __awaiter(void 0, void 0, void 0, function () {
125
+ var res;
126
+ return __generator(this, function (_a) {
127
+ switch (_a.label) {
128
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
129
+ active: true,
130
+ content: new Map([["en", "# Terms\nPlease agree."]]),
131
+ order: 1,
132
+ slug: "terms",
133
+ title: "Terms of Service",
134
+ type: "terms",
135
+ version: 1,
136
+ })];
137
+ case 1:
138
+ _a.sent();
139
+ return [4 /*yield*/, adminAgent.get("/consent-forms").expect(200)];
140
+ case 2:
141
+ res = _a.sent();
142
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(1);
143
+ (0, bun_test_1.expect)(res.body.data[0].title).toBe("Terms of Service");
144
+ return [2 /*return*/];
145
+ }
146
+ });
147
+ }); });
148
+ (0, bun_test_1.it)("blocks non-admins from listing forms", function () { return __awaiter(void 0, void 0, void 0, function () {
149
+ return __generator(this, function (_a) {
150
+ switch (_a.label) {
151
+ case 0: return [4 /*yield*/, userAgent.get("/consent-forms").expect(405)];
152
+ case 1:
153
+ _a.sent();
154
+ return [2 /*return*/];
155
+ }
156
+ });
157
+ }); });
158
+ (0, bun_test_1.it)("creates a consent form as admin", function () { return __awaiter(void 0, void 0, void 0, function () {
159
+ var res;
160
+ return __generator(this, function (_a) {
161
+ switch (_a.label) {
162
+ case 0: return [4 /*yield*/, adminAgent
163
+ .post("/consent-forms")
164
+ .send({
165
+ active: false,
166
+ content: { en: "# Privacy\nWe protect your data." },
167
+ order: 2,
168
+ slug: "privacy",
169
+ title: "Privacy Policy",
170
+ type: "privacy",
171
+ version: 1,
172
+ })
173
+ .expect(201)];
174
+ case 1:
175
+ res = _a.sent();
176
+ (0, bun_test_1.expect)(res.body.data.title).toBe("Privacy Policy");
177
+ (0, bun_test_1.expect)(res.body.data.slug).toBe("privacy");
178
+ return [2 /*return*/];
179
+ }
180
+ });
181
+ }); });
182
+ (0, bun_test_1.it)("updates a consent form as admin", function () { return __awaiter(void 0, void 0, void 0, function () {
183
+ var form, res;
184
+ return __generator(this, function (_a) {
185
+ switch (_a.label) {
186
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
187
+ active: false,
188
+ content: new Map([["en", "# HIPAA"]]),
189
+ order: 3,
190
+ slug: "hipaa",
191
+ title: "HIPAA Notice",
192
+ type: "hipaa",
193
+ version: 1,
194
+ })];
195
+ case 1:
196
+ form = _a.sent();
197
+ return [4 /*yield*/, adminAgent
198
+ .patch("/consent-forms/".concat(form._id))
199
+ .send({ title: "HIPAA Authorization" })
200
+ .expect(200)];
201
+ case 2:
202
+ res = _a.sent();
203
+ (0, bun_test_1.expect)(res.body.data.title).toBe("HIPAA Authorization");
204
+ return [2 /*return*/];
205
+ }
206
+ });
207
+ }); });
208
+ });
209
+ (0, bun_test_1.describe)("POST /consent-forms/:id/publish", function () {
210
+ (0, bun_test_1.it)("creates a new version and activates it", function () { return __awaiter(void 0, void 0, void 0, function () {
211
+ var form, res, oldForm;
212
+ return __generator(this, function (_a) {
213
+ switch (_a.label) {
214
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
215
+ active: true,
216
+ content: new Map([["en", "# Terms v1"]]),
217
+ order: 1,
218
+ slug: "terms-publish",
219
+ title: "Terms v1",
220
+ type: "terms",
221
+ version: 1,
222
+ })];
223
+ case 1:
224
+ form = _a.sent();
225
+ return [4 /*yield*/, adminAgent.post("/consent-forms/".concat(form._id, "/publish")).expect(200)];
226
+ case 2:
227
+ res = _a.sent();
228
+ (0, bun_test_1.expect)(res.body.data.version).toBe(2);
229
+ (0, bun_test_1.expect)(res.body.data.active).toBe(true);
230
+ (0, bun_test_1.expect)(res.body.data.slug).toBe("terms-publish");
231
+ return [4 /*yield*/, consentForm_1.ConsentForm.findById(form._id)];
232
+ case 3:
233
+ oldForm = _a.sent();
234
+ (0, bun_test_1.expect)(oldForm === null || oldForm === void 0 ? void 0 : oldForm.active).toBe(false);
235
+ return [2 /*return*/];
236
+ }
237
+ });
238
+ }); });
239
+ (0, bun_test_1.it)("increments version number correctly", function () { return __awaiter(void 0, void 0, void 0, function () {
240
+ var form, res;
241
+ return __generator(this, function (_a) {
242
+ switch (_a.label) {
243
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
244
+ active: true,
245
+ content: new Map([["en", "# Content"]]),
246
+ order: 1,
247
+ slug: "versioned",
248
+ title: "Versioned Form",
249
+ type: "agreement",
250
+ version: 3,
251
+ })];
252
+ case 1:
253
+ form = _a.sent();
254
+ return [4 /*yield*/, adminAgent.post("/consent-forms/".concat(form._id, "/publish")).expect(200)];
255
+ case 2:
256
+ res = _a.sent();
257
+ (0, bun_test_1.expect)(res.body.data.version).toBe(4);
258
+ return [2 /*return*/];
259
+ }
260
+ });
261
+ }); });
262
+ (0, bun_test_1.it)("requires admin to publish", function () { return __awaiter(void 0, void 0, void 0, function () {
263
+ var form;
264
+ return __generator(this, function (_a) {
265
+ switch (_a.label) {
266
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
267
+ active: true,
268
+ content: new Map([["en", "# Terms"]]),
269
+ order: 1,
270
+ slug: "terms-nonadmin",
271
+ title: "Terms",
272
+ type: "terms",
273
+ version: 1,
274
+ })];
275
+ case 1:
276
+ form = _a.sent();
277
+ return [4 /*yield*/, userAgent.post("/consent-forms/".concat(form._id, "/publish")).expect(403)];
278
+ case 2:
279
+ _a.sent();
280
+ return [2 /*return*/];
281
+ }
282
+ });
283
+ }); });
284
+ });
285
+ (0, bun_test_1.describe)("GET /consent-responses (admin read-only)", function () {
286
+ (0, bun_test_1.it)("returns empty list when no responses", function () { return __awaiter(void 0, void 0, void 0, function () {
287
+ var res;
288
+ return __generator(this, function (_a) {
289
+ switch (_a.label) {
290
+ case 0: return [4 /*yield*/, adminAgent.get("/consent-responses").expect(200)];
291
+ case 1:
292
+ res = _a.sent();
293
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(0);
294
+ return [2 /*return*/];
295
+ }
296
+ });
297
+ }); });
298
+ (0, bun_test_1.it)("lists responses for admins", function () { return __awaiter(void 0, void 0, void 0, function () {
299
+ var form, res;
300
+ return __generator(this, function (_a) {
301
+ switch (_a.label) {
302
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
303
+ active: true,
304
+ content: new Map([["en", "# Terms"]]),
305
+ order: 1,
306
+ slug: "terms-resp",
307
+ title: "Terms",
308
+ type: "terms",
309
+ version: 1,
310
+ })];
311
+ case 1:
312
+ form = _a.sent();
313
+ return [4 /*yield*/, consentResponse_1.ConsentResponse.create({
314
+ agreed: true,
315
+ agreedAt: new Date(),
316
+ consentFormId: form._id,
317
+ formVersionSnapshot: 1,
318
+ locale: "en",
319
+ userId: notAdmin._id,
320
+ })];
321
+ case 2:
322
+ _a.sent();
323
+ return [4 /*yield*/, adminAgent.get("/consent-responses").expect(200)];
324
+ case 3:
325
+ res = _a.sent();
326
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(1);
327
+ (0, bun_test_1.expect)(res.body.data[0].agreed).toBe(true);
328
+ return [2 /*return*/];
329
+ }
330
+ });
331
+ }); });
332
+ (0, bun_test_1.it)("blocks non-admins from listing responses", function () { return __awaiter(void 0, void 0, void 0, function () {
333
+ return __generator(this, function (_a) {
334
+ switch (_a.label) {
335
+ case 0: return [4 /*yield*/, userAgent.get("/consent-responses").expect(405)];
336
+ case 1:
337
+ _a.sent();
338
+ return [2 /*return*/];
339
+ }
340
+ });
341
+ }); });
342
+ (0, bun_test_1.it)("blocks create on consent-responses", function () { return __awaiter(void 0, void 0, void 0, function () {
343
+ return __generator(this, function (_a) {
344
+ switch (_a.label) {
345
+ case 0: return [4 /*yield*/, adminAgent.post("/consent-responses").send({}).expect(405)];
346
+ case 1:
347
+ _a.sent();
348
+ return [2 /*return*/];
349
+ }
350
+ });
351
+ }); });
352
+ });
353
+ (0, bun_test_1.describe)("GET /consents/pending", function () {
354
+ (0, bun_test_1.it)("returns empty array when no active forms", function () { return __awaiter(void 0, void 0, void 0, function () {
355
+ var res;
356
+ return __generator(this, function (_a) {
357
+ switch (_a.label) {
358
+ case 0: return [4 /*yield*/, userAgent.get("/consents/pending").expect(200)];
359
+ case 1:
360
+ res = _a.sent();
361
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(0);
362
+ return [2 /*return*/];
363
+ }
364
+ });
365
+ }); });
366
+ (0, bun_test_1.it)("returns active forms the user hasn't responded to", function () { return __awaiter(void 0, void 0, void 0, function () {
367
+ var res;
368
+ return __generator(this, function (_a) {
369
+ switch (_a.label) {
370
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
371
+ active: true,
372
+ content: new Map([["en", "# Terms"]]),
373
+ order: 1,
374
+ slug: "pending-terms",
375
+ title: "Terms",
376
+ type: "terms",
377
+ version: 1,
378
+ })];
379
+ case 1:
380
+ _a.sent();
381
+ return [4 /*yield*/, userAgent.get("/consents/pending").expect(200)];
382
+ case 2:
383
+ res = _a.sent();
384
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(1);
385
+ (0, bun_test_1.expect)(res.body.data[0].title).toBe("Terms");
386
+ return [2 /*return*/];
387
+ }
388
+ });
389
+ }); });
390
+ (0, bun_test_1.it)("excludes forms the user has already responded to at the current version", function () { return __awaiter(void 0, void 0, void 0, function () {
391
+ var form, res;
392
+ return __generator(this, function (_a) {
393
+ switch (_a.label) {
394
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
395
+ active: true,
396
+ content: new Map([["en", "# Terms"]]),
397
+ order: 1,
398
+ slug: "responded-terms",
399
+ title: "Terms",
400
+ type: "terms",
401
+ version: 1,
402
+ })];
403
+ case 1:
404
+ form = _a.sent();
405
+ return [4 /*yield*/, consentResponse_1.ConsentResponse.create({
406
+ agreed: true,
407
+ agreedAt: new Date(),
408
+ consentFormId: form._id,
409
+ formVersionSnapshot: 1,
410
+ locale: "en",
411
+ userId: notAdmin._id,
412
+ })];
413
+ case 2:
414
+ _a.sent();
415
+ return [4 /*yield*/, userAgent.get("/consents/pending").expect(200)];
416
+ case 3:
417
+ res = _a.sent();
418
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(0);
419
+ return [2 /*return*/];
420
+ }
421
+ });
422
+ }); });
423
+ (0, bun_test_1.it)("includes forms when the user responded to an older version", function () { return __awaiter(void 0, void 0, void 0, function () {
424
+ var form, res;
425
+ return __generator(this, function (_a) {
426
+ switch (_a.label) {
427
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
428
+ active: true,
429
+ content: new Map([["en", "# Terms v2"]]),
430
+ order: 1,
431
+ slug: "updated-terms",
432
+ title: "Terms",
433
+ type: "terms",
434
+ version: 2,
435
+ })];
436
+ case 1:
437
+ form = _a.sent();
438
+ // User responded to version 1
439
+ return [4 /*yield*/, consentResponse_1.ConsentResponse.create({
440
+ agreed: true,
441
+ agreedAt: new Date(),
442
+ consentFormId: form._id,
443
+ formVersionSnapshot: 1,
444
+ locale: "en",
445
+ userId: notAdmin._id,
446
+ })];
447
+ case 2:
448
+ // User responded to version 1
449
+ _a.sent();
450
+ return [4 /*yield*/, userAgent.get("/consents/pending").expect(200)];
451
+ case 3:
452
+ res = _a.sent();
453
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(1);
454
+ return [2 /*return*/];
455
+ }
456
+ });
457
+ }); });
458
+ (0, bun_test_1.it)("returns forms sorted by order field", function () { return __awaiter(void 0, void 0, void 0, function () {
459
+ var res;
460
+ return __generator(this, function (_a) {
461
+ switch (_a.label) {
462
+ case 0: return [4 /*yield*/, Promise.all([
463
+ consentForm_1.ConsentForm.create({
464
+ active: true,
465
+ content: new Map([["en", "# Second"]]),
466
+ order: 2,
467
+ slug: "second-form",
468
+ title: "Second Form",
469
+ type: "privacy",
470
+ version: 1,
471
+ }),
472
+ consentForm_1.ConsentForm.create({
473
+ active: true,
474
+ content: new Map([["en", "# First"]]),
475
+ order: 1,
476
+ slug: "first-form",
477
+ title: "First Form",
478
+ type: "terms",
479
+ version: 1,
480
+ }),
481
+ ])];
482
+ case 1:
483
+ _a.sent();
484
+ return [4 /*yield*/, userAgent.get("/consents/pending").expect(200)];
485
+ case 2:
486
+ res = _a.sent();
487
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(2);
488
+ (0, bun_test_1.expect)(res.body.data[0].title).toBe("First Form");
489
+ (0, bun_test_1.expect)(res.body.data[1].title).toBe("Second Form");
490
+ return [2 /*return*/];
491
+ }
492
+ });
493
+ }); });
494
+ (0, bun_test_1.it)("applies resolveConsentForms callback to filter forms", function () { return __awaiter(void 0, void 0, void 0, function () {
495
+ var filteredApp, filteredAgent, res;
496
+ return __generator(this, function (_a) {
497
+ switch (_a.label) {
498
+ case 0: return [4 /*yield*/, Promise.all([
499
+ consentForm_1.ConsentForm.create({
500
+ active: true,
501
+ content: new Map([["en", "# Privacy"]]),
502
+ order: 1,
503
+ slug: "resolver-privacy",
504
+ title: "Privacy",
505
+ type: "privacy",
506
+ version: 1,
507
+ }),
508
+ consentForm_1.ConsentForm.create({
509
+ active: true,
510
+ content: new Map([["en", "# Terms"]]),
511
+ order: 2,
512
+ slug: "resolver-terms",
513
+ title: "Terms",
514
+ type: "terms",
515
+ version: 1,
516
+ }),
517
+ ])];
518
+ case 1:
519
+ _a.sent();
520
+ filteredApp = buildApp({
521
+ resolveConsentForms: function (_user, forms) {
522
+ return forms.filter(function (f) { return f.type === "privacy"; });
523
+ },
524
+ });
525
+ return [4 /*yield*/, (0, tests_1.authAsUser)(filteredApp, "notAdmin")];
526
+ case 2:
527
+ filteredAgent = _a.sent();
528
+ return [4 /*yield*/, filteredAgent.get("/consents/pending").expect(200)];
529
+ case 3:
530
+ res = _a.sent();
531
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(1);
532
+ (0, bun_test_1.expect)(res.body.data[0].type).toBe("privacy");
533
+ return [2 /*return*/];
534
+ }
535
+ });
536
+ }); });
537
+ (0, bun_test_1.it)("resolveConsentForms can filter by user admin status", function () { return __awaiter(void 0, void 0, void 0, function () {
538
+ var filteredApp, filteredAdmin, filteredUser, adminRes, userRes;
539
+ return __generator(this, function (_a) {
540
+ switch (_a.label) {
541
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
542
+ active: true,
543
+ content: new Map([["en", "# Terms"]]),
544
+ order: 1,
545
+ slug: "admin-filter-terms",
546
+ title: "Terms",
547
+ type: "terms",
548
+ version: 1,
549
+ })];
550
+ case 1:
551
+ _a.sent();
552
+ filteredApp = buildApp({
553
+ resolveConsentForms: function (user, forms) { return (user.admin ? [] : forms); },
554
+ });
555
+ return [4 /*yield*/, (0, tests_1.authAsUser)(filteredApp, "admin")];
556
+ case 2:
557
+ filteredAdmin = _a.sent();
558
+ return [4 /*yield*/, (0, tests_1.authAsUser)(filteredApp, "notAdmin")];
559
+ case 3:
560
+ filteredUser = _a.sent();
561
+ return [4 /*yield*/, filteredAdmin.get("/consents/pending").expect(200)];
562
+ case 4:
563
+ adminRes = _a.sent();
564
+ (0, bun_test_1.expect)(adminRes.body.data).toHaveLength(0);
565
+ return [4 /*yield*/, filteredUser.get("/consents/pending").expect(200)];
566
+ case 5:
567
+ userRes = _a.sent();
568
+ (0, bun_test_1.expect)(userRes.body.data).toHaveLength(1);
569
+ return [2 /*return*/];
570
+ }
571
+ });
572
+ }); });
573
+ (0, bun_test_1.it)("requires authentication", function () { return __awaiter(void 0, void 0, void 0, function () {
574
+ var app;
575
+ return __generator(this, function (_a) {
576
+ switch (_a.label) {
577
+ case 0:
578
+ app = buildApp();
579
+ return [4 /*yield*/, (0, supertest_1.default)(app).get("/consents/pending").expect(401)];
580
+ case 1:
581
+ _a.sent();
582
+ return [2 /*return*/];
583
+ }
584
+ });
585
+ }); });
586
+ });
587
+ (0, bun_test_1.describe)("POST /consents/respond", function () {
588
+ var form;
589
+ (0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
590
+ return __generator(this, function (_a) {
591
+ switch (_a.label) {
592
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
593
+ active: true,
594
+ content: new Map([["en", "# Terms"]]),
595
+ order: 1,
596
+ slug: "respond-terms",
597
+ title: "Terms",
598
+ type: "terms",
599
+ version: 1,
600
+ })];
601
+ case 1:
602
+ form = _a.sent();
603
+ return [2 /*return*/];
604
+ }
605
+ });
606
+ }); });
607
+ (0, bun_test_1.it)("creates a consent response", function () { return __awaiter(void 0, void 0, void 0, function () {
608
+ var res;
609
+ return __generator(this, function (_a) {
610
+ switch (_a.label) {
611
+ case 0: return [4 /*yield*/, userAgent
612
+ .post("/consents/respond")
613
+ .send({
614
+ agreed: true,
615
+ consentFormId: form._id,
616
+ locale: "en",
617
+ })
618
+ .expect(200)];
619
+ case 1:
620
+ res = _a.sent();
621
+ (0, bun_test_1.expect)(res.body.data.agreed).toBe(true);
622
+ (0, bun_test_1.expect)(res.body.data.locale).toBe("en");
623
+ return [2 /*return*/];
624
+ }
625
+ });
626
+ }); });
627
+ (0, bun_test_1.it)("returns 400 when consentFormId is missing", function () { return __awaiter(void 0, void 0, void 0, function () {
628
+ return __generator(this, function (_a) {
629
+ switch (_a.label) {
630
+ case 0: return [4 /*yield*/, userAgent.post("/consents/respond").send({ agreed: true, locale: "en" }).expect(400)];
631
+ case 1:
632
+ _a.sent();
633
+ return [2 /*return*/];
634
+ }
635
+ });
636
+ }); });
637
+ (0, bun_test_1.it)("returns 400 when agreed field is missing", function () { return __awaiter(void 0, void 0, void 0, function () {
638
+ return __generator(this, function (_a) {
639
+ switch (_a.label) {
640
+ case 0: return [4 /*yield*/, userAgent
641
+ .post("/consents/respond")
642
+ .send({ consentFormId: form._id, locale: "en" })
643
+ .expect(400)];
644
+ case 1:
645
+ _a.sent();
646
+ return [2 /*return*/];
647
+ }
648
+ });
649
+ }); });
650
+ (0, bun_test_1.it)("returns 400 when locale is missing", function () { return __awaiter(void 0, void 0, void 0, function () {
651
+ return __generator(this, function (_a) {
652
+ switch (_a.label) {
653
+ case 0: return [4 /*yield*/, userAgent
654
+ .post("/consents/respond")
655
+ .send({ agreed: true, consentFormId: form._id })
656
+ .expect(400)];
657
+ case 1:
658
+ _a.sent();
659
+ return [2 /*return*/];
660
+ }
661
+ });
662
+ }); });
663
+ (0, bun_test_1.it)("returns 400 when form is not active", function () { return __awaiter(void 0, void 0, void 0, function () {
664
+ var inactiveForm;
665
+ return __generator(this, function (_a) {
666
+ switch (_a.label) {
667
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
668
+ active: false,
669
+ content: new Map([["en", "# Inactive"]]),
670
+ order: 5,
671
+ slug: "inactive-form",
672
+ title: "Inactive Form",
673
+ type: "custom",
674
+ version: 1,
675
+ })];
676
+ case 1:
677
+ inactiveForm = _a.sent();
678
+ return [4 /*yield*/, userAgent
679
+ .post("/consents/respond")
680
+ .send({ agreed: true, consentFormId: inactiveForm._id, locale: "en" })
681
+ .expect(400)];
682
+ case 2:
683
+ _a.sent();
684
+ return [2 /*return*/];
685
+ }
686
+ });
687
+ }); });
688
+ (0, bun_test_1.it)("validates required checkboxes when agreed is true", function () { return __awaiter(void 0, void 0, void 0, function () {
689
+ var formWithRequired, res;
690
+ return __generator(this, function (_a) {
691
+ switch (_a.label) {
692
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
693
+ active: true,
694
+ checkboxes: [{ label: "I confirm", required: true }],
695
+ content: new Map([["en", "# Required Checkbox Form"]]),
696
+ order: 6,
697
+ slug: "required-checkbox-form",
698
+ title: "Required Checkbox Form",
699
+ type: "agreement",
700
+ version: 1,
701
+ })];
702
+ case 1:
703
+ formWithRequired = _a.sent();
704
+ // Agree without checking the required checkbox
705
+ return [4 /*yield*/, userAgent
706
+ .post("/consents/respond")
707
+ .send({
708
+ agreed: true,
709
+ checkboxValues: { "0": false },
710
+ consentFormId: formWithRequired._id,
711
+ locale: "en",
712
+ })
713
+ .expect(400)];
714
+ case 2:
715
+ // Agree without checking the required checkbox
716
+ _a.sent();
717
+ return [4 /*yield*/, userAgent
718
+ .post("/consents/respond")
719
+ .send({
720
+ agreed: true,
721
+ checkboxValues: { "0": true },
722
+ consentFormId: formWithRequired._id,
723
+ locale: "en",
724
+ })
725
+ .expect(200)];
726
+ case 3:
727
+ res = _a.sent();
728
+ (0, bun_test_1.expect)(res.body.data.agreed).toBe(true);
729
+ return [2 /*return*/];
730
+ }
731
+ });
732
+ }); });
733
+ (0, bun_test_1.it)("requires signature when captureSignature is true and agreed is true", function () { return __awaiter(void 0, void 0, void 0, function () {
734
+ var sigForm, res;
735
+ return __generator(this, function (_a) {
736
+ switch (_a.label) {
737
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
738
+ active: true,
739
+ captureSignature: true,
740
+ content: new Map([["en", "# Signature Required"]]),
741
+ order: 7,
742
+ slug: "sig-form",
743
+ title: "Signature Form",
744
+ type: "agreement",
745
+ version: 1,
746
+ })];
747
+ case 1:
748
+ sigForm = _a.sent();
749
+ return [4 /*yield*/, userAgent
750
+ .post("/consents/respond")
751
+ .send({ agreed: true, consentFormId: sigForm._id, locale: "en" })
752
+ .expect(400)];
753
+ case 2:
754
+ _a.sent();
755
+ return [4 /*yield*/, userAgent
756
+ .post("/consents/respond")
757
+ .send({
758
+ agreed: true,
759
+ consentFormId: sigForm._id,
760
+ locale: "en",
761
+ signature: "data:image/png;base64,abc123",
762
+ })
763
+ .expect(200)];
764
+ case 3:
765
+ res = _a.sent();
766
+ (0, bun_test_1.expect)(res.body.data.signature).toBe("data:image/png;base64,abc123");
767
+ return [2 /*return*/];
768
+ }
769
+ });
770
+ }); });
771
+ (0, bun_test_1.it)("stores formVersionSnapshot always", function () { return __awaiter(void 0, void 0, void 0, function () {
772
+ var res;
773
+ return __generator(this, function (_a) {
774
+ switch (_a.label) {
775
+ case 0: return [4 /*yield*/, userAgent
776
+ .post("/consents/respond")
777
+ .send({ agreed: true, consentFormId: form._id, locale: "en" })
778
+ .expect(200)];
779
+ case 1:
780
+ res = _a.sent();
781
+ (0, bun_test_1.expect)(res.body.data.formVersionSnapshot).toBe(1);
782
+ return [2 /*return*/];
783
+ }
784
+ });
785
+ }); });
786
+ (0, bun_test_1.it)("stores audit trail fields when auditTrail is enabled", function () { return __awaiter(void 0, void 0, void 0, function () {
787
+ var res;
788
+ return __generator(this, function (_a) {
789
+ switch (_a.label) {
790
+ case 0: return [4 /*yield*/, userAgent
791
+ .post("/consents/respond")
792
+ .send({ agreed: true, consentFormId: form._id, locale: "en" })
793
+ .expect(200)];
794
+ case 1:
795
+ res = _a.sent();
796
+ (0, bun_test_1.expect)(res.body.data.contentSnapshot).toBeDefined();
797
+ (0, bun_test_1.expect)(res.body.data.contentSnapshot).toContain("Terms");
798
+ return [2 /*return*/];
799
+ }
800
+ });
801
+ }); });
802
+ (0, bun_test_1.it)("requires authentication", function () { return __awaiter(void 0, void 0, void 0, function () {
803
+ var app;
804
+ return __generator(this, function (_a) {
805
+ switch (_a.label) {
806
+ case 0:
807
+ app = buildApp();
808
+ return [4 /*yield*/, (0, supertest_1.default)(app)
809
+ .post("/consents/respond")
810
+ .send({ agreed: true, consentFormId: form._id, locale: "en" })
811
+ .expect(401)];
812
+ case 1:
813
+ _a.sent();
814
+ return [2 /*return*/];
815
+ }
816
+ });
817
+ }); });
818
+ });
819
+ (0, bun_test_1.describe)("GET /consents/my", function () {
820
+ (0, bun_test_1.it)("returns empty array when user has no consents", function () { return __awaiter(void 0, void 0, void 0, function () {
821
+ var res;
822
+ return __generator(this, function (_a) {
823
+ switch (_a.label) {
824
+ case 0: return [4 /*yield*/, userAgent.get("/consents/my").expect(200)];
825
+ case 1:
826
+ res = _a.sent();
827
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(0);
828
+ return [2 /*return*/];
829
+ }
830
+ });
831
+ }); });
832
+ (0, bun_test_1.it)("returns user consent history with populated form data", function () { return __awaiter(void 0, void 0, void 0, function () {
833
+ var form, res, item;
834
+ return __generator(this, function (_a) {
835
+ switch (_a.label) {
836
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
837
+ active: true,
838
+ checkboxes: [{ label: "I agree to the terms", required: true }],
839
+ content: new Map([["en", "# Terms"]]),
840
+ order: 1,
841
+ slug: "my-terms",
842
+ title: "Terms of Service",
843
+ type: "terms",
844
+ version: 2,
845
+ })];
846
+ case 1:
847
+ form = _a.sent();
848
+ return [4 /*yield*/, consentResponse_1.ConsentResponse.create({
849
+ agreed: true,
850
+ agreedAt: new Date(),
851
+ checkboxValues: new Map([["0", true]]),
852
+ consentFormId: form._id,
853
+ formVersionSnapshot: 2,
854
+ locale: "en",
855
+ userId: notAdmin._id,
856
+ })];
857
+ case 2:
858
+ _a.sent();
859
+ return [4 /*yield*/, userAgent.get("/consents/my").expect(200)];
860
+ case 3:
861
+ res = _a.sent();
862
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(1);
863
+ item = res.body.data[0];
864
+ (0, bun_test_1.expect)(item.agreed).toBe(true);
865
+ (0, bun_test_1.expect)(item.locale).toBe("en");
866
+ (0, bun_test_1.expect)(item.formVersionSnapshot).toBe(2);
867
+ (0, bun_test_1.expect)(item.form).toBeDefined();
868
+ (0, bun_test_1.expect)(item.form.title).toBe("Terms of Service");
869
+ (0, bun_test_1.expect)(item.form.slug).toBe("my-terms");
870
+ (0, bun_test_1.expect)(item.form.type).toBe("terms");
871
+ (0, bun_test_1.expect)(item.form.version).toBe(2);
872
+ (0, bun_test_1.expect)(item.form.checkboxes).toHaveLength(1);
873
+ (0, bun_test_1.expect)(item.form.checkboxes[0].label).toBe("I agree to the terms");
874
+ return [2 /*return*/];
875
+ }
876
+ });
877
+ }); });
878
+ (0, bun_test_1.it)("returns responses sorted by agreedAt descending", function () { return __awaiter(void 0, void 0, void 0, function () {
879
+ var form, olderDate, newerDate, res;
880
+ return __generator(this, function (_a) {
881
+ switch (_a.label) {
882
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
883
+ active: true,
884
+ content: new Map([["en", "# Terms"]]),
885
+ order: 1,
886
+ slug: "sorted-terms",
887
+ title: "Terms",
888
+ type: "terms",
889
+ version: 1,
890
+ })];
891
+ case 1:
892
+ form = _a.sent();
893
+ olderDate = new Date("2025-01-01T00:00:00Z");
894
+ newerDate = new Date("2025-06-01T00:00:00Z");
895
+ return [4 /*yield*/, consentResponse_1.ConsentResponse.create({
896
+ agreed: true,
897
+ agreedAt: olderDate,
898
+ consentFormId: form._id,
899
+ formVersionSnapshot: 1,
900
+ locale: "en",
901
+ userId: notAdmin._id,
902
+ })];
903
+ case 2:
904
+ _a.sent();
905
+ return [4 /*yield*/, consentResponse_1.ConsentResponse.create({
906
+ agreed: false,
907
+ agreedAt: newerDate,
908
+ consentFormId: form._id,
909
+ formVersionSnapshot: 1,
910
+ locale: "en",
911
+ userId: notAdmin._id,
912
+ })];
913
+ case 3:
914
+ _a.sent();
915
+ return [4 /*yield*/, userAgent.get("/consents/my").expect(200)];
916
+ case 4:
917
+ res = _a.sent();
918
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(2);
919
+ (0, bun_test_1.expect)(res.body.data[0].agreed).toBe(false); // newer first
920
+ (0, bun_test_1.expect)(res.body.data[1].agreed).toBe(true); // older second
921
+ return [2 /*return*/];
922
+ }
923
+ });
924
+ }); });
925
+ (0, bun_test_1.it)("includes audit trail fields when present", function () { return __awaiter(void 0, void 0, void 0, function () {
926
+ var form, res, item;
927
+ return __generator(this, function (_a) {
928
+ switch (_a.label) {
929
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
930
+ active: true,
931
+ content: new Map([["en", "# Audit Terms"]]),
932
+ order: 1,
933
+ slug: "audit-my-terms",
934
+ title: "Audit Terms",
935
+ type: "terms",
936
+ version: 1,
937
+ })];
938
+ case 1:
939
+ form = _a.sent();
940
+ return [4 /*yield*/, consentResponse_1.ConsentResponse.create({
941
+ agreed: true,
942
+ agreedAt: new Date(),
943
+ consentFormId: form._id,
944
+ contentSnapshot: "# Audit Terms",
945
+ formVersionSnapshot: 1,
946
+ ipAddress: "192.168.1.1",
947
+ locale: "en",
948
+ userAgent: "Mozilla/5.0 Test Agent",
949
+ userId: notAdmin._id,
950
+ })];
951
+ case 2:
952
+ _a.sent();
953
+ return [4 /*yield*/, userAgent.get("/consents/my").expect(200)];
954
+ case 3:
955
+ res = _a.sent();
956
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(1);
957
+ item = res.body.data[0];
958
+ (0, bun_test_1.expect)(item.ipAddress).toBe("192.168.1.1");
959
+ (0, bun_test_1.expect)(item.userAgent).toBe("Mozilla/5.0 Test Agent");
960
+ (0, bun_test_1.expect)(item.contentSnapshot).toBe("# Audit Terms");
961
+ return [2 /*return*/];
962
+ }
963
+ });
964
+ }); });
965
+ (0, bun_test_1.it)("includes signature when present", function () { return __awaiter(void 0, void 0, void 0, function () {
966
+ var form, signedAt, res, item;
967
+ return __generator(this, function (_a) {
968
+ switch (_a.label) {
969
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
970
+ active: true,
971
+ captureSignature: true,
972
+ content: new Map([["en", "# Signature Terms"]]),
973
+ order: 1,
974
+ slug: "sig-my-terms",
975
+ title: "Signature Terms",
976
+ type: "agreement",
977
+ version: 1,
978
+ })];
979
+ case 1:
980
+ form = _a.sent();
981
+ signedAt = new Date();
982
+ return [4 /*yield*/, consentResponse_1.ConsentResponse.create({
983
+ agreed: true,
984
+ agreedAt: new Date(),
985
+ consentFormId: form._id,
986
+ formVersionSnapshot: 1,
987
+ locale: "en",
988
+ signature: "data:image/png;base64,sig123",
989
+ signedAt: signedAt,
990
+ userId: notAdmin._id,
991
+ })];
992
+ case 2:
993
+ _a.sent();
994
+ return [4 /*yield*/, userAgent.get("/consents/my").expect(200)];
995
+ case 3:
996
+ res = _a.sent();
997
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(1);
998
+ item = res.body.data[0];
999
+ (0, bun_test_1.expect)(item.signature).toBe("data:image/png;base64,sig123");
1000
+ (0, bun_test_1.expect)(item.signedAt).toBeDefined();
1001
+ return [2 /*return*/];
1002
+ }
1003
+ });
1004
+ }); });
1005
+ (0, bun_test_1.it)("does not return other users' consents", function () { return __awaiter(void 0, void 0, void 0, function () {
1006
+ var form, adminRes, userRes;
1007
+ return __generator(this, function (_a) {
1008
+ switch (_a.label) {
1009
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
1010
+ active: true,
1011
+ content: new Map([["en", "# Isolation Terms"]]),
1012
+ order: 1,
1013
+ slug: "isolation-terms",
1014
+ title: "Isolation Terms",
1015
+ type: "terms",
1016
+ version: 1,
1017
+ })];
1018
+ case 1:
1019
+ form = _a.sent();
1020
+ return [4 /*yield*/, consentResponse_1.ConsentResponse.create({
1021
+ agreed: true,
1022
+ agreedAt: new Date(),
1023
+ consentFormId: form._id,
1024
+ formVersionSnapshot: 1,
1025
+ locale: "en",
1026
+ userId: admin._id,
1027
+ })];
1028
+ case 2:
1029
+ _a.sent();
1030
+ return [4 /*yield*/, consentResponse_1.ConsentResponse.create({
1031
+ agreed: true,
1032
+ agreedAt: new Date(),
1033
+ consentFormId: form._id,
1034
+ formVersionSnapshot: 1,
1035
+ locale: "en",
1036
+ userId: notAdmin._id,
1037
+ })];
1038
+ case 3:
1039
+ _a.sent();
1040
+ return [4 /*yield*/, adminAgent.get("/consents/my").expect(200)];
1041
+ case 4:
1042
+ adminRes = _a.sent();
1043
+ (0, bun_test_1.expect)(adminRes.body.data).toHaveLength(1);
1044
+ (0, bun_test_1.expect)(adminRes.body.data[0].form.title).toBe("Isolation Terms");
1045
+ return [4 /*yield*/, userAgent.get("/consents/my").expect(200)];
1046
+ case 5:
1047
+ userRes = _a.sent();
1048
+ (0, bun_test_1.expect)(userRes.body.data).toHaveLength(1);
1049
+ (0, bun_test_1.expect)(userRes.body.data[0].form.title).toBe("Isolation Terms");
1050
+ return [2 /*return*/];
1051
+ }
1052
+ });
1053
+ }); });
1054
+ (0, bun_test_1.it)("requires authentication", function () { return __awaiter(void 0, void 0, void 0, function () {
1055
+ var app;
1056
+ return __generator(this, function (_a) {
1057
+ switch (_a.label) {
1058
+ case 0:
1059
+ app = buildApp();
1060
+ return [4 /*yield*/, (0, supertest_1.default)(app).get("/consents/my").expect(401)];
1061
+ case 1:
1062
+ _a.sent();
1063
+ return [2 /*return*/];
1064
+ }
1065
+ });
1066
+ }); });
1067
+ });
1068
+ (0, bun_test_1.describe)("GET /consents/audit/:userId", function () {
1069
+ (0, bun_test_1.it)("returns audit history for a user when auditTrail is enabled", function () { return __awaiter(void 0, void 0, void 0, function () {
1070
+ var form, res;
1071
+ return __generator(this, function (_a) {
1072
+ switch (_a.label) {
1073
+ case 0: return [4 /*yield*/, consentForm_1.ConsentForm.create({
1074
+ active: true,
1075
+ content: new Map([["en", "# Audit Terms"]]),
1076
+ order: 1,
1077
+ slug: "audit-terms",
1078
+ title: "Audit Terms",
1079
+ type: "terms",
1080
+ version: 1,
1081
+ })];
1082
+ case 1:
1083
+ form = _a.sent();
1084
+ return [4 /*yield*/, consentResponse_1.ConsentResponse.create({
1085
+ agreed: true,
1086
+ agreedAt: new Date(),
1087
+ consentFormId: form._id,
1088
+ contentSnapshot: "# Audit Terms",
1089
+ formVersionSnapshot: 1,
1090
+ locale: "en",
1091
+ userId: notAdmin._id,
1092
+ })];
1093
+ case 2:
1094
+ _a.sent();
1095
+ return [4 /*yield*/, adminAgent.get("/consents/audit/".concat(notAdmin._id)).expect(200)];
1096
+ case 3:
1097
+ res = _a.sent();
1098
+ (0, bun_test_1.expect)(res.body.data).toHaveLength(1);
1099
+ (0, bun_test_1.expect)(res.body.data[0].agreed).toBe(true);
1100
+ (0, bun_test_1.expect)(res.body.data[0].form.title).toBe("Audit Terms");
1101
+ return [2 /*return*/];
1102
+ }
1103
+ });
1104
+ }); });
1105
+ (0, bun_test_1.it)("returns 403 for non-admin users", function () { return __awaiter(void 0, void 0, void 0, function () {
1106
+ return __generator(this, function (_a) {
1107
+ switch (_a.label) {
1108
+ case 0: return [4 /*yield*/, userAgent.get("/consents/audit/".concat(notAdmin._id)).expect(403)];
1109
+ case 1:
1110
+ _a.sent();
1111
+ return [2 /*return*/];
1112
+ }
1113
+ });
1114
+ }); });
1115
+ (0, bun_test_1.it)("returns 404 when auditTrail is disabled", function () { return __awaiter(void 0, void 0, void 0, function () {
1116
+ var noAuditApp, noAuditAdmin;
1117
+ return __generator(this, function (_a) {
1118
+ switch (_a.label) {
1119
+ case 0:
1120
+ noAuditApp = buildApp({ auditTrail: false });
1121
+ return [4 /*yield*/, (0, tests_1.authAsUser)(noAuditApp, "admin")];
1122
+ case 1:
1123
+ noAuditAdmin = _a.sent();
1124
+ return [4 /*yield*/, noAuditAdmin.get("/consents/audit/".concat(notAdmin._id)).expect(404)];
1125
+ case 2:
1126
+ _a.sent();
1127
+ return [2 /*return*/];
1128
+ }
1129
+ });
1130
+ }); });
1131
+ });
1132
+ });