@tellescope/sdk 1.236.2 → 1.237.1
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/enduser.d.ts +1 -0
- package/lib/cjs/enduser.d.ts.map +1 -1
- package/lib/cjs/enduser.js +1 -0
- package/lib/cjs/enduser.js.map +1 -1
- package/lib/cjs/sdk.d.ts +1 -0
- package/lib/cjs/sdk.d.ts.map +1 -1
- package/lib/cjs/sdk.js +1 -0
- package/lib/cjs/sdk.js.map +1 -1
- package/lib/cjs/tests/api_tests/inbox_thread_assignment_updates.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/inbox_thread_assignment_updates.test.js +172 -64
- package/lib/cjs/tests/api_tests/inbox_thread_assignment_updates.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/inbox_thread_mdb_filter.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/inbox_thread_mdb_filter.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/inbox_thread_mdb_filter.test.js +372 -0
- package/lib/cjs/tests/api_tests/inbox_thread_mdb_filter.test.js.map +1 -0
- package/lib/cjs/tests/tests.js +571 -105
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/enduser.d.ts +3 -0
- package/lib/esm/enduser.d.ts.map +1 -1
- package/lib/esm/enduser.js +1 -0
- package/lib/esm/enduser.js.map +1 -1
- package/lib/esm/sdk.d.ts +5 -2
- package/lib/esm/sdk.d.ts.map +1 -1
- package/lib/esm/sdk.js +1 -0
- package/lib/esm/sdk.js.map +1 -1
- package/lib/esm/tests/api_tests/inbox_thread_assignment_updates.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/inbox_thread_assignment_updates.test.js +172 -64
- package/lib/esm/tests/api_tests/inbox_thread_assignment_updates.test.js.map +1 -1
- package/lib/esm/tests/api_tests/inbox_thread_mdb_filter.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/inbox_thread_mdb_filter.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/inbox_thread_mdb_filter.test.js +368 -0
- package/lib/esm/tests/api_tests/inbox_thread_mdb_filter.test.js.map +1 -0
- package/lib/esm/tests/tests.js +571 -105
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/enduser.ts +4 -0
- package/src/sdk.ts +4 -0
- package/src/tests/api_tests/inbox_thread_assignment_updates.test.ts +99 -0
- package/src/tests/tests.ts +399 -1
- package/test_generated.pdf +0 -0
|
@@ -354,6 +354,105 @@ export const inbox_thread_assignment_updates_tests = async ({ sdk, sdkNonAdmin }
|
|
|
354
354
|
sdk.api.sms_messages.deleteOne(upsertSMS.id),
|
|
355
355
|
])
|
|
356
356
|
|
|
357
|
+
// Test 10: returnCount parameter - basic count
|
|
358
|
+
console.log("Testing load_threads returnCount parameter...")
|
|
359
|
+
|
|
360
|
+
const countResult = await sdk.api.inbox_threads.load_threads({ returnCount: true })
|
|
361
|
+
assert(typeof countResult.count === 'number', "returnCount should return a count field with a number")
|
|
362
|
+
assert(countResult.threads === undefined, "returnCount should not return threads array")
|
|
363
|
+
|
|
364
|
+
// Verify count matches actual thread count
|
|
365
|
+
const allThreads = await sdk.api.inbox_threads.load_threads({})
|
|
366
|
+
assert(countResult.count === allThreads.threads.length, `Count (${countResult.count}) should match threads length (${allThreads.threads.length})`)
|
|
367
|
+
|
|
368
|
+
console.log("✅ returnCount basic test passed")
|
|
369
|
+
|
|
370
|
+
// Test 11: returnCount with enduserIds filter
|
|
371
|
+
console.log("Testing returnCount with enduserIds filter...")
|
|
372
|
+
|
|
373
|
+
const filteredThreads = await sdk.api.inbox_threads.load_threads({ enduserIds: [testEnduser.id] })
|
|
374
|
+
const filteredCount = await sdk.api.inbox_threads.load_threads({ enduserIds: [testEnduser.id], returnCount: true })
|
|
375
|
+
|
|
376
|
+
assert(typeof filteredCount.count === 'number', "Filtered returnCount should return a count")
|
|
377
|
+
assert(filteredCount.count === filteredThreads.threads.length, `Filtered count (${filteredCount.count}) should match filtered threads length (${filteredThreads.threads.length})`)
|
|
378
|
+
|
|
379
|
+
console.log("✅ returnCount with enduserIds filter test passed")
|
|
380
|
+
|
|
381
|
+
// Test 12: returnCount returns 0 for non-matching filters
|
|
382
|
+
console.log("Testing returnCount returns 0 for non-matching filters...")
|
|
383
|
+
|
|
384
|
+
const nonMatchingCount = await sdk.api.inbox_threads.load_threads({
|
|
385
|
+
enduserIds: ['000000000000000000000000'], // Non-existent enduser ID
|
|
386
|
+
returnCount: true
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
assert(nonMatchingCount.count === 0, `Non-matching filter count should be 0, got ${nonMatchingCount.count}`)
|
|
390
|
+
|
|
391
|
+
console.log("✅ returnCount with non-matching filter test passed")
|
|
392
|
+
|
|
393
|
+
// Test 13: mdbFilter - filter by type
|
|
394
|
+
console.log("Testing mdbFilter - filter by type...")
|
|
395
|
+
const emailTypeFilter = await sdk.api.inbox_threads.load_threads({
|
|
396
|
+
mdbFilter: { type: 'Email' }
|
|
397
|
+
})
|
|
398
|
+
const foundEmailByType = emailTypeFilter.threads.find(t => t.id === emailThread.id)
|
|
399
|
+
const foundSmsByType = emailTypeFilter.threads.find(t => t.id === smsThread.id)
|
|
400
|
+
assert(!!foundEmailByType, 'Email thread should be found when filtering by Email type')
|
|
401
|
+
assert(!foundSmsByType, 'SMS thread should not be found when filtering by Email type')
|
|
402
|
+
console.log("✅ mdbFilter type filter test passed")
|
|
403
|
+
|
|
404
|
+
// Test 14: mdbFilter - filter by multiple types ($in)
|
|
405
|
+
console.log("Testing mdbFilter - filter by multiple types...")
|
|
406
|
+
const multiTypeFilter = await sdk.api.inbox_threads.load_threads({
|
|
407
|
+
mdbFilter: { type: { $in: ['Email', 'SMS'] } }
|
|
408
|
+
})
|
|
409
|
+
const foundEmailMulti = multiTypeFilter.threads.find(t => t.id === emailThread.id)
|
|
410
|
+
const foundSmsMulti = multiTypeFilter.threads.find(t => t.id === smsThread.id)
|
|
411
|
+
const foundChatMulti = multiTypeFilter.threads.find(t => t.id === chatThread.id)
|
|
412
|
+
assert(!!foundEmailMulti, 'Email thread should be found')
|
|
413
|
+
assert(!!foundSmsMulti, 'SMS thread should be found')
|
|
414
|
+
assert(!foundChatMulti, 'Chat thread should not be found when filtering Email/SMS')
|
|
415
|
+
console.log("✅ mdbFilter multiple types filter test passed")
|
|
416
|
+
|
|
417
|
+
// Test 15: mdbFilter - filter by assignedTo
|
|
418
|
+
console.log("Testing mdbFilter - filter by assignedTo...")
|
|
419
|
+
// First assign the email thread (may already be assigned from earlier tests)
|
|
420
|
+
await sdk.api.inbox_threads.updateOne(emailThread.id, { assignedTo: [testUser.id] })
|
|
421
|
+
const assigneeFilter = await sdk.api.inbox_threads.load_threads({
|
|
422
|
+
mdbFilter: { assignedTo: testUser.id }
|
|
423
|
+
})
|
|
424
|
+
const foundAssigned = assigneeFilter.threads.find(t => t.id === emailThread.id)
|
|
425
|
+
assert(!!foundAssigned, 'Email thread should be found when filtering by assignee')
|
|
426
|
+
console.log("✅ mdbFilter assignedTo filter test passed")
|
|
427
|
+
|
|
428
|
+
// Test 16: mdbFilter - combined with existing params
|
|
429
|
+
console.log("Testing mdbFilter combined with enduserIds...")
|
|
430
|
+
const combinedFilter = await sdk.api.inbox_threads.load_threads({
|
|
431
|
+
enduserIds: [testEnduser.id],
|
|
432
|
+
mdbFilter: { type: 'Email' }
|
|
433
|
+
})
|
|
434
|
+
const foundCombined = combinedFilter.threads.find(t => t.id === emailThread.id)
|
|
435
|
+
assert(!!foundCombined, 'Email thread should be found with combined filters')
|
|
436
|
+
console.log("✅ mdbFilter combined filter test passed")
|
|
437
|
+
|
|
438
|
+
// Test 17: mdbFilter with returnCount
|
|
439
|
+
console.log("Testing mdbFilter with returnCount...")
|
|
440
|
+
const mdbFilterCount = await sdk.api.inbox_threads.load_threads({
|
|
441
|
+
mdbFilter: { type: 'Email' },
|
|
442
|
+
returnCount: true
|
|
443
|
+
})
|
|
444
|
+
assert(typeof mdbFilterCount.count === 'number', 'mdbFilter with returnCount should return count')
|
|
445
|
+
assert((mdbFilterCount.count ?? 0) >= 1, 'Count should be at least 1 for Email type')
|
|
446
|
+
console.log("✅ mdbFilter with returnCount test passed")
|
|
447
|
+
|
|
448
|
+
// Test 18: mdbFilter with empty object (should return all)
|
|
449
|
+
console.log("Testing mdbFilter with empty object...")
|
|
450
|
+
const emptyMdbFilter = await sdk.api.inbox_threads.load_threads({
|
|
451
|
+
mdbFilter: {}
|
|
452
|
+
})
|
|
453
|
+
assert(emptyMdbFilter.threads.length > 0, 'Empty mdbFilter should return threads')
|
|
454
|
+
console.log("✅ mdbFilter empty object test passed")
|
|
455
|
+
|
|
357
456
|
console.log("🎉 All InboxThread assignment update tests passed!")
|
|
358
457
|
|
|
359
458
|
} finally {
|
package/src/tests/tests.ts
CHANGED
|
@@ -12911,6 +12911,403 @@ const inbox_threads_loading_tests = async () => {
|
|
|
12911
12911
|
])
|
|
12912
12912
|
}
|
|
12913
12913
|
|
|
12914
|
+
const inbox_threads_new_fields_tests = async () => {
|
|
12915
|
+
log_header("Inbox Thread New Fields Tests (archivedAt, trashedAt, senderIds)")
|
|
12916
|
+
|
|
12917
|
+
const e = await sdk.api.endusers.createOne({ fname: 'Test', lname: 'NewFields' })
|
|
12918
|
+
|
|
12919
|
+
// Use the new reset_threads endpoint for full resets (delete threads + reset dates)
|
|
12920
|
+
const resetThreadsAndDates = () => sdk.api.inbox_threads.reset_threads()
|
|
12921
|
+
|
|
12922
|
+
// Keep separate helper for just resetting dates - needed for merge tests
|
|
12923
|
+
// where we want to keep existing threads but allow rebuild
|
|
12924
|
+
let i = 0
|
|
12925
|
+
const start = new Date()
|
|
12926
|
+
const resetThreadBuildingDates = () => (
|
|
12927
|
+
sdk.api.organizations.updateOne(businessId, { // Uses global businessId constant
|
|
12928
|
+
inboxThreadsBuiltFrom: new Date(start.getTime() + (i++)),
|
|
12929
|
+
inboxThreadsBuiltTo: new Date(start.getTime() + (i++))
|
|
12930
|
+
})
|
|
12931
|
+
)
|
|
12932
|
+
// Start with clean state
|
|
12933
|
+
await resetThreadsAndDates()
|
|
12934
|
+
const from = new Date(start.getTime() - 10000)
|
|
12935
|
+
|
|
12936
|
+
// Test 1: Sender ID Tests - Email
|
|
12937
|
+
log_header("Sender ID Tests - Email")
|
|
12938
|
+
await sdk.api.emails.createOne({
|
|
12939
|
+
logOnly: true,
|
|
12940
|
+
subject: 'Test Email Inbound',
|
|
12941
|
+
textContent: 'Inbound email',
|
|
12942
|
+
enduserId: e.id,
|
|
12943
|
+
inbound: true,
|
|
12944
|
+
userId: sdk.userInfo.id,
|
|
12945
|
+
})
|
|
12946
|
+
await sdk.api.emails.createOne({
|
|
12947
|
+
logOnly: true,
|
|
12948
|
+
subject: 'Test Email Inbound', // Same subject to be same thread
|
|
12949
|
+
textContent: 'Outbound email',
|
|
12950
|
+
enduserId: e.id,
|
|
12951
|
+
inbound: false,
|
|
12952
|
+
userId: sdk.userInfo.id,
|
|
12953
|
+
})
|
|
12954
|
+
|
|
12955
|
+
await async_test(
|
|
12956
|
+
'build email threads with sender IDs',
|
|
12957
|
+
() => sdk.api.inbox_threads.build_threads({ from, to: new Date() }),
|
|
12958
|
+
{ onResult: ({ alreadyBuilt }) => !alreadyBuilt }
|
|
12959
|
+
)
|
|
12960
|
+
await async_test(
|
|
12961
|
+
'verify email thread has correct sender IDs',
|
|
12962
|
+
() => sdk.api.inbox_threads.load_threads({ }),
|
|
12963
|
+
{ onResult: ({ threads }) => {
|
|
12964
|
+
const emailThread = threads.find(t => t.type === 'Email')
|
|
12965
|
+
return !!emailThread
|
|
12966
|
+
&& emailThread.recentOutboundUserId === sdk.userInfo.id
|
|
12967
|
+
&& emailThread.recentInboundEnduserId === e.id
|
|
12968
|
+
}}
|
|
12969
|
+
)
|
|
12970
|
+
|
|
12971
|
+
// Test 2: Sender ID Tests - SMS
|
|
12972
|
+
log_header("Sender ID Tests - SMS")
|
|
12973
|
+
await resetThreadsAndDates()
|
|
12974
|
+
await sdk.api.sms_messages.createOne({
|
|
12975
|
+
logOnly: true,
|
|
12976
|
+
inbound: true,
|
|
12977
|
+
enduserId: e.id,
|
|
12978
|
+
message: 'Inbound SMS',
|
|
12979
|
+
userId: sdk.userInfo.id,
|
|
12980
|
+
phoneNumber: '+15555555555',
|
|
12981
|
+
enduserPhoneNumber: '+15555555556',
|
|
12982
|
+
})
|
|
12983
|
+
await sdk.api.sms_messages.createOne({
|
|
12984
|
+
logOnly: true,
|
|
12985
|
+
inbound: false,
|
|
12986
|
+
enduserId: e.id,
|
|
12987
|
+
message: 'Outbound SMS',
|
|
12988
|
+
userId: sdk.userInfo.id,
|
|
12989
|
+
phoneNumber: '+15555555555',
|
|
12990
|
+
enduserPhoneNumber: '+15555555556',
|
|
12991
|
+
})
|
|
12992
|
+
|
|
12993
|
+
await async_test(
|
|
12994
|
+
'build SMS threads with sender IDs',
|
|
12995
|
+
() => sdk.api.inbox_threads.build_threads({ from, to: new Date() }),
|
|
12996
|
+
{ onResult: ({ alreadyBuilt }) => !alreadyBuilt }
|
|
12997
|
+
)
|
|
12998
|
+
await async_test(
|
|
12999
|
+
'verify SMS thread has correct sender IDs',
|
|
13000
|
+
() => sdk.api.inbox_threads.load_threads({ }),
|
|
13001
|
+
{ onResult: ({ threads }) => {
|
|
13002
|
+
const smsThread = threads.find(t => t.type === 'SMS')
|
|
13003
|
+
return !!smsThread
|
|
13004
|
+
&& smsThread.recentOutboundUserId === sdk.userInfo.id
|
|
13005
|
+
&& smsThread.recentInboundEnduserId === e.id
|
|
13006
|
+
}}
|
|
13007
|
+
)
|
|
13008
|
+
|
|
13009
|
+
// Test 3: Sender ID Tests - ChatRoom
|
|
13010
|
+
log_header("Sender ID Tests - ChatRoom")
|
|
13011
|
+
await resetThreadsAndDates()
|
|
13012
|
+
const chatRoom = await sdk.api.chat_rooms.createOne({
|
|
13013
|
+
title: 'Test Chat Room',
|
|
13014
|
+
userIds: [sdk.userInfo.id],
|
|
13015
|
+
enduserIds: [e.id],
|
|
13016
|
+
})
|
|
13017
|
+
// First message from user (outbound)
|
|
13018
|
+
await sdk.api.chats.createOne({ roomId: chatRoom.id, message: 'User message', senderId: sdk.userInfo.id })
|
|
13019
|
+
await wait(undefined, 500)
|
|
13020
|
+
|
|
13021
|
+
await async_test(
|
|
13022
|
+
'build chat threads after user message',
|
|
13023
|
+
() => sdk.api.inbox_threads.build_threads({ from, to: new Date() }),
|
|
13024
|
+
{ onResult: ({ alreadyBuilt }) => !alreadyBuilt }
|
|
13025
|
+
)
|
|
13026
|
+
await async_test(
|
|
13027
|
+
'verify chat thread has outbound userId only',
|
|
13028
|
+
() => sdk.api.inbox_threads.load_threads({ }),
|
|
13029
|
+
{ onResult: ({ threads }) => {
|
|
13030
|
+
const chatThread = threads.find(t => t.type === 'Chat')
|
|
13031
|
+
return !!chatThread
|
|
13032
|
+
&& chatThread.recentOutboundUserId === sdk.userInfo.id
|
|
13033
|
+
&& !chatThread.recentInboundEnduserId
|
|
13034
|
+
}}
|
|
13035
|
+
)
|
|
13036
|
+
|
|
13037
|
+
// Now enduser sends a message (becomes recentSender, but merge preserves previous outbound userId)
|
|
13038
|
+
await sdk.api.chats.createOne({ roomId: chatRoom.id, message: 'Enduser message', enduserId: e.id, senderId: e.id })
|
|
13039
|
+
await wait(undefined, 500)
|
|
13040
|
+
await resetThreadBuildingDates() // Only reset dates, keep existing thread for merge test
|
|
13041
|
+
|
|
13042
|
+
await async_test(
|
|
13043
|
+
'rebuild chat threads after enduser message',
|
|
13044
|
+
() => sdk.api.inbox_threads.build_threads({ from, to: new Date() }),
|
|
13045
|
+
{ onResult: ({ alreadyBuilt }) => !alreadyBuilt }
|
|
13046
|
+
)
|
|
13047
|
+
await async_test(
|
|
13048
|
+
'verify chat thread has both sender IDs (merge preserves previous)',
|
|
13049
|
+
() => sdk.api.inbox_threads.load_threads({ }),
|
|
13050
|
+
{ onResult: ({ threads }) => {
|
|
13051
|
+
const chatThread = threads.find(t => t.type === 'Chat')
|
|
13052
|
+
// ChatRoom only tracks one recentSender at a time, but merge preserves both IDs
|
|
13053
|
+
return !!chatThread
|
|
13054
|
+
&& chatThread.recentOutboundUserId === sdk.userInfo.id // preserved from previous build
|
|
13055
|
+
&& chatThread.recentInboundEnduserId === e.id // from current build
|
|
13056
|
+
}}
|
|
13057
|
+
)
|
|
13058
|
+
|
|
13059
|
+
// Test 4: Sender ID Tests - GroupMMS
|
|
13060
|
+
log_header("Sender ID Tests - GroupMMS")
|
|
13061
|
+
await resetThreadsAndDates()
|
|
13062
|
+
const groupMMS = await sdk.api.group_mms_conversations.createOne({
|
|
13063
|
+
enduserIds: [e.id],
|
|
13064
|
+
userIds: [sdk.userInfo.id],
|
|
13065
|
+
userStates: [],
|
|
13066
|
+
messages: [
|
|
13067
|
+
{ message: 'Inbound message', sender: e.id, timestamp: Date.now() - 1000, logOnly: true },
|
|
13068
|
+
{ message: 'Outbound message', sender: sdk.userInfo.id, timestamp: Date.now(), logOnly: true },
|
|
13069
|
+
],
|
|
13070
|
+
})
|
|
13071
|
+
|
|
13072
|
+
await async_test(
|
|
13073
|
+
'build GroupMMS threads with sender IDs',
|
|
13074
|
+
() => sdk.api.inbox_threads.build_threads({ from, to: new Date() }),
|
|
13075
|
+
{ onResult: ({ alreadyBuilt }) => !alreadyBuilt }
|
|
13076
|
+
)
|
|
13077
|
+
await async_test(
|
|
13078
|
+
'verify GroupMMS thread has correct sender IDs',
|
|
13079
|
+
() => sdk.api.inbox_threads.load_threads({ }),
|
|
13080
|
+
{ onResult: ({ threads }) => {
|
|
13081
|
+
const groupMMSThread = threads.find(t => t.type === 'GroupMMS')
|
|
13082
|
+
return !!groupMMSThread
|
|
13083
|
+
&& groupMMSThread.recentOutboundUserId === sdk.userInfo.id
|
|
13084
|
+
&& groupMMSThread.recentInboundEnduserId === e.id
|
|
13085
|
+
}}
|
|
13086
|
+
)
|
|
13087
|
+
|
|
13088
|
+
// Test 5: Sender ID Tests - PhoneCall
|
|
13089
|
+
log_header("Sender ID Tests - PhoneCall")
|
|
13090
|
+
await resetThreadsAndDates()
|
|
13091
|
+
const inboundCall = await sdk.api.phone_calls.createOne({
|
|
13092
|
+
enduserId: e.id,
|
|
13093
|
+
inbound: true,
|
|
13094
|
+
to: '+15555555555',
|
|
13095
|
+
from: '+15555555556',
|
|
13096
|
+
userId: sdk.userInfo.id,
|
|
13097
|
+
})
|
|
13098
|
+
|
|
13099
|
+
await async_test(
|
|
13100
|
+
'build phone call threads (inbound)',
|
|
13101
|
+
() => sdk.api.inbox_threads.build_threads({ from, to: new Date() }),
|
|
13102
|
+
{ onResult: ({ alreadyBuilt }) => !alreadyBuilt }
|
|
13103
|
+
)
|
|
13104
|
+
await async_test(
|
|
13105
|
+
'verify inbound phone call thread has enduserId',
|
|
13106
|
+
() => sdk.api.inbox_threads.load_threads({ }),
|
|
13107
|
+
{ onResult: ({ threads }) => {
|
|
13108
|
+
const callThread = threads.find(t => t.type === 'Phone' && t.threadId === inboundCall.id)
|
|
13109
|
+
return !!callThread
|
|
13110
|
+
&& !callThread.recentOutboundUserId
|
|
13111
|
+
&& callThread.recentInboundEnduserId === e.id
|
|
13112
|
+
}}
|
|
13113
|
+
)
|
|
13114
|
+
|
|
13115
|
+
// Test outbound call separately to avoid date range issues
|
|
13116
|
+
await resetThreadsAndDates()
|
|
13117
|
+
const outboundCall = await sdk.api.phone_calls.createOne({
|
|
13118
|
+
enduserId: e.id,
|
|
13119
|
+
inbound: false,
|
|
13120
|
+
to: '+15555555556',
|
|
13121
|
+
from: '+15555555555',
|
|
13122
|
+
userId: sdk.userInfo.id,
|
|
13123
|
+
})
|
|
13124
|
+
|
|
13125
|
+
await async_test(
|
|
13126
|
+
'build phone call threads (outbound)',
|
|
13127
|
+
() => sdk.api.inbox_threads.build_threads({ from, to: new Date() }),
|
|
13128
|
+
{ onResult: ({ alreadyBuilt }) => !alreadyBuilt }
|
|
13129
|
+
)
|
|
13130
|
+
await async_test(
|
|
13131
|
+
'verify outbound phone call thread has userId',
|
|
13132
|
+
() => sdk.api.inbox_threads.load_threads({ }),
|
|
13133
|
+
{ onResult: ({ threads }) => {
|
|
13134
|
+
const callThread = threads.find(t => t.type === 'Phone' && t.threadId === outboundCall.id)
|
|
13135
|
+
return !!callThread
|
|
13136
|
+
&& callThread.recentOutboundUserId === sdk.userInfo.id
|
|
13137
|
+
&& !callThread.recentInboundEnduserId
|
|
13138
|
+
}}
|
|
13139
|
+
)
|
|
13140
|
+
|
|
13141
|
+
// Test 6: Archive/Trash Tests - Propagation
|
|
13142
|
+
log_header("Archive/Trash Tests - Propagation")
|
|
13143
|
+
await resetThreadsAndDates()
|
|
13144
|
+
const archivedDate = new Date()
|
|
13145
|
+
await sdk.api.emails.createOne({
|
|
13146
|
+
logOnly: true,
|
|
13147
|
+
subject: 'Archived Email',
|
|
13148
|
+
textContent: 'This email is archived',
|
|
13149
|
+
enduserId: e.id,
|
|
13150
|
+
inbound: true,
|
|
13151
|
+
userId: sdk.userInfo.id,
|
|
13152
|
+
archivedAt: archivedDate,
|
|
13153
|
+
})
|
|
13154
|
+
|
|
13155
|
+
await async_test(
|
|
13156
|
+
'build threads with archived email',
|
|
13157
|
+
() => sdk.api.inbox_threads.build_threads({ from, to: new Date() }),
|
|
13158
|
+
{ onResult: ({ alreadyBuilt }) => !alreadyBuilt }
|
|
13159
|
+
)
|
|
13160
|
+
await async_test(
|
|
13161
|
+
'verify thread has archivedAt populated',
|
|
13162
|
+
() => sdk.api.inbox_threads.load_threads({ }),
|
|
13163
|
+
{ onResult: ({ threads }) => {
|
|
13164
|
+
const emailThread = threads.find(t => t.type === 'Email')
|
|
13165
|
+
return !!emailThread
|
|
13166
|
+
&& !!emailThread.archivedAt
|
|
13167
|
+
&& new Date(emailThread.archivedAt).getTime() === archivedDate.getTime()
|
|
13168
|
+
}}
|
|
13169
|
+
)
|
|
13170
|
+
|
|
13171
|
+
// Test 7: Archive/Trash Tests - Clearing (new message clears archived status)
|
|
13172
|
+
log_header("Archive/Trash Tests - Clearing")
|
|
13173
|
+
await sdk.api.emails.createOne({
|
|
13174
|
+
logOnly: true,
|
|
13175
|
+
subject: 'Archived Email', // Same subject = same thread
|
|
13176
|
+
textContent: 'This email is NOT archived',
|
|
13177
|
+
enduserId: e.id,
|
|
13178
|
+
inbound: true,
|
|
13179
|
+
userId: sdk.userInfo.id,
|
|
13180
|
+
// No archivedAt
|
|
13181
|
+
})
|
|
13182
|
+
await resetThreadBuildingDates() // Only reset dates, keep existing thread for merge test
|
|
13183
|
+
|
|
13184
|
+
await async_test(
|
|
13185
|
+
'rebuild threads after non-archived message',
|
|
13186
|
+
() => sdk.api.inbox_threads.build_threads({ from, to: new Date() }),
|
|
13187
|
+
{ onResult: ({ alreadyBuilt }) => !alreadyBuilt }
|
|
13188
|
+
)
|
|
13189
|
+
await async_test(
|
|
13190
|
+
'verify thread archivedAt is cleared',
|
|
13191
|
+
() => sdk.api.inbox_threads.load_threads({ }),
|
|
13192
|
+
{ onResult: ({ threads }) => {
|
|
13193
|
+
const emailThread = threads.find(t => t.type === 'Email')
|
|
13194
|
+
return !!emailThread && emailThread.archivedAt === ''
|
|
13195
|
+
}}
|
|
13196
|
+
)
|
|
13197
|
+
|
|
13198
|
+
// Test 8: Archive/Trash Tests - trashedAt propagation
|
|
13199
|
+
log_header("Archive/Trash Tests - Trashed Propagation")
|
|
13200
|
+
await resetThreadsAndDates()
|
|
13201
|
+
const trashedDate = new Date()
|
|
13202
|
+
await sdk.api.sms_messages.createOne({
|
|
13203
|
+
logOnly: true,
|
|
13204
|
+
inbound: true,
|
|
13205
|
+
enduserId: e.id,
|
|
13206
|
+
message: 'Trashed SMS',
|
|
13207
|
+
userId: sdk.userInfo.id,
|
|
13208
|
+
phoneNumber: '+15555555557',
|
|
13209
|
+
enduserPhoneNumber: '+15555555558',
|
|
13210
|
+
trashedAt: trashedDate,
|
|
13211
|
+
})
|
|
13212
|
+
|
|
13213
|
+
await async_test(
|
|
13214
|
+
'build threads with trashed SMS',
|
|
13215
|
+
() => sdk.api.inbox_threads.build_threads({ from, to: new Date() }),
|
|
13216
|
+
{ onResult: ({ alreadyBuilt }) => !alreadyBuilt }
|
|
13217
|
+
)
|
|
13218
|
+
await async_test(
|
|
13219
|
+
'verify thread has trashedAt populated',
|
|
13220
|
+
() => sdk.api.inbox_threads.load_threads({ }),
|
|
13221
|
+
{ onResult: ({ threads }) => {
|
|
13222
|
+
const smsThread = threads.find(t => t.type === 'SMS' && t.phoneNumber === '+15555555557')
|
|
13223
|
+
return !!smsThread
|
|
13224
|
+
&& !!smsThread.trashedAt
|
|
13225
|
+
&& new Date(smsThread.trashedAt).getTime() === trashedDate.getTime()
|
|
13226
|
+
}}
|
|
13227
|
+
)
|
|
13228
|
+
|
|
13229
|
+
// Test 9: Archive/Trash Tests - Most Recent Archived, Older Not
|
|
13230
|
+
log_header("Archive/Trash Tests - Most Recent Archived, Older Not")
|
|
13231
|
+
await resetThreadsAndDates()
|
|
13232
|
+
// Create non-archived message first (older)
|
|
13233
|
+
await sdk.api.emails.createOne({
|
|
13234
|
+
logOnly: true,
|
|
13235
|
+
subject: 'Archive Order Test',
|
|
13236
|
+
textContent: 'Older non-archived email',
|
|
13237
|
+
enduserId: e.id,
|
|
13238
|
+
inbound: true,
|
|
13239
|
+
userId: sdk.userInfo.id,
|
|
13240
|
+
// No archivedAt
|
|
13241
|
+
})
|
|
13242
|
+
|
|
13243
|
+
await wait(undefined, 100) // Small delay to ensure ordering
|
|
13244
|
+
|
|
13245
|
+
// Create archived message second (newer = most recent)
|
|
13246
|
+
await sdk.api.emails.createOne({
|
|
13247
|
+
logOnly: true,
|
|
13248
|
+
subject: 'Archive Order Test', // Same subject = same thread
|
|
13249
|
+
textContent: 'Newer archived email',
|
|
13250
|
+
enduserId: e.id,
|
|
13251
|
+
inbound: true,
|
|
13252
|
+
userId: sdk.userInfo.id,
|
|
13253
|
+
archivedAt: new Date(),
|
|
13254
|
+
})
|
|
13255
|
+
|
|
13256
|
+
await async_test(
|
|
13257
|
+
'build threads for archive order test',
|
|
13258
|
+
() => sdk.api.inbox_threads.build_threads({ from, to: new Date() }),
|
|
13259
|
+
{ onResult: ({ alreadyBuilt }) => !alreadyBuilt }
|
|
13260
|
+
)
|
|
13261
|
+
await async_test(
|
|
13262
|
+
'verify thread archivedAt follows most recent message (IS archived)',
|
|
13263
|
+
() => sdk.api.inbox_threads.load_threads({ }),
|
|
13264
|
+
{ onResult: ({ threads }) => {
|
|
13265
|
+
const emailThread = threads.find(t => t.type === 'Email')
|
|
13266
|
+
// Most recent message is archived, so thread should be archived
|
|
13267
|
+
return !!emailThread && !!emailThread.archivedAt
|
|
13268
|
+
}}
|
|
13269
|
+
)
|
|
13270
|
+
|
|
13271
|
+
// Test 10: Reset Threads Endpoint - Comprehensive Coverage
|
|
13272
|
+
log_header("Reset Threads Endpoint Test")
|
|
13273
|
+
|
|
13274
|
+
// Test 10a: Verify threads are deleted and count returned
|
|
13275
|
+
const beforeReset = await sdk.api.inbox_threads.load_threads({})
|
|
13276
|
+
assert(beforeReset.threads.length > 0, 'no threads before reset test', 'threads exist before reset test')
|
|
13277
|
+
|
|
13278
|
+
const resetResult = await sdk.api.inbox_threads.reset_threads()
|
|
13279
|
+
assert(resetResult.deletedCount > 0, 'no threads deleted by reset', 'reset_threads deleted threads')
|
|
13280
|
+
|
|
13281
|
+
const afterReset = await sdk.api.inbox_threads.load_threads({})
|
|
13282
|
+
assert(afterReset.threads.length === 0, 'threads remain after reset', 'all threads deleted after reset')
|
|
13283
|
+
|
|
13284
|
+
// Test 10b: Verify organization dates are reset to epoch
|
|
13285
|
+
const org = await sdk.api.organizations.getOne(businessId)
|
|
13286
|
+
const epochTime = new Date(0).getTime()
|
|
13287
|
+
assert(
|
|
13288
|
+
new Date(org.inboxThreadsBuiltFrom ?? 0).getTime() === epochTime,
|
|
13289
|
+
'inboxThreadsBuiltFrom not reset to epoch',
|
|
13290
|
+
'organization inboxThreadsBuiltFrom reset to epoch'
|
|
13291
|
+
)
|
|
13292
|
+
assert(
|
|
13293
|
+
new Date(org.inboxThreadsBuiltTo ?? 0).getTime() === epochTime,
|
|
13294
|
+
'inboxThreadsBuiltTo not reset to epoch',
|
|
13295
|
+
'organization inboxThreadsBuiltTo reset to epoch'
|
|
13296
|
+
)
|
|
13297
|
+
|
|
13298
|
+
// Test 10c: Verify reset with no threads returns deletedCount: 0
|
|
13299
|
+
const emptyResetResult = await sdk.api.inbox_threads.reset_threads()
|
|
13300
|
+
assert(emptyResetResult.deletedCount === 0, 'deletedCount should be 0 when no threads', 'reset with no threads returns 0')
|
|
13301
|
+
|
|
13302
|
+
// Cleanup
|
|
13303
|
+
await Promise.all([
|
|
13304
|
+
sdk.api.endusers.deleteOne(e.id),
|
|
13305
|
+
sdk.api.chat_rooms.deleteOne(chatRoom.id).catch(() => {}),
|
|
13306
|
+
sdk.api.group_mms_conversations.deleteOne(groupMMS.id).catch(() => {}),
|
|
13307
|
+
resetThreadsAndDates(), // Use the new endpoint for cleanup
|
|
13308
|
+
])
|
|
13309
|
+
}
|
|
13310
|
+
|
|
12914
13311
|
const get_next_reminder_timestamp_tests = () => {
|
|
12915
13312
|
log_header("Get Next Reminder Timestamp Tests")
|
|
12916
13313
|
|
|
@@ -13173,6 +13570,8 @@ const ip_address_form_tests = async () => {
|
|
|
13173
13570
|
await replace_enduser_template_values_tests()
|
|
13174
13571
|
await mfa_tests()
|
|
13175
13572
|
await setup_tests(sdk, sdkNonAdmin)
|
|
13573
|
+
await inbox_threads_new_fields_tests()
|
|
13574
|
+
await inbox_thread_assignment_updates_tests({ sdk, sdkNonAdmin })
|
|
13176
13575
|
await auto_merge_form_submission_tests({ sdk, sdkNonAdmin })
|
|
13177
13576
|
await threadKeyTests()
|
|
13178
13577
|
await automation_trigger_tests()
|
|
@@ -13187,7 +13586,6 @@ const ip_address_form_tests = async () => {
|
|
|
13187
13586
|
await test_ticket_automation_assignment_and_optimization()
|
|
13188
13587
|
await monthly_availability_restrictions_tests({ sdk, sdkNonAdmin })
|
|
13189
13588
|
await journey_error_branching_tests({ sdk, sdkNonAdmin })
|
|
13190
|
-
await inbox_thread_assignment_updates_tests({ sdk, sdkNonAdmin })
|
|
13191
13589
|
await message_assignment_trigger_tests({ sdk })
|
|
13192
13590
|
await inbox_threads_building_tests()
|
|
13193
13591
|
await inbox_threads_loading_tests()
|
package/test_generated.pdf
CHANGED
|
Binary file
|