@tellescope/sdk 1.232.0 → 1.233.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/tests/api_tests/custom_aggregation.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/custom_aggregation.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/custom_aggregation.test.js +198 -0
- package/lib/cjs/tests/api_tests/custom_aggregation.test.js.map +1 -0
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +192 -103
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/tests/api_tests/custom_aggregation.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/custom_aggregation.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/custom_aggregation.test.js +194 -0
- package/lib/esm/tests/api_tests/custom_aggregation.test.js.map +1 -0
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +192 -103
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -11
- package/src/tests/api_tests/custom_aggregation.test.ts +140 -0
- package/src/tests/tests.ts +78 -1
- package/test_generated.pdf +0 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
require('source-map-support').install();
|
|
2
|
+
|
|
3
|
+
import { Session } from "../../sdk"
|
|
4
|
+
import {
|
|
5
|
+
async_test,
|
|
6
|
+
log_header,
|
|
7
|
+
} from "@tellescope/testing"
|
|
8
|
+
import { setup_tests } from "../setup"
|
|
9
|
+
|
|
10
|
+
const host = process.env.API_URL || 'http://localhost:8080' as const
|
|
11
|
+
|
|
12
|
+
// Main test function that can be called independently
|
|
13
|
+
export const custom_aggregation_tests = async ({ sdk, sdkNonAdmin } : { sdk: Session, sdkNonAdmin: Session }) => {
|
|
14
|
+
log_header("Custom Aggregation Tests")
|
|
15
|
+
|
|
16
|
+
// Create test data: an enduser with a password to ensure hashedPassword gets set
|
|
17
|
+
const testEnduser = await sdk.api.endusers.createOne({
|
|
18
|
+
fname: 'CustomAgg',
|
|
19
|
+
lname: 'TestUser',
|
|
20
|
+
email: 'custom-agg-test@example.com',
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
// Set a password on the enduser (this creates a hashedPassword field)
|
|
24
|
+
await sdk.api.endusers.set_password({
|
|
25
|
+
id: testEnduser.id,
|
|
26
|
+
password: 'TestPassword123!',
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
// Test 1: Basic aggregation works
|
|
31
|
+
await async_test(
|
|
32
|
+
"Custom aggregation - basic query works",
|
|
33
|
+
() => sdk.api.analytics_frames.custom_aggregation({
|
|
34
|
+
modelName: 'endusers',
|
|
35
|
+
aggregation: [
|
|
36
|
+
{ $match: { fname: 'CustomAgg' } },
|
|
37
|
+
{ $count: 'total' }
|
|
38
|
+
]
|
|
39
|
+
}),
|
|
40
|
+
{ onResult: r => r.result[0]?.total === 1 }
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
// Test 2: Aggregation returns enduser data
|
|
44
|
+
await async_test(
|
|
45
|
+
"Custom aggregation - returns enduser fields",
|
|
46
|
+
() => sdk.api.analytics_frames.custom_aggregation({
|
|
47
|
+
modelName: 'endusers',
|
|
48
|
+
aggregation: [
|
|
49
|
+
{ $match: { fname: 'CustomAgg' } },
|
|
50
|
+
{ $project: { fname: 1, lname: 1, email: 1 } }
|
|
51
|
+
]
|
|
52
|
+
}),
|
|
53
|
+
{ onResult: r => {
|
|
54
|
+
const user = r.result[0]
|
|
55
|
+
return user.fname === 'CustomAgg'
|
|
56
|
+
&& user.lname === 'TestUser'
|
|
57
|
+
&& user.email === 'custom-agg-test@example.com'
|
|
58
|
+
}}
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
// Test 3: CRITICAL - hashedPassword is redacted even if requested
|
|
62
|
+
await async_test(
|
|
63
|
+
"Custom aggregation - hashedPassword is redacted (explicit project)",
|
|
64
|
+
() => sdk.api.analytics_frames.custom_aggregation({
|
|
65
|
+
modelName: 'endusers',
|
|
66
|
+
aggregation: [
|
|
67
|
+
{ $match: { fname: 'CustomAgg' } },
|
|
68
|
+
{ $project: { fname: 1, hashedPassword: 1 } } // Explicitly request password
|
|
69
|
+
]
|
|
70
|
+
}),
|
|
71
|
+
{ onResult: r => {
|
|
72
|
+
const user = r.result[0]
|
|
73
|
+
// Should have fname but NOT hashedPassword
|
|
74
|
+
return user.fname === 'CustomAgg' && user.hashedPassword === undefined
|
|
75
|
+
}}
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
// Test 4: hashedPassword is redacted even without explicit project
|
|
79
|
+
await async_test(
|
|
80
|
+
"Custom aggregation - hashedPassword is redacted (no project)",
|
|
81
|
+
() => sdk.api.analytics_frames.custom_aggregation({
|
|
82
|
+
modelName: 'endusers',
|
|
83
|
+
aggregation: [
|
|
84
|
+
{ $match: { fname: 'CustomAgg' } },
|
|
85
|
+
{ $limit: 1 }
|
|
86
|
+
]
|
|
87
|
+
}),
|
|
88
|
+
{ onResult: r => {
|
|
89
|
+
const user = r.result[0]
|
|
90
|
+
// Should return user data but NOT hashedPassword
|
|
91
|
+
return user.fname === 'CustomAgg' && user.hashedPassword === undefined
|
|
92
|
+
}}
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
// Test 5: Aggregation with grouping doesn't leak hashedPassword
|
|
96
|
+
await async_test(
|
|
97
|
+
"Custom aggregation - hashedPassword redacted in grouped results",
|
|
98
|
+
() => sdk.api.analytics_frames.custom_aggregation({
|
|
99
|
+
modelName: 'endusers',
|
|
100
|
+
aggregation: [
|
|
101
|
+
{ $match: { fname: 'CustomAgg' } },
|
|
102
|
+
{ $group: { _id: '$fname', count: { $sum: 1 }, data: { $push: '$$ROOT' } } }
|
|
103
|
+
]
|
|
104
|
+
}),
|
|
105
|
+
{ onResult: r => {
|
|
106
|
+
const group = r.result[0]
|
|
107
|
+
const user = group.data[0]
|
|
108
|
+
// Even in grouped results, hashedPassword should not be present
|
|
109
|
+
return group.count === 1 && user.hashedPassword === undefined
|
|
110
|
+
}}
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
console.log("✅ All custom aggregation tests passed")
|
|
114
|
+
} finally {
|
|
115
|
+
// Cleanup
|
|
116
|
+
await sdk.api.endusers.deleteOne(testEnduser.id)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Allow running this test file independently
|
|
121
|
+
if (require.main === module) {
|
|
122
|
+
console.log(`🌐 Using API URL: ${host}`)
|
|
123
|
+
const sdk = new Session({ host })
|
|
124
|
+
const sdkNonAdmin = new Session({ host })
|
|
125
|
+
|
|
126
|
+
const runTests = async () => {
|
|
127
|
+
await setup_tests(sdk, sdkNonAdmin)
|
|
128
|
+
await custom_aggregation_tests({ sdk, sdkNonAdmin })
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
runTests()
|
|
132
|
+
.then(() => {
|
|
133
|
+
console.log("✅ Custom aggregation test suite completed successfully")
|
|
134
|
+
process.exit(0)
|
|
135
|
+
})
|
|
136
|
+
.catch((error) => {
|
|
137
|
+
console.error("❌ Custom aggregation test suite failed:", error)
|
|
138
|
+
process.exit(1)
|
|
139
|
+
})
|
|
140
|
+
}
|
package/src/tests/tests.ts
CHANGED
|
@@ -72,6 +72,7 @@ import { message_assignment_trigger_tests } from "./api_tests/message_assignment
|
|
|
72
72
|
import { time_tracks_tests } from "./api_tests/time_tracks.test";
|
|
73
73
|
import { monthly_availability_restrictions_tests } from "./api_tests/monthly_availability_restrictions.test";
|
|
74
74
|
import { calendar_event_limits_tests } from "./api_tests/calendar_event_limits.test";
|
|
75
|
+
import { custom_aggregation_tests } from "./api_tests/custom_aggregation.test";
|
|
75
76
|
|
|
76
77
|
const UniquenessViolationMessage = 'Uniqueness Violation'
|
|
77
78
|
|
|
@@ -4403,6 +4404,77 @@ const set_fields_tests = async () => {
|
|
|
4403
4404
|
{ onResult: e => Number(e.fields?.yyyyDaysBetween) === 10 }
|
|
4404
4405
|
)
|
|
4405
4406
|
|
|
4407
|
+
// Test setting timezone built-in field
|
|
4408
|
+
log_header("Set Fields Built-in Field Tests (Timezone)")
|
|
4409
|
+
|
|
4410
|
+
const e4 = await sdk.api.endusers.createOne({})
|
|
4411
|
+
|
|
4412
|
+
const t7 = await sdk.api.automation_triggers.createOne({
|
|
4413
|
+
title: "Set Timezone Test", status: 'Active',
|
|
4414
|
+
event: { type: 'Field Equals', info: { field: 'triggerTimezone', value: 'set-eastern' } },
|
|
4415
|
+
action: {
|
|
4416
|
+
type: 'Set Fields',
|
|
4417
|
+
info: {
|
|
4418
|
+
fields: [
|
|
4419
|
+
{ name: 'timezone', type: 'Custom Value', value: 'US/Eastern' }
|
|
4420
|
+
]
|
|
4421
|
+
},
|
|
4422
|
+
}
|
|
4423
|
+
})
|
|
4424
|
+
|
|
4425
|
+
await sdk.api.endusers.updateOne(e4.id, { fields: { triggerTimezone: 'set-eastern' } })
|
|
4426
|
+
await wait(undefined, 1000)
|
|
4427
|
+
await async_test(
|
|
4428
|
+
"Set Fields: set timezone built-in field to US/Eastern",
|
|
4429
|
+
() => sdk.api.endusers.getOne(e4.id),
|
|
4430
|
+
{ onResult: e => e.timezone === 'US/Eastern' }
|
|
4431
|
+
)
|
|
4432
|
+
|
|
4433
|
+
// Test with different timezone format
|
|
4434
|
+
const t8 = await sdk.api.automation_triggers.createOne({
|
|
4435
|
+
title: "Set Timezone America/Los_Angeles Test", status: 'Active',
|
|
4436
|
+
event: { type: 'Field Equals', info: { field: 'triggerTimezone', value: 'set-pacific' } },
|
|
4437
|
+
action: {
|
|
4438
|
+
type: 'Set Fields',
|
|
4439
|
+
info: {
|
|
4440
|
+
fields: [
|
|
4441
|
+
{ name: 'timezone', type: 'Custom Value', value: 'America/Los_Angeles' }
|
|
4442
|
+
]
|
|
4443
|
+
},
|
|
4444
|
+
}
|
|
4445
|
+
})
|
|
4446
|
+
|
|
4447
|
+
await sdk.api.endusers.updateOne(e4.id, { fields: { triggerTimezone: 'set-pacific' } })
|
|
4448
|
+
await wait(undefined, 1000)
|
|
4449
|
+
await async_test(
|
|
4450
|
+
"Set Fields: update timezone to America/Los_Angeles",
|
|
4451
|
+
() => sdk.api.endusers.getOne(e4.id),
|
|
4452
|
+
{ onResult: e => e.timezone === 'America/Los_Angeles' }
|
|
4453
|
+
)
|
|
4454
|
+
|
|
4455
|
+
// Test setting multiple built-in fields including timezone
|
|
4456
|
+
const t9 = await sdk.api.automation_triggers.createOne({
|
|
4457
|
+
title: "Set Multiple Built-ins Test", status: 'Active',
|
|
4458
|
+
event: { type: 'Field Equals', info: { field: 'triggerTimezone', value: 'set-multiple' } },
|
|
4459
|
+
action: {
|
|
4460
|
+
type: 'Set Fields',
|
|
4461
|
+
info: {
|
|
4462
|
+
fields: [
|
|
4463
|
+
{ name: 'timezone', type: 'Custom Value', value: 'America/Chicago' },
|
|
4464
|
+
{ name: 'defaultFromPhone', type: 'Custom Value', value: '+13125551234' }
|
|
4465
|
+
]
|
|
4466
|
+
},
|
|
4467
|
+
}
|
|
4468
|
+
})
|
|
4469
|
+
|
|
4470
|
+
await sdk.api.endusers.updateOne(e4.id, { fields: { triggerTimezone: 'set-multiple' } })
|
|
4471
|
+
await wait(undefined, 1000)
|
|
4472
|
+
await async_test(
|
|
4473
|
+
"Set Fields: set multiple built-in fields including timezone",
|
|
4474
|
+
() => sdk.api.endusers.getOne(e4.id),
|
|
4475
|
+
{ onResult: e => e.timezone === 'America/Chicago' && e.defaultFromPhone === '+13125551234' }
|
|
4476
|
+
)
|
|
4477
|
+
|
|
4406
4478
|
return Promise.all([
|
|
4407
4479
|
sdk.api.automation_triggers.deleteOne(t1.id),
|
|
4408
4480
|
sdk.api.automation_triggers.deleteOne(t2.id),
|
|
@@ -4410,9 +4482,13 @@ const set_fields_tests = async () => {
|
|
|
4410
4482
|
sdk.api.automation_triggers.deleteOne(t4.id),
|
|
4411
4483
|
sdk.api.automation_triggers.deleteOne(t5.id),
|
|
4412
4484
|
sdk.api.automation_triggers.deleteOne(t6.id),
|
|
4485
|
+
sdk.api.automation_triggers.deleteOne(t7.id),
|
|
4486
|
+
sdk.api.automation_triggers.deleteOne(t8.id),
|
|
4487
|
+
sdk.api.automation_triggers.deleteOne(t9.id),
|
|
4413
4488
|
sdk.api.endusers.deleteOne(e1.id),
|
|
4414
4489
|
sdk.api.endusers.deleteOne(e2.id),
|
|
4415
4490
|
sdk.api.endusers.deleteOne(e3.id),
|
|
4491
|
+
sdk.api.endusers.deleteOne(e4.id),
|
|
4416
4492
|
sdk.api.calendar_events.deleteOne(a1.id),
|
|
4417
4493
|
])
|
|
4418
4494
|
}
|
|
@@ -13046,12 +13122,13 @@ const ip_address_form_tests = async () => {
|
|
|
13046
13122
|
await replace_enduser_template_values_tests()
|
|
13047
13123
|
await mfa_tests()
|
|
13048
13124
|
await setup_tests(sdk, sdkNonAdmin)
|
|
13125
|
+
await custom_aggregation_tests({ sdk, sdkNonAdmin })
|
|
13126
|
+
await automation_trigger_tests()
|
|
13049
13127
|
await formsort_tests()
|
|
13050
13128
|
await self_serve_appointment_booking_tests()
|
|
13051
13129
|
await time_tracks_tests({ sdk, sdkNonAdmin })
|
|
13052
13130
|
await calendar_event_limits_tests({ sdk, sdkNonAdmin })
|
|
13053
13131
|
await test_ticket_automation_assignment_and_optimization()
|
|
13054
|
-
await automation_trigger_tests()
|
|
13055
13132
|
await test_ticket_automation_assignment_and_optimization()
|
|
13056
13133
|
await afteraction_day_of_month_delay_tests({ sdk, sdkNonAdmin })
|
|
13057
13134
|
await monthly_availability_restrictions_tests({ sdk, sdkNonAdmin })
|
package/test_generated.pdf
CHANGED
|
Binary file
|