@tellescope/sdk 1.244.4 → 1.245.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/tests/api_tests/medication_added_trigger.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/medication_added_trigger.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/medication_added_trigger.test.js +452 -0
- package/lib/cjs/tests/api_tests/medication_added_trigger.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/openloop_webhooks.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/openloop_webhooks.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/openloop_webhooks.test.js +833 -0
- package/lib/cjs/tests/api_tests/openloop_webhooks.test.js.map +1 -0
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +142 -134
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/tests/api_tests/medication_added_trigger.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/medication_added_trigger.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/medication_added_trigger.test.js +448 -0
- package/lib/esm/tests/api_tests/medication_added_trigger.test.js.map +1 -0
- package/lib/esm/tests/api_tests/openloop_webhooks.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/openloop_webhooks.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/openloop_webhooks.test.js +829 -0
- package/lib/esm/tests/api_tests/openloop_webhooks.test.js.map +1 -0
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +142 -134
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/tests/api_tests/medication_added_trigger.test.ts +306 -0
- package/src/tests/api_tests/openloop_webhooks.test.ts +662 -0
- package/src/tests/tests.ts +5 -1
- package/test_generated.pdf +0 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { Session } from "../../sdk"
|
|
2
|
+
import { log_header, wait, async_test } from "@tellescope/testing"
|
|
3
|
+
import { Enduser, EnduserMedication } from "@tellescope/types-client"
|
|
4
|
+
import { PLACEHOLDER_ID } from "@tellescope/constants"
|
|
5
|
+
import { setup_tests } from "../setup"
|
|
6
|
+
|
|
7
|
+
const host = process.env.API_URL || "http://localhost:8080"
|
|
8
|
+
|
|
9
|
+
export const medication_added_trigger_tests = async ({ sdk, sdkNonAdmin } : { sdk: Session, sdkNonAdmin: Session }) => {
|
|
10
|
+
log_header("Automation Trigger Tests (Medication Added)")
|
|
11
|
+
|
|
12
|
+
// Create automation triggers for different scenarios
|
|
13
|
+
|
|
14
|
+
// T1: No filters — fires for any medication
|
|
15
|
+
const t1 = await sdk.api.automation_triggers.createOne({
|
|
16
|
+
event: { type: 'Medication Added', info: { titles: [], protocols: [] } },
|
|
17
|
+
action: { type: 'Add Tags', info: { tags: ['Med-Any'] }},
|
|
18
|
+
status: 'Active',
|
|
19
|
+
title: "Medication - Any"
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
// T2: Title filter only
|
|
23
|
+
const t2 = await sdk.api.automation_triggers.createOne({
|
|
24
|
+
event: { type: 'Medication Added', info: { titles: ['Lisinopril'], protocols: [] } },
|
|
25
|
+
action: { type: 'Add Tags', info: { tags: ['Med-Title-Match'] }},
|
|
26
|
+
status: 'Active',
|
|
27
|
+
title: "Medication - Title Match"
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
// T3: Protocol filter only
|
|
31
|
+
const t3 = await sdk.api.automation_triggers.createOne({
|
|
32
|
+
event: { type: 'Medication Added', info: { titles: [], protocols: ['Weight Loss'] } },
|
|
33
|
+
action: { type: 'Add Tags', info: { tags: ['Med-Protocol-Match'] }},
|
|
34
|
+
status: 'Active',
|
|
35
|
+
title: "Medication - Protocol Match"
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// T4: Title + protocol filter
|
|
39
|
+
const t4 = await sdk.api.automation_triggers.createOne({
|
|
40
|
+
event: { type: 'Medication Added', info: { titles: ['Metformin'], protocols: ['Diabetes'] } },
|
|
41
|
+
action: { type: 'Add Tags', info: { tags: ['Med-Title-And-Protocol'] }},
|
|
42
|
+
status: 'Active',
|
|
43
|
+
title: "Medication - Title and Protocol"
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
// T5: Protocol filter that won't match
|
|
47
|
+
const t5 = await sdk.api.automation_triggers.createOne({
|
|
48
|
+
event: { type: 'Medication Added', info: { titles: [], protocols: ['Dermatology'] } },
|
|
49
|
+
action: { type: 'Add Tags', info: { tags: ['Med-Derm-Protocol'] }},
|
|
50
|
+
status: 'Active',
|
|
51
|
+
title: "Medication - Dermatology Protocol"
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
// Create separate endusers to avoid trigger throttling (1 minute per trigger per enduser)
|
|
55
|
+
const enduser1 = await sdk.api.endusers.createOne({})
|
|
56
|
+
const enduser2 = await sdk.api.endusers.createOne({})
|
|
57
|
+
const enduser3 = await sdk.api.endusers.createOne({})
|
|
58
|
+
const enduser4 = await sdk.api.endusers.createOne({})
|
|
59
|
+
const enduser5 = await sdk.api.endusers.createOne({})
|
|
60
|
+
const enduser6 = await sdk.api.endusers.createOne({})
|
|
61
|
+
|
|
62
|
+
// Test 1: Any medication — empty titles + empty protocols → fires for any medication
|
|
63
|
+
const med1 = await sdk.api.enduser_medications.createOne({
|
|
64
|
+
enduserId: enduser1.id,
|
|
65
|
+
title: 'Aspirin',
|
|
66
|
+
})
|
|
67
|
+
await wait(undefined, 500)
|
|
68
|
+
await async_test(
|
|
69
|
+
"Medication Added - Any medication (no filters)",
|
|
70
|
+
() => sdk.api.endusers.getOne(enduser1.id),
|
|
71
|
+
{ onResult: (e: Enduser) => !!e.tags?.includes('Med-Any') }
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
// Test 2: Title filter only — matching title, no protocol filter → fires
|
|
75
|
+
const med2 = await sdk.api.enduser_medications.createOne({
|
|
76
|
+
enduserId: enduser2.id,
|
|
77
|
+
title: 'Lisinopril',
|
|
78
|
+
})
|
|
79
|
+
await wait(undefined, 500)
|
|
80
|
+
await async_test(
|
|
81
|
+
"Medication Added - Title filter match",
|
|
82
|
+
() => sdk.api.endusers.getOne(enduser2.id),
|
|
83
|
+
{ onResult: (e: Enduser) => !!e.tags?.includes('Med-Title-Match') }
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
// Test 3: Protocol filter only — matching protocol, no title filter → fires
|
|
87
|
+
const med3 = await sdk.api.enduser_medications.createOne({
|
|
88
|
+
enduserId: enduser3.id,
|
|
89
|
+
title: 'Semaglutide',
|
|
90
|
+
protocol: 'Weight Loss',
|
|
91
|
+
})
|
|
92
|
+
await wait(undefined, 500)
|
|
93
|
+
await async_test(
|
|
94
|
+
"Medication Added - Protocol filter match",
|
|
95
|
+
() => sdk.api.endusers.getOne(enduser3.id),
|
|
96
|
+
{ onResult: (e: Enduser) => !!e.tags?.includes('Med-Protocol-Match') }
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
// Test 4: Title + protocol filter — both match → fires
|
|
100
|
+
const med4 = await sdk.api.enduser_medications.createOne({
|
|
101
|
+
enduserId: enduser4.id,
|
|
102
|
+
title: 'Metformin',
|
|
103
|
+
protocol: 'Diabetes',
|
|
104
|
+
})
|
|
105
|
+
await wait(undefined, 500)
|
|
106
|
+
await async_test(
|
|
107
|
+
"Medication Added - Title and protocol filter match",
|
|
108
|
+
() => sdk.api.endusers.getOne(enduser4.id),
|
|
109
|
+
{ onResult: (e: Enduser) => !!e.tags?.includes('Med-Title-And-Protocol') }
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
// Test 5: Non-matching protocol — protocol filter doesn't match → does NOT fire
|
|
113
|
+
const med5 = await sdk.api.enduser_medications.createOne({
|
|
114
|
+
enduserId: enduser5.id,
|
|
115
|
+
title: 'Ibuprofen',
|
|
116
|
+
protocol: 'Pain Management',
|
|
117
|
+
})
|
|
118
|
+
await wait(undefined, 500)
|
|
119
|
+
await async_test(
|
|
120
|
+
"Medication Added - Non-matching protocol does NOT fire",
|
|
121
|
+
() => sdk.api.endusers.getOne(enduser5.id),
|
|
122
|
+
{ onResult: (e: Enduser) => !!e.tags?.includes('Med-Any') && !e.tags?.includes('Med-Derm-Protocol') }
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
// Test 6: No protocol on medication — trigger has protocol filter, medication has no protocol → does NOT fire
|
|
126
|
+
const med6 = await sdk.api.enduser_medications.createOne({
|
|
127
|
+
enduserId: enduser6.id,
|
|
128
|
+
title: 'Amoxicillin',
|
|
129
|
+
})
|
|
130
|
+
await wait(undefined, 500)
|
|
131
|
+
await async_test(
|
|
132
|
+
"Medication Added - No protocol on med, protocol filter does NOT fire",
|
|
133
|
+
() => sdk.api.endusers.getOne(enduser6.id),
|
|
134
|
+
{ onResult: (e: Enduser) => !!e.tags?.includes('Med-Any') && !e.tags?.includes('Med-Protocol-Match') && !e.tags?.includes('Med-Derm-Protocol') }
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
// Clean up test data - triggers first
|
|
139
|
+
await sdk.api.automation_triggers.deleteOne(t1.id)
|
|
140
|
+
await sdk.api.automation_triggers.deleteOne(t2.id)
|
|
141
|
+
await sdk.api.automation_triggers.deleteOne(t3.id)
|
|
142
|
+
await sdk.api.automation_triggers.deleteOne(t4.id)
|
|
143
|
+
await sdk.api.automation_triggers.deleteOne(t5.id)
|
|
144
|
+
|
|
145
|
+
// Clean up endusers (also cleans up medications)
|
|
146
|
+
await sdk.api.endusers.deleteOne(enduser1.id)
|
|
147
|
+
await sdk.api.endusers.deleteOne(enduser2.id)
|
|
148
|
+
await sdk.api.endusers.deleteOne(enduser3.id)
|
|
149
|
+
await sdk.api.endusers.deleteOne(enduser4.id)
|
|
150
|
+
await sdk.api.endusers.deleteOne(enduser5.id)
|
|
151
|
+
await sdk.api.endusers.deleteOne(enduser6.id)
|
|
152
|
+
} finally {}
|
|
153
|
+
|
|
154
|
+
// ---- Beluga Webhook Integration Test ----
|
|
155
|
+
log_header("Beluga RX_WRITTEN Webhook Integration Test (Protocol)")
|
|
156
|
+
|
|
157
|
+
// Create a form with belugaVisitType set (this becomes the protocol)
|
|
158
|
+
const belugaForm = await sdk.api.forms.createOne({
|
|
159
|
+
title: 'Beluga Protocol Test Form',
|
|
160
|
+
belugaVisitType: 'Weight Loss',
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
const belugaEnduser = await sdk.api.endusers.createOne({})
|
|
164
|
+
|
|
165
|
+
// Create a form response that the webhook can look up by masterId
|
|
166
|
+
const belugaFormResponse = await sdk.api.form_responses.createOne({
|
|
167
|
+
formId: belugaForm.id,
|
|
168
|
+
enduserId: belugaEnduser.id,
|
|
169
|
+
formTitle: belugaForm.title,
|
|
170
|
+
responses: [{
|
|
171
|
+
fieldId: PLACEHOLDER_ID,
|
|
172
|
+
fieldTitle: 'placeholder',
|
|
173
|
+
answer: { type: 'string', value: 'test' },
|
|
174
|
+
}],
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
// Create a trigger that filters on protocol 'Weight Loss'
|
|
178
|
+
const belugaTrigger = await sdk.api.automation_triggers.createOne({
|
|
179
|
+
event: { type: 'Medication Added', info: { titles: [], protocols: ['Weight Loss'] } },
|
|
180
|
+
action: { type: 'Add Tags', info: { tags: ['Med-Beluga-Protocol'] }},
|
|
181
|
+
status: 'Active',
|
|
182
|
+
title: "Medication - Beluga Protocol Test"
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
// Simulate the Beluga RX_WRITTEN webhook
|
|
186
|
+
const webhookResponse = await fetch(`${host}/v1/webhooks/beluga`, {
|
|
187
|
+
method: 'POST',
|
|
188
|
+
headers: { 'Content-Type': 'application/json' },
|
|
189
|
+
body: JSON.stringify({
|
|
190
|
+
masterId: `tellescope_${belugaFormResponse.id}`,
|
|
191
|
+
event: 'RX_WRITTEN',
|
|
192
|
+
docName: 'Dr. Test',
|
|
193
|
+
medsPrescribed: [{
|
|
194
|
+
name: 'Semaglutide',
|
|
195
|
+
strength: '0.25mg',
|
|
196
|
+
refills: '3',
|
|
197
|
+
quantity: '1',
|
|
198
|
+
medId: 'test-ndc-123',
|
|
199
|
+
rxId: 'test-rx-456',
|
|
200
|
+
}],
|
|
201
|
+
}),
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
if (!webhookResponse.ok) {
|
|
205
|
+
throw new Error(`Beluga webhook failed with status ${webhookResponse.status}: ${await webhookResponse.text()}`)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
await wait(undefined, 500)
|
|
209
|
+
|
|
210
|
+
// Verify the trigger fired (enduser got the tag)
|
|
211
|
+
await async_test(
|
|
212
|
+
"Beluga RX_WRITTEN - Protocol trigger fires",
|
|
213
|
+
() => sdk.api.endusers.getOne(belugaEnduser.id),
|
|
214
|
+
{ onResult: (e: Enduser) => !!e.tags?.includes('Med-Beluga-Protocol') }
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
// Verify the medication was created with correct protocol and source
|
|
218
|
+
const belugaMeds = await sdk.api.enduser_medications.getSome({ filter: { enduserId: belugaEnduser.id } })
|
|
219
|
+
const belugaMed = belugaMeds[0]
|
|
220
|
+
await async_test(
|
|
221
|
+
"Beluga RX_WRITTEN - Medication has protocol from form belugaVisitType",
|
|
222
|
+
async () => belugaMed,
|
|
223
|
+
{ onResult: (m: EnduserMedication) => m.protocol === 'Weight Loss' && m.source === 'Beluga' && m.title === 'Semaglutide' }
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
try {
|
|
227
|
+
// Clean up Beluga test data
|
|
228
|
+
await sdk.api.automation_triggers.deleteOne(belugaTrigger.id)
|
|
229
|
+
await sdk.api.forms.deleteOne(belugaForm.id)
|
|
230
|
+
await sdk.api.endusers.deleteOne(belugaEnduser.id) // also cleans up form response and medications
|
|
231
|
+
} finally {}
|
|
232
|
+
|
|
233
|
+
// ---- Set Fields with {{medication.name}} Test ----
|
|
234
|
+
log_header("Medication Added - Set Fields with {{medication.name}}")
|
|
235
|
+
|
|
236
|
+
const setFieldsTrigger = await sdk.api.automation_triggers.createOne({
|
|
237
|
+
event: { type: 'Medication Added', info: { titles: [], protocols: [] } },
|
|
238
|
+
action: { type: 'Set Fields', info: { fields: [{ name: 'Medication Name', type: 'Custom Value' as const, value: '{{medication.name}}' }] }},
|
|
239
|
+
status: 'Active',
|
|
240
|
+
title: "Medication - Set Fields medication.name"
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
const setFieldsEnduser = await sdk.api.endusers.createOne({})
|
|
244
|
+
|
|
245
|
+
const setFieldsMed = await sdk.api.enduser_medications.createOne({
|
|
246
|
+
enduserId: setFieldsEnduser.id,
|
|
247
|
+
title: 'Lisinopril 10mg',
|
|
248
|
+
})
|
|
249
|
+
await wait(undefined, 500)
|
|
250
|
+
|
|
251
|
+
await async_test(
|
|
252
|
+
"Medication Added - Set Fields copies medication.name to enduser field",
|
|
253
|
+
() => sdk.api.endusers.getOne(setFieldsEnduser.id),
|
|
254
|
+
{ onResult: (e: Enduser) => e.fields?.['Medication Name'] === 'Lisinopril 10mg' }
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
// Test with title-filtered trigger to verify medication context is passed correctly
|
|
258
|
+
const setFieldsTriggerFiltered = await sdk.api.automation_triggers.createOne({
|
|
259
|
+
event: { type: 'Medication Added', info: { titles: ['Metformin 500mg'], protocols: [] } },
|
|
260
|
+
action: { type: 'Set Fields', info: { fields: [{ name: 'Specific Med', type: 'Custom Value' as const, value: '{{medication.name}}' }] }},
|
|
261
|
+
status: 'Active',
|
|
262
|
+
title: "Medication - Set Fields filtered"
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
const setFieldsEnduser2 = await sdk.api.endusers.createOne({})
|
|
266
|
+
|
|
267
|
+
const setFieldsMed2 = await sdk.api.enduser_medications.createOne({
|
|
268
|
+
enduserId: setFieldsEnduser2.id,
|
|
269
|
+
title: 'Metformin 500mg',
|
|
270
|
+
})
|
|
271
|
+
await wait(undefined, 500)
|
|
272
|
+
|
|
273
|
+
await async_test(
|
|
274
|
+
"Medication Added - Set Fields with title filter copies medication.name",
|
|
275
|
+
() => sdk.api.endusers.getOne(setFieldsEnduser2.id),
|
|
276
|
+
{ onResult: (e: Enduser) => e.fields?.['Specific Med'] === 'Metformin 500mg' }
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
try {
|
|
280
|
+
await sdk.api.automation_triggers.deleteOne(setFieldsTrigger.id)
|
|
281
|
+
await sdk.api.automation_triggers.deleteOne(setFieldsTriggerFiltered.id)
|
|
282
|
+
await sdk.api.endusers.deleteOne(setFieldsEnduser.id)
|
|
283
|
+
await sdk.api.endusers.deleteOne(setFieldsEnduser2.id)
|
|
284
|
+
} finally {}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Allow running this test file independently
|
|
288
|
+
if (require.main === module) {
|
|
289
|
+
const sdk = new Session({ host })
|
|
290
|
+
const sdkNonAdmin = new Session({ host })
|
|
291
|
+
|
|
292
|
+
const runTests = async () => {
|
|
293
|
+
await setup_tests(sdk, sdkNonAdmin)
|
|
294
|
+
await medication_added_trigger_tests({ sdk, sdkNonAdmin })
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
runTests()
|
|
298
|
+
.then(() => {
|
|
299
|
+
console.log("✅ Medication Added trigger tests completed successfully")
|
|
300
|
+
process.exit(0)
|
|
301
|
+
})
|
|
302
|
+
.catch((error) => {
|
|
303
|
+
console.error("❌ Medication Added trigger tests failed:", error)
|
|
304
|
+
process.exit(1)
|
|
305
|
+
})
|
|
306
|
+
}
|