@tellescope/sdk 1.244.1 → 1.244.3

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 (44) hide show
  1. package/lib/cjs/sdk.d.ts +3 -0
  2. package/lib/cjs/sdk.d.ts.map +1 -1
  3. package/lib/cjs/sdk.js.map +1 -1
  4. package/lib/cjs/session.d.ts +8 -1
  5. package/lib/cjs/session.d.ts.map +1 -1
  6. package/lib/cjs/session.js +2 -4
  7. package/lib/cjs/session.js.map +1 -1
  8. package/lib/cjs/tests/api_tests/elation_user_id.test.d.ts +6 -0
  9. package/lib/cjs/tests/api_tests/elation_user_id.test.d.ts.map +1 -0
  10. package/lib/cjs/tests/api_tests/elation_user_id.test.js +106 -0
  11. package/lib/cjs/tests/api_tests/elation_user_id.test.js.map +1 -0
  12. package/lib/cjs/tests/api_tests/get_some_projection.test.d.ts +6 -0
  13. package/lib/cjs/tests/api_tests/get_some_projection.test.d.ts.map +1 -0
  14. package/lib/cjs/tests/api_tests/get_some_projection.test.js +373 -0
  15. package/lib/cjs/tests/api_tests/get_some_projection.test.js.map +1 -0
  16. package/lib/cjs/tests/tests.d.ts.map +1 -1
  17. package/lib/cjs/tests/tests.js +268 -184
  18. package/lib/cjs/tests/tests.js.map +1 -1
  19. package/lib/esm/sdk.d.ts +5 -2
  20. package/lib/esm/sdk.d.ts.map +1 -1
  21. package/lib/esm/sdk.js.map +1 -1
  22. package/lib/esm/session.d.ts +8 -1
  23. package/lib/esm/session.d.ts.map +1 -1
  24. package/lib/esm/session.js +2 -4
  25. package/lib/esm/session.js.map +1 -1
  26. package/lib/esm/tests/api_tests/elation_user_id.test.d.ts +6 -0
  27. package/lib/esm/tests/api_tests/elation_user_id.test.d.ts.map +1 -0
  28. package/lib/esm/tests/api_tests/elation_user_id.test.js +102 -0
  29. package/lib/esm/tests/api_tests/elation_user_id.test.js.map +1 -0
  30. package/lib/esm/tests/api_tests/get_some_projection.test.d.ts +6 -0
  31. package/lib/esm/tests/api_tests/get_some_projection.test.d.ts.map +1 -0
  32. package/lib/esm/tests/api_tests/get_some_projection.test.js +369 -0
  33. package/lib/esm/tests/api_tests/get_some_projection.test.js.map +1 -0
  34. package/lib/esm/tests/tests.d.ts.map +1 -1
  35. package/lib/esm/tests/tests.js +268 -184
  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 +5 -4
  40. package/src/session.ts +13 -3
  41. package/src/tests/api_tests/elation_user_id.test.ts +59 -0
  42. package/src/tests/api_tests/get_some_projection.test.ts +245 -0
  43. package/src/tests/tests.ts +113 -12
  44. package/test_generated.pdf +0 -0
