@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.
- package/lib/cjs/sdk.d.ts +1 -0
- package/lib/cjs/sdk.d.ts.map +1 -1
- package/lib/cjs/sdk.js.map +1 -1
- package/lib/cjs/tests/api_tests/afteraction_day_of_month_delay.test.js +1 -1
- package/lib/cjs/tests/api_tests/afteraction_day_of_month_delay.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/load_threads_autobuild.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/load_threads_autobuild.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/load_threads_autobuild.test.js +283 -0
- package/lib/cjs/tests/api_tests/load_threads_autobuild.test.js.map +1 -0
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +116 -111
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/sdk.d.ts +1 -0
- package/lib/esm/sdk.d.ts.map +1 -1
- package/lib/esm/sdk.js.map +1 -1
- package/lib/esm/tests/api_tests/afteraction_day_of_month_delay.test.js +1 -1
- package/lib/esm/tests/api_tests/afteraction_day_of_month_delay.test.js.map +1 -1
- package/lib/esm/tests/api_tests/load_threads_autobuild.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/load_threads_autobuild.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/load_threads_autobuild.test.js +279 -0
- package/lib/esm/tests/api_tests/load_threads_autobuild.test.js.map +1 -0
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +116 -111
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/sdk.ts +1 -1
- package/src/tests/api_tests/afteraction_day_of_month_delay.test.ts +1 -1
- package/src/tests/api_tests/load_threads_autobuild.test.ts +203 -0
- package/src/tests/tests.ts +38 -34
- 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
|
+
}
|
package/src/tests/tests.ts
CHANGED
|
@@ -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()
|
package/test_generated.pdf
CHANGED
|
Binary file
|