@tellescope/sdk 1.250.2 → 1.252.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.
Files changed (136) hide show
  1. package/lib/cjs/sdk.d.ts +9 -0
  2. package/lib/cjs/sdk.d.ts.map +1 -1
  3. package/lib/cjs/sdk.js +3 -0
  4. package/lib/cjs/sdk.js.map +1 -1
  5. package/lib/cjs/tests/api_tests/account_switcher.test.d.ts.map +1 -1
  6. package/lib/cjs/tests/api_tests/account_switcher.test.js +1700 -306
  7. package/lib/cjs/tests/api_tests/account_switcher.test.js.map +1 -1
  8. package/lib/cjs/tests/api_tests/calendar_event_webhook_template.test.d.ts +6 -0
  9. package/lib/cjs/tests/api_tests/calendar_event_webhook_template.test.d.ts.map +1 -0
  10. package/lib/cjs/tests/api_tests/calendar_event_webhook_template.test.js +337 -0
  11. package/lib/cjs/tests/api_tests/calendar_event_webhook_template.test.js.map +1 -0
  12. package/lib/cjs/tests/api_tests/enduser_login.test.d.ts +6 -0
  13. package/lib/cjs/tests/api_tests/enduser_login.test.d.ts.map +1 -0
  14. package/lib/cjs/tests/api_tests/enduser_login.test.js +315 -0
  15. package/lib/cjs/tests/api_tests/enduser_login.test.js.map +1 -0
  16. package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.d.ts +6 -0
  17. package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.d.ts.map +1 -0
  18. package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.js +287 -0
  19. package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.js.map +1 -0
  20. package/lib/cjs/tests/api_tests/push_forms_to_portal_group_completion.test.d.ts +6 -0
  21. package/lib/cjs/tests/api_tests/push_forms_to_portal_group_completion.test.d.ts.map +1 -0
  22. package/lib/cjs/tests/api_tests/push_forms_to_portal_group_completion.test.js +406 -0
  23. package/lib/cjs/tests/api_tests/push_forms_to_portal_group_completion.test.js.map +1 -0
  24. package/lib/cjs/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.d.ts +28 -0
  25. package/lib/cjs/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.d.ts.map +1 -0
  26. package/lib/cjs/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.js +349 -0
  27. package/lib/cjs/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.js.map +1 -0
  28. package/lib/cjs/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts +28 -0
  29. package/lib/cjs/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts.map +1 -0
  30. package/lib/cjs/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js +247 -0
  31. package/lib/cjs/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js.map +1 -0
  32. package/lib/cjs/tests/api_tests/security/F-0007-invite-user-enumeration.test.d.ts +29 -0
  33. package/lib/cjs/tests/api_tests/security/F-0007-invite-user-enumeration.test.d.ts.map +1 -0
  34. package/lib/cjs/tests/api_tests/security/F-0007-invite-user-enumeration.test.js +278 -0
  35. package/lib/cjs/tests/api_tests/security/F-0007-invite-user-enumeration.test.js.map +1 -0
  36. package/lib/cjs/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.d.ts +24 -0
  37. package/lib/cjs/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.d.ts.map +1 -0
  38. package/lib/cjs/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.js +201 -0
  39. package/lib/cjs/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.js.map +1 -0
  40. package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html.test.d.ts +2 -0
  41. package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html.test.d.ts.map +1 -0
  42. package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html.test.js +148 -0
  43. package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html.test.js.map +1 -0
  44. package/lib/cjs/tests/api_tests/security/F-0016-prototype-pollution.test.d.ts +2 -0
  45. package/lib/cjs/tests/api_tests/security/F-0016-prototype-pollution.test.d.ts.map +1 -0
  46. package/lib/cjs/tests/api_tests/security/F-0016-prototype-pollution.test.js +88 -0
  47. package/lib/cjs/tests/api_tests/security/F-0016-prototype-pollution.test.js.map +1 -0
  48. package/lib/cjs/tests/api_tests/set_fields_order_templates.test.d.ts +6 -0
  49. package/lib/cjs/tests/api_tests/set_fields_order_templates.test.d.ts.map +1 -0
  50. package/lib/cjs/tests/api_tests/set_fields_order_templates.test.js +373 -0
  51. package/lib/cjs/tests/api_tests/set_fields_order_templates.test.js.map +1 -0
  52. package/lib/cjs/tests/setup.d.ts.map +1 -1
  53. package/lib/cjs/tests/setup.js +47 -32
  54. package/lib/cjs/tests/setup.js.map +1 -1
  55. package/lib/cjs/tests/tests.d.ts.map +1 -1
  56. package/lib/cjs/tests/tests.js +215 -159
  57. package/lib/cjs/tests/tests.js.map +1 -1
  58. package/lib/esm/sdk.d.ts +9 -0
  59. package/lib/esm/sdk.d.ts.map +1 -1
  60. package/lib/esm/sdk.js +3 -0
  61. package/lib/esm/sdk.js.map +1 -1
  62. package/lib/esm/tests/api_tests/account_switcher.test.d.ts.map +1 -1
  63. package/lib/esm/tests/api_tests/account_switcher.test.js +1702 -305
  64. package/lib/esm/tests/api_tests/account_switcher.test.js.map +1 -1
  65. package/lib/esm/tests/api_tests/calendar_event_webhook_template.test.d.ts +6 -0
  66. package/lib/esm/tests/api_tests/calendar_event_webhook_template.test.d.ts.map +1 -0
  67. package/lib/esm/tests/api_tests/calendar_event_webhook_template.test.js +333 -0
  68. package/lib/esm/tests/api_tests/calendar_event_webhook_template.test.js.map +1 -0
  69. package/lib/esm/tests/api_tests/enduser_login.test.d.ts +6 -0
  70. package/lib/esm/tests/api_tests/enduser_login.test.d.ts.map +1 -0
  71. package/lib/esm/tests/api_tests/enduser_login.test.js +308 -0
  72. package/lib/esm/tests/api_tests/enduser_login.test.js.map +1 -0
  73. package/lib/esm/tests/api_tests/enduser_login_phi_disclosure.test.d.ts +6 -0
  74. package/lib/esm/tests/api_tests/enduser_login_phi_disclosure.test.d.ts.map +1 -0
  75. package/lib/esm/tests/api_tests/enduser_login_phi_disclosure.test.js +268 -0
  76. package/lib/esm/tests/api_tests/enduser_login_phi_disclosure.test.js.map +1 -0
  77. package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.d.ts +6 -0
  78. package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.d.ts.map +1 -0
  79. package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.js +280 -0
  80. package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.js.map +1 -0
  81. package/lib/esm/tests/api_tests/push_forms_to_portal_group_completion.test.d.ts +6 -0
  82. package/lib/esm/tests/api_tests/push_forms_to_portal_group_completion.test.d.ts.map +1 -0
  83. package/lib/esm/tests/api_tests/push_forms_to_portal_group_completion.test.js +402 -0
  84. package/lib/esm/tests/api_tests/push_forms_to_portal_group_completion.test.js.map +1 -0
  85. package/lib/esm/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.d.ts +28 -0
  86. package/lib/esm/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.d.ts.map +1 -0
  87. package/lib/esm/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.js +345 -0
  88. package/lib/esm/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.js.map +1 -0
  89. package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts +28 -0
  90. package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts.map +1 -0
  91. package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js +243 -0
  92. package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js.map +1 -0
  93. package/lib/esm/tests/api_tests/security/F-0007-invite-user-enumeration.test.d.ts +29 -0
  94. package/lib/esm/tests/api_tests/security/F-0007-invite-user-enumeration.test.d.ts.map +1 -0
  95. package/lib/esm/tests/api_tests/security/F-0007-invite-user-enumeration.test.js +271 -0
  96. package/lib/esm/tests/api_tests/security/F-0007-invite-user-enumeration.test.js.map +1 -0
  97. package/lib/esm/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.d.ts +24 -0
  98. package/lib/esm/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.d.ts.map +1 -0
  99. package/lib/esm/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.js +194 -0
  100. package/lib/esm/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.js.map +1 -0
  101. package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html.test.d.ts +2 -0
  102. package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html.test.d.ts.map +1 -0
  103. package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html.test.js +144 -0
  104. package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html.test.js.map +1 -0
  105. package/lib/esm/tests/api_tests/security/F-0016-prototype-pollution.test.d.ts +2 -0
  106. package/lib/esm/tests/api_tests/security/F-0016-prototype-pollution.test.d.ts.map +1 -0
  107. package/lib/esm/tests/api_tests/security/F-0016-prototype-pollution.test.js +84 -0
  108. package/lib/esm/tests/api_tests/security/F-0016-prototype-pollution.test.js.map +1 -0
  109. package/lib/esm/tests/api_tests/set_fields_order_templates.test.d.ts +6 -0
  110. package/lib/esm/tests/api_tests/set_fields_order_templates.test.d.ts.map +1 -0
  111. package/lib/esm/tests/api_tests/set_fields_order_templates.test.js +369 -0
  112. package/lib/esm/tests/api_tests/set_fields_order_templates.test.js.map +1 -0
  113. package/lib/esm/tests/setup.d.ts.map +1 -1
  114. package/lib/esm/tests/setup.js +47 -32
  115. package/lib/esm/tests/setup.js.map +1 -1
  116. package/lib/esm/tests/tests.d.ts.map +1 -1
  117. package/lib/esm/tests/tests.js +215 -159
  118. package/lib/esm/tests/tests.js.map +1 -1
  119. package/lib/tsconfig.tsbuildinfo +1 -1
  120. package/package.json +10 -10
  121. package/src/sdk.ts +12 -0
  122. package/src/tests/api_tests/account_switcher.test.ts +1283 -0
  123. package/src/tests/api_tests/calendar_event_webhook_template.test.ts +204 -0
  124. package/src/tests/api_tests/enduser_login.test.ts +215 -0
  125. package/src/tests/api_tests/enduser_login_rate_limits.test.ts +178 -0
  126. package/src/tests/api_tests/push_forms_to_portal_group_completion.test.ts +223 -0
  127. package/src/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.ts +236 -0
  128. package/src/tests/api_tests/security/F-0005-ai-conversations-rbac.test.ts +154 -0
  129. package/src/tests/api_tests/security/F-0007-invite-user-enumeration.test.ts +198 -0
  130. package/src/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.ts +130 -0
  131. package/src/tests/api_tests/security/F-0013-sanitize-user-html.test.ts +109 -0
  132. package/src/tests/api_tests/security/F-0016-prototype-pollution.test.ts +50 -0
  133. package/src/tests/api_tests/set_fields_order_templates.test.ts +258 -0
  134. package/src/tests/setup.ts +8 -1
  135. package/src/tests/tests.ts +35 -5
  136. package/test_generated.pdf +0 -0
