@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.
- package/lib/cjs/sdk.d.ts +9 -0
- package/lib/cjs/sdk.d.ts.map +1 -1
- package/lib/cjs/sdk.js +3 -0
- package/lib/cjs/sdk.js.map +1 -1
- package/lib/cjs/tests/api_tests/account_switcher.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/account_switcher.test.js +1700 -306
- package/lib/cjs/tests/api_tests/account_switcher.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/calendar_event_webhook_template.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/calendar_event_webhook_template.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/calendar_event_webhook_template.test.js +337 -0
- package/lib/cjs/tests/api_tests/calendar_event_webhook_template.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/enduser_login.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/enduser_login.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/enduser_login.test.js +315 -0
- package/lib/cjs/tests/api_tests/enduser_login.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.js +287 -0
- package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/push_forms_to_portal_group_completion.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/push_forms_to_portal_group_completion.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/push_forms_to_portal_group_completion.test.js +406 -0
- package/lib/cjs/tests/api_tests/push_forms_to_portal_group_completion.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.d.ts +28 -0
- package/lib/cjs/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.js +349 -0
- package/lib/cjs/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts +28 -0
- package/lib/cjs/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js +247 -0
- package/lib/cjs/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0007-invite-user-enumeration.test.d.ts +29 -0
- package/lib/cjs/tests/api_tests/security/F-0007-invite-user-enumeration.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0007-invite-user-enumeration.test.js +278 -0
- package/lib/cjs/tests/api_tests/security/F-0007-invite-user-enumeration.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.d.ts +24 -0
- package/lib/cjs/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.js +201 -0
- package/lib/cjs/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html.test.d.ts +2 -0
- package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html.test.js +148 -0
- package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0016-prototype-pollution.test.d.ts +2 -0
- package/lib/cjs/tests/api_tests/security/F-0016-prototype-pollution.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0016-prototype-pollution.test.js +88 -0
- package/lib/cjs/tests/api_tests/security/F-0016-prototype-pollution.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/set_fields_order_templates.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/set_fields_order_templates.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/set_fields_order_templates.test.js +373 -0
- package/lib/cjs/tests/api_tests/set_fields_order_templates.test.js.map +1 -0
- package/lib/cjs/tests/setup.d.ts.map +1 -1
- package/lib/cjs/tests/setup.js +47 -32
- package/lib/cjs/tests/setup.js.map +1 -1
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +215 -159
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/sdk.d.ts +9 -0
- package/lib/esm/sdk.d.ts.map +1 -1
- package/lib/esm/sdk.js +3 -0
- package/lib/esm/sdk.js.map +1 -1
- package/lib/esm/tests/api_tests/account_switcher.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/account_switcher.test.js +1702 -305
- package/lib/esm/tests/api_tests/account_switcher.test.js.map +1 -1
- package/lib/esm/tests/api_tests/calendar_event_webhook_template.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/calendar_event_webhook_template.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/calendar_event_webhook_template.test.js +333 -0
- package/lib/esm/tests/api_tests/calendar_event_webhook_template.test.js.map +1 -0
- package/lib/esm/tests/api_tests/enduser_login.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/enduser_login.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/enduser_login.test.js +308 -0
- package/lib/esm/tests/api_tests/enduser_login.test.js.map +1 -0
- package/lib/esm/tests/api_tests/enduser_login_phi_disclosure.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/enduser_login_phi_disclosure.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/enduser_login_phi_disclosure.test.js +268 -0
- package/lib/esm/tests/api_tests/enduser_login_phi_disclosure.test.js.map +1 -0
- package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.js +280 -0
- package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.js.map +1 -0
- package/lib/esm/tests/api_tests/push_forms_to_portal_group_completion.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/push_forms_to_portal_group_completion.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/push_forms_to_portal_group_completion.test.js +402 -0
- package/lib/esm/tests/api_tests/push_forms_to_portal_group_completion.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.d.ts +28 -0
- package/lib/esm/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.js +345 -0
- package/lib/esm/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts +28 -0
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js +243 -0
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0007-invite-user-enumeration.test.d.ts +29 -0
- package/lib/esm/tests/api_tests/security/F-0007-invite-user-enumeration.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0007-invite-user-enumeration.test.js +271 -0
- package/lib/esm/tests/api_tests/security/F-0007-invite-user-enumeration.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.d.ts +24 -0
- package/lib/esm/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.js +194 -0
- package/lib/esm/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html.test.d.ts +2 -0
- package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html.test.js +144 -0
- package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0016-prototype-pollution.test.d.ts +2 -0
- package/lib/esm/tests/api_tests/security/F-0016-prototype-pollution.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0016-prototype-pollution.test.js +84 -0
- package/lib/esm/tests/api_tests/security/F-0016-prototype-pollution.test.js.map +1 -0
- package/lib/esm/tests/api_tests/set_fields_order_templates.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/set_fields_order_templates.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/set_fields_order_templates.test.js +369 -0
- package/lib/esm/tests/api_tests/set_fields_order_templates.test.js.map +1 -0
- package/lib/esm/tests/setup.d.ts.map +1 -1
- package/lib/esm/tests/setup.js +47 -32
- package/lib/esm/tests/setup.js.map +1 -1
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +215 -159
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/sdk.ts +12 -0
- package/src/tests/api_tests/account_switcher.test.ts +1283 -0
- package/src/tests/api_tests/calendar_event_webhook_template.test.ts +204 -0
- package/src/tests/api_tests/enduser_login.test.ts +215 -0
- package/src/tests/api_tests/enduser_login_rate_limits.test.ts +178 -0
- package/src/tests/api_tests/push_forms_to_portal_group_completion.test.ts +223 -0
- package/src/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.ts +236 -0
- package/src/tests/api_tests/security/F-0005-ai-conversations-rbac.test.ts +154 -0
- package/src/tests/api_tests/security/F-0007-invite-user-enumeration.test.ts +198 -0
- package/src/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.ts +130 -0
- package/src/tests/api_tests/security/F-0013-sanitize-user-html.test.ts +109 -0
- package/src/tests/api_tests/security/F-0016-prototype-pollution.test.ts +50 -0
- package/src/tests/api_tests/set_fields_order_templates.test.ts +258 -0
- package/src/tests/setup.ts +8 -1
- package/src/tests/tests.ts +35 -5
- 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
|
+
}
|
package/src/tests/setup.ts
CHANGED
|
@@ -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,
|
package/src/tests/tests.ts
CHANGED
|
@@ -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 })
|
package/test_generated.pdf
CHANGED
|
Binary file
|