@tellescope/sdk 1.255.8 → 1.255.10

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 (71) hide show
  1. package/lib/cjs/enduser.d.ts +1 -0
  2. package/lib/cjs/enduser.d.ts.map +1 -1
  3. package/lib/cjs/sdk.d.ts +3 -2
  4. package/lib/cjs/sdk.d.ts.map +1 -1
  5. package/lib/cjs/tests/api_tests/calendar_event_limits.test.js +1 -1
  6. package/lib/cjs/tests/api_tests/calendar_event_limits.test.js.map +1 -1
  7. package/lib/cjs/tests/api_tests/dont_sync_to_elation_form_submission.test.d.ts +6 -0
  8. package/lib/cjs/tests/api_tests/dont_sync_to_elation_form_submission.test.d.ts.map +1 -0
  9. package/lib/cjs/tests/api_tests/dont_sync_to_elation_form_submission.test.js +166 -0
  10. package/lib/cjs/tests/api_tests/dont_sync_to_elation_form_submission.test.js.map +1 -0
  11. package/lib/cjs/tests/api_tests/enduser_cross_access_isolation.test.js +8 -8
  12. package/lib/cjs/tests/api_tests/enduser_cross_access_isolation.test.js.map +1 -1
  13. package/lib/cjs/tests/api_tests/nutrition_tracking.test.d.ts +6 -0
  14. package/lib/cjs/tests/api_tests/nutrition_tracking.test.d.ts.map +1 -0
  15. package/lib/cjs/tests/api_tests/nutrition_tracking.test.js +483 -0
  16. package/lib/cjs/tests/api_tests/nutrition_tracking.test.js.map +1 -0
  17. package/lib/cjs/tests/api_tests/webhook_error_handling.test.d.ts +6 -0
  18. package/lib/cjs/tests/api_tests/webhook_error_handling.test.d.ts.map +1 -0
  19. package/lib/cjs/tests/api_tests/webhook_error_handling.test.js +324 -0
  20. package/lib/cjs/tests/api_tests/webhook_error_handling.test.js.map +1 -0
  21. package/lib/cjs/tests/setup.d.ts +11 -1
  22. package/lib/cjs/tests/setup.d.ts.map +1 -1
  23. package/lib/cjs/tests/setup.js +19 -1
  24. package/lib/cjs/tests/setup.js.map +1 -1
  25. package/lib/cjs/tests/tests.d.ts.map +1 -1
  26. package/lib/cjs/tests/tests.js +207 -192
  27. package/lib/cjs/tests/tests.js.map +1 -1
  28. package/lib/esm/sdk.d.ts +2 -2
  29. package/lib/esm/tests/api_tests/calendar_event_limits.test.js +2 -2
  30. package/lib/esm/tests/api_tests/calendar_event_limits.test.js.map +1 -1
  31. package/lib/esm/tests/api_tests/custom_dashboards.test.d.ts.map +1 -1
  32. package/lib/esm/tests/api_tests/custom_dashboards.test.js +259 -33
  33. package/lib/esm/tests/api_tests/custom_dashboards.test.js.map +1 -1
  34. package/lib/esm/tests/api_tests/dont_sync_to_elation_form_submission.test.d.ts +6 -0
  35. package/lib/esm/tests/api_tests/dont_sync_to_elation_form_submission.test.d.ts.map +1 -0
  36. package/lib/esm/tests/api_tests/dont_sync_to_elation_form_submission.test.js +162 -0
  37. package/lib/esm/tests/api_tests/dont_sync_to_elation_form_submission.test.js.map +1 -0
  38. package/lib/esm/tests/api_tests/enduser_cross_access_isolation.test.js +9 -9
  39. package/lib/esm/tests/api_tests/enduser_cross_access_isolation.test.js.map +1 -1
  40. package/lib/esm/tests/api_tests/medication_added_trigger.test.d.ts.map +1 -1
  41. package/lib/esm/tests/api_tests/medication_added_trigger.test.js +206 -136
  42. package/lib/esm/tests/api_tests/medication_added_trigger.test.js.map +1 -1
  43. package/lib/esm/tests/api_tests/nutrition_tracking.test.d.ts +6 -0
  44. package/lib/esm/tests/api_tests/nutrition_tracking.test.d.ts.map +1 -0
  45. package/lib/esm/tests/api_tests/nutrition_tracking.test.js +479 -0
  46. package/lib/esm/tests/api_tests/nutrition_tracking.test.js.map +1 -0
  47. package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts +10 -0
  48. package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts.map +1 -1
  49. package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js +184 -41
  50. package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js.map +1 -1
  51. package/lib/esm/tests/api_tests/webhook_error_handling.test.d.ts +6 -0
  52. package/lib/esm/tests/api_tests/webhook_error_handling.test.d.ts.map +1 -0
  53. package/lib/esm/tests/api_tests/webhook_error_handling.test.js +317 -0
  54. package/lib/esm/tests/api_tests/webhook_error_handling.test.js.map +1 -0
  55. package/lib/esm/tests/setup.d.ts +11 -1
  56. package/lib/esm/tests/setup.d.ts.map +1 -1
  57. package/lib/esm/tests/setup.js +17 -0
  58. package/lib/esm/tests/setup.js.map +1 -1
  59. package/lib/esm/tests/tests.d.ts.map +1 -1
  60. package/lib/esm/tests/tests.js +233 -206
  61. package/lib/esm/tests/tests.js.map +1 -1
  62. package/lib/tsconfig.tsbuildinfo +1 -1
  63. package/package.json +8 -8
  64. package/src/tests/api_tests/calendar_event_limits.test.ts +2 -2
  65. package/src/tests/api_tests/dont_sync_to_elation_form_submission.test.ts +91 -0
  66. package/src/tests/api_tests/enduser_cross_access_isolation.test.ts +6 -6
  67. package/src/tests/api_tests/nutrition_tracking.test.ts +425 -0
  68. package/src/tests/api_tests/webhook_error_handling.test.ts +190 -0
  69. package/src/tests/setup.ts +13 -0
  70. package/src/tests/tests.ts +29 -18
  71. package/test_generated.pdf +0 -0
