@tellescope/sdk 1.237.0 → 1.237.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/lib/cjs/sdk.d.ts +1 -0
  2. package/lib/cjs/sdk.d.ts.map +1 -1
  3. package/lib/cjs/sdk.js +1 -0
  4. package/lib/cjs/sdk.js.map +1 -1
  5. package/lib/cjs/tests/api_tests/inbox_thread_assignment_updates.test.d.ts.map +1 -1
  6. package/lib/cjs/tests/api_tests/inbox_thread_assignment_updates.test.js +227 -64
  7. package/lib/cjs/tests/api_tests/inbox_thread_assignment_updates.test.js.map +1 -1
  8. package/lib/cjs/tests/api_tests/inbox_thread_draft_scheduled.test.d.ts +6 -0
  9. package/lib/cjs/tests/api_tests/inbox_thread_draft_scheduled.test.d.ts.map +1 -0
  10. package/lib/cjs/tests/api_tests/inbox_thread_draft_scheduled.test.js +717 -0
  11. package/lib/cjs/tests/api_tests/inbox_thread_draft_scheduled.test.js.map +1 -0
  12. package/lib/cjs/tests/api_tests/inbox_thread_mdb_filter.test.d.ts +6 -0
  13. package/lib/cjs/tests/api_tests/inbox_thread_mdb_filter.test.d.ts.map +1 -0
  14. package/lib/cjs/tests/api_tests/inbox_thread_mdb_filter.test.js +372 -0
  15. package/lib/cjs/tests/api_tests/inbox_thread_mdb_filter.test.js.map +1 -0
  16. package/lib/cjs/tests/tests.d.ts.map +1 -1
  17. package/lib/cjs/tests/tests.js +575 -105
  18. package/lib/cjs/tests/tests.js.map +1 -1
  19. package/lib/esm/sdk.d.ts +1 -0
  20. package/lib/esm/sdk.d.ts.map +1 -1
  21. package/lib/esm/sdk.js +1 -0
  22. package/lib/esm/sdk.js.map +1 -1
  23. package/lib/esm/tests/api_tests/inbox_thread_assignment_updates.test.d.ts.map +1 -1
  24. package/lib/esm/tests/api_tests/inbox_thread_assignment_updates.test.js +227 -64
  25. package/lib/esm/tests/api_tests/inbox_thread_assignment_updates.test.js.map +1 -1
  26. package/lib/esm/tests/api_tests/inbox_thread_draft_scheduled.test.d.ts +6 -0
  27. package/lib/esm/tests/api_tests/inbox_thread_draft_scheduled.test.d.ts.map +1 -0
  28. package/lib/esm/tests/api_tests/inbox_thread_draft_scheduled.test.js +713 -0
  29. package/lib/esm/tests/api_tests/inbox_thread_draft_scheduled.test.js.map +1 -0
  30. package/lib/esm/tests/api_tests/inbox_thread_mdb_filter.test.d.ts +6 -0
  31. package/lib/esm/tests/api_tests/inbox_thread_mdb_filter.test.d.ts.map +1 -0
  32. package/lib/esm/tests/api_tests/inbox_thread_mdb_filter.test.js +368 -0
  33. package/lib/esm/tests/api_tests/inbox_thread_mdb_filter.test.js.map +1 -0
  34. package/lib/esm/tests/tests.d.ts.map +1 -1
  35. package/lib/esm/tests/tests.js +575 -105
  36. package/lib/esm/tests/tests.js.map +1 -1
  37. package/lib/tsconfig.tsbuildinfo +1 -1
  38. package/package.json +10 -10
  39. package/src/sdk.ts +4 -0
  40. package/src/tests/api_tests/inbox_thread_assignment_updates.test.ts +149 -0
  41. package/src/tests/api_tests/inbox_thread_draft_scheduled.test.ts +625 -0
  42. package/src/tests/tests.ts +401 -1
  43. package/test_generated.pdf +0 -0
