@tellescope/sdk 1.237.6 → 1.239.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 (31) 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.map +1 -1
  4. package/lib/cjs/tests/api_tests/afteraction_day_of_month_delay.test.js +1 -1
  5. package/lib/cjs/tests/api_tests/afteraction_day_of_month_delay.test.js.map +1 -1
  6. package/lib/cjs/tests/api_tests/load_threads_autobuild.test.d.ts +6 -0
  7. package/lib/cjs/tests/api_tests/load_threads_autobuild.test.d.ts.map +1 -0
  8. package/lib/cjs/tests/api_tests/load_threads_autobuild.test.js +283 -0
  9. package/lib/cjs/tests/api_tests/load_threads_autobuild.test.js.map +1 -0
  10. package/lib/cjs/tests/tests.d.ts.map +1 -1
  11. package/lib/cjs/tests/tests.js +116 -111
  12. package/lib/cjs/tests/tests.js.map +1 -1
  13. package/lib/esm/sdk.d.ts +1 -0
  14. package/lib/esm/sdk.d.ts.map +1 -1
  15. package/lib/esm/sdk.js.map +1 -1
  16. package/lib/esm/tests/api_tests/afteraction_day_of_month_delay.test.js +1 -1
  17. package/lib/esm/tests/api_tests/afteraction_day_of_month_delay.test.js.map +1 -1
  18. package/lib/esm/tests/api_tests/load_threads_autobuild.test.d.ts +6 -0
  19. package/lib/esm/tests/api_tests/load_threads_autobuild.test.d.ts.map +1 -0
  20. package/lib/esm/tests/api_tests/load_threads_autobuild.test.js +279 -0
  21. package/lib/esm/tests/api_tests/load_threads_autobuild.test.js.map +1 -0
  22. package/lib/esm/tests/tests.d.ts.map +1 -1
  23. package/lib/esm/tests/tests.js +116 -111
  24. package/lib/esm/tests/tests.js.map +1 -1
  25. package/lib/tsconfig.tsbuildinfo +1 -1
  26. package/package.json +10 -10
  27. package/src/sdk.ts +1 -1
  28. package/src/tests/api_tests/afteraction_day_of_month_delay.test.ts +1 -1
  29. package/src/tests/api_tests/load_threads_autobuild.test.ts +203 -0
  30. package/src/tests/tests.ts +38 -34
  31. package/test_generated.pdf +0 -0