@@ -0,0 +1,190 @@
1
+ require('source-map-support').install();
2
+
3
+ import express from "express"
4
+ import bodyParser from "body-parser"
5
+ import crypto from "crypto"
6
+ import http from "http"
7
+
8
+ import { Session } from "../../sdk"
9
+ import {
10
+ assert,
11
+ async_test,
12
+ log_header,
13
+ wait,
14
+ } from "@tellescope/testing"
15
+ import { setup_tests } from "../setup"
16
+
17
+ const host = process.env.API_URL || 'http://localhost:8080' as const
18
+
19
+ const TEST_SECRET = "this is a test secret for verifying integrity of web hooks"
20
+ const sha256 = (s: string) => crypto.createHash('sha256').update(s).digest('hex')
21
+
22
+ // DNS resolution for the reserved .invalid TLD always fails => axios ENOTFOUND (no err.response)
23
+ const ENOTFOUND_URL = `http://webhook-error-handling-test.invalid/hook`
24
+
25
+ const POLL_TIMEOUT_MS = 10_000
26
+ const POLL_INTERVAL_MS = 500
27
+
28
+ const find_log_for_url = async (sdk: Session, url: string) => {
29
+ const start = Date.now()
30
+ while (Date.now() - start < POLL_TIMEOUT_MS) {
31
+ const logs = await sdk.api.webhook_logs.getSome({ limit: 50, sort: 'newFirst' as any }) as Array<any>
32
+ const match = logs.find(l => l.url === url)
33
+ if (match) return match
34
+ await wait(undefined, POLL_INTERVAL_MS)
35
+ }
36
+ return null
37
+ }
38
+
39
+ const get_failure_count = async (sdk: Session) => {
40
+ const configs = await sdk.api.webhooks.getSome() as Array<any>
41
+ return (configs[0]?.deliveryFailureCount ?? 0) as number
42
+ }
43
+
44
+ // the $inc on the webhook config is fire-and-forget — poll until it lands
45
+ const wait_for_failure_count = async (sdk: Session, expected: number) => {
46
+ const start = Date.now()
47
+ let count = -1
48
+ while (Date.now() - start < POLL_TIMEOUT_MS) {
49
+ count = await get_failure_count(sdk)
50
+ if (count === expected) return count
51
+ await wait(undefined, POLL_INTERVAL_MS)
52
+ }
53
+ return count
54
+ }
55
+
56
+ // Main test function that can be called independently
57
+ export const webhook_error_handling_tests = async ({ sdk, sdkNonAdmin } : { sdk: Session, sdkNonAdmin: Session }) => {
58
+ log_header("Webhook Error Handling Tests")
59
+
60
+ // local receiver: error paths for failure scenarios, a healthy path that verifies integrity
61
+ const app = express()
62
+ app.use(bodyParser.json({ limit: '25mb' }))
63
+
64
+ let successIntegrityVerified = false
65
+ app.post('/fail-400', (_, res) => { res.status(400).json({ error: 'bad request' }) })
66
+ app.post('/fail-500', (_, res) => { res.status(500).json({ error: 'server error' }) })
67
+ app.post('/success', (req, res) => {
68
+ const { records, timestamp, integrity } = req.body
69
+ successIntegrityVerified = (
70
+ sha256((records ?? []).map((r: { id: string }) => r.id).join('') + timestamp + TEST_SECRET) === integrity
71
+ )
72
+ res.status(200).json({})
73
+ })
74
+
75
+ const server: http.Server = await new Promise(resolve => {
76
+ const s = app.listen(0, '127.0.0.1', () => resolve(s))
77
+ })
78
+ const receiverBase = `http://127.0.0.1:${(server.address() as any).port}`
79
+
80
+ const enduserIds: string[] = []
81
+ const trigger_delivery = async (label: string) => {
82
+ const enduser = await sdk.api.endusers.createOne({ email: `webhook-error-${label}-${Date.now()}@tellescope.com` })
83
+ enduserIds.push(enduser.id)
84
+ }
85
+
86
+ try {
87
+ await async_test(
88
+ 'configure webhook',
89
+ () => sdk.api.webhooks.configure({ url: ENOTFOUND_URL, secret: TEST_SECRET }),
90
+ { shouldError: false, onResult: () => true },
91
+ )
92
+ await sdk.api.webhooks.update({ subscriptionUpdates: { endusers: { create: true, update: false, delete: false } } })
93
+
94
+ const initialCount = await get_failure_count(sdk)
95
+
96
+ // Scenario 1: ENOTFOUND — no HTTP response at all
97
+ await trigger_delivery('enotfound')
98
+ const enotfoundLog = await find_log_for_url(sdk, ENOTFOUND_URL)
99
+ assert(!!enotfoundLog, 'no webhook_logs entry for ENOTFOUND delivery', 'ENOTFOUND failure logged to webhook_logs')
100
+ assert(
101
+ typeof enotfoundLog?.response === 'string' && enotfoundLog.response.length > 0,
102
+ `expected string error message response, got: ${JSON.stringify(enotfoundLog?.response)}`,
103
+ 'ENOTFOUND log has error message as response'
104
+ )
105
+ assert(enotfoundLog?.responseCode === undefined, 'unexpected responseCode for ENOTFOUND', 'ENOTFOUND log has no responseCode')
106
+ assert(
107
+ await wait_for_failure_count(sdk, initialCount + 1) === initialCount + 1,
108
+ 'deliveryFailureCount not incremented after ENOTFOUND',
109
+ 'deliveryFailureCount incremented after ENOTFOUND'
110
+ )
111
+
112
+ // Scenario 2a: HTTP 400 from the receiver
113
+ await sdk.api.webhooks.update({ url: `${receiverBase}/fail-400` })
114
+ await trigger_delivery('http400')
115
+ const log400 = await find_log_for_url(sdk, `${receiverBase}/fail-400`)
116
+ assert(log400?.responseCode === 400, `expected responseCode 400, got ${log400?.responseCode}`, 'HTTP 400 responseCode recorded')
117
+ assert(
118
+ await wait_for_failure_count(sdk, initialCount + 2) === initialCount + 2,
119
+ 'deliveryFailureCount not incremented after HTTP 400',
120
+ 'deliveryFailureCount incremented after HTTP 400'
121
+ )
122
+
123
+ // Scenario 2b: HTTP 500 from the receiver
124
+ await sdk.api.webhooks.update({ url: `${receiverBase}/fail-500` })
125
+ await trigger_delivery('http500')
126
+ const log500 = await find_log_for_url(sdk, `${receiverBase}/fail-500`)
127
+ assert(log500?.responseCode === 500, `expected responseCode 500, got ${log500?.responseCode}`, 'HTTP 500 responseCode recorded')
128
+ assert(
129
+ await wait_for_failure_count(sdk, initialCount + 3) === initialCount + 3,
130
+ 'deliveryFailureCount not incremented after HTTP 500',
131
+ 'deliveryFailureCount incremented after HTTP 500'
132
+ )
133
+
134
+ // Scenario 3 (timeout): skipped — WEBHOOK_TIMEOUT_MS is a constant (15s), not env-overridable,
135
+ // and a 15s+ non-responding receiver would make this suite unacceptably slow.
136
+ // Covered by security/F-0155-webhook-timeout.test.ts via send_automation_webhook.
137
+
138
+ // Scenario 4: success path unchanged — 200 logged, counter untouched
139
+ await sdk.api.webhooks.update({ url: `${receiverBase}/success` })
140
+ await trigger_delivery('success')
141
+ const successLog = await find_log_for_url(sdk, `${receiverBase}/success`)
142
+ assert(successLog?.responseCode === 200, `expected responseCode 200, got ${successLog?.responseCode}`, 'success responseCode recorded')
143
+ assert(successIntegrityVerified, 'integrity check failed on success delivery', 'success delivery integrity verified')
144
+ await wait(undefined, 1000) // allow any (erroneous) counter update to land before checking
145
+ assert(
146
+ await get_failure_count(sdk) === initialCount + 3,
147
+ 'deliveryFailureCount changed on successful delivery',
148
+ 'deliveryFailureCount untouched on success'
149
+ )
150
+
151
+ // deliveryFailureCount is server-managed: not settable through the public update endpoint
152
+ const configs = await sdk.api.webhooks.getSome() as Array<any>
153
+ const webhookId = configs[0]?.id
154
+ await sdk.api.webhooks.updateOne(webhookId, { deliveryFailureCount: 9999 } as any).catch(() => {}) // may reject (readonly)
155
+ assert(
156
+ await get_failure_count(sdk) === initialCount + 3,
157
+ 'customer was able to overwrite deliveryFailureCount',
158
+ 'deliveryFailureCount not customer-settable'
159
+ )
160
+ } finally {
161
+ // stop deliveries for subsequent tests and shut down the local receiver
162
+ await sdk.api.webhooks.update({ subscriptionUpdates: { endusers: { create: false, update: false, delete: false } } }).catch(() => {})
163
+ server.close()
164
+ for (const id of enduserIds) {
165
+ try { await sdk.api.endusers.deleteOne(id) } catch {}
166
+ }
167
+ }
168
+ }
169
+
170
+ // Allow running this test file independently
171
+ if (require.main === module) {
172
+ console.log(`🌐 Using API URL: ${host}`)
173
+ const sdk = new Session({ host })
174
+ const sdkNonAdmin = new Session({ host })
175
+
176
+ const runTests = async () => {
177
+ await setup_tests(sdk, sdkNonAdmin)
178
+ await webhook_error_handling_tests({ sdk, sdkNonAdmin })
179
+ }
180
+
181
+ runTests()
182
+ .then(() => {
183
+ console.log("✅ Webhook error handling test suite completed successfully")
184
+ process.exit(0)
185
+ })
186
+ .catch((error) => {
187
+ console.error("❌ Webhook error handling test suite failed:", error)
188
+ process.exit(1)
189
+ })
190
+ }
@@ -159,4 +159,17 @@ export const setup_tests = async (sdk: Session, sdkNonAdmin: Session) => {
159
159
  sdk.api.users.updateOne(sdk.userInfo.id, { notificationEmailsDisabled: true }),
160
160
  sdk.api.users.updateOne(sdkNonAdmin.userInfo.id, { notificationEmailsDisabled: true }),
161
161
  ]).catch(console.error)