@@ -0,0 +1,59 @@
1
+ require('source-map-support').install();
2
+
3
+ import { Session } from "../../sdk"
4
+ import {
5
+ async_test,
6
+ handleAnyError,
7
+ log_header,
8
+ } from "@tellescope/testing"
9
+ import { setup_tests } from "../setup"
10
+
11
+ const host = process.env.API_URL || 'http://localhost:8080' as const
12
+
13
+ export const elation_user_id_tests = async ({ sdk, sdkNonAdmin } : { sdk: Session, sdkNonAdmin: Session }) => {
14
+ log_header("Elation User ID Tests")
15
+
16
+ const randomElationUserId = Math.floor(Math.random() * 1000000)
17
+
18
+ // Admin can set elationUserId
19
+ await async_test(
20
+ `admin can update elationUserId`,
21
+ () => sdk.api.users.updateOne(sdk.userInfo.id, { elationUserId: randomElationUserId }),
22
+ { shouldError: false, onResult: (u) => u.elationUserId === randomElationUserId }
23
+ )
24
+
25
+ // Verify the value persists on read
26
+ await async_test(
27
+ `elationUserId persists after update`,
28
+ () => sdk.api.users.getOne(sdk.userInfo.id),
29
+ { shouldError: false, onResult: (u) => u.elationUserId === randomElationUserId }
30
+ )
31
+
32
+ // Non-admin cannot update elationUserId
33
+ await async_test(
34
+ `non-admin cannot update elationUserId`,
35
+ () => sdkNonAdmin.api.users.updateOne(sdkNonAdmin.userInfo.id, { elationUserId: 999999 }),
36
+ handleAnyError
37
+ )
38
+ }
39
+
40
+ // Allow running this test file independently
41
+ if (require.main === module) {
42
+ const sdk = new Session({ host })
43
+ const sdkNonAdmin = new Session({ host })
44
+
45
+ const runTests = async () => {
46
+ await setup_tests(sdk, sdkNonAdmin)
47
+ await elation_user_id_tests({ sdk, sdkNonAdmin })
48
+ }
49
+
50
+ runTests()
51
+ .then(() => {
52
+ console.log("✅ Elation User ID test suite completed successfully")
53
+ process.exit(0)
54
+ })
55
+ .catch((error) => {
56
+ console.error("❌ Elation User ID test suite failed:", error)
57
+ process.exit(1)
58
+ })
59
+ }
@@ -0,0 +1,245 @@
1
+ require('source-map-support').install();
2
+
3
+ import { Session } from "../../sdk"
4
+ import {
5
+ assert,
6
+ async_test,
7
+ log_header,
8
+ } from "@tellescope/testing"
9
+ import { setup_tests } from "../setup"
10
+
11
+ const host = process.env.API_URL || 'http://localhost:8080' as const
12
+
13
+ // Main test function that can be called independently
14
+ export const get_some_projection_tests = async ({ sdk, sdkNonAdmin } : { sdk: Session, sdkNonAdmin: Session }) => {
15
+ log_header("getSome Projection Support")
16
+
17
+ // Create test enduser
18
+ const testEnduser = await sdk.api.endusers.createOne({ fname: 'ProjectionTest', lname: 'User', email: 'projection-test@tellescope.com' })
19
+
20
+ let observationIds: string[] = []
21
+
22
+ try {
23
+ // Create test observations
24
+ const obs1 = await sdk.api.enduser_observations.createOne({
25
+ enduserId: testEnduser.id,
26
+ status: 'final',
27
+ category: 'vital-signs',
28
+ measurement: { value: 120, unit: 'mmHg' },
29
+ })
30
+ const obs2 = await sdk.api.enduser_observations.createOne({
31
+ enduserId: testEnduser.id,
32
+ status: 'final',
33
+ category: 'vital-signs',
34
+ measurement: { value: 80, unit: 'mmHg' },
35
+ })
36
+ const obs3 = await sdk.api.enduser_observations.createOne({
37
+ enduserId: testEnduser.id,
38
+ status: 'final',
39
+ category: 'vital-signs',
40
+ measurement: { value: 98, unit: 'bpm' },
41
+ })
42
+ observationIds = [obs1.id, obs2.id, obs3.id]
43
+
44
+ // Test 1: Inclusion projection returns only specified fields
45
+ await async_test(
46
+ 'projection-inclusion',
47
+ async () => {
48
+ const results = await sdk.api.enduser_observations.getSome({
49
+ filter: { enduserId: testEnduser.id },
50
+ projection: { timestamp: 1, measurement: 1, enduserId: 1 },
51
+ })
52
+ assert(results.length === 3, 'Expected 3 observations with projection', 'Got correct count with projection')
53
+
54
+ for (const r of results) {
55
+ assert(r.id !== undefined, 'id should always be present')
56
+ assert(r.createdAt !== undefined, 'createdAt should always be present')
57
+ assert(r.measurement !== undefined, 'measurement should be present in projection')
58
+ assert(r.enduserId !== undefined, 'enduserId should be present in projection')
59
+ assert(r.timestamp !== undefined, 'timestamp should be present in projection')
60
+ // Fields NOT in projection should be excluded
61
+ assert((r as any).status === undefined, 'status should NOT be present when not in projection')
62
+ assert((r as any).category === undefined, 'category should NOT be present when not in projection')
63
+ }
64
+ return results
65
+ },
66
+ { onResult: () => true },
67
+ )
68
+
69
+ // Test 2: No projection returns all fields (backward compatibility)
70
+ await async_test(
71
+ 'no-projection-returns-all-fields',
72
+ async () => {
73
+ const results = await sdk.api.enduser_observations.getSome({
74
+ filter: { enduserId: testEnduser.id },
75
+ })
76
+ assert(results.length === 3, 'Expected 3 observations without projection')
77
+
78
+ for (const r of results) {
79
+ assert(r.id !== undefined, 'id should be present')
80
+ assert(r.status !== undefined, 'status should be present without projection')
81
+ assert(r.category !== undefined, 'category should be present without projection')
82
+ assert(r.measurement !== undefined, 'measurement should be present without projection')
83
+ assert(r.enduserId !== undefined, 'enduserId should be present without projection')
84
+ }
85
+ return results
86
+ },
87
+ { onResult: () => true },
88
+ )
89
+
90
+ // Test 3: Projection with other filters (filter, limit, sortBy)
91
+ await async_test(
92
+ 'projection-with-filters',
93
+ async () => {
94
+ const results = await sdk.api.enduser_observations.getSome({
95
+ filter: { enduserId: testEnduser.id },
96
+ projection: { measurement: 1 },
97
+ limit: 2,
98
+ sortBy: 'timestamp',
99
+ })
100
+ assert(results.length === 2, 'Expected 2 observations with limit=2', `Got ${results.length}`)
101
+
102
+ for (const r of results) {
103
+ assert(r.measurement !== undefined, 'measurement should be present in projection')
104
+ assert((r as any).status === undefined, 'status should NOT be present when not in projection')
105
+ }
106
+ return results
107
+ },
108
+ { onResult: () => true },
109
+ )
110
+
111
+ // Test 4: Projection works across different models (endusers)
112
+ await async_test(
113
+ 'projection-on-endusers',
114
+ async () => {
115
+ const results = await sdk.api.endusers.getSome({
116
+ filter: { email: 'projection-test@tellescope.com' },
117
+ projection: { fname: 1, email: 1 },
118
+ })
119
+ assert(results.length >= 1, 'Expected at least 1 enduser')
120
+
121
+ const enduser = results[0]
122
+ assert(enduser.id !== undefined, 'id should always be present')
123
+ assert(enduser.fname !== undefined, 'fname should be present in projection')
124
+ assert(enduser.email !== undefined, 'email should be present in projection')
125
+ assert((enduser as any).lname === undefined, 'lname should NOT be present when not in projection')
126
+ return results
127
+ },
128
+ { onResult: () => true },
129
+ )
130
+
131
+ // Test 5: Projection with pagination (lastId)
132
+ await async_test(
133
+ 'projection-with-pagination',
134
+ async () => {
135
+ // First page
136
+ const page1 = await sdk.api.enduser_observations.getSome({
137
+ filter: { enduserId: testEnduser.id },
138
+ projection: { measurement: 1, enduserId: 1 },
139
+ limit: 2,
140
+ sort: 'oldFirst',
141
+ })
142
+ assert(page1.length === 2, 'Expected 2 observations on first page')
143
+
144
+ // Second page using lastId from first page
145
+ const lastId = page1[page1.length - 1].id
146
+ const page2 = await sdk.api.enduser_observations.getSome({
147
+ filter: { enduserId: testEnduser.id },
148
+ projection: { measurement: 1, enduserId: 1 },
149
+ limit: 2,
150
+ sort: 'oldFirst',
151
+ lastId,
152
+ })
153
+ assert(page2.length === 1, 'Expected 1 observation on second page')
154
+
155
+ // Verify consistent fields across pages
156
+ for (const r of [...page1, ...page2]) {
157
+ assert(r.measurement !== undefined, 'measurement should be present across pages')
158
+ assert(r.enduserId !== undefined, 'enduserId should be present across pages')
159
+ assert((r as any).status === undefined, 'status should NOT be present across pages')
160
+ }
161
+ return [...page1, ...page2]
162
+ },
163
+ { onResult: () => true },
164
+ )
165
+
166
+ // Test 6: Empty projection returns all fields (no crash)
167
+ await async_test(
168
+ 'empty-projection',
169
+ async () => {
170
+ const results = await sdk.api.enduser_observations.getSome({
171
+ filter: { enduserId: testEnduser.id },
172
+ projection: {},
173
+ })
174
+ assert(results.length === 3, 'Expected 3 observations with empty projection')
175
+
176
+ for (const r of results) {
177
+ assert(r.status !== undefined, 'status should be present with empty projection')
178
+ assert(r.category !== undefined, 'category should be present with empty projection')
179
+ assert(r.measurement !== undefined, 'measurement should be present with empty projection')
180
+ }
181
+ return results
182
+ },
183
+ { onResult: () => true },
184
+ )
185
+
186
+ // Test 7: Non-admin access with projection (RBA still applies)
187
+ await async_test(
188
+ 'non-admin-projection',
189
+ async () => {
190
+ const results = await sdkNonAdmin.api.enduser_observations.getSome({
191
+ filter: { enduserId: testEnduser.id },
192
+ projection: { measurement: 1, enduserId: 1 },
193
+ })
194
+ // Non-admin should still get results (RBA should apply)
195
+ assert(Array.isArray(results), 'Non-admin should receive an array response')
196
+
197
+ for (const r of results) {
198
+ assert(r.measurement !== undefined, 'measurement should be present for non-admin projection')
199
+ assert(r.enduserId !== undefined, 'enduserId should be present for non-admin projection')
200
+ }
201
+ return results
202
+ },
203
+ { onResult: () => true },
204
+ )
205
+
206
+ } finally {
207
+ // Cleanup: Delete test resources
208
+ try {
209
+ for (const obsId of observationIds) {
210
+ await sdk.api.enduser_observations.deleteOne(obsId)
211
+ }
212
+ await sdk.api.endusers.deleteOne(testEnduser.id)
213
+ } catch (error) {
214
+ console.error('Cleanup error:', error)
215
+ // Try to at least delete the enduser (cascade deletes observations)
216
+ try {
217
+ await sdk.api.endusers.deleteOne(testEnduser.id)
218
+ } catch (deleteError) {
219
+ console.error('Failed to delete test enduser:', deleteError)
220
+ }
221
+ }
222
+ }
223
+ }
224
+
225
+ // Allow running this test file independently
226
+ if (require.main === module) {
227
+ console.log(`🌐 Using API URL: ${host}`)
228
+ const sdk = new Session({ host })
229
+ const sdkNonAdmin = new Session({ host })
230
+
231
+ const runTests = async () => {
232
+ await setup_tests(sdk, sdkNonAdmin)
233
+ await get_some_projection_tests({ sdk, sdkNonAdmin })
234
+ }
235
+
236
+ runTests()
237
+ .then(() => {
238
+ console.log("✅ getSome projection test suite completed successfully")
239
+ process.exit(0)
240
+ })
241
+ .catch((error) => {
242
+ console.error("❌ getSome projection test suite failed:", error)
243
+ process.exit(1)
244
+ })
245
+ }
@@ -36,6 +36,7 @@ import {
36
36
 
37
37
  import { Session, APIQuery, EnduserSession } from "../sdk"
38
38
  import { enduser_observations_acknowledge_tests } from "./api_tests/enduser_observations_acknowledge.test"
39
+ import { get_some_projection_tests } from "./api_tests/get_some_projection.test"
39
40
  import { create_user_notifications_trigger_tests } from "./api_tests/create_user_notifications_trigger.test"
40
41
  import { inbox_thread_assignment_updates_tests } from "./api_tests/inbox_thread_assignment_updates.test"
41
42
  import { inbox_thread_draft_scheduled_tests } from "./api_tests/inbox_thread_draft_scheduled.test"
@@ -85,6 +86,7 @@ import { database_cascade_delete_tests } from "./api_tests/database_cascade_dele
85
86
  import { ai_conversations_tests } from "./api_tests/ai_conversations.test";
86
87
  import { load_team_chat_tests } from "./api_tests/load_team_chat.test";
87
88
  import { form_started_trigger_tests } from "./api_tests/form_started_trigger.test";
89
+ import { elation_user_id_tests } from "./api_tests/elation_user_id.test";
88
90
 
89
91
  const UniquenessViolationMessage = 'Uniqueness Violation'
90
92
 
@@ -3415,6 +3417,12 @@ const order_status_equals_tests = async () => {
3415
3417
  status: 'Active',
3416
3418
  title: "Title Partial Condition"
3417
3419
  })