@@ -0,0 +1,203 @@
1
+ import { Session } from "../../sdk"
2
+ import { assert, log_header, wait } from "@tellescope/testing"
3
+ import { setup_tests } from "../setup"
4
+
5
+ export const load_threads_autobuild_tests = async ({
6
+ sdk,
7
+ sdkNonAdmin
8
+ }: {
9
+ sdk: Session,
10
+ sdkNonAdmin: Session
11
+ }) => {
12
+ log_header("Load Threads with Autobuild Tests")
13
+
14
+ let testEnduser: any
15
+ let testUser: any
16
+
17
+ try {
18
+ // Setup test data
19
+ testEnduser = await sdk.api.endusers.createOne({
20
+ email: `autobuild-test-${Date.now()}@test.com`,
21
+ fname: "Autobuild",
22
+ lname: "Test"
23
+ })
24
+
25
+ testUser = await sdk.api.users.createOne({
26
+ email: `autobuild-user-${Date.now()}@test.com`,
27
+ fname: "Test",
28
+ lname: "User"
29
+ })
30
+
31
+ // Reset threads before testing
32
+ await sdk.api.inbox_threads.reset_threads()
33
+
34
+ // Test 1: Autobuild with no existing threads (bootstrap case)
35
+ log_header("Test 1: Basic autobuild from scratch (bootstrap)")
36
+ const sms1 = await sdk.api.sms_messages.createOne({
37
+ message: "Test message for autobuild",
38
+ enduserId: testEnduser.id,
39
+ userId: testUser.id,
40
+ inbound: true,
41
+ phoneNumber: "+15555555555",
42
+ enduserPhoneNumber: "+15555555556",
43
+ logOnly: true,
44
+ })
45
+
46
+ const result1 = await sdk.api.inbox_threads.load_threads({
47
+ autobuild: true
48
+ })
49
+
50
+ assert(result1.threads.length === 1, "Should load 1 thread after autobuild")
51
+ assert(result1.threads[0].type === 'SMS', "Thread should be SMS type")
52
+
53
+ // Test 2: Idempotency - calling autobuild again doesn't duplicate
54
+ log_header("Test 2: Autobuild idempotency")
55
+ const result2 = await sdk.api.inbox_threads.load_threads({
56
+ autobuild: true
57
+ })
58
+
59
+ assert(result2.threads.length === 1, "Should still have 1 thread (no duplicates)")
60
+
61
+ // Test 3: Autobuild with filters
62
+ log_header("Test 3: Autobuild combined with enduserIds filter")
63
+ const testEnduser2 = await sdk.api.endusers.createOne({
64
+ email: `autobuild-test2-${Date.now()}@test.com`,
65
+ fname: "Autobuild2",
66
+ lname: "Test2"
67
+ })
68
+
69
+ const sms2 = await sdk.api.sms_messages.createOne({
70
+ message: "Second test message",
71
+ enduserId: testEnduser2.id,
72
+ userId: testUser.id,
73
+ inbound: true,
74
+ phoneNumber: "+15555555557",
75
+ enduserPhoneNumber: "+15555555558",
76
+ logOnly: true,
77
+ })
78
+
79
+ const result3 = await sdk.api.inbox_threads.load_threads({
80
+ autobuild: true,
81
+ enduserIds: [testEnduser.id]
82
+ })
83
+
84
+ assert(result3.threads.length === 1, "Should filter to only 1 enduser's thread")
85
+ assert(result3.threads[0].enduserIds.includes(testEnduser.id), "Should be first enduser's thread")
86
+
87
+ // Test 4: Autobuild with phoneNumber filter
88
+ log_header("Test 4: Autobuild with phoneNumber filter")
89
+ const result4 = await sdk.api.inbox_threads.load_threads({
90
+ autobuild: true,
91
+ phoneNumber: "+15555555555"
92
+ })
93
+
94
+ assert(result4.threads.length === 1, "Should filter by phone number")
95
+ assert(result4.threads[0].phoneNumber === '+15555555555', "Should match phone number")
96
+
97
+ // Test 5: Autobuild with returnCount
98
+ log_header("Test 5: Autobuild with returnCount")
99
+ const result5 = await sdk.api.inbox_threads.load_threads({
100
+ autobuild: true,
101
+ returnCount: true
102
+ })
103
+
104
+ assert(result5.count === 2, "Should return count of 2 threads")
105
+ assert(!result5.threads || result5.threads.length === 0, "Should not return threads when returnCount=true")
106
+
107
+ // Test 6: Autobuild with pagination (backwards paging)
108
+ log_header("Test 6: Autobuild with pagination (paging backwards)")
109
+
110
+ // Get the oldest thread's timestamp
111
+ const allThreads = await sdk.api.inbox_threads.load_threads({
112
+ autobuild: false
113
+ })
114
+ const oldestThread = allThreads.threads[allThreads.threads.length - 1]
115
+
116
+ // Load threads with lastTimestamp to simulate paging backwards
117
+ const result6 = await sdk.api.inbox_threads.load_threads({
118
+ autobuild: true,
119
+ lastTimestamp: oldestThread.timestamp
120
+ })
121
+
122
+ // Should still return threads (may include older ones if any exist)
123
+ assert(Array.isArray(result6.threads), "Should return threads when paging backwards")
124
+
125
+ // Test 6b: Autobuild without lastTimestamp (loading current/newer data)
126
+ log_header("Test 6b: Autobuild loads newer data when no lastTimestamp")
127
+ const result6b = await sdk.api.inbox_threads.load_threads({
128
+ autobuild: true
129
+ })
130
+
131
+ assert(result6b.threads.length >= 2, "Should load current threads")
132
+
133
+ // Test 7: Non-admin user can use autobuild but sees filtered threads
134
+ log_header("Test 7: Non-admin autobuild with access control")
135
+ const result7 = await sdkNonAdmin.api.inbox_threads.load_threads({
136
+ autobuild: true
137
+ })
138
+
139
+ // Non-admin should only see threads they have access to
140
+ // (Exact assertion depends on role setup in setup_tests)
141
+ assert(Array.isArray(result7.threads), "Non-admin should get threads array")
142
+
143
+ // Test 8: Autobuild with draft and scheduled messages
144
+ log_header("Test 8: Autobuild includes draft messages")
145
+ const draftSms = await sdk.api.sms_messages.createOne({
146
+ message: "Draft message",
147
+ enduserId: testEnduser.id,
148
+ userId: testUser.id,
149
+ inbound: false,
150
+ phoneNumber: "+15555555555",
151
+ enduserPhoneNumber: "+15555555556",
152
+ isDraft: true,
153
+ logOnly: true,
154
+ })
155
+
156
+ // Wait to ensure message ObjectId timestamp is in the past before building
157
+ await wait(undefined, 2000)
158
+
159
+ const result8 = await sdk.api.inbox_threads.load_threads({
160
+ autobuild: true,
161
+ enduserIds: [testEnduser.id]
162
+ })
163
+
164
+ const threadWithDraft = result8.threads.find(t =>
165
+ t.phoneNumber === '+15555555555' && t.enduserPhoneNumber === '+15555555556'
166
+ )
167
+ assert(!!threadWithDraft, "Should find thread with draft")
168
+ assert(!!threadWithDraft?.draftMessageIds?.includes(draftSms.id), "Should include draft message ID")
169
+
170
+ console.log("✅ All autobuild tests passed!")
171
+
172
+ // Cleanup
173
+ await sdk.api.endusers.deleteOne(testEnduser2.id)
174
+
175
+ } finally {
176
+ // Cleanup
177
+ if (testEnduser) await sdk.api.endusers.deleteOne(testEnduser.id).catch(console.error)
178
+ if (testUser) await sdk.api.users.deleteOne(testUser.id).catch(console.error)
179
+ await sdk.api.inbox_threads.reset_threads().catch(console.error)
180
+ }
181
+ }
182
+
183
+ // Allow running this test independently
184
+ if (require.main === module) {
185
+ const host = process.env.API_URL || 'http://localhost:8080'
186
+ const sdk = new Session({ host })
187
+ const sdkNonAdmin = new Session({ host })
188
+
189
+ const runTests = async () => {
190
+ await setup_tests(sdk, sdkNonAdmin)
191
+ await load_threads_autobuild_tests({ sdk, sdkNonAdmin })
192
+ }
193
+
194
+ runTests()
195
+ .then(() => {
196
+ console.log("✅ Load threads autobuild test suite completed successfully")
197
+ process.exit(0)
198
+ })
199
+ .catch((error) => {
200
+ console.error("❌ Load threads autobuild test suite failed:", error)
201
+ process.exit(1)
202
+ })
203
+ }
@@ -39,6 +39,7 @@ import { enduser_observations_acknowledge_tests } from "./api_tests/enduser_obse
39
39
  import { create_user_notifications_trigger_tests } from "./api_tests/create_user_notifications_trigger.test"