162
+ }
163
+
164
+ // Establishes an enduser session WITHOUT hitting the IP-rate-limited /login-enduser endpoint
165
+ // (throttleByIp: 20/min + 100/hr per IP — the full suite shares one IP and can exceed both).
166
+ // Use for test setup; reserve enduserSDK.authenticate for tests OF the login flow itself.
167
+ export const authenticate_enduser_via_token = async (
168
+ sdk: Session,
169
+ enduserSDK: EnduserSession,
170
+ filter: { id?: string, email?: string, externalId?: string },
171
+ ) => {
172
+ const { authToken, enduser } = await sdk.api.endusers.generate_auth_token(filter)
173
+ await enduserSDK.handle_new_session({ authToken, enduser })
174
+ return enduser
162
175
  }
@@ -56,7 +56,7 @@ import { journey_error_branching_tests } from "./api_tests/journey_error_branchi
56
56
  import { journey_delete_cancels_actions_tests } from "./api_tests/journey_delete_cancels_actions.test"
57
57
  import { afteraction_day_of_month_delay_tests } from "./api_tests/afteraction_day_of_month_delay.test"
58
58
  import { push_forms_to_portal_group_completion_tests } from "./api_tests/push_forms_to_portal_group_completion.test"
59
- import { setup_tests } from "./setup"
59
+ import { authenticate_enduser_via_token, setup_tests } from "./setup"
60
60
  import { evaluate_conditional_logic_for_enduser_fields, FORM_LOGIC_CALCULATED_FIELDS, get_care_team_primary, get_flattened_fields, get_next_reminder_timestamp, object_is_empty, replace_enduser_template_values, replace_form_field_template_values, responses_satisfy_conditions, truncate_string, weighted_round_robin, YYYY_MM_DD_to_MM_DD_YYYY } from "@tellescope/utilities"