@@ -0,0 +1,713 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ var __generator = (this && this.__generator) || function (thisArg, body) {
11
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
+ function verb(n) { return function (v) { return step([n, v]); }; }
14
+ function step(op) {
15
+ if (f) throw new TypeError("Generator is already executing.");
16
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
+ 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;
18
+ if (y = 0, t) op = [op[0] & 2, t.value];
19
+ switch (op[0]) {
20
+ case 0: case 1: t = op; break;
21
+ case 4: _.label++; return { value: op[1], done: false };
22
+ case 5: _.label++; y = op[1]; op = [0]; continue;
23
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
+ default:
25
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
+ if (t[2]) _.ops.pop();
30
+ _.trys.pop(); continue;
31
+ }
32
+ op = body.call(thisArg, _);
33
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
+ }
36
+ };
37
+ require('source-map-support').install();
38
+ import { Session } from "../../sdk";
39
+ import { assert, log_header, wait, } from "@tellescope/testing";
40
+ import { setup_tests } from "../setup";
41
+ var host = process.env.API_URL || 'http://localhost:8080';
42
+ export var inbox_thread_draft_scheduled_tests = function (_a) {
43
+ var sdk = _a.sdk, sdkNonAdmin = _a.sdkNonAdmin;
44
+ return __awaiter(void 0, void 0, void 0, function () {
45
+ var timestamp, from, testUser, testEnduser, resetAndBuildThreads, phoneNumber_1, enduserPhoneNumber_1, sentSMS, draftSMS, loadedThreads, smsThread, futureDate, scheduledSMS, loadedThreads2, threadWithScheduled, emailSubject_1, sentEmail, draftEmail, loadedThreads3, emailThread, scheduledEmail, loadedThreads4, emailThreadWithScheduled, draftOnlyEnduserPhoneNumber_1, draftOnlySMS, loadedThreads5, draftOnlyThread, sentOnlyPhoneNumber_1, sentOnlyEnduserPhoneNumber_1, loadedThreads6, sentOnlyThread, chatRoom, farFuture, draftChat, loadedThreads7, chatThreadBefore_1, loadedThreads7b, chatThreadWithDraft, loadedThreads8, chatThreadAfter, deleteTestPhoneNumber_1, deleteTestEnduserPhoneNumber_1, draftSmsToDelete, loadedThreads9a, smsDeleteThread_1, loadedThreads9b, smsDeleteThreadAfter, deleteEmailSubject_1, draftEmailToDelete, loadedThreads10a, emailDeleteThread_1, loadedThreads10b, emailDeleteThreadAfter, chatRoomForDeletion, farFuture2, draftChatToDelete, loadedThreads11a, chatDeleteThread_1, loadedThreads11b, chatDeleteThreadWithDraft, loadedThreads11c, chatDeleteThreadAfter;
46
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
47
+ return __generator(this, function (_v) {
48
+ switch (_v.label) {
49
+ case 0:
50
+ log_header("InboxThread Draft and Scheduled Message Tests");
51
+ timestamp = Date.now();
52
+ from = new Date(Date.now() - 1000 * 60 * 60) // 1 hour ago
53
+ ;
54
+ return [4 /*yield*/, sdk.api.users.createOne({
55
+ fname: "Test",
56
+ lname: "User",
57
+ email: "test-draft-scheduled-".concat(timestamp, "@test.com"),
58
+ notificationEmailsDisabled: true
59
+ })];
60
+ case 1:
61
+ testUser = _v.sent();
62
+ return [4 /*yield*/, sdk.api.endusers.createOne({
63
+ fname: "Test",
64
+ lname: "Patient",
65
+ email: "test-patient-draft-".concat(timestamp, "@test.com"),
66
+ phone: "+15555555555", // Required for SMS tests
67
+ })
68
+ // Helper to reset and rebuild threads
69
+ ];
70
+ case 2:
71
+ testEnduser = _v.sent();
72
+ resetAndBuildThreads = function () { return __awaiter(void 0, void 0, void 0, function () {
73
+ return __generator(this, function (_a) {
74
+ switch (_a.label) {
75
+ case 0: return [4 /*yield*/, sdk.api.inbox_threads.reset_threads()];
76
+ case 1:
77
+ _a.sent();
78
+ return [4 /*yield*/, sdk.api.inbox_threads.build_threads({ from: from, to: new Date() })];
79
+ case 2:
80
+ _a.sent();
81
+ return [2 /*return*/];
82
+ }
83
+ });
84
+ }); };
85
+ _v.label = 3;
86
+ case 3:
87
+ _v.trys.push([3, , 62, 66]);
88
+ // ===== SMS Draft/Scheduled Tests =====
89
+ log_header("SMS Draft and Scheduled Tests");
90
+ // Test 1: Draft SMS should be tracked in draftMessageIds but excluded from preview
91
+ console.log("Testing draft SMS tracking...");
92
+ phoneNumber_1 = "+15555555550";
93
+ enduserPhoneNumber_1 = "+15555555551";
94
+ // Create an inbound SMS to establish the thread with proper phone numbers
95
+ return [4 /*yield*/, sdk.api.sms_messages.createOne({
96
+ message: "Inbound message to establish thread",
97
+ enduserId: testEnduser.id,
98
+ userId: testUser.id,
99
+ inbound: true,
100
+ phoneNumber: phoneNumber_1,
101
+ enduserPhoneNumber: enduserPhoneNumber_1,
102
+ logOnly: true,
103
+ })
104
+ // Create a regular outbound SMS
105
+ ];
106
+ case 4:
107
+ // Create an inbound SMS to establish the thread with proper phone numbers
108
+ _v.sent();
109
+ return [4 /*yield*/, sdk.api.sms_messages.createOne({
110
+ message: "This is a sent message",
111
+ enduserId: testEnduser.id,
112
+ userId: testUser.id,
113
+ inbound: false,
114
+ phoneNumber: phoneNumber_1,
115
+ enduserPhoneNumber: enduserPhoneNumber_1,
116
+ logOnly: true,
117
+ })
118
+ // Create a draft SMS
119
+ ];
120
+ case 5:
121
+ sentSMS = _v.sent();
122
+ return [4 /*yield*/, sdk.api.sms_messages.createOne({
123
+ message: "This is a draft message",
124
+ enduserId: testEnduser.id,
125
+ userId: testUser.id,
126
+ inbound: false,
127
+ phoneNumber: phoneNumber_1,
128
+ enduserPhoneNumber: enduserPhoneNumber_1,
129
+ isDraft: true,
130
+ logOnly: true,
131
+ })
132
+ // Build threads from messages
133
+ ];
134
+ case 6:
135
+ draftSMS = _v.sent();
136
+ // Build threads from messages
137
+ return [4 /*yield*/, resetAndBuildThreads()
138
+ // Load the thread and verify
139
+ ];
140
+ case 7:
141
+ // Build threads from messages
142
+ _v.sent();
143
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
144
+ case 8:
145
+ loadedThreads = _v.sent();
146
+ smsThread = loadedThreads.threads.find(function (t) {
147
+ return t.type === 'SMS' && t.phoneNumber === phoneNumber_1 && t.enduserPhoneNumber === enduserPhoneNumber_1;
148
+ });
149
+ assert(!!smsThread, "SMS thread should be found");
150
+ assert(((_b = smsThread.draftMessageIds) === null || _b === void 0 ? void 0 : _b.includes(draftSMS.id)) === true, "Draft SMS ID should be in draftMessageIds. Got: ".concat(JSON.stringify(smsThread.draftMessageIds)));
151
+ assert(((_c = smsThread.preview) === null || _c === void 0 ? void 0 : _c.includes("This is a sent message")) === true, "Preview should be from sent message, not draft. Got: ".concat(smsThread.preview));
152
+ console.log("✅ Draft SMS tracking test passed");
153
+ // Test 2: Scheduled SMS (future sendAt) should be tracked in scheduledMessageIds
154
+ console.log("Testing scheduled SMS tracking...");
155
+ futureDate = new Date(Date.now() + 24 * 60 * 60 * 1000) // 24 hours from now
156
+ ;
157
+ return [4 /*yield*/, sdk.api.sms_messages.createOne({
158
+ message: "This is a scheduled message",
159
+ enduserId: testEnduser.id,
160
+ userId: testUser.id,
161
+ inbound: false,
162
+ phoneNumber: phoneNumber_1,
163
+ enduserPhoneNumber: enduserPhoneNumber_1,
164
+ sendAt: futureDate,
165
+ logOnly: true,
166
+ })
167
+ // Rebuild threads
168
+ ];
169
+ case 9:
170
+ scheduledSMS = _v.sent();
171
+ // Rebuild threads
172
+ return [4 /*yield*/, resetAndBuildThreads()];
173
+ case 10:
174
+ // Rebuild threads
175
+ _v.sent();
176
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
177
+ case 11:
178
+ loadedThreads2 = _v.sent();
179
+ threadWithScheduled = loadedThreads2.threads.find(function (t) {
180
+ return t.type === 'SMS' && t.phoneNumber === phoneNumber_1 && t.enduserPhoneNumber === enduserPhoneNumber_1;
181
+ });
182
+ assert(!!threadWithScheduled, "SMS thread should be found");
183
+ assert(((_d = threadWithScheduled.scheduledMessageIds) === null || _d === void 0 ? void 0 : _d.includes(scheduledSMS.id)) === true, "Scheduled SMS ID should be in scheduledMessageIds. Got: ".concat(JSON.stringify(threadWithScheduled.scheduledMessageIds)));
184
+ assert(((_e = threadWithScheduled.preview) === null || _e === void 0 ? void 0 : _e.includes("This is a scheduled message")) !== true, "Preview should NOT be from scheduled message. Got: ".concat(threadWithScheduled.preview));
185
+ console.log("✅ Scheduled SMS tracking test passed");
186
+ // ===== Email Draft/Scheduled Tests =====
187
+ log_header("Email Draft and Scheduled Tests");
188
+ // Test 3: Draft email should be tracked in draftMessageIds
189
+ console.log("Testing draft email tracking...");
190
+ emailSubject_1 = "Draft Test Email ".concat(timestamp);
191
+ return [4 /*yield*/, sdk.api.emails.createOne({
192
+ subject: emailSubject_1,
193
+ textContent: "This is a sent email",
194
+ enduserId: testEnduser.id,
195
+ userId: testUser.id,
196
+ messageId: "sent-email-".concat(timestamp),
197
+ logOnly: true,
198
+ })
199
+ // Create a draft email
200
+ ];
201
+ case 12:
202
+ sentEmail = _v.sent();
203
+ return [4 /*yield*/, sdk.api.emails.createOne({
204
+ subject: emailSubject_1,
205
+ textContent: "This is a draft email",
206
+ enduserId: testEnduser.id,
207
+ userId: testUser.id,
208
+ messageId: "draft-email-".concat(timestamp),
209
+ isDraft: true,
210
+ logOnly: true,
211
+ })
212
+ // Rebuild threads
213
+ ];
214
+ case 13:
215
+ draftEmail = _v.sent();
216
+ // Rebuild threads
217
+ return [4 /*yield*/, resetAndBuildThreads()];
218
+ case 14:
219
+ // Rebuild threads
220
+ _v.sent();
221
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
222
+ case 15:
223
+ loadedThreads3 = _v.sent();
224
+ emailThread = loadedThreads3.threads.find(function (t) { return t.type === 'Email' && t.title === emailSubject_1; });
225
+ assert(!!emailThread, "Email thread should be found");
226
+ assert(((_f = emailThread.draftMessageIds) === null || _f === void 0 ? void 0 : _f.includes(draftEmail.id)) === true, "Draft Email ID should be in draftMessageIds. Got: ".concat(JSON.stringify(emailThread.draftMessageIds)));
227
+ assert(((_g = emailThread.preview) === null || _g === void 0 ? void 0 : _g.includes("This is a sent email")) === true, "Preview should be from sent email, not draft. Got: ".concat(emailThread.preview));
228
+ console.log("✅ Draft email tracking test passed");
229
+ // Test 4: Scheduled email (future sendAt) should be tracked in scheduledMessageIds
230
+ console.log("Testing scheduled email tracking...");
231
+ return [4 /*yield*/, sdk.api.emails.createOne({
232
+ subject: emailSubject_1,
233
+ textContent: "This is a scheduled email",
234
+ enduserId: testEnduser.id,
235
+ userId: testUser.id,
236
+ messageId: "scheduled-email-".concat(timestamp),
237
+ sendAt: futureDate,
238
+ logOnly: true,
239
+ })
240
+ // Rebuild threads
241
+ ];
242
+ case 16:
243
+ scheduledEmail = _v.sent();
244
+ // Rebuild threads
245
+ return [4 /*yield*/, resetAndBuildThreads()];
246
+ case 17:
247
+ // Rebuild threads
248
+ _v.sent();
249
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
250
+ case 18:
251
+ loadedThreads4 = _v.sent();
252
+ emailThreadWithScheduled = loadedThreads4.threads.find(function (t) { return t.type === 'Email' && t.title === emailSubject_1; });
253
+ assert(!!emailThreadWithScheduled, "Email thread should be found");
254
+ assert(((_h = emailThreadWithScheduled.scheduledMessageIds) === null || _h === void 0 ? void 0 : _h.includes(scheduledEmail.id)) === true, "Scheduled Email ID should be in scheduledMessageIds. Got: ".concat(JSON.stringify(emailThreadWithScheduled.scheduledMessageIds)));
255
+ assert(((_j = emailThreadWithScheduled.preview) === null || _j === void 0 ? void 0 : _j.includes("This is a scheduled email")) !== true, "Preview should NOT be from scheduled email. Got: ".concat(emailThreadWithScheduled.preview));
256
+ console.log("✅ Scheduled email tracking test passed");
257
+ // Test 5: Thread with ONLY drafts should still have a preview from the drafts
258
+ console.log("Testing thread with only draft messages...");
259
+ draftOnlyEnduserPhoneNumber_1 = "+15555555561";
260
+ return [4 /*yield*/, sdk.api.sms_messages.createOne({
261
+ message: "This is the only message and it is a draft",
262
+ enduserId: testEnduser.id,
263
+ userId: testUser.id,
264
+ inbound: false,
265
+ phoneNumber: "+15555555560",
266
+ enduserPhoneNumber: draftOnlyEnduserPhoneNumber_1,
267
+ isDraft: true,
268
+ logOnly: true,
269
+ })
270
+ // Rebuild threads
271
+ ];
272
+ case 19:
273
+ draftOnlySMS = _v.sent();
274
+ // Rebuild threads
275
+ return [4 /*yield*/, resetAndBuildThreads()];
276
+ case 20:
277
+ // Rebuild threads
278
+ _v.sent();
279
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})
280
+ // Match only on enduserPhoneNumber since there's no inbound to set phoneNumber
281
+ ];
282
+ case 21:
283
+ loadedThreads5 = _v.sent();
284
+ draftOnlyThread = loadedThreads5.threads.find(function (t) {
285
+ return t.type === 'SMS' && t.enduserPhoneNumber === draftOnlyEnduserPhoneNumber_1;
286
+ });
287
+ assert(!!draftOnlyThread, "Draft-only thread should be found");
288
+ assert(((_k = draftOnlyThread.draftMessageIds) === null || _k === void 0 ? void 0 : _k.includes(draftOnlySMS.id)) === true, "Draft SMS ID should be in draftMessageIds");
289
+ // When only drafts exist, the draft is used as fallback for preview
290
+ assert(((_l = draftOnlyThread.preview) === null || _l === void 0 ? void 0 : _l.includes("only message")) === true, "Preview should fall back to draft when no sent messages exist. Got: ".concat(draftOnlyThread.preview));
291
+ console.log("✅ Thread with only draft messages test passed");
292
+ // Test 6: Verify fields are correctly typed as arrays
293
+ console.log("Testing field types...");
294
+ assert(Array.isArray(smsThread.draftMessageIds), "draftMessageIds should be an array");
295
+ assert(Array.isArray(threadWithScheduled.scheduledMessageIds), "scheduledMessageIds should be an array");
296
+ console.log("✅ Field types test passed");
297
+ // Test 7: Threads with NO drafts/scheduled should have empty arrays (not undefined)
298
+ console.log("Testing empty array defaults for threads with only sent messages...");
299
+ sentOnlyPhoneNumber_1 = "+15555555570";
300
+ sentOnlyEnduserPhoneNumber_1 = "+15555555571";
301
+ // Create an inbound message to establish the thread with proper phone numbers
302
+ return [4 /*yield*/, sdk.api.sms_messages.createOne({
303
+ message: "Inbound message",
304
+ enduserId: testEnduser.id,
305
+ userId: testUser.id,
306
+ inbound: true,
307
+ phoneNumber: sentOnlyPhoneNumber_1,
308
+ enduserPhoneNumber: sentOnlyEnduserPhoneNumber_1,
309
+ logOnly: true,
310
+ })
311
+ // Create an outbound sent message (no draft, no scheduled)
312
+ ];
313
+ case 22:
314
+ // Create an inbound message to establish the thread with proper phone numbers
315
+ _v.sent();
316
+ // Create an outbound sent message (no draft, no scheduled)
317
+ return [4 /*yield*/, sdk.api.sms_messages.createOne({
318
+ message: "This is a sent message only",
319
+ enduserId: testEnduser.id,
320
+ userId: testUser.id,
321
+ inbound: false,
322
+ phoneNumber: sentOnlyPhoneNumber_1,
323
+ enduserPhoneNumber: sentOnlyEnduserPhoneNumber_1,
324
+ logOnly: true,
325
+ })
326
+ // Rebuild threads
327
+ ];
328
+ case 23:
329
+ // Create an outbound sent message (no draft, no scheduled)
330
+ _v.sent();
331
+ // Rebuild threads
332
+ return [4 /*yield*/, resetAndBuildThreads()];
333
+ case 24:
334
+ // Rebuild threads
335
+ _v.sent();
336
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
337
+ case 25:
338
+ loadedThreads6 = _v.sent();
339
+ sentOnlyThread = loadedThreads6.threads.find(function (t) {
340
+ return t.type === 'SMS' && t.phoneNumber === sentOnlyPhoneNumber_1 && t.enduserPhoneNumber === sentOnlyEnduserPhoneNumber_1;
341
+ });
342
+ assert(!!sentOnlyThread, "Sent-only thread should be found");
343
+ assert(Array.isArray(sentOnlyThread.draftMessageIds) && sentOnlyThread.draftMessageIds.length === 0, "draftMessageIds should be an empty array when no drafts exist. Got: ".concat(JSON.stringify(sentOnlyThread.draftMessageIds)));
344
+ assert(Array.isArray(sentOnlyThread.scheduledMessageIds) && sentOnlyThread.scheduledMessageIds.length === 0, "scheduledMessageIds should be an empty array when no scheduled messages exist. Got: ".concat(JSON.stringify(sentOnlyThread.scheduledMessageIds)));
345
+ console.log("✅ Empty array defaults test passed");
346
+ // ===== Chat Draft Cleanup on Send Tests =====
347
+ log_header("Chat Draft Cleanup on Send Tests");
348
+ // Test 8: Verify draftMessageIds is cleaned up when a draft chat is sent
349
+ // Note: Chat threads don't auto-populate draftMessageIds during build_threads,
350
+ // so we manually set it up to test the cleanup logic in the event handler
351
+ console.log("Testing draft chat cleanup on send...");
352
+ return [4 /*yield*/, sdk.api.chat_rooms.createOne({
353
+ userIds: [testUser.id],
354
+ enduserIds: [testEnduser.id],
355
+ })
356
+ // Create a non-draft message first to establish the room (sets recentMessageSentAt)
357
+ // This is required for the room to be included in build_threads
358
+ ];
359
+ case 26:
360
+ chatRoom = _v.sent();
361
+ // Create a non-draft message first to establish the room (sets recentMessageSentAt)
362
+ // This is required for the room to be included in build_threads
363
+ return [4 /*yield*/, sdk.api.chats.createOne({
364
+ roomId: chatRoom.id,
365
+ message: "Initial message to establish room",
366
+ senderId: testEnduser.id,
367
+ })
368
+ // Create a draft chat message (isDraft: true, sendAt far in future like webapp does)
369
+ ];
370
+ case 27:
371
+ // Create a non-draft message first to establish the room (sets recentMessageSentAt)
372
+ // This is required for the room to be included in build_threads
373
+ _v.sent();
374
+ farFuture = new Date(Date.now() + 100 * 365 * 24 * 60 * 60 * 1000) // 100 years
375
+ ;
376
+ return [4 /*yield*/, sdk.api.chats.createOne({
377
+ roomId: chatRoom.id,
378
+ message: "This is a draft chat message",
379
+ senderId: testUser.id,
380
+ isDraft: true,
381
+ sendAt: farFuture,
382
+ })
383
+ // Build threads to create the Chat thread
384
+ ];
385
+ case 28:
386
+ draftChat = _v.sent();
387
+ // Build threads to create the Chat thread
388
+ return [4 /*yield*/, resetAndBuildThreads()];
389
+ case 29:
390
+ // Build threads to create the Chat thread
391
+ _v.sent();
392
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
393
+ case 30:
394
+ loadedThreads7 = _v.sent();
395
+ chatThreadBefore_1 = loadedThreads7.threads.find(function (t) { var _a; return t.type === 'Chat' && ((_a = t.enduserIds) === null || _a === void 0 ? void 0 : _a.includes(testEnduser.id)); });
396
+ assert(!!chatThreadBefore_1, "Chat thread should be found");
397
+ // Manually add the draft ID to draftMessageIds to simulate the setup
398
+ // (Chat thread building doesn't auto-populate this, but the cleanup should still work)
399
+ return [4 /*yield*/, sdk.api.inbox_threads.updateOne(chatThreadBefore_1.id, {
400
+ draftMessageIds: [draftChat.id],
401
+ })
402
+ // Verify manual setup worked
403
+ ];
404
+ case 31:
405
+ // Manually add the draft ID to draftMessageIds to simulate the setup
406
+ // (Chat thread building doesn't auto-populate this, but the cleanup should still work)
407
+ _v.sent();
408
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
409
+ case 32:
410
+ loadedThreads7b = _v.sent();
411
+ chatThreadWithDraft = loadedThreads7b.threads.find(function (t) { return t.id === chatThreadBefore_1.id; });
412
+ assert(((_m = chatThreadWithDraft.draftMessageIds) === null || _m === void 0 ? void 0 : _m.includes(draftChat.id)) === true, "Draft chat ID should be in draftMessageIds after manual setup. Got: ".concat(JSON.stringify(chatThreadWithDraft.draftMessageIds)));
413
+ console.log("✅ Draft chat manually added to draftMessageIds");
414
+ // "Send" the draft by updating isDraft to false and sendAt to now
415
+ // This mimics what the webapp does when user clicks send
416
+ return [4 /*yield*/, sdk.api.chats.updateOne(draftChat.id, {
417
+ isDraft: false,
418
+ sendAt: new Date(), // Now - triggers the scheduled chat handler
419
+ })
420
+ // Wait for the side effect to process
421
+ ];
422
+ case 33:
423
+ // "Send" the draft by updating isDraft to false and sendAt to now
424
+ // This mimics what the webapp does when user clicks send
425
+ _v.sent();
426
+ // Wait for the side effect to process
427
+ return [4 /*yield*/, wait(undefined, 500)
428
+ // Reload the thread and verify cleanup happened
429
+ ];
430
+ case 34:
431
+ // Wait for the side effect to process
432
+ _v.sent();
433
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
434
+ case 35:
435
+ loadedThreads8 = _v.sent();
436
+ chatThreadAfter = loadedThreads8.threads.find(function (t) { return t.id === chatThreadBefore_1.id; });
437
+ assert(!!chatThreadAfter, "Chat thread should be found after send");
438
+ assert(((_o = chatThreadAfter.draftMessageIds) === null || _o === void 0 ? void 0 : _o.includes(draftChat.id)) === false, "Draft chat ID should be REMOVED from draftMessageIds after send. Got: ".concat(JSON.stringify(chatThreadAfter.draftMessageIds)));
439
+ console.log("✅ Draft chat cleanup on send test passed");
440
+ // Cleanup chat room
441
+ return [4 /*yield*/, sdk.api.chat_rooms.deleteOne(chatRoom.id).catch(console.error)
442
+ // ===== Message Deletion Cleanup Tests =====
443
+ ];
444
+ case 36:
445
+ // Cleanup chat room
446
+ _v.sent();
447
+ // ===== Message Deletion Cleanup Tests =====
448
+ log_header("Message Deletion Cleanup Tests");
449
+ // Test 9: SMS draft deletion should remove ID from draftMessageIds
450
+ console.log("Testing SMS draft deletion cleanup...");
451
+ deleteTestPhoneNumber_1 = "+15555555580";
452
+ deleteTestEnduserPhoneNumber_1 = "+15555555581";
453
+ // Create an inbound SMS to establish the thread
454
+ return [4 /*yield*/, sdk.api.sms_messages.createOne({
455
+ message: "Inbound message to establish thread for deletion test",
456
+ enduserId: testEnduser.id,
457
+ userId: testUser.id,
458
+ inbound: true,
459
+ phoneNumber: deleteTestPhoneNumber_1,
460
+ enduserPhoneNumber: deleteTestEnduserPhoneNumber_1,
461
+ logOnly: true,
462
+ })
463
+ // Create a draft SMS
464
+ ];
465
+ case 37:
466
+ // Create an inbound SMS to establish the thread
467
+ _v.sent();
468
+ return [4 /*yield*/, sdk.api.sms_messages.createOne({
469
+ message: "This draft will be deleted",
470
+ enduserId: testEnduser.id,
471
+ userId: testUser.id,
472
+ inbound: false,
473
+ phoneNumber: deleteTestPhoneNumber_1,
474
+ enduserPhoneNumber: deleteTestEnduserPhoneNumber_1,
475
+ isDraft: true,
476
+ logOnly: true,
477
+ })
478
+ // Build threads to populate draftMessageIds
479
+ ];
480
+ case 38:
481
+ draftSmsToDelete = _v.sent();
482
+ // Build threads to populate draftMessageIds
483
+ return [4 /*yield*/, resetAndBuildThreads()
484
+ // Verify the draft ID is in the thread
485
+ ];
486
+ case 39:
487
+ // Build threads to populate draftMessageIds
488
+ _v.sent();
489
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
490
+ case 40:
491
+ loadedThreads9a = _v.sent();
492
+ smsDeleteThread_1 = loadedThreads9a.threads.find(function (t) {
493
+ return t.type === 'SMS' && t.phoneNumber === deleteTestPhoneNumber_1 && t.enduserPhoneNumber === deleteTestEnduserPhoneNumber_1;
494
+ });
495
+ assert(!!smsDeleteThread_1, "SMS thread for deletion test should be found");
496
+ assert(((_p = smsDeleteThread_1.draftMessageIds) === null || _p === void 0 ? void 0 : _p.includes(draftSmsToDelete.id)) === true, "Draft SMS ID should be in draftMessageIds before deletion. Got: ".concat(JSON.stringify(smsDeleteThread_1.draftMessageIds)));
497
+ // Delete the draft SMS
498
+ return [4 /*yield*/, sdk.api.sms_messages.deleteOne(draftSmsToDelete.id)
499
+ // Wait for the delete side effect to process
500
+ ];
501
+ case 41:
502
+ // Delete the draft SMS
503
+ _v.sent();
504
+ // Wait for the delete side effect to process
505
+ return [4 /*yield*/, wait(undefined, 500)
506
+ // Verify the draft ID has been removed
507
+ ];
508
+ case 42:
509
+ // Wait for the delete side effect to process
510
+ _v.sent();
511
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
512
+ case 43:
513
+ loadedThreads9b = _v.sent();
514
+ smsDeleteThreadAfter = loadedThreads9b.threads.find(function (t) { return t.id === smsDeleteThread_1.id; });
515
+ assert(!!smsDeleteThreadAfter, "SMS thread should still exist after draft deletion");
516
+ assert(((_q = smsDeleteThreadAfter.draftMessageIds) === null || _q === void 0 ? void 0 : _q.includes(draftSmsToDelete.id)) === false, "Draft SMS ID should be REMOVED from draftMessageIds after deletion. Got: ".concat(JSON.stringify(smsDeleteThreadAfter.draftMessageIds)));
517
+ console.log("✅ SMS draft deletion cleanup test passed");
518
+ // Test 10: Email draft deletion should remove ID from draftMessageIds
519
+ console.log("Testing email draft deletion cleanup...");
520
+ deleteEmailSubject_1 = "Delete Test Email ".concat(timestamp);
521
+ // Create a sent email first to establish the thread
522
+ return [4 /*yield*/, sdk.api.emails.createOne({
523
+ subject: deleteEmailSubject_1,
524
+ textContent: "Sent email to establish thread for deletion test",
525
+ enduserId: testEnduser.id,
526
+ userId: testUser.id,
527
+ messageId: "sent-email-delete-test-".concat(timestamp),
528
+ logOnly: true,
529
+ })
530
+ // Create a draft email
531
+ ];
532
+ case 44:
533
+ // Create a sent email first to establish the thread
534
+ _v.sent();
535
+ return [4 /*yield*/, sdk.api.emails.createOne({
536
+ subject: deleteEmailSubject_1,
537
+ textContent: "This draft email will be deleted",
538
+ enduserId: testEnduser.id,
539
+ userId: testUser.id,
540
+ messageId: "draft-email-delete-test-".concat(timestamp),
541
+ isDraft: true,
542
+ logOnly: true,
543
+ })
544
+ // Build threads to populate draftMessageIds
545
+ ];
546
+ case 45:
547
+ draftEmailToDelete = _v.sent();
548
+ // Build threads to populate draftMessageIds
549
+ return [4 /*yield*/, resetAndBuildThreads()
550
+ // Verify the draft ID is in the thread
551
+ ];
552
+ case 46:
553
+ // Build threads to populate draftMessageIds
554
+ _v.sent();
555
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
556
+ case 47:
557
+ loadedThreads10a = _v.sent();
558
+ emailDeleteThread_1 = loadedThreads10a.threads.find(function (t) { return t.type === 'Email' && t.title === deleteEmailSubject_1; });
559
+ assert(!!emailDeleteThread_1, "Email thread for deletion test should be found");
560
+ assert(((_r = emailDeleteThread_1.draftMessageIds) === null || _r === void 0 ? void 0 : _r.includes(draftEmailToDelete.id)) === true, "Draft Email ID should be in draftMessageIds before deletion. Got: ".concat(JSON.stringify(emailDeleteThread_1.draftMessageIds)));
561
+ // Delete the draft email
562
+ return [4 /*yield*/, sdk.api.emails.deleteOne(draftEmailToDelete.id)
563
+ // Wait for the delete side effect to process
564
+ ];
565
+ case 48:
566
+ // Delete the draft email
567
+ _v.sent();
568
+ // Wait for the delete side effect to process
569
+ return [4 /*yield*/, wait(undefined, 500)
570
+ // Verify the draft ID has been removed
571
+ ];
572
+ case 49:
573
+ // Wait for the delete side effect to process
574
+ _v.sent();
575
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
576
+ case 50:
577
+ loadedThreads10b = _v.sent();
578
+ emailDeleteThreadAfter = loadedThreads10b.threads.find(function (t) { return t.id === emailDeleteThread_1.id; });
579
+ assert(!!emailDeleteThreadAfter, "Email thread should still exist after draft deletion");
580
+ assert(((_s = emailDeleteThreadAfter.draftMessageIds) === null || _s === void 0 ? void 0 : _s.includes(draftEmailToDelete.id)) === false, "Draft Email ID should be REMOVED from draftMessageIds after deletion. Got: ".concat(JSON.stringify(emailDeleteThreadAfter.draftMessageIds)));
581
+ console.log("✅ Email draft deletion cleanup test passed");
582
+ // Test 11: Chat draft deletion should remove ID from draftMessageIds
583
+ console.log("Testing chat draft deletion cleanup...");
584
+ return [4 /*yield*/, sdk.api.chat_rooms.createOne({
585
+ userIds: [testUser.id],
586
+ enduserIds: [testEnduser.id],
587
+ })
588
+ // Create a non-draft message first to establish the room
589
+ ];
590
+ case 51:
591
+ chatRoomForDeletion = _v.sent();
592
+ // Create a non-draft message first to establish the room
593
+ return [4 /*yield*/, sdk.api.chats.createOne({
594
+ roomId: chatRoomForDeletion.id,
595
+ message: "Initial message to establish room for deletion test",
596
+ senderId: testEnduser.id,
597
+ })
598
+ // Create a draft chat message
599
+ ];
600
+ case 52:
601
+ // Create a non-draft message first to establish the room
602
+ _v.sent();
603
+ farFuture2 = new Date(Date.now() + 100 * 365 * 24 * 60 * 60 * 1000);
604
+ return [4 /*yield*/, sdk.api.chats.createOne({
605
+ roomId: chatRoomForDeletion.id,
606
+ message: "This draft chat will be deleted",
607
+ senderId: testUser.id,
608
+ isDraft: true,
609
+ sendAt: farFuture2,
610
+ })
611
+ // Build threads to create the Chat thread
612
+ ];
613
+ case 53:
614
+ draftChatToDelete = _v.sent();
615
+ // Build threads to create the Chat thread
616
+ return [4 /*yield*/, resetAndBuildThreads()];
617
+ case 54:
618
+ // Build threads to create the Chat thread
619
+ _v.sent();
620
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
621
+ case 55:
622
+ loadedThreads11a = _v.sent();
623
+ chatDeleteThread_1 = loadedThreads11a.threads.find(function (t) { var _a; return t.type === 'Chat' && ((_a = t.enduserIds) === null || _a === void 0 ? void 0 : _a.includes(testEnduser.id)); });
624
+ assert(!!chatDeleteThread_1, "Chat thread for deletion test should be found");
625
+ // Manually add the draft ID to draftMessageIds (since chat threads don't auto-populate this)
626
+ return [4 /*yield*/, sdk.api.inbox_threads.updateOne(chatDeleteThread_1.id, {
627
+ draftMessageIds: [draftChatToDelete.id],
628
+ })
629
+ // Verify manual setup worked
630
+ ];
631
+ case 56:
632
+ // Manually add the draft ID to draftMessageIds (since chat threads don't auto-populate this)
633
+ _v.sent();
634
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
635
+ case 57:
636
+ loadedThreads11b = _v.sent();
637
+ chatDeleteThreadWithDraft = loadedThreads11b.threads.find(function (t) { return t.id === chatDeleteThread_1.id; });
638
+ assert(((_t = chatDeleteThreadWithDraft.draftMessageIds) === null || _t === void 0 ? void 0 : _t.includes(draftChatToDelete.id)) === true, "Draft chat ID should be in draftMessageIds after manual setup. Got: ".concat(JSON.stringify(chatDeleteThreadWithDraft.draftMessageIds)));
639
+ // Delete the draft chat
640
+ return [4 /*yield*/, sdk.api.chats.deleteOne(draftChatToDelete.id)
641
+ // Wait for the delete side effect to process
642
+ ];
643
+ case 58:
644
+ // Delete the draft chat
645
+ _v.sent();
646
+ // Wait for the delete side effect to process
647
+ return [4 /*yield*/, wait(undefined, 500)
648
+ // Verify the draft ID has been removed
649
+ ];
650
+ case 59:
651
+ // Wait for the delete side effect to process
652
+ _v.sent();
653
+ return [4 /*yield*/, sdk.api.inbox_threads.load_threads({})];
654
+ case 60:
655
+ loadedThreads11c = _v.sent();
656
+ chatDeleteThreadAfter = loadedThreads11c.threads.find(function (t) { return t.id === chatDeleteThread_1.id; });
657
+ assert(!!chatDeleteThreadAfter, "Chat thread should still exist after draft deletion");
658
+ assert(((_u = chatDeleteThreadAfter.draftMessageIds) === null || _u === void 0 ? void 0 : _u.includes(draftChatToDelete.id)) === false, "Draft Chat ID should be REMOVED from draftMessageIds after deletion. Got: ".concat(JSON.stringify(chatDeleteThreadAfter.draftMessageIds)));
659
+ console.log("✅ Chat draft deletion cleanup test passed");
660
+ // Cleanup deletion test chat room
661
+ return [4 /*yield*/, sdk.api.chat_rooms.deleteOne(chatRoomForDeletion.id).catch(console.error)];
662
+ case 61:
663
+ // Cleanup deletion test chat room
664
+ _v.sent();
665
+ console.log("🎉 All InboxThread draft/scheduled tests passed!");
666
+ return [3 /*break*/, 66];
667
+ case 62:
668
+ // Cleanup
669
+ return [4 /*yield*/, sdk.api.inbox_threads.reset_threads().catch(console.error)];
670
+ case 63:
671
+ // Cleanup
672
+ _v.sent();
673
+ return [4 /*yield*/, sdk.api.endusers.deleteOne(testEnduser.id).catch(console.error)];
674
+ case 64:
675
+ _v.sent();
676
+ return [4 /*yield*/, sdk.api.users.deleteOne(testUser.id).catch(console.error)];
677
+ case 65:
678
+ _v.sent();
679
+ return [7 /*endfinally*/];
680
+ case 66: return [2 /*return*/];
681
+ }
682
+ });
683
+ });
684
+ };
685
+ // Allow running this test file independently
686
+ if (require.main === module) {
687
+ console.log("\uD83C\uDF10 Using API URL: ".concat(host));
688
+ var sdk_1 = new Session({ host: host });
689
+ var sdkNonAdmin_1 = new Session({ host: host });
690
+ var runTests = function () { return __awaiter(void 0, void 0, void 0, function () {
691
+ return __generator(this, function (_a) {
692
+ switch (_a.label) {
693
+ case 0: return [4 /*yield*/, setup_tests(sdk_1, sdkNonAdmin_1)];
694
+ case 1:
695
+ _a.sent();
696
+ return [4 /*yield*/, inbox_thread_draft_scheduled_tests({ sdk: sdk_1, sdkNonAdmin: sdkNonAdmin_1 })];
697
+ case 2:
698
+ _a.sent();
699
+ return [2 /*return*/];
700
+ }
701
+ });
702
+ }); };
703
+ runTests()
704
+ .then(function () {
705
+ console.log("✅ InboxThread draft/scheduled test suite completed successfully");
706
+ process.exit(0);
707
+ })
708
+ .catch(function (error) {
709
+ console.error("❌ InboxThread draft/scheduled test suite failed:", error);
710
+ process.exit(1);
711
+ });
712
+ }
713
+ //# sourceMappingURL=inbox_thread_draft_scheduled.test.js.map