@@ -0,0 +1,258 @@
1
+ require('source-map-support').install();
2
+
3
+ import { Session } from "../../sdk"
4
+ import {
5
+ assert,
6
+ async_test,
7
+ log_header,
8
+ wait,
9
+ } from "@tellescope/testing"
10
+ import { setup_tests } from "../setup"
11
+
12
+ const host = process.env.API_URL || 'http://localhost:8080' as const
13
+
14
+ const TRIGGER_TITLE_BLOCK_A = "Order Templates: Block A"
15
+ const TRIGGER_TITLE_BLOCK_B = "Order Templates: Block B"
16
+
17
+ const buildSetFieldsAction = (prefix: string) => ({
18
+ type: 'Set Fields' as const,
19
+ info: {
20
+ fields: [
21
+ { name: `${prefix}_status`, value: '{{order.status}}', type: 'Custom Value' as const },
22
+ { name: `${prefix}_tracking`, value: '{{order.tracking}}', type: 'Custom Value' as const },
23
+ { name: `${prefix}_carrier`, value: '{{order.carrier}}', type: 'Custom Value' as const },
24
+ { name: `${prefix}_sku`, value: '{{order.sku}}', type: 'Custom Value' as const },
25
+ { name: `${prefix}_externalId`, value: '{{order.externalId}}', type: 'Custom Value' as const },
26
+ { name: `${prefix}_id`, value: '{{order.id}}', type: 'Custom Value' as const },
27
+ { name: `${prefix}_protocol`, value: '{{order.protocol}}', type: 'Custom Value' as const },
28
+ ],
29
+ },
30
+ })
31
+
32
+ // Block A: Direct EnduserOrder creation path
33
+ const direct_order_creation_block = async ({ sdk }: { sdk: Session }) => {
34
+ log_header("Block A: Direct EnduserOrder creation -> {{order.*}} in Set Fields")
35
+
36
+ const enduser = await sdk.api.endusers.createOne({})
37
+ const trigger = await sdk.api.automation_triggers.createOne({
38
+ title: TRIGGER_TITLE_BLOCK_A,
39
+ status: 'Active',
40
+ event: { type: 'Order Status Equals', info: { source: 'Beluga', status: 'Shipped' } },
41
+ action: buildSetFieldsAction('pharmacy'),
42
+ })
43
+
44
+ let createdOrderId: string | undefined
45
+ let nonMatchingOrderId: string | undefined
46
+
47
+ try {
48
+ const order = await sdk.api.enduser_orders.createOne({
49
+ enduserId: enduser.id,
50
+ source: 'Beluga',
51
+ status: 'Shipped',
52
+ title: 'Beluga Pharmacy Order',
53
+ externalId: 'EXT-A-123',
54
+ tracking: '1Z-AAA',
55
+ carrier: 'UPS',
56
+ sku: 'SKU-A',
57
+ protocol: 'wl1',
58
+ })
59
+ createdOrderId = order.id
60
+
61
+ await wait(undefined, 250) // allow trigger + Set Fields to run
62
+
63
+ await async_test(
64
+ "Block A: {{order.*}} templates resolve to literal values",
65
+ () => sdk.api.endusers.getOne(enduser.id),
66
+ { onResult: e => !!(
67
+ e.fields?.pharmacy_status === 'Shipped'
68
+ && e.fields?.pharmacy_tracking === '1Z-AAA'
69
+ && e.fields?.pharmacy_carrier === 'UPS'
70
+ && e.fields?.pharmacy_sku === 'SKU-A'
71
+ && e.fields?.pharmacy_externalId === 'EXT-A-123'
72
+ && e.fields?.pharmacy_protocol === 'wl1'
73
+ && typeof e.fields?.pharmacy_id === 'string'
74
+ && (e.fields?.pharmacy_id as string).length > 0
75
+ && (e.fields?.pharmacy_id as string) === order.id
76
+ )}
77
+ )
78
+
79
+ // Negative case: status that doesn't match the trigger should NOT alter fields
80
+ const beforeNonMatch = await sdk.api.endusers.getOne(enduser.id)
81
+ const snapshot = {
82
+ pharmacy_status: beforeNonMatch.fields?.pharmacy_status,
83
+ pharmacy_tracking: beforeNonMatch.fields?.pharmacy_tracking,
84
+ pharmacy_carrier: beforeNonMatch.fields?.pharmacy_carrier,
85
+ pharmacy_sku: beforeNonMatch.fields?.pharmacy_sku,
86
+ pharmacy_externalId: beforeNonMatch.fields?.pharmacy_externalId,
87
+ pharmacy_id: beforeNonMatch.fields?.pharmacy_id,
88
+ pharmacy_protocol: beforeNonMatch.fields?.pharmacy_protocol,
89
+ }
90
+
91
+ const nonMatching = await sdk.api.enduser_orders.createOne({
92
+ enduserId: enduser.id,
93
+ source: 'Beluga',
94
+ status: 'In Fulfillment', // does NOT match the trigger
95
+ title: 'Beluga Pharmacy Order (other status)',
96
+ externalId: 'EXT-A-NOMATCH',
97
+ tracking: 'NOPE',
98
+ carrier: 'NoCarrier',
99
+ sku: 'SKU-NOPE',
100
+ protocol: 'nope',
101
+ })
102
+ nonMatchingOrderId = nonMatching.id
103
+
104
+ await wait(undefined, 250)
105
+
106
+ await async_test(
107
+ "Block A: non-matching status leaves fields unchanged",
108
+ () => sdk.api.endusers.getOne(enduser.id),
109
+ { onResult: e => !!(
110
+ e.fields?.pharmacy_status === snapshot.pharmacy_status
111
+ && e.fields?.pharmacy_tracking === snapshot.pharmacy_tracking
112
+ && e.fields?.pharmacy_carrier === snapshot.pharmacy_carrier
113
+ && e.fields?.pharmacy_sku === snapshot.pharmacy_sku
114
+ && e.fields?.pharmacy_externalId === snapshot.pharmacy_externalId
115
+ && e.fields?.pharmacy_id === snapshot.pharmacy_id
116
+ && e.fields?.pharmacy_protocol === snapshot.pharmacy_protocol
117
+ )}
118
+ )
119
+ } finally {
120
+ if (createdOrderId) await sdk.api.enduser_orders.deleteOne(createdOrderId).catch(console.error)
121
+ if (nonMatchingOrderId) await sdk.api.enduser_orders.deleteOne(nonMatchingOrderId).catch(console.error)
122
+ await sdk.api.automation_triggers.deleteOne(trigger.id).catch(console.error)
123
+ await sdk.api.endusers.deleteOne(enduser.id).catch(console.error)
124
+ }
125
+ }
126
+
127
+ // Block B: Beluga webhook integration path
128
+ const beluga_webhook_block = async ({ sdk }: { sdk: Session }) => {
129
+ log_header("Block B: Beluga webhook -> {{order.*}} in Set Fields")
130
+
131
+ const webhookUrl = `${host}/v1/webhooks/beluga`
132
+ const externalOrderId = `EXT-B-${Date.now()}`
133
+
134
+ const enduser = await sdk.api.endusers.createOne({})
135
+ const form = await sdk.api.forms.createOne({ title: 'Order Templates Beluga Form' })
136
+ const formResponse = await sdk.api.form_responses.createOne({
137
+ formId: form.id,
138
+ enduserId: enduser.id,
139
+ formTitle: form.title,
140
+ })
141
+
142
+ const trigger = await sdk.api.automation_triggers.createOne({
143
+ title: TRIGGER_TITLE_BLOCK_B,
144
+ status: 'Active',
145
+ event: { type: 'Order Status Equals', info: { source: 'Beluga', status: 'Shipped' } },
146
+ action: buildSetFieldsAction('pharmacy'),
147
+ })
148
+
149
+ const deliveredTrigger = await sdk.api.automation_triggers.createOne({
150
+ title: `${TRIGGER_TITLE_BLOCK_B} (Delivered)`,
151
+ status: 'Active',
152
+ event: { type: 'Order Status Equals', info: { source: 'Beluga', status: 'Delivered' } },
153
+ action: buildSetFieldsAction('pharmacy'),
154
+ })
155
+
156
+ try {
157
+ // Step 1: PHARMACY_ORDER_SHIPPED
158
+ const shippedRes = await fetch(webhookUrl, {
159
+ method: 'POST',
160
+ headers: { 'Content-Type': 'application/json' },
161
+ body: JSON.stringify({
162
+ masterId: `tellescope_${formResponse.id}`,
163
+ event: 'PHARMACY_ORDER_SHIPPED',
164
+ orderId: externalOrderId,
165
+ info: { carrier: 'FedEx', tracking: '7777-BBB' },
166
+ }),
167
+ })
168
+ assert(shippedRes.status === 200, `Beluga webhook (shipped) expected 200, got ${shippedRes.status}`)
169
+
170
+ await wait(undefined, 250) // webhook upsert + trigger + Set Fields
171
+
172
+ await async_test(
173
+ "Block B: Beluga PHARMACY_ORDER_SHIPPED resolves {{order.*}} into enduser fields",
174
+ () => sdk.api.endusers.getOne(enduser.id),
175
+ { onResult: e => !!(
176
+ e.fields?.pharmacy_status === 'Shipped'
177
+ && e.fields?.pharmacy_tracking === '7777-BBB'
178
+ && e.fields?.pharmacy_carrier === 'FedEx'
179
+ && e.fields?.pharmacy_externalId === externalOrderId
180
+ && typeof e.fields?.pharmacy_id === 'string'
181
+ && (e.fields?.pharmacy_id as string).length > 0
182
+ // Webhook does not set sku/protocol -> default branch in helper -> ''
183
+ && e.fields?.pharmacy_sku === ''
184
+ && e.fields?.pharmacy_protocol === ''
185
+ )}
186
+ )
187
+
188
+ // Step 2: PHARMACY_ORDER_DELIVERED for the same order
189
+ const deliveredRes = await fetch(webhookUrl, {
190
+ method: 'POST',
191
+ headers: { 'Content-Type': 'application/json' },
192
+ body: JSON.stringify({
193
+ masterId: `tellescope_${formResponse.id}`,
194
+ event: 'PHARMACY_ORDER_DELIVERED',
195
+ orderId: externalOrderId,
196
+ }),
197
+ })
198
+ assert(deliveredRes.status === 200, `Beluga webhook (delivered) expected 200, got ${deliveredRes.status}`)
199
+
200
+ await wait(undefined, 250)
201
+
202
+ await async_test(
203
+ "Block B: PHARMACY_ORDER_DELIVERED flips pharmacy_status to 'Delivered'",
204
+ () => sdk.api.endusers.getOne(enduser.id),
205
+ { onResult: e => !!(
206
+ e.fields?.pharmacy_status === 'Delivered'
207
+ && e.fields?.pharmacy_externalId === externalOrderId
208
+ )}
209
+ )
210
+ } finally {
211
+ // Clean up the order created by the webhook
212
+ try {
213
+ const orders = await sdk.api.enduser_orders.getSome({
214
+ filter: { source: 'Beluga', externalId: externalOrderId } as any,
215
+ })
216
+ for (const o of orders) {
217
+ await sdk.api.enduser_orders.deleteOne(o.id).catch(console.error)
218
+ }
219
+ } catch (err) {
220
+ console.error(err)
221
+ }
222
+
223
+ await sdk.api.automation_triggers.deleteOne(trigger.id).catch(console.error)
224
+ await sdk.api.automation_triggers.deleteOne(deliveredTrigger.id).catch(console.error)
225
+ await sdk.api.form_responses.deleteOne(formResponse.id).catch(console.error)
226
+ await sdk.api.forms.deleteOne(form.id).catch(console.error)
227
+ await sdk.api.endusers.deleteOne(enduser.id).catch(console.error)
228
+ }
229
+ }
230
+
231
+ export const set_fields_order_templates_tests = async (
232
+ { sdk, sdkNonAdmin }: { sdk: Session, sdkNonAdmin: Session }
233
+ ) => {
234
+ log_header("Set Fields: {{order.*}} template resolution")
235
+ await direct_order_creation_block({ sdk })
236
+ await beluga_webhook_block({ sdk })
237
+ }
238
+
239
+ if (require.main === module) {
240
+ console.log(`Using API URL: ${host}`)
241
+ const sdk = new Session({ host })
242
+ const sdkNonAdmin = new Session({ host })
243
+
244
+ const runTests = async () => {
245
+ await setup_tests(sdk, sdkNonAdmin)
246
+ await set_fields_order_templates_tests({ sdk, sdkNonAdmin })
247
+ }
248
+
249
+ runTests()
250
+ .then(() => {
251
+ console.log("set_fields_order_templates test suite completed successfully")
252
+ process.exit(0)
253
+ })
254
+ .catch((error) => {
255
+ console.error("set_fields_order_templates test suite failed:", error)
256
+ process.exit(1)
257
+ })
258
+ }
@@ -37,9 +37,16 @@ export const setup_tests = async (sdk: Session, sdkNonAdmin: Session) => {
37
37
  // Authenticate the SDKs first
38
38
  await sdk.authenticate(email, password)
39
39
  await sdkNonAdmin.authenticate(nonAdminEmail, nonAdminPassword)
40
-
40
+
41
41
  await async_test('test_authenticated', sdk.test_authenticated, { expectedResult: 'Authenticated!' })
42
42
 
43
+ // Defensive: clear residual OTP gating from a previously-aborted run of
44
+ // enduser_session_invalidation_tests, which would otherwise cause enduser
45
+ // tokens minted in subsequent tests to be rejected as Unauthenticated.
46
+ await sdk.api.organizations.updateOne(sdk.userInfo.businessId, {
47
+ portalSettings: { authentication: { requireOTP: false, requireOTPAfterPassword: false } },
48
+ }, { replaceObjectFields: true })
49
+
43
50
  await async_test(
44
51
  'test_authenticated (with API Key)',
45
52
  (new Session({ host, apiKey: '3n5q0SCBT_iUvZz-b9BJtX7o7HQUVJ9v132PgHJNJsg.' /* local test key */ })).test_authenticated,
@@ -49,6 +49,7 @@ import { purchase_made_trigger_tests } from "./api_tests/purchase_made_trigger.t
49
49
  import { appointment_rescheduled_trigger_tests } from "./api_tests/appointment_rescheduled_trigger.test"
50
50
  import { journey_error_branching_tests } from "./api_tests/journey_error_branching.test"
51
51
  import { afteraction_day_of_month_delay_tests } from "./api_tests/afteraction_day_of_month_delay.test"
52
+ import { push_forms_to_portal_group_completion_tests } from "./api_tests/push_forms_to_portal_group_completion.test"
52
53
  import { setup_tests } from "./setup"
53
54
  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"
54
55
  import { DEFAULT_OPERATIONS, PLACEHOLDER_ID, ZENDESK_INTEGRATIONS_TITLE, ZOOM_TITLE } from "@tellescope/constants"
@@ -74,6 +75,8 @@ import {
74
75
 
75
76
  import fs from "fs"
76
77
  import { load_inbox_data_tests } from "./api_tests/load_inbox_data.test";
78
+ import { enduser_login_tests } from "./api_tests/enduser_login.test";
79
+ import { enduser_login_rate_limits_tests } from "./api_tests/enduser_login_rate_limits.test";
77
80
  import { eom_procedure_codes_tests } from "./api_tests/eom_procedure_codes.test";
78
81
  import { cross_org_api_key_tests } from "./api_tests/cross_org_api_key.test";
79
82
  import { custom_dashboards_tests } from "./api_tests/custom_dashboards.test";
@@ -86,6 +89,12 @@ import { custom_aggregation_tests } from "./api_tests/custom_aggregation.test";
86
89
  import { chats_analytics_tests } from "./api_tests/chats_analytics.test";
87
90
  import { no_access_permission_checks_tests } from "./api_tests/no_access_permission_checks.test";
88
91
  import { field_redaction_tests } from "./api_tests/field_redaction.test";
92
+ import { data_sync_redaction_bypass_tests } from "./api_tests/security/F-0001-data-sync-redaction-bypass.test";
93
+ import { ai_conversations_rbac_tests } from "./api_tests/security/F-0005-ai-conversations-rbac.test";
94
+ import { invite_user_enumeration_tests } from "./api_tests/security/F-0007-invite-user-enumeration.test";
95
+ import { handle_incoming_communication_cross_tenant_tests } from "./api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test";
96
+ import { sanitize_user_html_xss_tests } from "./api_tests/security/F-0013-sanitize-user-html.test";
97
+ import { prototype_pollution_tests } from "./api_tests/security/F-0016-prototype-pollution.test";
89
98
  import { bulk_assignment_tests } from "./api_tests/bulk_assignment.test";
90
99
  import { managed_content_enduser_access_tests } from "./api_tests/managed_content_enduser_access.test";
91
100
  import { managed_content_file_access_tests } from "./api_tests/managed_content_file_access.test";
@@ -102,9 +111,12 @@ import { organization_settings_duplicates_tests } from "./api_tests/organization
102
111
  import { calendar_events_bulk_update_tests } from "./api_tests/calendar_events_bulk_update.test";
103
112
  import { openloop_webhooks_tests } from "./api_tests/openloop_webhooks.test";
104
113
  import { beluga_pharmacy_mappings_tests } from "./api_tests/beluga_pharmacy_mappings.test";
114
+ import { account_switcher_tests } from "./api_tests/account_switcher.test";
115
+ import { set_fields_order_templates_tests } from "./api_tests/set_fields_order_templates.test";
105
116
  import { date_string_validation_tests } from "./api_tests/date_string_validation.test";
106
117
  import { enduser_session_invalidation_tests } from "./api_tests/enduser_session_invalidation.test";
107
118
  import { enduser_cross_access_isolation_tests } from "./api_tests/enduser_cross_access_isolation.test";
119
+ import { calendar_event_webhook_template_tests } from "./api_tests/calendar_event_webhook_template.test";
108
120
 
109
121
  const UniquenessViolationMessage = 'Uniqueness Violation'
110
122
 
@@ -5088,7 +5100,9 @@ const trigger_events_api_tests = async () => {
5088
5100
  const automation_trigger_tests = async () => {
5089
5101
  log_header("Automation Trigger Tests")
5090
5102
 
5103
+ await push_forms_to_portal_group_completion_tests({ sdk, sdkNonAdmin })
5091
5104
  await order_status_equals_tests()
5105
+ await set_fields_order_templates_tests({ sdk, sdkNonAdmin })
5092
5106
  await medication_added_trigger_tests({ sdk, sdkNonAdmin })
5093
5107
  await appointment_cancelled_tests()
5094
5108
  await set_fields_tests()
@@ -7121,16 +7135,18 @@ const merge_enduser_tests = async () => {
7121
7135
  const stripeCustomerId = 'example_cu_id';
7122
7136
  const stripeKey = 'example_stripe_key';
7123
7137
  const [source, destination, otherEnduser] = (await sdk.api.endusers.createSome([
7124
- {
7125
- email: 'source@tellescope.com', fname: 'source', lname: 'enduser',
7126
- references: [{ type: '2', id: '2.2' }, { type: '3', id: '3.2' }, { type: '4', id: '4.2'}],
7138
+ {
7139
+ email: 'source@tellescope.com', fname: 'source', lname: 'enduser',
7140
+ references: [{ type: '2', id: '2.2' }, { type: '3', id: '3.2' }, { type: '4', id: '4.2'}],
7127
7141
  // @ts-ignore
7128
7142
  stripeCustomerId,
7129
7143
  stripeKey,
7130
7144
  athenaPracticeId: '12345',
7131
7145
  athenaDepartmentId: '54321',
7146
+ insurance: { memberId: 'src-member', payerName: 'Source Payer' },
7147
+ insuranceSecondary: { memberId: 'src-secondary' },
7132
7148
  },
7133
- { email: 'destination@tellescope.com', source: '4', externalId: "4", references: [{ type: '1', id: '1' }, { type: '2', id: '2' }] },
7149
+ { email: 'destination@tellescope.com', source: '4', externalId: "4", references: [{ type: '1', id: '1' }, { type: '2', id: '2' }], insurance: { memberId: 'dest-member', payerName: 'Dest Payer' } },
7134
7150
  { email: 'other@tellescope.com'},
7135
7151
  ])).created
7136
7152
 
@@ -7179,7 +7195,10 @@ const merge_enduser_tests = async () => {
7179
7195
  && e.references?.find(r => r.type === '1')?.id === '1'
7180
7196
  && e.references?.find(r => r.type === '2')?.id === '2'
7181
7197
  && e.references?.find(r => r.type === '3')?.id === '3.2'
7182
- && !e.references?.find(r => r.type === '4')?.id
7198
+ && !e.references?.find(r => r.type === '4')?.id
7199
+ && e.insurance?.memberId === 'dest-member'
7200
+ && e.insurance?.payerName === 'Dest Payer'
7201
+ && e.insuranceSecondary?.memberId === 'src-secondary'
7183
7202
  )}
7184
7203
  )
7185
7204
 
@@ -14310,8 +14329,19 @@ const ip_address_form_tests = async () => {
14310
14329
  await replace_form_field_template_values_tests()
14311
14330
  await mfa_tests()
14312
14331
  await setup_tests(sdk, sdkNonAdmin)
14332
+ await invite_user_enumeration_tests({ sdk, sdkNonAdmin })
14333
+ await handle_incoming_communication_cross_tenant_tests({ sdk, sdkNonAdmin })
14334
+ await calendar_event_webhook_template_tests({ sdk, sdkNonAdmin })
14313
14335
  await outbound_chat_sent_trigger_tests({ sdk })
14336
+ await enduser_login_rate_limits_tests({ sdk, sdkNonAdmin })
14337
+ await data_sync_redaction_bypass_tests({ sdk, sdkNonAdmin })
14338
+ await ai_conversations_rbac_tests({ sdk, sdkNonAdmin })
14339
+ await sanitize_user_html_xss_tests()
14340
+ await prototype_pollution_tests()
14314
14341
  await automation_trigger_tests()
14342
+ await account_switcher_tests({ sdk, sdkNonAdmin })
14343
+ await enduser_login_tests({ sdk, sdkNonAdmin })
14344
+ await outbound_chat_sent_trigger_tests({ sdk })
14315
14345
  await enduser_cross_access_isolation_tests({ sdk, sdkNonAdmin })
14316
14346
  await eom_procedure_codes_tests({ sdk, sdkNonAdmin })
14317
14347
  await cross_org_api_key_tests({ sdk, sdkNonAdmin })
Binary file