61
61
  import { DEFAULT_OPERATIONS, PLACEHOLDER_ID, ZENDESK_INTEGRATIONS_TITLE, ZOOM_TITLE } from "@tellescope/constants"
62
62
  import {
@@ -94,6 +94,7 @@ import { monthly_availability_restrictions_tests } from "./api_tests/monthly_ava
94
94
  import { calendar_event_limits_tests } from "./api_tests/calendar_event_limits.test";
95
95
  import { custom_aggregation_tests } from "./api_tests/custom_aggregation.test";
96
96
  import { chats_analytics_tests } from "./api_tests/chats_analytics.test";
97
+ import { nutrition_tracking_tests } from "./api_tests/nutrition_tracking.test";
97
98
  import { no_access_permission_checks_tests } from "./api_tests/no_access_permission_checks.test";
98
99
  import { resource_access_tags_tests } from "./api_tests/resource_access_tags.test";
99
100
  import { field_redaction_tests } from "./api_tests/field_redaction.test";
@@ -120,6 +121,7 @@ import { ai_conversations_tests } from "./api_tests/ai_conversations.test";
120
121
  import { load_team_chat_tests } from "./api_tests/load_team_chat.test";
121
122
  import { form_started_trigger_tests } from "./api_tests/form_started_trigger.test";
122
123
  import { form_submitted_trigger_tests } from "./api_tests/form_submitted_trigger.test";
124
+ import { dont_sync_to_elation_form_submission_tests } from "./api_tests/dont_sync_to_elation_form_submission.test";
123
125
  import { medication_added_trigger_tests } from "./api_tests/medication_added_trigger.test";
124
126
  import { conditional_logic_medication_unit_tests } from "./unit_tests/conditional_logic_medication.test";
125
127
  import { elation_user_id_tests } from "./api_tests/elation_user_id.test";
@@ -136,6 +138,7 @@ import { date_string_validation_tests } from "./api_tests/date_string_validation
136
138
  import { enduser_session_invalidation_tests } from "./api_tests/enduser_session_invalidation.test";
137
139
  import { enduser_cross_access_isolation_tests } from "./api_tests/enduser_cross_access_isolation.test";
138
140
  import { calendar_event_webhook_template_tests } from "./api_tests/calendar_event_webhook_template.test";
141
+ import { webhook_error_handling_tests } from "./api_tests/webhook_error_handling.test";
139
142
 
140
143
  const UniquenessViolationMessage = 'Uniqueness Violation'
141
144
 
@@ -282,7 +285,7 @@ const sub_organization_tests = async() => {
282
285
  await async_test(`subsub get subsub`, () => sdkSubSub.api.endusers.getOne(subSubEnduser.id), passOnAnyResult)
283
286
 
284
287
  await sdk.api.endusers.set_password({ id: rootEnduser.id, password })
285
- await enduserSDK.authenticate(rootEnduser.email!, password)
288
+ await authenticate_enduser_via_token(sdk, enduserSDK, { id: rootEnduser.id })
286
289
  await async_test(
287
290
  `root enduser create`,
288
291
  () => enduserSDK.api.engagement_events.createOne({ significance: 1, type: 'test', enduserId: rootEnduser.id }),
@@ -294,7 +297,7 @@ const sub_organization_tests = async() => {
294
297
 
295
298
 
296
299
  await sdk.api.endusers.set_password({ id: subEnduser.id, password })
297
- await enduserSDK.authenticate(subEnduser.email!, password)
300
+ await authenticate_enduser_via_token(sdk, enduserSDK, { id: subEnduser.id })
298
301
  await async_test(
299
302
  `sub enduser create`,
300
303
  () => enduserSDK.api.engagement_events.createOne({ significance: 1, type: 'test', enduserId: subEnduser.id }),
@@ -302,7 +305,7 @@ const sub_organization_tests = async() => {
302
305
  )
303
306
 
304
307
  await sdk.api.endusers.set_password({ id: subSubEnduser.id, password })
305
- await enduserSDK.authenticate(subSubEnduser.email!, password)
308
+ await authenticate_enduser_via_token(sdk, enduserSDK, { id: subSubEnduser.id })
306
309
  await async_test(
307
310
  `subSub enduser create`,
308
311
  () => enduserSDK.api.engagement_events.createOne({ significance: 1, type: 'test', enduserId: subSubEnduser.id }),
@@ -826,9 +829,14 @@ const enduser_tests = async (queries=sdk.api.endusers) => {
826
829
  )
827
830
  await async_test(
828
831
  `enduser registered can log in`,
829
- () => enduserSDK.authenticate('test3@gmail.com', 'testenduserpassword'),
832
+ () => enduserSDK.authenticate('test3@gmail.com', 'testenduserpassword'),
830
833
  { onResult: e => !!e.authToken && e.enduser.email === 'test3@gmail.com' },
831
834
  )
835
+ await async_test(
836
+ `enduser login rejects a wrong password`,
837
+ () => new EnduserSession({ host, businessId }).authenticate('test3@gmail.com', 'wrong-password'),
838
+ handleAnyError,
839
+ )
832
840
 
833
841
  await async_test(
834
842
  `update-enduser email conflict`,
@@ -1378,7 +1386,7 @@ const chat_tests = async() => {
1378
1386
 
1379
1387
  const enduser = await sdk.api.endusers.createOne({ email })
1380
1388
  await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
1381
- await enduserSDK.authenticate(email, password).catch(console.error)
1389
+ await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id }).catch(console.error)
1382
1390
 
1383
1391
  const room = await sdk.api.chat_rooms.createOne({ type: 'internal', userIds: [userId] })
1384
1392
  const chat = await sdk.api.chats.createOne({ roomId: room.id, message: "Hello!" })
@@ -1521,7 +1529,7 @@ const enduserAccessTests = async () => {
1521
1529
  const enduser = await sdk.api.endusers.createOne({ email })
1522
1530
  const enduser2 = await sdk.api.endusers.createOne({ email: 'hi' + email })
1523
1531
  await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
1524
- await enduserSDK.authenticate(email, password).catch(console.error)
1532
+ await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id }).catch(console.error)
1525
1533
 
1526
1534
  await wait(undefined, 1000) // wait so that refresh_session generates a new authToken (different timestamp)
1527
1535
 
@@ -1706,7 +1714,7 @@ const files_tests = async () => {
1706
1714
  log_header("Files")
1707
1715
  const enduser = await sdk.api.endusers.createOne({ email })
1708
1716
  await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
1709
- await enduserSDK.authenticate(email, password).catch(console.error)
1717
+ await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id }).catch(console.error)
1710
1718
  await sdkNonAdmin.authenticate(nonAdminEmail, nonAdminPassword) // to use new role, handle logout on role change
1711
1719
 
1712
1720
  const buff = buffer.Buffer.from('test file data')
@@ -1817,7 +1825,7 @@ const enduser_session_tests = async () => {
1817
1825
 
1818
1826
  const enduser = await sdk.api.endusers.createOne({ email })
1819
1827
  await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
1820
- await enduserSDK.authenticate(email, password).catch(console.error)
1828
+ await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id }).catch(console.error)
1821
1829
 
1822
1830
  const users = await enduserSDK.api.users.display_info()
1823
1831
  assert(users && users.length > 0, 'No users returned', 'Get user display info for enduser')
@@ -5839,7 +5847,7 @@ export const meetings_tests = async () => {
5839
5847
 
5840
5848
  const enduser = await sdk.api.endusers.createOne({ email })
5841
5849
  await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
5842
- await enduserSDK.authenticate(email, password).catch(console.error)
5850
+ await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id }).catch(console.error)
5843
5851
 
5844
5852
  const privateMeeting = await sdk.api.meetings.start_meeting({ })
5845
5853
  const publicMeeting = await sdk.api.meetings.start_meeting({ publicRead: true })
@@ -6205,7 +6213,7 @@ const community_tests = async () => {
6205
6213
 
6206
6214
  const enduser = await sdk.api.endusers.createOne({ email })
6207
6215
  await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
6208
- await enduserSDK.authenticate(email, password).catch(console.error)
6216
+ await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id }).catch(console.error)
6209
6217
 
6210
6218
  const forum = await sdk.api.forums.createOne({ title: 'test', publicRead: true })
6211
6219
  const privateForum = await sdk.api.forums.createOne({ title: 'test 2', publicRead: false })
@@ -6352,7 +6360,7 @@ const redaction_tests = async () => {
6352
6360
  unredactedFields: [{ field: 'testField', value: 'testValue' }] as any,
6353
6361
  })