3420
+ const t8 = await sdk.api.automation_triggers.createOne({
3421
+ event: { type: 'Order Status Equals', info: { source: 'Source', status: "Update", titlePartialsAnd: ['PARTIAL-A', 'PARTIAL-B'] } },
3422
+ action: { type: 'Add Tags', info: { tags: ['Title Partial And Update'] }},
3423
+ status: 'Active',
3424
+ title: "Title Partial And Condition"
3425
+ })
3418
3426
 
3419
3427
  const e = await sdk.api.endusers.createOne({})
3420
3428
 
@@ -3565,6 +3573,37 @@ const order_status_equals_tests = async () => {
3565
3573
  ) }
3566
3574
  )
3567
3575
 
3576
+ await sdk.api.enduser_orders.updateOne(u.id, { status: 'Toggle', externalId: "also avoid rate limit 5" })
3577
+ await sdk.api.enduser_orders.updateOne(u.id, { status: "Update", title: "PARTIAL-A only" })
3578
+ await wait(undefined, 500) // allow triggers to happen
3579
+ await async_test(
3580
+ "Title partial AND no match (only one partial present)",
3581
+ () => sdk.api.endusers.getOne(e.id),
3582
+ { onResult: e => !!(
3583
+ e.tags?.length === 7
3584
+ && !e.tags?.includes('Title Partial And Update')
3585
+ ) }
3586
+ )
3587
+
3588
+ await sdk.api.enduser_orders.updateOne(u.id, { status: 'Toggle', externalId: "also avoid rate limit 6" })
3589
+ await sdk.api.enduser_orders.updateOne(u.id, { status: "Update", title: "PARTIAL-A and PARTIAL-B together" })
3590
+ await wait(undefined, 500) // allow triggers to happen
3591
+ await async_test(
3592
+ "Title partial AND update tag added (both partials present)",
3593
+ () => sdk.api.endusers.getOne(e.id),
3594
+ { onResult: e => !!(
3595
+ e.tags?.length === 8
3596
+ && e.tags?.includes('Source')
3597
+ && e.tags?.includes('Fill')
3598
+ && e.tags?.includes('Status Update')
3599
+ && e.tags?.includes('Fill Update')
3600
+ && e.tags?.includes('SKU Update')
3601
+ && e.tags?.includes('SKU Partial Update')
3602
+ && e.tags?.includes('Title Partial Update')
3603
+ && e.tags?.includes('Title Partial And Update')
3604
+ ) }
3605
+ )
3606
+
3568
3607
  await Promise.all([
3569
3608
  sdk.api.automation_triggers.deleteOne(t1.id),
3570
3609
  sdk.api.automation_triggers.deleteOne(t2.id),
@@ -3573,6 +3612,7 @@ const order_status_equals_tests = async () => {
3573
3612
  sdk.api.automation_triggers.deleteOne(t5.id),
3574
3613
  sdk.api.automation_triggers.deleteOne(t6.id),
3575
3614
  sdk.api.automation_triggers.deleteOne(t7.id),
3615
+ sdk.api.automation_triggers.deleteOne(t8.id),
3576
3616
  sdk.api.endusers.deleteOne(e.id),
3577
3617
  ])
3578
3618
  }