40
40
  import { inbox_thread_assignment_updates_tests } from "./api_tests/inbox_thread_assignment_updates.test"
41
41
  import { inbox_thread_draft_scheduled_tests } from "./api_tests/inbox_thread_draft_scheduled.test"
42
+ import { load_threads_autobuild_tests } from "./api_tests/load_threads_autobuild.test"
42
43
  import { appointment_completed_trigger_tests } from "./api_tests/appointment_completed_trigger.test"
43
44
  import { purchase_made_trigger_tests } from "./api_tests/purchase_made_trigger.test"
44
45
  import { appointment_rescheduled_trigger_tests } from "./api_tests/appointment_rescheduled_trigger.test"
@@ -10286,7 +10287,7 @@ const sync_tests = async () => {
10286
10287
  await async_test(
10287
10288
  "No new records, admin",
10288
10289
  () => sdk.sync({ from }),
10289
- { onResult: ({ results }) => results.length === 0 },
10290
+ { onResult: ({ results, to }) => results.length === 0 && typeof to === 'string' && !isNaN(new Date(to).getTime()) },
10290
10291
  )
10291
10292
  await async_test(
10292
10293
  "No new records, non-admin",
@@ -10299,12 +10300,13 @@ const sync_tests = async () => {
10299
10300
  await async_test(
10300
10301
  "Enduser create, admin",
10301
10302
  () => sdk.sync({ from }),
10302
- { onResult: ({ results }) => (
10303
- results.length === 1
10304
- && results[0].modelName === 'endusers'
10305
- && results[0].recordId === e.id
10306
- && results[0].data.includes(e.id)
10303
+ { onResult: ({ results, to }) => (
10304
+ results.length === 1
10305
+ && results[0].modelName === 'endusers'
10306
+ && results[0].recordId === e.id
10307
+ && results[0].data.includes(e.id)
10307
10308
  && JSON.parse(results[0].data) // tests no error throwing
10309
+ && typeof to === 'string' && !isNaN(new Date(to).getTime())
10308
10310
  )},
10309
10311
  )
10310
10312
  await async_test(
@@ -10328,11 +10330,12 @@ const sync_tests = async () => {
10328
10330
  await async_test(
10329
10331
  "Enduser update, admin",
10330
10332
  () => sdk.sync({ from }),
10331
- { onResult: ({ results }) => (
10332
- results.length === 1
10333
- && results[0].modelName === 'endusers'
10334
- && results[0].recordId === e.id
10335
- && results[0].data.includes("UPDATE_TEST")
10333
+ { onResult: ({ results, to }) => (
10334
+ results.length === 1
10335
+ && results[0].modelName === 'endusers'
10336
+ && results[0].recordId === e.id
10337
+ && results[0].data.includes("UPDATE_TEST")
10338
+ && typeof to === 'string' && !isNaN(new Date(to).getTime())
10336
10339
  )},
10337
10340
  )
10338
10341
  await async_test(
@@ -10420,9 +10423,9 @@ const sync_tests = async () => {
10420
10423
  await async_test(
10421
10424
  "Non-admin can access ticket (and enduser) after enduser assignment",
10422
10425
  () => sdkNonAdmin.sync({ from }),
10423
- {
10426
+ {
10424
10427
  onResult: ({ results }) => (
10425
- results.length === 3
10428
+ results.length === 3
10426
10429
  && results.filter(r => r.modelName === 'tickets' && r.recordId === t.id).length === 1
10427
10430
  && results.filter(r => r.modelName === 'endusers' && r.recordId === e.id).length === 1
10428
10431
  )
@@ -10444,9 +10447,9 @@ const sync_tests = async () => {
10444
10447
  await async_test(
10445
10448
  "Enduser update non-admin assignment, revoked access to enduser and ticket",
10446
10449
  () => sdkNonAdmin.sync({ from }),
10447
- { onResult: ({ results }) =>
10450
+ { onResult: ({ results }) =>
10448
10451
  // still has user notification
10449
- results.length === 1 &&
10452
+ results.length === 1 &&
10450
10453
  results.filter(r => r.modelName === 'user_notifications').length === 1
10451
10454
  },
10452
10455
  )
@@ -10468,20 +10471,20 @@ const sync_tests = async () => {
10468
10471
  "Enduser delete, admin",
10469
10472
  () => sdk.sync({ from }),
10470
10473
  { onResult: ({ results }) => (
10471
- results.length === 3
10472
- && results[0].modelName === 'endusers'
10473
- && results[0].recordId === e.id
10474
- && results[0].data === 'deleted'
10474
+ results.length === 3
10475
+ && results[0].modelName === 'endusers'
10476
+ && results[0].recordId === e.id
10477
+ && results[0].data === 'deleted'
10475
10478
  )},
10476
10479
  )
10477
10480
  await async_test(
10478
10481
  "Enduser delete, non-admin",
10479
10482
  () => sdkNonAdmin.sync({ from }),
10480
- { onResult: ({ results }) =>
10483
+ { onResult: ({ results }) =>
10481
10484
  // still includes user notification
10482
- results.length === 1
10485
+ results.length === 1
10483
10486
  && results.filter(r => r.modelName === 'user_notifications').length === 1
10484
- },
10487
+ },
10485
10488
  )
10486
10489
  await async_test(
10487
10490
  "Enduser delete, sub organization",
@@ -10493,7 +10496,7 @@ const sync_tests = async () => {
10493
10496
  () => sdkOther.sync({ from }),
10494
10497
  { onResult: ({ results }) => results.filter(e => e.modelName === 'endusers' && e.data !== 'deleted').length === 0 },
10495
10498
  )
10496
-
10499
+
10497
10500
  // bulk create test coverage
10498
10501
  const [e2] = (await sdk.api.endusers.createSome([{ }])).created
10499
10502
  await wait(undefined, 100)
@@ -10501,10 +10504,10 @@ const sync_tests = async () => {
10501
10504
  "Bulk Enduser create, admin",
10502
10505
  () => sdk.sync({ from }),
10503
10506
  { onResult: ({ results }) => (
10504
- results.length === 4
10505
- && results[0].modelName === 'endusers'
10506
- && results[0].recordId === e2.id
10507
- && results[0].data.includes(e2.id)
10507
+ results.length === 4
10508
+ && results[0].modelName === 'endusers'
10509
+ && results[0].recordId === e2.id
10510
+ && results[0].data.includes(e2.id)
10508
10511
  && JSON.parse(results[0].data) // tests no error throwing
10509
10512
  )},
10510
10513
  )
@@ -10530,20 +10533,20 @@ const sync_tests = async () => {
10530
10533
  "Bulk Enduser delete, admin",
10531
10534
  () => sdk.sync({ from }),
10532
10535
  { onResult: ({ results }) => (
10533
- results.length === 4
10534
- && results[0].modelName === 'endusers'
10535
- && results[0].recordId === e2.id
10536
- && results[0].data === 'deleted'
10536
+ results.length === 4
10537
+ && results[0].modelName === 'endusers'
10538
+ && results[0].recordId === e2.id
10539
+ && results[0].data === 'deleted'
10537
10540
  )},
10538
10541
  )
10539
10542
  await async_test(
10540
10543
  "Bulk Enduser delete, non-admin",
10541
10544
  () => sdkNonAdmin.sync({ from }),
10542
- { onResult: ({ results }) =>
10545
+ { onResult: ({ results }) =>
10543
10546
  // still includes user notification
10544
- results.length === 1
10547
+ results.length === 1
10545
10548
  && results.filter(r => r.modelName === 'user_notifications').length === 1
10546
- },
10549
+ },
10547
10550
  )
10548
10551
  await async_test(
10549
10552
  "Bulk Enduser delete, sub organization",
@@ -13596,6 +13599,7 @@ const ip_address_form_tests = async () => {
13596
13599
  await setup_tests(sdk, sdkNonAdmin)
13597
13600
  await inbox_thread_assignment_updates_tests({ sdk, sdkNonAdmin })
13598
13601
  await inbox_thread_draft_scheduled_tests({ sdk, sdkNonAdmin })
13602
+ await load_threads_autobuild_tests({ sdk, sdkNonAdmin })
13599
13603
  await inbox_threads_new_fields_tests()
13600
13604
  await auto_merge_form_submission_tests({ sdk, sdkNonAdmin })
13601
13605
  await threadKeyTests()
Binary file