6354
6362
  await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
6355
- await enduserSDK.authenticate(email, password).catch(console.error)
6363
+ await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id }).catch(console.error)
6356
6364
 
6357
6365
  const endusers = await enduserSDK.api.endusers.getSome()
6358
6366
  const forUser = await sdk.api.endusers.getSome()
@@ -6599,7 +6607,7 @@ export const calendar_event_RSVPs_tests = async () => {
6599
6607
  log_header("Calendar Event RSVPs")
6600
6608
 
6601
6609
  await enduserSDK.register({ email: 'rsvps@tellescope.com', password: "testenduserpassword" })
6602
- await enduserSDK.authenticate('rsvps@tellescope.com', "testenduserpassword")
6610
+ await authenticate_enduser_via_token(sdk, enduserSDK, { email: 'rsvps@tellescope.com' })
6603
6611
 
6604
6612
  const event = await sdk.api.calendar_events.createOne({
6605
6613
  title: "RSVP Event",
@@ -6684,7 +6692,7 @@ const post_comments_tests = async () => {
6684
6692
  log_header("Post Comments")
6685
6693
 
6686
6694
  await enduserSDK.register({ email: 'rsvps@tellescope.com', password: "testenduserpassword" })
6687
- await enduserSDK.authenticate('rsvps@tellescope.com', "testenduserpassword")
6695
+ await authenticate_enduser_via_token(sdk, enduserSDK, { email: 'rsvps@tellescope.com' })
6688
6696
 
6689
6697
  const forumId = (await sdk.api.forums.createOne({ title: "RSVP Event", publicRead: true })).id
6690
6698
  const postId = (await sdk.api.forum_posts.createOne({ forumId, title: 'Post', htmlContent: '', textContent: '', })).id
@@ -6902,13 +6910,13 @@ export const self_serve_appointment_booking_tests = async () => {
6902
6910
  })
6903
6911
 
6904
6912
  const enduserSDK2 = new EnduserSession({ host, businessId })
6905
- await enduserSDK2.authenticate('sebass+ca@tellescope.com', password).catch(console.error)
6913
+ await authenticate_enduser_via_token(sdk, enduserSDK2, { email: 'sebass+ca@tellescope.com' }).catch(console.error)
6906
6914
 
6907
6915
  const enduserSDK3 = new EnduserSession({ host, businessId })
6908
- await enduserSDK3.authenticate('sebass+3@tellescope.com', password).catch(console.error)
6916
+ await authenticate_enduser_via_token(sdk, enduserSDK3, { email: 'sebass+3@tellescope.com' }).catch(console.error)
6909
6917
 
6910
6918
  // NY Enduser Tests
6911
- await enduserSDK.authenticate('sebass+ny@tellescope.com', password).catch(console.error)
6919
+ await authenticate_enduser_via_token(sdk, enduserSDK, { email: 'sebass+ny@tellescope.com' }).catch(console.error)
6912
6920
  await async_test(
6913
6921
  '30 minute slots for state restriction',
6914
6922
  () => enduserSDK.api.calendar_events.get_appointment_availability({
@@ -7569,7 +7577,7 @@ const run_autoreply_test = async (title: string, { expectingAutoreply, autoreply
7569
7577
 
7570
7578
  const enduser = await sdk.api.endusers.createOne({ fname: 'Autoreply', lname: "Test", email: "autoreply@tellescope.com" })
7571
7579
  await sdk.api.endusers.set_password({ id: enduser.id, password })
7572
- await enduserSDK.authenticate(enduser.email!, password)
7580
+ await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id })
7573
7581
 
7574
7582
  const room = await sdk.api.chat_rooms.createOne({
7575
7583
  userIds: [sdk.userInfo.id],
@@ -15054,6 +15062,7 @@ const ip_address_form_tests = async () => {
15054
15062
  await invite_user_enumeration_tests({ sdk, sdkNonAdmin })
15055
15063
  await handle_incoming_communication_cross_tenant_tests({ sdk, sdkNonAdmin })
15056
15064
  await calendar_event_webhook_template_tests({ sdk, sdkNonAdmin })
15065
+ await webhook_error_handling_tests({ sdk, sdkNonAdmin })
15057
15066
  await outbound_chat_sent_trigger_tests({ sdk })
15058
15067
  await enduser_login_rate_limits_tests({ sdk, sdkNonAdmin })
15059
15068
  await data_sync_redaction_bypass_tests({ sdk, sdkNonAdmin })
@@ -15074,6 +15083,7 @@ const ip_address_form_tests = async () => {
15074
15083
  await chats_analytics_tests({ sdk, sdkNonAdmin })
15075
15084
  await field_redaction_tests({ sdk, sdkNonAdmin })
15076
15085
  await form_submitted_trigger_tests({ sdk, sdkNonAdmin })
15086
+ await dont_sync_to_elation_form_submission_tests({ sdk, sdkNonAdmin })
15077
15087
  await date_string_validation_tests({ sdk, sdkNonAdmin })
15078
15088
  await openloop_webhooks_tests({ sdk, sdkNonAdmin })
15079
15089
  await mdi_webhooks_tests({ sdk, sdkNonAdmin })
@@ -15120,6 +15130,7 @@ const ip_address_form_tests = async () => {
15120
15130
  await inbox_threads_loading_tests()
15121
15131
  await load_inbox_data_tests({ sdk, sdkNonAdmin })
15122
15132
  await enduser_observations_acknowledge_tests({ sdk, sdkNonAdmin })
15133
+ await nutrition_tracking_tests({ sdk, sdkNonAdmin })
15123
15134
  await translations_tests({ sdk, sdkNonAdmin })
15124
15135
  await create_user_notifications_trigger_tests({ sdk })
15125
15136
  await group_mms_active_tests()
Binary file