@@ -4970,6 +5010,7 @@ const trigger_events_api_tests = async () => {
4970
5010
  const automation_trigger_tests = async () => {
4971
5011
  log_header("Automation Trigger Tests")
4972
5012
 
5013
+ await order_status_equals_tests()
4973
5014
  await appointment_cancelled_tests()
4974
5015
  await set_fields_tests()
4975
5016
  await purchase_made_trigger_tests({ sdk, sdkNonAdmin })
@@ -4977,7 +5018,6 @@ const automation_trigger_tests = async () => {
4977
5018
  await form_response_set_fields_trigger_tests()
4978
5019
  await form_response_set_fields_journey_tests()
4979
5020
  await appointment_completed_trigger_tests({ sdk, sdkNonAdmin })
4980
- await order_status_equals_tests()
4981
5021
  await trigger_events_api_tests()
4982
5022
  await fields_changed_tests()
4983
5023
  await field_equals_trigger_tests()
@@ -5572,28 +5612,87 @@ const redaction_tests = async () => {
5572
5612
  log_header("Redaction")
5573
5613
 
5574
5614
  const enduser = await sdk.api.endusers.createOne({ email })
5575
- const enduserOther = await sdk.api.endusers.createOne({ email: 'otherenduser@tellescope.com' })
5615
+ const enduserOther = await sdk.api.endusers.createOne({
5616
+ email: 'otherenduser@tellescope.com',
5617
+ unredactedFields: [{ field: 'testField', value: 'testValue' }] as any,
5618
+ })
5576
5619
  await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
5577
- await enduserSDK.authenticate(email, password).catch(console.error)
5620
+ await enduserSDK.authenticate(email, password).catch(console.error)
5578
5621
 
5579
5622
  const endusers = await enduserSDK.api.endusers.getSome()
5580
5623
  const forUser = await sdk.api.endusers.getSome()
5581
5624
  assert(endusers.length > 0, "enduser can't fetch others", "enduser get others successful")
5582
5625
 
5626
+ // endusers reading OTHER endusers should only see id, displayName, unredactedFields, and unredactedTags
5627
+ const ALLOWED_OTHER_ENDUSER_FIELDS = ['id', 'displayName', 'unredactedFields', 'unredactedTags']
5628
+ const otherEndusers = endusers.filter(e => e.id !== enduser.id)
5629
+ assert(otherEndusers.length > 0, 'no other endusers found', 'found other endusers to check redaction')
5630
+ for (const other of otherEndusers) {
5631
+ const keys = Object.keys(other)
5632
+ assert(
5633
+ keys.every(k => ALLOWED_OTHER_ENDUSER_FIELDS.includes(k)),
5634
+ `other enduser has extra fields: ${keys.filter(k => !ALLOWED_OTHER_ENDUSER_FIELDS.includes(k)).join(', ')}`,
5635
+ 'other enduser correctly redacted to only id, displayName, unredactedFields, unredactedTags',
5636
+ )
5637
+ assert(
5638
+ keys.includes('id'),
5639
+ `other enduser missing id`,
5640
+ 'other enduser has id',
5641
+ )
5642
+ }
5643
+
5644
+ // verify unredactedFields are preserved for other endusers when defined
5645
+ const otherWithUnredacted = otherEndusers.find(e => e.id === enduserOther.id)
5646
+ if (otherWithUnredacted) {
5647
+ assert(
5648
+ !!(otherWithUnredacted as any).unredactedFields?.length,
5649
+ 'unredactedFields missing on other enduser',
5650
+ 'unredactedFields preserved on other enduser when defined',
5651
+ )
5652
+ }
5653
+
5654
+ // verify unredactedFields/unredactedTags are omitted when not set on the enduser
5655
+ const otherWithoutUnredacted = otherEndusers.find(e => e.id !== enduserOther.id)
5656
+ if (otherWithoutUnredacted) {
5657
+ assert(
5658
+ !('unredactedFields' in otherWithoutUnredacted),
5659
+ 'unredactedFields present when not set',
5660
+ 'unredactedFields omitted when not defined on enduser',
5661
+ )
5662
+ assert(
5663
+ !('unredactedTags' in otherWithoutUnredacted),
5664
+ 'unredactedTags present when not set',
5665
+ 'unredactedTags omitted when not defined on enduser',
5666
+ )
5667
+ }
5668
+
5669
+ // enduser reading their own profile should still have non-redacted fields (not just id + displayName)
5670
+ const selfEnduser = endusers.find(e => e.id === enduser.id)
5671
+ if (selfEnduser) {
5672
+ assert(
5673
+ Object.keys(selfEnduser).length > ALLOWED_OTHER_ENDUSER_FIELDS.length,
5674
+ 'self enduser overly redacted',
5675
+ 'self enduser retains non-redacted fields',
5676
+ )
5677
+ }
5678
+
5679
+ // verify schema-level redactions still apply to self
5583
5680
  const redactedFields = (
5584
5681
  Object.keys(schema.endusers.fields)
5585
- .filter(f =>
5682
+ .filter(f =>
5586
5683
  schema.endusers.fields[f as keyof typeof schema.endusers.fields]?.redactions?.includes('enduser')
5587
5684
  || schema.endusers.fields[f as keyof typeof schema.endusers.fields]?.redactions?.includes('all')
5588
5685
  )
5589
5686
  )
5590
5687
  assert(redactedFields.length > 0, 'no redacted fields', 'redacted fields exists')
5591
5688
 
5592
- assert(
5593
- endusers.find(e => redactedFields.filter(f => !!e[f as keyof typeof e]).length > 0) === undefined,
5594
- 'got redacted data',
5595
- 'data correctly redacted',
5596
- )
5689
+ if (selfEnduser) {
5690
+ assert(
5691
+ redactedFields.filter(f => !!(selfEnduser as any)[f]).length === 0,
5692
+ 'self enduser got redacted data',
5693
+ 'self enduser data correctly redacted per schema',
5694
+ )
5695
+ }
5597
5696
 
5598
5697
  assert(
5599
5698
  !forUser.find(u => u.hashedPassword),
@@ -10124,8 +10223,8 @@ export const ticket_reminder_tests = async () => {
10124
10223
  const title = 't'
10125
10224
 
10126
10225
  const LEEWAY = 200
10127
- const withLeeway = (source: number | undefined, target: number) => (
10128
- source !== undefined && ((source - LEEWAY) < target || (source + LEEWAY) > target)
10226
+ const withLeeway = (source: number | null | undefined, target: number) => (
10227
+ source != null && ((source - LEEWAY) < target || (source + LEEWAY) > target)
10129
10228
  )
10130
10229
 
10131
10230
  await async_test(
@@ -13947,6 +14046,9 @@ const ip_address_form_tests = async () => {
13947
14046
  await replace_enduser_template_values_tests()
13948
14047
  await mfa_tests()
13949
14048
  await setup_tests(sdk, sdkNonAdmin)
14049
+ await automation_trigger_tests()
14050
+ await get_some_projection_tests({ sdk, sdkNonAdmin })
14051
+ await elation_user_id_tests({ sdk, sdkNonAdmin })
13950
14052
  await custom_dashboards_tests({ sdk, sdkNonAdmin })
13951
14053
  await concurrent_build_threads_tests({ sdk, sdkNonAdmin })
13952
14054
  await custom_aggregation_tests({ sdk, sdkNonAdmin })
@@ -13961,7 +14063,6 @@ const ip_address_form_tests = async () => {
13961
14063
  await inbox_threads_new_fields_tests()
13962
14064
  await auto_merge_form_submission_tests({ sdk, sdkNonAdmin })
13963
14065
  await threadKeyTests()
13964
- await automation_trigger_tests()
13965
14066
  await managed_content_enduser_access_tests({ sdk, sdkNonAdmin })
13966
14067
  await afteraction_day_of_month_delay_tests({ sdk, sdkNonAdmin })
13967
14068
  await bulk_assignment_tests({ sdk, sdkNonAdmin })
Binary file