@tellescope/sdk 1.247.0 → 1.249.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/.env +3 -0
- package/lib/cjs/sdk.d.ts +7 -1
- 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/chats_analytics.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/chats_analytics.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/chats_analytics.test.js +256 -0
- package/lib/cjs/tests/api_tests/chats_analytics.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/cross_org_api_key.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/cross_org_api_key.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/cross_org_api_key.test.js +748 -0
- package/lib/cjs/tests/api_tests/cross_org_api_key.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/date_string_validation.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/date_string_validation.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/date_string_validation.test.js +142 -0
- package/lib/cjs/tests/api_tests/date_string_validation.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/enduser_session_invalidation.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/enduser_session_invalidation.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/enduser_session_invalidation.test.js +667 -0
- package/lib/cjs/tests/api_tests/enduser_session_invalidation.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/eom_billing_codes.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/eom_billing_codes.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/eom_billing_codes.test.js +162 -0
- package/lib/cjs/tests/api_tests/eom_billing_codes.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/eom_procedure_codes.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/eom_procedure_codes.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/eom_procedure_codes.test.js +339 -0
- package/lib/cjs/tests/api_tests/eom_procedure_codes.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/field_redaction.test.d.ts +13 -0
- package/lib/cjs/tests/api_tests/field_redaction.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/field_redaction.test.js +818 -0
- package/lib/cjs/tests/api_tests/field_redaction.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/form_submitted_trigger.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/form_submitted_trigger.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/form_submitted_trigger.test.js +429 -0
- package/lib/cjs/tests/api_tests/form_submitted_trigger.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/integrations_redacted.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/integrations_redacted.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/integrations_redacted.test.js +273 -0
- package/lib/cjs/tests/api_tests/integrations_redacted.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/managed_content_file_access.test.d.ts +13 -0
- package/lib/cjs/tests/api_tests/managed_content_file_access.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/managed_content_file_access.test.js +385 -0
- package/lib/cjs/tests/api_tests/managed_content_file_access.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/openloop_webhooks.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/openloop_webhooks.test.js +108 -24
- package/lib/cjs/tests/api_tests/openloop_webhooks.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/organization_settings_duplicates.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/organization_settings_duplicates.test.js +25 -2
- package/lib/cjs/tests/api_tests/organization_settings_duplicates.test.js.map +1 -1
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +310 -183
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/sdk.d.ts +9 -3
- 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/session.d.ts +1 -0
- package/lib/esm/session.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/chats_analytics.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/chats_analytics.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/chats_analytics.test.js +252 -0
- package/lib/esm/tests/api_tests/chats_analytics.test.js.map +1 -0
- package/lib/esm/tests/api_tests/cross_org_api_key.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/cross_org_api_key.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/cross_org_api_key.test.js +744 -0
- package/lib/esm/tests/api_tests/cross_org_api_key.test.js.map +1 -0
- package/lib/esm/tests/api_tests/date_string_validation.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/date_string_validation.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/date_string_validation.test.js +138 -0
- package/lib/esm/tests/api_tests/date_string_validation.test.js.map +1 -0
- package/lib/esm/tests/api_tests/enduser_session_invalidation.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/enduser_session_invalidation.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/enduser_session_invalidation.test.js +663 -0
- package/lib/esm/tests/api_tests/enduser_session_invalidation.test.js.map +1 -0
- package/lib/esm/tests/api_tests/eom_billing_codes.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/eom_billing_codes.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/eom_billing_codes.test.js +158 -0
- package/lib/esm/tests/api_tests/eom_billing_codes.test.js.map +1 -0
- package/lib/esm/tests/api_tests/eom_procedure_codes.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/eom_procedure_codes.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/eom_procedure_codes.test.js +335 -0
- package/lib/esm/tests/api_tests/eom_procedure_codes.test.js.map +1 -0
- package/lib/esm/tests/api_tests/field_redaction.test.d.ts +13 -0
- package/lib/esm/tests/api_tests/field_redaction.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/field_redaction.test.js +814 -0
- package/lib/esm/tests/api_tests/field_redaction.test.js.map +1 -0
- package/lib/esm/tests/api_tests/form_submitted_trigger.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/form_submitted_trigger.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/form_submitted_trigger.test.js +425 -0
- package/lib/esm/tests/api_tests/form_submitted_trigger.test.js.map +1 -0
- package/lib/esm/tests/api_tests/integrations_redacted.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/integrations_redacted.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/integrations_redacted.test.js +269 -0
- package/lib/esm/tests/api_tests/integrations_redacted.test.js.map +1 -0
- package/lib/esm/tests/api_tests/managed_content_file_access.test.d.ts +13 -0
- package/lib/esm/tests/api_tests/managed_content_file_access.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/managed_content_file_access.test.js +358 -0
- package/lib/esm/tests/api_tests/managed_content_file_access.test.js.map +1 -0
- package/lib/esm/tests/api_tests/openloop_webhooks.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/openloop_webhooks.test.js +108 -24
- package/lib/esm/tests/api_tests/openloop_webhooks.test.js.map +1 -1
- package/lib/esm/tests/api_tests/organization_settings_duplicates.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/organization_settings_duplicates.test.js +25 -2
- package/lib/esm/tests/api_tests/organization_settings_duplicates.test.js.map +1 -1
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +310 -183
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/sdk.ts +14 -0
- package/src/tests/api_tests/chats_analytics.test.ts +182 -0
- package/src/tests/api_tests/cross_org_api_key.test.ts +665 -0
- package/src/tests/api_tests/date_string_validation.test.ts +107 -0
- package/src/tests/api_tests/enduser_session_invalidation.test.ts +361 -0
- package/src/tests/api_tests/eom_procedure_codes.test.ts +296 -0
- package/src/tests/api_tests/field_redaction.test.ts +669 -0
- package/src/tests/api_tests/form_started_trigger.test.ts +1 -1
- package/src/tests/api_tests/form_submitted_trigger.test.ts +281 -0
- package/src/tests/api_tests/integrations_redacted.test.ts +245 -0
- package/src/tests/api_tests/managed_content_file_access.test.ts +214 -0
- package/src/tests/api_tests/openloop_webhooks.test.ts +64 -0
- package/src/tests/api_tests/organization_settings_duplicates.test.ts +14 -0
- package/src/tests/tests.ts +95 -7
- package/test_generated.pdf +0 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
require('source-map-support').install();
|
|
2
|
+
|
|
3
|
+
import * as buffer from 'buffer'
|
|
4
|
+
import { Session, EnduserSession } from "../../sdk"
|
|
5
|
+
import {
|
|
6
|
+
async_test,
|
|
7
|
+
log_header,
|
|
8
|
+
} from "@tellescope/testing"
|
|
9
|
+
import { setup_tests } from "../setup"
|
|
10
|
+
|
|
11
|
+
const host = process.env.API_URL || 'http://localhost:8080' as const
|
|
12
|
+
const businessId = '60398b1131a295e64f084ff6'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Tests for file_download_URL enduser access via managed content fallback.
|
|
16
|
+
*
|
|
17
|
+
* Verifies the backend fallback logic that allows endusers to access files
|
|
18
|
+
* attached to managed content records they have access to, even when the
|
|
19
|
+
* file itself does not have enduserId set or publicRead: true.
|
|
20
|
+
*/
|
|
21
|
+
export const managed_content_file_access_tests = async ({ sdk, sdkNonAdmin }: { sdk: Session, sdkNonAdmin: Session }) => {
|
|
22
|
+
log_header("Managed Content File Access Tests")
|
|
23
|
+
|
|
24
|
+
const contentRecordIds: string[] = []
|
|
25
|
+
const assignmentIds: string[] = []
|
|
26
|
+
const fileIds: string[] = []
|
|
27
|
+
let testEnduserId: string | undefined
|
|
28
|
+
let otherEnduserId: string | undefined
|
|
29
|
+
let enduserSDK: EnduserSession | undefined
|
|
30
|
+
let otherEnduserSDK: EnduserSession | undefined
|
|
31
|
+
|
|
32
|
+
const uploadFile = async (
|
|
33
|
+
name: string,
|
|
34
|
+
opts: { enduserId?: string, publicRead?: boolean } = {}
|
|
35
|
+
) => {
|
|
36
|
+
const buff = buffer.Buffer.from(`test file content for ${name}`)
|
|
37
|
+
const { presignedUpload, file } = await sdk.api.files.prepare_file_upload({
|
|
38
|
+
name,
|
|
39
|
+
type: 'text/plain',
|
|
40
|
+
size: buff.byteLength,
|
|
41
|
+
...opts,
|
|
42
|
+
})
|
|
43
|
+
await sdk.UPLOAD(presignedUpload as any, buff)
|
|
44
|
+
await sdk.api.files.confirm_file_upload({ id: file.id })
|
|
45
|
+
fileIds.push(file.id)
|
|
46
|
+
return file
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
console.log("Setting up test data...")
|
|
51
|
+
|
|
52
|
+
const testEnduser = await sdk.api.endusers.createOne({
|
|
53
|
+
email: `mcr_file_access_test_${Date.now()}@test.tellescope.com`,
|
|
54
|
+
})
|
|
55
|
+
testEnduserId = testEnduser.id
|
|
56
|
+
await sdk.api.endusers.set_password({ id: testEnduser.id, password: 'TestPassword123!' })
|
|
57
|
+
|
|
58
|
+
const otherEnduser = await sdk.api.endusers.createOne({
|
|
59
|
+
email: `mcr_file_access_other_${Date.now()}@test.tellescope.com`,
|
|
60
|
+
})
|
|
61
|
+
otherEnduserId = otherEnduser.id
|
|
62
|
+
await sdk.api.endusers.set_password({ id: otherEnduser.id, password: 'TestPassword123!' })
|
|
63
|
+
|
|
64
|
+
enduserSDK = new EnduserSession({ host, businessId })
|
|
65
|
+
await enduserSDK.authenticate(testEnduser.email!, 'TestPassword123!')
|
|
66
|
+
|
|
67
|
+
otherEnduserSDK = new EnduserSession({ host, businessId })
|
|
68
|
+
await otherEnduserSDK.authenticate(otherEnduser.email!, 'TestPassword123!')
|
|
69
|
+
|
|
70
|
+
// ===== Test 1: File attached to assignmentType: 'All' content - enduser CAN access =====
|
|
71
|
+
const fileForAll = await uploadFile('mcr-file-all.txt')
|
|
72
|
+
const contentAll = await sdk.api.managed_content_records.createOne({
|
|
73
|
+
title: 'MCR File Access - All',
|
|
74
|
+
htmlContent: '<p>All</p>',
|
|
75
|
+
textContent: 'All',
|
|
76
|
+
assignmentType: 'All',
|
|
77
|
+
attachments: [{ secureName: fileForAll.secureName, type: 'file', name: fileForAll.name }],
|
|
78
|
+
})
|
|
79
|
+
contentRecordIds.push(contentAll.id)
|
|
80
|
+
|
|
81
|
+
await async_test(
|
|
82
|
+
'staff-uploaded file in assignmentType:All content - enduser CAN access',
|
|
83
|
+
async () => {
|
|
84
|
+
const result = await enduserSDK!.api.files.file_download_URL({ secureName: fileForAll.secureName })
|
|
85
|
+
return !!result?.downloadURL
|
|
86
|
+
},
|
|
87
|
+
{ onResult: (r) => r === true }
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
// ===== Test 2: File attached to Individual content for enduser A - enduser B CANNOT access =====
|
|
91
|
+
const fileForIndividual = await uploadFile('mcr-file-individual.txt')
|
|
92
|
+
const contentIndividual = await sdk.api.managed_content_records.createOne({
|
|
93
|
+
title: 'MCR File Access - Individual',
|
|
94
|
+
htmlContent: '<p>Individual</p>',
|
|
95
|
+
textContent: 'Individual',
|
|
96
|
+
enduserId: testEnduser.id,
|
|
97
|
+
attachments: [{ secureName: fileForIndividual.secureName, type: 'file', name: fileForIndividual.name }],
|
|
98
|
+
})
|
|
99
|
+
contentRecordIds.push(contentIndividual.id)
|
|
100
|
+
|
|
101
|
+
await async_test(
|
|
102
|
+
'file attached to Individual content - assigned enduser CAN access',
|
|
103
|
+
async () => {
|
|
104
|
+
const result = await enduserSDK!.api.files.file_download_URL({ secureName: fileForIndividual.secureName })
|
|
105
|
+
return !!result?.downloadURL
|
|
106
|
+
},
|
|
107
|
+
{ onResult: (r) => r === true }
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
await async_test(
|
|
111
|
+
'file attached to Individual content - unassigned enduser CANNOT access',
|
|
112
|
+
async () => {
|
|
113
|
+
try {
|
|
114
|
+
await otherEnduserSDK!.api.files.file_download_URL({ secureName: fileForIndividual.secureName })
|
|
115
|
+
return false
|
|
116
|
+
} catch (err) {
|
|
117
|
+
return true
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
{ onResult: (r) => r === true }
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
// ===== Test 3: File not attached to any managed content - enduser CANNOT access =====
|
|
124
|
+
const fileNoContent = await uploadFile('mcr-file-no-content.txt')
|
|
125
|
+
|
|
126
|
+
await async_test(
|
|
127
|
+
'file not attached to any managed content - enduser CANNOT access',
|
|
128
|
+
async () => {
|
|
129
|
+
try {
|
|
130
|
+
await enduserSDK!.api.files.file_download_URL({ secureName: fileNoContent.secureName })
|
|
131
|
+
return false
|
|
132
|
+
} catch (err) {
|
|
133
|
+
return true
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{ onResult: (r) => r === true }
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
// ===== Test 4: File with enduserId set - existing behavior preserved =====
|
|
140
|
+
const fileWithEnduser = await uploadFile('mcr-file-with-enduser.txt', { enduserId: testEnduser.id })
|
|
141
|
+
|
|
142
|
+
await async_test(
|
|
143
|
+
'file with enduserId set - enduser CAN access (no fallback needed)',
|
|
144
|
+
async () => {
|
|
145
|
+
const result = await enduserSDK!.api.files.file_download_URL({ secureName: fileWithEnduser.secureName })
|
|
146
|
+
return !!result?.downloadURL
|
|
147
|
+
},
|
|
148
|
+
{ onResult: (r) => r === true }
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
// ===== Test 5: File with publicRead: true - existing behavior preserved =====
|
|
152
|
+
const filePublic = await uploadFile('mcr-file-public.txt', { publicRead: true })
|
|
153
|
+
|
|
154
|
+
await async_test(
|
|
155
|
+
'file with publicRead - enduser CAN access',
|
|
156
|
+
async () => {
|
|
157
|
+
const result = await enduserSDK!.api.files.file_download_URL({ secureName: filePublic.secureName })
|
|
158
|
+
return !!result?.downloadURL
|
|
159
|
+
},
|
|
160
|
+
{ onResult: (r) => r === true }
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
console.log("All Managed Content File Access tests passed!")
|
|
164
|
+
|
|
165
|
+
} finally {
|
|
166
|
+
console.log("Cleaning up test data...")
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
for (const assignmentId of assignmentIds) {
|
|
170
|
+
await sdk.api.managed_content_record_assignments.deleteOne(assignmentId).catch(() => {})
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
for (const recordId of contentRecordIds) {
|
|
174
|
+
await sdk.api.managed_content_records.deleteOne(recordId).catch(() => {})
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
for (const fileId of fileIds) {
|
|
178
|
+
await sdk.api.files.deleteOne(fileId).catch(() => {})
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (testEnduserId) {
|
|
182
|
+
await sdk.api.endusers.deleteOne(testEnduserId).catch(() => {})
|
|
183
|
+
}
|
|
184
|
+
if (otherEnduserId) {
|
|
185
|
+
await sdk.api.endusers.deleteOne(otherEnduserId).catch(() => {})
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
console.log("Cleanup completed")
|
|
189
|
+
} catch (error) {
|
|
190
|
+
console.error('Cleanup error:', error)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (require.main === module) {
|
|
196
|
+
console.log(`Using API URL: ${host}`)
|
|
197
|
+
const sdk = new Session({ host })
|
|
198
|
+
const sdkNonAdmin = new Session({ host })
|
|
199
|
+
|
|
200
|
+
const runTests = async () => {
|
|
201
|
+
await setup_tests(sdk, sdkNonAdmin)
|
|
202
|
+
await managed_content_file_access_tests({ sdk, sdkNonAdmin })
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
runTests()
|
|
206
|
+
.then(() => {
|
|
207
|
+
console.log("Managed content file access test suite completed successfully")
|
|
208
|
+
process.exit(0)
|
|
209
|
+
})
|
|
210
|
+
.catch((error) => {
|
|
211
|
+
console.error("Managed content file access test suite failed:", error)
|
|
212
|
+
process.exit(1)
|
|
213
|
+
})
|
|
214
|
+
}
|
|
@@ -144,6 +144,27 @@ export const openloop_webhooks_tests = async ({ sdk, sdkNonAdmin }: { sdk: Sessi
|
|
|
144
144
|
{ onResult: (r: boolean) => r === true }
|
|
145
145
|
)
|
|
146
146
|
|
|
147
|
+
await async_test(
|
|
148
|
+
'V1: order_confirmation maps program_code to protocol field',
|
|
149
|
+
async () => {
|
|
150
|
+
const orderNum = `ol-conf-protocol-${uid()}`
|
|
151
|
+
const res = await postV1(makeV1Confirmation({
|
|
152
|
+
patientID: healthieId1,
|
|
153
|
+
orderNumber: orderNum,
|
|
154
|
+
program_code: 'Weight-Loss',
|
|
155
|
+
}))
|
|
156
|
+
assert(res.status === 200, `Expected 200, got ${res.status}`)
|
|
157
|
+
|
|
158
|
+
const orders = await sdk.api.enduser_orders.getSome({
|
|
159
|
+
filter: { source: 'OpenLoop', externalId: orderNum }
|
|
160
|
+
})
|
|
161
|
+
assert(orders.length === 1, `Expected 1 order, got ${orders.length}`)
|
|
162
|
+
assert(orders[0].protocol === 'Weight-Loss', `protocol mismatch: ${orders[0].protocol}`)
|
|
163
|
+
return true
|
|
164
|
+
},
|
|
165
|
+
{ onResult: (r: boolean) => r === true }
|
|
166
|
+
)
|
|
167
|
+
|
|
147
168
|
await async_test(
|
|
148
169
|
'V1: order_confirmation idempotency - same order not duplicated',
|
|
149
170
|
async () => {
|
|
@@ -314,6 +335,28 @@ export const openloop_webhooks_tests = async ({ sdk, sdkNonAdmin }: { sdk: Sessi
|
|
|
314
335
|
{ onResult: (r: boolean) => r === true }
|
|
315
336
|
)
|
|
316
337
|
|
|
338
|
+
await async_test(
|
|
339
|
+
'V1: order_shipped maps program_code to protocol field',
|
|
340
|
+
async () => {
|
|
341
|
+
const orderNum = `ol-ship-protocol-${uid()}`
|
|
342
|
+
await postV1(makeV1Confirmation({ patientID: healthieId1, orderNumber: orderNum }))
|
|
343
|
+
const res = await postV1(makeV1Shipped({
|
|
344
|
+
patientID: healthieId1,
|
|
345
|
+
orderNumber: orderNum,
|
|
346
|
+
program_code: 'Diabetes',
|
|
347
|
+
}))
|
|
348
|
+
assert(res.status === 200, `Expected 200, got ${res.status}`)
|
|
349
|
+
|
|
350
|
+
const orders = await sdk.api.enduser_orders.getSome({
|
|
351
|
+
filter: { source: 'OpenLoop', externalId: orderNum }
|
|
352
|
+
})
|
|
353
|
+
assert(orders.length === 1, `Expected 1 order, got ${orders.length}`)
|
|
354
|
+
assert(orders[0].protocol === 'Diabetes', `protocol mismatch: ${orders[0].protocol}`)
|
|
355
|
+
return true
|
|
356
|
+
},
|
|
357
|
+
{ onResult: (r: boolean) => r === true }
|
|
358
|
+
)
|
|
359
|
+
|
|
317
360
|
// ===== SECTION D: V1 enduserId Isolation =====
|
|
318
361
|
log_header("V1 enduserId Isolation")
|
|
319
362
|
|
|
@@ -414,6 +457,27 @@ export const openloop_webhooks_tests = async ({ sdk, sdkNonAdmin }: { sdk: Sessi
|
|
|
414
457
|
{ onResult: (r: boolean) => r === true }
|
|
415
458
|
)
|
|
416
459
|
|
|
460
|
+
await async_test(
|
|
461
|
+
'V2: prescription-created maps program_code to protocol field',
|
|
462
|
+
async () => {
|
|
463
|
+
const orderNum = `v2-protocol-${uid()}`
|
|
464
|
+
const res = await postV2(makeV2Payload('prescription-created', {
|
|
465
|
+
id: orderNum,
|
|
466
|
+
patientId: healthieId1,
|
|
467
|
+
program_code: 'GLP-1',
|
|
468
|
+
}))
|
|
469
|
+
assert(res.status === 200, `Expected 200, got ${res.status}`)
|
|
470
|
+
|
|
471
|
+
const orders = await sdk.api.enduser_orders.getSome({
|
|
472
|
+
filter: { source: 'OpenLoop', externalId: orderNum }
|
|
473
|
+
})
|
|
474
|
+
assert(orders.length === 1, `Expected 1 order, got ${orders.length}`)
|
|
475
|
+
assert(orders[0].protocol === 'GLP-1', `protocol mismatch: ${orders[0].protocol}`)
|
|
476
|
+
return true
|
|
477
|
+
},
|
|
478
|
+
{ onResult: (r: boolean) => r === true }
|
|
479
|
+
)
|
|
480
|
+
|
|
417
481
|
await async_test(
|
|
418
482
|
'V2: prescription-shipped updates with carrier and tracking',
|
|
419
483
|
async () => {
|
|
@@ -176,6 +176,20 @@ export const organization_settings_duplicates_tests = async ({ sdk, sdkNonAdmin
|
|
|
176
176
|
},
|
|
177
177
|
}
|
|
178
178
|
}, { replaceObjectFields: true })
|
|
179
|
+
|
|
180
|
+
// === D. subdomain is readonly ===
|
|
181
|
+
const orgBefore = await sdk.api.organizations.getOne(orgId)
|
|
182
|
+
await async_test(
|
|
183
|
+
"subdomain field is readonly — update does not change persisted value",
|
|
184
|
+
async () => {
|
|
185
|
+
await sdk.api.organizations.updateOne(orgId, {
|
|
186
|
+
subdomain: `readonly-attempt-${Date.now()}`,
|
|
187
|
+
} as any).catch(() => undefined) // tolerate either silent-drop or unknown-field rejection
|
|
188
|
+
const orgAfter = await sdk.api.organizations.getOne(orgId)
|
|
189
|
+
return orgAfter.subdomain === orgBefore.subdomain
|
|
190
|
+
},
|
|
191
|
+
{ onResult: (unchanged: boolean) => unchanged === true }
|
|
192
|
+
)
|
|
179
193
|
}
|
|
180
194
|
|
|
181
195
|
// Allow running this test file independently
|
package/src/tests/tests.ts
CHANGED
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
|
|
37
37
|
import { Session, APIQuery, EnduserSession } from "../sdk"
|
|
38
38
|
import { enduser_observations_acknowledge_tests } from "./api_tests/enduser_observations_acknowledge.test"
|
|
39
|
+
import { integrations_redacted_tests } from "./api_tests/integrations_redacted.test"
|
|
39
40
|
import { get_some_projection_tests } from "./api_tests/get_some_projection.test"
|
|
40
41
|
import { mdb_sort_tests } from "./api_tests/mdb_sort.test"
|
|
41
42
|
import { create_user_notifications_trigger_tests } from "./api_tests/create_user_notifications_trigger.test"
|
|
@@ -73,26 +74,34 @@ import {
|
|
|
73
74
|
|
|
74
75
|
import fs from "fs"
|
|
75
76
|
import { load_inbox_data_tests } from "./api_tests/load_inbox_data.test";
|
|
77
|
+
import { eom_procedure_codes_tests } from "./api_tests/eom_procedure_codes.test";
|
|
78
|
+
import { cross_org_api_key_tests } from "./api_tests/cross_org_api_key.test";
|
|
76
79
|
import { custom_dashboards_tests } from "./api_tests/custom_dashboards.test";
|
|
77
80
|
import { message_assignment_trigger_tests } from "./api_tests/message_assignment_trigger.test";
|
|
78
81
|
import { time_tracks_tests, time_tracks_historical_tests, time_tracks_correction_tests, time_tracks_review_tests, time_tracks_lock_tests, time_tracks_edge_case_tests } from "./api_tests/time_tracks.test";
|
|
79
82
|
import { monthly_availability_restrictions_tests } from "./api_tests/monthly_availability_restrictions.test";
|
|
80
83
|
import { calendar_event_limits_tests } from "./api_tests/calendar_event_limits.test";
|
|
81
84
|
import { custom_aggregation_tests } from "./api_tests/custom_aggregation.test";
|
|
85
|
+
import { chats_analytics_tests } from "./api_tests/chats_analytics.test";
|
|
82
86
|
import { no_access_permission_checks_tests } from "./api_tests/no_access_permission_checks.test";
|
|
87
|
+
import { field_redaction_tests } from "./api_tests/field_redaction.test";
|
|
83
88
|
import { bulk_assignment_tests } from "./api_tests/bulk_assignment.test";
|
|
84
89
|
import { managed_content_enduser_access_tests } from "./api_tests/managed_content_enduser_access.test";
|
|
90
|
+
import { managed_content_file_access_tests } from "./api_tests/managed_content_file_access.test";
|
|
85
91
|
import { auto_merge_form_submission_tests } from "./api_tests/auto_merge_form_submission.test";
|
|
86
92
|
import { database_cascade_delete_tests } from "./api_tests/database_cascade_delete.test";
|
|
87
93
|
import { ai_conversations_tests } from "./api_tests/ai_conversations.test";
|
|
88
94
|
import { load_team_chat_tests } from "./api_tests/load_team_chat.test";
|
|
89
95
|
import { form_started_trigger_tests } from "./api_tests/form_started_trigger.test";
|
|
96
|
+
import { form_submitted_trigger_tests } from "./api_tests/form_submitted_trigger.test";
|
|
90
97
|
import { medication_added_trigger_tests } from "./api_tests/medication_added_trigger.test";
|
|
91
98
|
import { elation_user_id_tests } from "./api_tests/elation_user_id.test";
|
|
92
99
|
import { organization_settings_duplicates_tests } from "./api_tests/organization_settings_duplicates.test";
|
|
93
100
|
import { calendar_events_bulk_update_tests } from "./api_tests/calendar_events_bulk_update.test";
|
|
94
101
|
import { openloop_webhooks_tests } from "./api_tests/openloop_webhooks.test";
|
|
95
102
|
import { beluga_pharmacy_mappings_tests } from "./api_tests/beluga_pharmacy_mappings.test";
|
|
103
|
+
import { date_string_validation_tests } from "./api_tests/date_string_validation.test";
|
|
104
|
+
import { enduser_session_invalidation_tests } from "./api_tests/enduser_session_invalidation.test";
|
|
96
105
|
|
|
97
106
|
const UniquenessViolationMessage = 'Uniqueness Violation'
|
|
98
107
|
|
|
@@ -3429,6 +3438,12 @@ const order_status_equals_tests = async () => {
|
|
|
3429
3438
|
status: 'Active',
|
|
3430
3439
|
title: "Title Partial And Condition"
|
|
3431
3440
|
})
|
|
3441
|
+
const t9 = await sdk.api.automation_triggers.createOne({
|
|
3442
|
+
event: { type: 'Order Status Equals', info: { source: 'Source', status: "Update", protocols: ['Protocol-A'] } },
|
|
3443
|
+
action: { type: 'Add Tags', info: { tags: ['Protocol Match'] }},
|
|
3444
|
+
status: 'Active',
|
|
3445
|
+
title: "Protocol Condition"
|
|
3446
|
+
})
|
|
3432
3447
|
|
|
3433
3448
|
const e = await sdk.api.endusers.createOne({})
|
|
3434
3449
|
|
|
@@ -3610,6 +3625,38 @@ const order_status_equals_tests = async () => {
|
|
|
3610
3625
|
) }
|
|
3611
3626
|
)
|
|
3612
3627
|
|
|
3628
|
+
await sdk.api.enduser_orders.updateOne(u.id, { status: 'Toggle', externalId: "also avoid rate limit 7" })
|
|
3629
|
+
await sdk.api.enduser_orders.updateOne(u.id, { status: "Update", protocol: 'Protocol-Mismatch', externalId: 'avoid rate limiting 7' })
|
|
3630
|
+
await wait(undefined, 500) // allow triggers to happen
|
|
3631
|
+
await async_test(
|
|
3632
|
+
"Protocol no match (wrong protocol)",
|
|
3633
|
+
() => sdk.api.endusers.getOne(e.id),
|
|
3634
|
+
{ onResult: e => !!(
|
|
3635
|
+
e.tags?.length === 8
|
|
3636
|
+
&& !e.tags?.includes('Protocol Match')
|
|
3637
|
+
) }
|
|
3638
|
+
)
|
|
3639
|
+
|
|
3640
|
+
await sdk.api.enduser_orders.updateOne(u.id, { status: 'Toggle', externalId: "also avoid rate limit 8" })
|
|
3641
|
+
await sdk.api.enduser_orders.updateOne(u.id, { status: "Update", protocol: 'Protocol-A', externalId: 'avoid rate limiting 8' })
|
|
3642
|
+
await wait(undefined, 500) // allow triggers to happen
|
|
3643
|
+
await async_test(
|
|
3644
|
+
"Protocol match tag added",
|
|
3645
|
+
() => sdk.api.endusers.getOne(e.id),
|
|
3646
|
+
{ onResult: e => !!(
|
|
3647
|
+
e.tags?.length === 9
|
|
3648
|
+
&& e.tags?.includes('Source')
|
|
3649
|
+
&& e.tags?.includes('Fill')
|
|
3650
|
+
&& e.tags?.includes('Status Update')
|
|
3651
|
+
&& e.tags?.includes('Fill Update')
|
|
3652
|
+
&& e.tags?.includes('SKU Update')
|
|
3653
|
+
&& e.tags?.includes('SKU Partial Update')
|
|
3654
|
+
&& e.tags?.includes('Title Partial Update')
|
|
3655
|
+
&& e.tags?.includes('Title Partial And Update')
|
|
3656
|
+
&& e.tags?.includes('Protocol Match')
|
|
3657
|
+
) }
|
|
3658
|
+
)
|
|
3659
|
+
|
|
3613
3660
|
await Promise.all([
|
|
3614
3661
|
sdk.api.automation_triggers.deleteOne(t1.id),
|
|
3615
3662
|
sdk.api.automation_triggers.deleteOne(t2.id),
|
|
@@ -3619,6 +3666,7 @@ const order_status_equals_tests = async () => {
|
|
|
3619
3666
|
sdk.api.automation_triggers.deleteOne(t6.id),
|
|
3620
3667
|
sdk.api.automation_triggers.deleteOne(t7.id),
|
|
3621
3668
|
sdk.api.automation_triggers.deleteOne(t8.id),
|
|
3669
|
+
sdk.api.automation_triggers.deleteOne(t9.id),
|
|
3622
3670
|
sdk.api.endusers.deleteOne(e.id),
|
|
3623
3671
|
])
|
|
3624
3672
|
}
|
|
@@ -5016,8 +5064,8 @@ const trigger_events_api_tests = async () => {
|
|
|
5016
5064
|
const automation_trigger_tests = async () => {
|
|
5017
5065
|
log_header("Automation Trigger Tests")
|
|
5018
5066
|
|
|
5019
|
-
await medication_added_trigger_tests({ sdk, sdkNonAdmin })
|
|
5020
5067
|
await order_status_equals_tests()
|
|
5068
|
+
await medication_added_trigger_tests({ sdk, sdkNonAdmin })
|
|
5021
5069
|
await appointment_cancelled_tests()
|
|
5022
5070
|
await set_fields_tests()
|
|
5023
5071
|
await purchase_made_trigger_tests({ sdk, sdkNonAdmin })
|
|
@@ -8588,7 +8636,7 @@ export const formsort_tests = async () => {
|
|
|
8588
8636
|
const form = await sdk.api.forms.createOne({ title: "FormSort" })
|
|
8589
8637
|
|
|
8590
8638
|
const postToFormsort = async ({ matchByName=false, createNewEnduser=false, enduserId, returnJSON=false, ...o }: {
|
|
8591
|
-
answers: { key: string, value: any }[],
|
|
8639
|
+
answers: { key: string, value: any, label?: string }[],
|
|
8592
8640
|
responder_uuid: string,
|
|
8593
8641
|
finalized: boolean,
|
|
8594
8642
|
matchByName?: boolean,
|
|
@@ -8605,8 +8653,8 @@ export const formsort_tests = async () => {
|
|
|
8605
8653
|
return await axios.post(url.toString(), o)
|
|
8606
8654
|
}
|
|
8607
8655
|
|
|
8608
|
-
const postToFormsortGeneric = async ({ matchByName=false, createNewEnduser=false, ...o }: {
|
|
8609
|
-
answers: { key: string, value: any }[],
|
|
8656
|
+
const postToFormsortGeneric = async ({ matchByName=false, createNewEnduser=false, ...o }: {
|
|
8657
|
+
answers: { key: string, value: any, label?: string }[],
|
|
8610
8658
|
responder_uuid: string,
|
|
8611
8659
|
finalized: boolean,
|
|
8612
8660
|
matchByName?: boolean,
|
|
@@ -8985,6 +9033,37 @@ export const formsort_tests = async () => {
|
|
|
8985
9033
|
onResult: r => r?.fname === 'ChangedFirst' && r?.lname === 'ChangedLast'
|
|
8986
9034
|
})
|
|
8987
9035
|
|
|
9036
|
+
// Test label as fieldTitle
|
|
9037
|
+
const validateFieldTitle = (fr: { responses?: { externalId?: string, fieldTitle?: string }[] }, key: string, expectedTitle: string): boolean => {
|
|
9038
|
+
return fr.responses?.find(r => r.externalId === key)?.fieldTitle === expectedTitle
|
|
9039
|
+
}
|
|
9040
|
+
|
|
9041
|
+
// Label provided: fieldTitle should use label, externalId should use key
|
|
9042
|
+
await postToFormsort({
|
|
9043
|
+
answers: [
|
|
9044
|
+
{ key: 'email', value: 'label-test@tellescope.com' },
|
|
9045
|
+
{ key: 'label_test_key', value: 'test_value', label: 'My Custom Label' },
|
|
9046
|
+
],
|
|
9047
|
+
responder_uuid: "label-test",
|
|
9048
|
+
finalized: true,
|
|
9049
|
+
})
|
|
9050
|
+
await async_test(`label as fieldTitle`, () => sdk.api.form_responses.getOne({ externalId: 'label-test' }), {
|
|
9051
|
+
onResult: r => validateFieldTitle(r, 'label_test_key', 'My Custom Label')
|
|
9052
|
+
})
|
|
9053
|
+
|
|
9054
|
+
// No label: fieldTitle should fall back to key
|
|
9055
|
+
await postToFormsort({
|
|
9056
|
+
answers: [
|
|
9057
|
+
{ key: 'email', value: 'no-label-test@tellescope.com' },
|
|
9058
|
+
{ key: 'no_label_key', value: 'test_value' },
|
|
9059
|
+
],
|
|
9060
|
+
responder_uuid: "no-label-test",
|
|
9061
|
+
finalized: true,
|
|
9062
|
+
})
|
|
9063
|
+
await async_test(`no label falls back to key as fieldTitle`, () => sdk.api.form_responses.getOne({ externalId: 'no-label-test' }), {
|
|
9064
|
+
onResult: r => validateFieldTitle(r, 'no_label_key', 'no_label_key')
|
|
9065
|
+
})
|
|
9066
|
+
|
|
8988
9067
|
// cleanup
|
|
8989
9068
|
const endusers = await sdk.api.endusers.getSome()
|
|
8990
9069
|
await Promise.all([
|
|
@@ -14126,8 +14205,18 @@ const ip_address_form_tests = async () => {
|
|
|
14126
14205
|
await replace_enduser_template_values_tests()
|
|
14127
14206
|
await mfa_tests()
|
|
14128
14207
|
await setup_tests(sdk, sdkNonAdmin)
|
|
14129
|
-
await
|
|
14208
|
+
await eom_procedure_codes_tests({ sdk, sdkNonAdmin })
|
|
14209
|
+
await cross_org_api_key_tests({ sdk, sdkNonAdmin })
|
|
14130
14210
|
await organization_settings_duplicates_tests({ sdk, sdkNonAdmin })
|
|
14211
|
+
await enduser_session_invalidation_tests({ sdk, sdkNonAdmin })
|
|
14212
|
+
await chats_analytics_tests({ sdk, sdkNonAdmin })
|
|
14213
|
+
await field_redaction_tests({ sdk, sdkNonAdmin })
|
|
14214
|
+
await form_submitted_trigger_tests({ sdk, sdkNonAdmin })
|
|
14215
|
+
await date_string_validation_tests({ sdk, sdkNonAdmin })
|
|
14216
|
+
await openloop_webhooks_tests({ sdk, sdkNonAdmin })
|
|
14217
|
+
await automation_trigger_tests()
|
|
14218
|
+
await integrations_redacted_tests({ sdk, sdkNonAdmin })
|
|
14219
|
+
await mdb_sort_tests({ sdk, sdkNonAdmin })
|
|
14131
14220
|
await search_tests()
|
|
14132
14221
|
await time_tracks_tests({ sdk, sdkNonAdmin })
|
|
14133
14222
|
await time_tracks_historical_tests({ sdk, sdkNonAdmin })
|
|
@@ -14136,8 +14225,6 @@ const ip_address_form_tests = async () => {
|
|
|
14136
14225
|
await time_tracks_lock_tests({ sdk, sdkNonAdmin })
|
|
14137
14226
|
await time_tracks_edge_case_tests({ sdk, sdkNonAdmin })
|
|
14138
14227
|
await calendar_event_limits_tests({ sdk, sdkNonAdmin })
|
|
14139
|
-
await openloop_webhooks_tests({ sdk, sdkNonAdmin })
|
|
14140
|
-
await automation_trigger_tests()
|
|
14141
14228
|
await get_some_projection_tests({ sdk, sdkNonAdmin })
|
|
14142
14229
|
await elation_user_id_tests({ sdk, sdkNonAdmin })
|
|
14143
14230
|
await custom_dashboards_tests({ sdk, sdkNonAdmin })
|
|
@@ -14156,6 +14243,7 @@ const ip_address_form_tests = async () => {
|
|
|
14156
14243
|
await beluga_pharmacy_mappings_tests({ sdk, sdkNonAdmin })
|
|
14157
14244
|
await threadKeyTests()
|
|
14158
14245
|
await managed_content_enduser_access_tests({ sdk, sdkNonAdmin })
|
|
14246
|
+
await managed_content_file_access_tests({ sdk, sdkNonAdmin })
|
|
14159
14247
|
await afteraction_day_of_month_delay_tests({ sdk, sdkNonAdmin })
|
|
14160
14248
|
await bulk_assignment_tests({ sdk, sdkNonAdmin })
|
|
14161
14249
|
await formsort_tests()
|
package/test_generated.pdf
CHANGED
|
Binary file
|