@tellescope/sdk 1.255.18 → 1.256.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 +7 -2
- package/lib/cjs/sdk.d.ts.map +1 -1
- package/lib/cjs/sdk.js +1 -0
- package/lib/cjs/sdk.js.map +1 -1
- package/lib/cjs/tests/api_tests/auto_merge_form_submission.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/auto_merge_form_submission.test.js +18 -8
- package/lib/cjs/tests/api_tests/auto_merge_form_submission.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/custom_dashboards.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/custom_dashboards.test.js +99 -8
- package/lib/cjs/tests/api_tests/custom_dashboards.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/default_summary_journey.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/default_summary_journey.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/file_download_unicode_names.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/file_download_unicode_names.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/file_download_unicode_names.test.js +278 -0
- package/lib/cjs/tests/api_tests/file_download_unicode_names.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/healthie_multi_integration.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/healthie_multi_integration.test.js +203 -72
- package/lib/cjs/tests/api_tests/healthie_multi_integration.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/openloop_webhooks.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/openloop_webhooks.test.js +212 -33
- package/lib/cjs/tests/api_tests/openloop_webhooks.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/phone_calls_cold_transfer.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/phone_calls_cold_transfer.test.js +85 -9
- package/lib/cjs/tests/api_tests/phone_calls_cold_transfer.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/phone_calls_conference_hold.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/phone_calls_conference_hold.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/phone_calls_conference_hold.test.js +102 -0
- package/lib/cjs/tests/api_tests/phone_calls_conference_hold.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/scoped_api_keys.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/scoped_api_keys.test.js +84 -81
- package/lib/cjs/tests/api_tests/scoped_api_keys.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.d.ts +2 -0
- package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.js +242 -0
- package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.d.ts +29 -0
- package/lib/cjs/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.js +443 -0
- package/lib/cjs/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.d.ts +35 -0
- package/lib/cjs/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.js +231 -0
- package/lib/cjs/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.js +121 -78
- package/lib/cjs/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.js +1003 -0
- package/lib/cjs/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/enduser-ai-summary-trust-gate.test.d.ts +17 -0
- package/lib/cjs/tests/api_tests/security/enduser-ai-summary-trust-gate.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js +215 -0
- package/lib/cjs/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/formsort_webhook_auth_field_lock.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/security/formsort_webhook_auth_field_lock.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/formsort_webhook_auth_field_lock.test.js +1200 -0
- package/lib/cjs/tests/api_tests/security/formsort_webhook_auth_field_lock.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/public_endpoint_auth_field_lock.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/security/public_endpoint_auth_field_lock.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/public_endpoint_auth_field_lock.test.js +2330 -0
- package/lib/cjs/tests/api_tests/security/public_endpoint_auth_field_lock.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/tickets_bulk_assign_care_team.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/tickets_bulk_assign_care_team.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/tickets_bulk_assign_care_team.test.js +204 -0
- package/lib/cjs/tests/api_tests/tickets_bulk_assign_care_team.test.js.map +1 -0
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +489 -255
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/enduser.d.ts +0 -1
- package/lib/esm/enduser.d.ts.map +1 -1
- package/lib/esm/sdk.d.ts +9 -5
- package/lib/esm/sdk.d.ts.map +1 -1
- package/lib/esm/sdk.js +1 -0
- package/lib/esm/sdk.js.map +1 -1
- package/lib/esm/session.d.ts +0 -1
- package/lib/esm/session.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/auto_merge_form_submission.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/auto_merge_form_submission.test.js +18 -8
- package/lib/esm/tests/api_tests/auto_merge_form_submission.test.js.map +1 -1
- package/lib/esm/tests/api_tests/custom_dashboards.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/custom_dashboards.test.js +99 -8
- package/lib/esm/tests/api_tests/custom_dashboards.test.js.map +1 -1
- package/lib/esm/tests/api_tests/default_summary_journey.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/default_summary_journey.test.js.map +1 -0
- package/lib/esm/tests/api_tests/file_download_unicode_names.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/file_download_unicode_names.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/file_download_unicode_names.test.js +248 -0
- package/lib/esm/tests/api_tests/file_download_unicode_names.test.js.map +1 -0
- package/lib/esm/tests/api_tests/healthie_multi_integration.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/healthie_multi_integration.test.js +205 -74
- package/lib/esm/tests/api_tests/healthie_multi_integration.test.js.map +1 -1
- package/lib/esm/tests/api_tests/openloop_webhooks.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/openloop_webhooks.test.js +213 -34
- package/lib/esm/tests/api_tests/openloop_webhooks.test.js.map +1 -1
- package/lib/esm/tests/api_tests/phone_calls_cold_transfer.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/phone_calls_cold_transfer.test.js +85 -9
- package/lib/esm/tests/api_tests/phone_calls_cold_transfer.test.js.map +1 -1
- package/lib/esm/tests/api_tests/phone_calls_conference_hold.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/phone_calls_conference_hold.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/phone_calls_conference_hold.test.js +98 -0
- package/lib/esm/tests/api_tests/phone_calls_conference_hold.test.js.map +1 -0
- package/lib/esm/tests/api_tests/scoped_api_keys.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/scoped_api_keys.test.js +84 -81
- package/lib/esm/tests/api_tests/scoped_api_keys.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.d.ts +2 -0
- package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.js +238 -0
- package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.d.ts +29 -0
- package/lib/esm/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.js +436 -0
- package/lib/esm/tests/api_tests/security/F-0015-webhook-outbound-ssrf.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.d.ts +35 -0
- package/lib/esm/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.js +224 -0
- package/lib/esm/tests/api_tests/security/F-0025-proxy-image-unauth-ssrf.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.js +121 -78
- package/lib/esm/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.js +996 -0
- package/lib/esm/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/enduser-ai-summary-trust-gate.test.d.ts +17 -0
- package/lib/esm/tests/api_tests/security/enduser-ai-summary-trust-gate.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js +211 -0
- package/lib/esm/tests/api_tests/security/enduser-ai-summary-trust-gate.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/formsort_webhook_auth_field_lock.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/security/formsort_webhook_auth_field_lock.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/formsort_webhook_auth_field_lock.test.js +1193 -0
- package/lib/esm/tests/api_tests/security/formsort_webhook_auth_field_lock.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/public_endpoint_auth_field_lock.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/security/public_endpoint_auth_field_lock.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/public_endpoint_auth_field_lock.test.js +2323 -0
- package/lib/esm/tests/api_tests/security/public_endpoint_auth_field_lock.test.js.map +1 -0
- package/lib/esm/tests/api_tests/tickets_bulk_assign_care_team.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/tickets_bulk_assign_care_team.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/tickets_bulk_assign_care_team.test.js +200 -0
- package/lib/esm/tests/api_tests/tickets_bulk_assign_care_team.test.js.map +1 -0
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +489 -255
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/sdk.ts +4 -0
- package/src/tests/api_tests/auto_merge_form_submission.test.ts +13 -4
- package/src/tests/api_tests/custom_dashboards.test.ts +92 -0
- package/src/tests/api_tests/file_download_unicode_names.test.ts +223 -0
- package/src/tests/api_tests/healthie_multi_integration.test.ts +103 -5
- package/src/tests/api_tests/openloop_webhooks.test.ts +138 -0
- package/src/tests/api_tests/phone_calls_cold_transfer.test.ts +54 -0
- package/src/tests/api_tests/phone_calls_conference_hold.test.ts +62 -0
- package/src/tests/api_tests/scoped_api_keys.test.ts +5 -0
- package/src/tests/api_tests/security/F-0013-sanitize-user-html-with-iframes.test.ts +215 -0
- package/src/tests/api_tests/security/F-0106-F-0110-enduser-write-restrictions.test.ts +38 -4
- package/src/tests/api_tests/security/F-0166-allowed-paths-wildcard-bypass.test.ts +721 -0
- package/src/tests/api_tests/security/enduser-ai-summary-trust-gate.test.ts +125 -0
- package/src/tests/api_tests/security/formsort_webhook_auth_field_lock.test.ts +753 -0
- package/src/tests/api_tests/security/public_endpoint_auth_field_lock.test.ts +1707 -0
- package/src/tests/api_tests/tickets_bulk_assign_care_team.test.ts +132 -0
- package/src/tests/tests.ts +232 -2
- package/test_generated.pdf +0 -0
- package/.env +0 -13
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
require('source-map-support').install();
|
|
2
|
+
|
|
3
|
+
import { Session } from "../../sdk"
|
|
4
|
+
import {
|
|
5
|
+
async_test,
|
|
6
|
+
log_header,
|
|
7
|
+
} from "@tellescope/testing"
|
|
8
|
+
import { setup_tests } from "../setup"
|
|
9
|
+
|
|
10
|
+
const host = process.env.API_URL || 'http://localhost:8080' as const
|
|
11
|
+
|
|
12
|
+
// Main test function for tickets bulk_assign addToCareTeam flag
|
|
13
|
+
export const tickets_bulk_assign_care_team_tests = async ({ sdk, sdkNonAdmin } : { sdk: Session, sdkNonAdmin: Session }) => {
|
|
14
|
+
log_header("Tickets Bulk Assign (addToCareTeam) Tests")
|
|
15
|
+
|
|
16
|
+
// Throwaway user to act as the new ticket owner
|
|
17
|
+
const owner = await sdk.api.users.createOne({
|
|
18
|
+
email: `test-bulk-assign-owner-${Date.now()}@test.com`,
|
|
19
|
+
fname: 'BulkAssign',
|
|
20
|
+
lname: 'Owner',
|
|
21
|
+
verifiedEmail: true,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const enduser1 = await sdk.api.endusers.createOne({ fname: 'BulkAssign', lname: 'PatientOne' })
|
|
25
|
+
const enduser2 = await sdk.api.endusers.createOne({ fname: 'BulkAssign', lname: 'PatientTwo' })
|
|
26
|
+
|
|
27
|
+
// Tickets are created without an owner so the on-create care team side effect doesn't run
|
|
28
|
+
const ticket1 = await sdk.api.tickets.createOne({ title: 'Bulk Assign Test 1', enduserId: enduser1.id })
|
|
29
|
+
const ticket2 = await sdk.api.tickets.createOne({ title: 'Bulk Assign Test 2', enduserId: enduser1.id })
|
|
30
|
+
const ticket3 = await sdk.api.tickets.createOne({ title: 'Bulk Assign Test 3', enduserId: enduser2.id, skipCareTeamAssignment: true })
|
|
31
|
+
const ticketNoEnduser = await sdk.api.tickets.createOne({ title: 'Bulk Assign Test 4' })
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
// Default behavior (flag omitted): owner set, care team untouched
|
|
35
|
+
await async_test(
|
|
36
|
+
"bulk_assign: assigns owner without flag",
|
|
37
|
+
() => sdk.api.tickets.bulk_assign({ ids: [ticket1.id], userId: owner.id }),
|
|
38
|
+
{ onResult: () => true }
|
|
39
|
+
)
|
|
40
|
+
await async_test(
|
|
41
|
+
"bulk_assign: owner set on ticket (no flag)",
|
|
42
|
+
() => sdk.api.tickets.getOne(ticket1.id),
|
|
43
|
+
{ onResult: t => t.owner === owner.id }
|
|
44
|
+
)
|
|
45
|
+
await async_test(
|
|
46
|
+
"bulk_assign: care team unchanged without flag",
|
|
47
|
+
() => sdk.api.endusers.getOne(enduser1.id),
|
|
48
|
+
{ onResult: e => !e.assignedTo?.includes(owner.id) }
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
// addToCareTeam: false behaves like omitted
|
|
52
|
+
await async_test(
|
|
53
|
+
"bulk_assign: addToCareTeam false leaves care team unchanged",
|
|
54
|
+
async () => {
|
|
55
|
+
await sdk.api.tickets.bulk_assign({ ids: [ticket1.id], userId: owner.id, addToCareTeam: false })
|
|
56
|
+
return sdk.api.endusers.getOne(enduser1.id)
|
|
57
|
+
},
|
|
58
|
+
{ onResult: e => !e.assignedTo?.includes(owner.id) }
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
// addToCareTeam: true adds owner to each ticket's enduser care team,
|
|
62
|
+
// including tickets flagged skipCareTeamAssignment (explicit flag wins),
|
|
63
|
+
// and tolerates tickets with no enduser
|
|
64
|
+
await async_test(
|
|
65
|
+
"bulk_assign: addToCareTeam true assigns owner and updates care teams",
|
|
66
|
+
() => sdk.api.tickets.bulk_assign({
|
|
67
|
+
ids: [ticket1.id, ticket2.id, ticket3.id, ticketNoEnduser.id],
|
|
68
|
+
userId: owner.id,
|
|
69
|
+
addToCareTeam: true,
|
|
70
|
+
}),
|
|
71
|
+
{ onResult: () => true }
|
|
72
|
+
)
|
|
73
|
+
await async_test(
|
|
74
|
+
"bulk_assign: owner added to care team (enduser1)",
|
|
75
|
+
() => sdk.api.endusers.getOne(enduser1.id),
|
|
76
|
+
{ onResult: e => !!e.assignedTo?.includes(owner.id) }
|
|
77
|
+
)
|
|
78
|
+
await async_test(
|
|
79
|
+
"bulk_assign: owner added to care team despite skipCareTeamAssignment (enduser2)",
|
|
80
|
+
() => sdk.api.endusers.getOne(enduser2.id),
|
|
81
|
+
{ onResult: e => !!e.assignedTo?.includes(owner.id) }
|
|
82
|
+
)
|
|
83
|
+
await async_test(
|
|
84
|
+
"bulk_assign: ticket without enduser still assigned",
|
|
85
|
+
() => sdk.api.tickets.getOne(ticketNoEnduser.id),
|
|
86
|
+
{ onResult: t => t.owner === owner.id }
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
// Idempotent when owner already on care team
|
|
90
|
+
await async_test(
|
|
91
|
+
"bulk_assign: addToCareTeam is idempotent",
|
|
92
|
+
async () => {
|
|
93
|
+
await sdk.api.tickets.bulk_assign({ ids: [ticket1.id], userId: owner.id, addToCareTeam: true })
|
|
94
|
+
return sdk.api.endusers.getOne(enduser1.id)
|
|
95
|
+
},
|
|
96
|
+
{ onResult: e => e.assignedTo?.filter(id => id === owner.id).length === 1 }
|
|
97
|
+
)
|
|
98
|
+
} finally {
|
|
99
|
+
// Cleanup
|
|
100
|
+
await Promise.all([
|
|
101
|
+
sdk.api.tickets.deleteOne(ticket1.id).catch(console.error),
|
|
102
|
+
sdk.api.tickets.deleteOne(ticket2.id).catch(console.error),
|
|
103
|
+
sdk.api.tickets.deleteOne(ticket3.id).catch(console.error),
|
|
104
|
+
sdk.api.tickets.deleteOne(ticketNoEnduser.id).catch(console.error),
|
|
105
|
+
sdk.api.endusers.deleteOne(enduser1.id).catch(console.error),
|
|
106
|
+
sdk.api.endusers.deleteOne(enduser2.id).catch(console.error),
|
|
107
|
+
sdk.api.users.deleteOne(owner.id).catch(console.error),
|
|
108
|
+
])
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Allow running this test file independently
|
|
113
|
+
if (require.main === module) {
|
|
114
|
+
console.log(`🌐 Using API URL: ${host}`)
|
|
115
|
+
const sdk = new Session({ host })
|
|
116
|
+
const sdkNonAdmin = new Session({ host })
|
|
117
|
+
|
|
118
|
+
const runTests = async () => {
|
|
119
|
+
await setup_tests(sdk, sdkNonAdmin)
|
|
120
|
+
await tickets_bulk_assign_care_team_tests({ sdk, sdkNonAdmin })
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
runTests()
|
|
124
|
+
.then(() => {
|
|
125
|
+
console.log("✅ Tickets bulk assign care team test suite completed successfully")
|
|
126
|
+
process.exit(0)
|
|
127
|
+
})
|
|
128
|
+
.catch((error) => {
|
|
129
|
+
console.error("❌ Tickets bulk assign care team test suite failed:", error)
|
|
130
|
+
process.exit(1)
|
|
131
|
+
})
|
|
132
|
+
}
|
package/src/tests/tests.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
CompoundFilter,
|
|
18
18
|
CreateTicketActionInfo,
|
|
19
19
|
FormResponseValue,
|
|
20
|
+
JourneyContext,
|
|
20
21
|
ModelName,
|
|
21
22
|
RoundRobinAssignmentInfo,
|
|
22
23
|
User,
|
|
@@ -41,6 +42,7 @@ import { user_portal_settings_tests } from "./api_tests/user_portal_settings.tes
|
|
|
41
42
|
import { integrations_redacted_tests } from "./api_tests/integrations_redacted.test"
|
|
42
43
|
import { healthie_multi_integration_tests } from "./api_tests/healthie_multi_integration.test"
|
|
43
44
|
import { get_some_projection_tests } from "./api_tests/get_some_projection.test"
|
|
45
|
+
import { file_download_unicode_names_tests } from "./api_tests/file_download_unicode_names.test"
|
|
44
46
|
import { mdb_sort_tests } from "./api_tests/mdb_sort.test"
|
|
45
47
|
import { create_user_notifications_trigger_tests } from "./api_tests/create_user_notifications_trigger.test"
|
|
46
48
|
import { inbox_thread_assignment_updates_tests } from "./api_tests/inbox_thread_assignment_updates.test"
|
|
@@ -82,6 +84,7 @@ import {
|
|
|
82
84
|
import fs from "fs"
|
|
83
85
|
import { load_inbox_data_tests } from "./api_tests/load_inbox_data.test";
|
|
84
86
|
import { phone_calls_cold_transfer_tests } from "./api_tests/phone_calls_cold_transfer.test";
|
|
87
|
+
import { phone_calls_conference_hold_tests } from "./api_tests/phone_calls_conference_hold.test";
|
|
85
88
|
import { enduser_login_tests } from "./api_tests/enduser_login.test";
|
|
86
89
|
import { enduser_login_rate_limits_tests } from "./api_tests/enduser_login_rate_limits.test";
|
|
87
90
|
import { eom_procedure_codes_tests } from "./api_tests/eom_procedure_codes.test";
|
|
@@ -109,12 +112,18 @@ import { invite_user_enumeration_tests } from "./api_tests/security/F-0007-invit
|
|
|
109
112
|
import { register_business_id_injection_tests } from "./api_tests/security/register_business_id_injection.test";
|
|
110
113
|
import { handle_incoming_communication_cross_tenant_tests } from "./api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test";
|
|
111
114
|
import { sanitize_user_html_xss_tests } from "./api_tests/security/F-0013-sanitize-user-html.test";
|
|
115
|
+
import { sanitize_user_html_with_iframes_tests } from "./api_tests/security/F-0013-sanitize-user-html-with-iframes.test";
|
|
112
116
|
import { prototype_pollution_tests } from "./api_tests/security/F-0016-prototype-pollution.test";
|
|
113
117
|
import { enduser_cross_create_tests } from "./api_tests/security/F-0116-F-0119-enduser-cross-create.test";
|
|
114
118
|
import { globalunique_leak_tests } from "./api_tests/security/F-0145-globalunique-leak.test";
|
|
115
119
|
import { load_inbox_redaction_tests } from "./api_tests/security/F-0151-load-inbox-redaction.test";
|
|
116
120
|
import { webhook_timeout_tests } from "./api_tests/security/F-0155-webhook-timeout.test";
|
|
121
|
+
import { enduser_ai_summary_trust_gate_tests } from "./api_tests/security/enduser-ai-summary-trust-gate.test";
|
|
122
|
+
import { allowed_paths_confinement_tests } from "./api_tests/security/F-0166-allowed-paths-wildcard-bypass.test";
|
|
123
|
+
import { public_endpoint_auth_field_lock_tests } from "./api_tests/security/public_endpoint_auth_field_lock.test";
|
|
124
|
+
import { formsort_webhook_auth_field_lock_tests } from "./api_tests/security/formsort_webhook_auth_field_lock.test";
|
|
117
125
|
import { bulk_assignment_tests } from "./api_tests/bulk_assignment.test";
|
|
126
|
+
import { tickets_bulk_assign_care_team_tests } from "./api_tests/tickets_bulk_assign_care_team.test";
|
|
118
127
|
import { managed_content_enduser_access_tests } from "./api_tests/managed_content_enduser_access.test";
|
|
119
128
|
import { managed_content_file_access_tests } from "./api_tests/managed_content_file_access.test";
|
|
120
129
|
import { auto_merge_form_submission_tests } from "./api_tests/auto_merge_form_submission.test";
|
|
@@ -7945,9 +7954,49 @@ const merge_enduser_tests = async () => {
|
|
|
7945
7954
|
{ onResult: e => e.attendees.length === 1 && !!e.attendees?.find(a => a.id === destination.id) }
|
|
7946
7955
|
)
|
|
7947
7956
|
|
|
7957
|
+
// merging two endusers that both lack insurance must leave the fields absent, NOT null.
|
|
7958
|
+
// a stored null breaks every later partial update: those get flattened to dotted paths
|
|
7959
|
+
// ('insurance.memberId'), and MongoDB rejects a dotted $set under a null parent
|
|
7960
|
+
const [noInsuranceSource, noInsuranceDestination] = (await sdk.api.endusers.createSome([
|
|
7961
|
+
{ email: 'noins-source@tellescope.com', fname: 'no', lname: 'insurance' },
|
|
7962
|
+
{ email: 'noins-destination@tellescope.com' },
|
|
7963
|
+
])).created
|
|
7964
|
+
|
|
7965
|
+
await sdk.api.endusers.merge({
|
|
7966
|
+
sourceEnduserId: noInsuranceSource.id,
|
|
7967
|
+
destinationEnduserId: noInsuranceDestination.id,
|
|
7968
|
+
})
|
|
7969
|
+
|
|
7970
|
+
await async_test(
|
|
7971
|
+
"Merged endusers have no null insurance",
|
|
7972
|
+
() => sdk.api.endusers.getOne(noInsuranceDestination.id),
|
|
7973
|
+
{ onResult: e => e.insurance === undefined && e.insuranceSecondary === undefined }
|
|
7974
|
+
)
|
|
7975
|
+
|
|
7976
|
+
await async_test(
|
|
7977
|
+
"Partial insurance update applies after merge",
|
|
7978
|
+
async () => {
|
|
7979
|
+
await sdk.api.endusers.updateOne(noInsuranceDestination.id, {
|
|
7980
|
+
insurance: { memberId: 'M1', payerName: 'Test Payer' },
|
|
7981
|
+
}) // no replaceObjectFields, matching the standard update from the UI
|
|
7982
|
+
return await sdk.api.endusers.getOne(noInsuranceDestination.id)
|
|
7983
|
+
},
|
|
7984
|
+
{ onResult: e => e.insurance?.memberId === 'M1' && e.insurance?.payerName === 'Test Payer' }
|
|
7985
|
+
)
|
|
7986
|
+
|
|
7987
|
+
await async_test(
|
|
7988
|
+
"Second partial insurance update merges",
|
|
7989
|
+
async () => {
|
|
7990
|
+
await sdk.api.endusers.updateOne(noInsuranceDestination.id, { insurance: { groupNumber: 'G1' } })
|
|
7991
|
+
return await sdk.api.endusers.getOne(noInsuranceDestination.id)
|
|
7992
|
+
},
|
|
7993
|
+
{ onResult: e => e.insurance?.groupNumber === 'G1' && e.insurance?.memberId === 'M1' }
|
|
7994
|
+
)
|
|
7995
|
+
|
|
7948
7996
|
await Promise.all([
|
|
7949
7997
|
sdk.api.endusers.deleteOne(destination.id),
|
|
7950
7998
|
sdk.api.endusers.deleteOne(otherEnduser.id),
|
|
7999
|
+
sdk.api.endusers.deleteOne(noInsuranceDestination.id),
|
|
7951
8000
|
sdk.api.calendar_events.deleteOne(event.id),
|
|
7952
8001
|
sdk.api.calendar_events.deleteOne(eventToMove.id),
|
|
7953
8002
|
])
|
|
@@ -8581,6 +8630,8 @@ const test_ticket_automation_assignment_and_optimization = async () => {
|
|
|
8581
8630
|
enduser,
|
|
8582
8631
|
closedForReason,
|
|
8583
8632
|
testDelayedChild,
|
|
8633
|
+
calendarEventId,
|
|
8634
|
+
ticketOwner,
|
|
8584
8635
|
} : {
|
|
8585
8636
|
assignedTo: string[]
|
|
8586
8637
|
info: Pick<CreateTicketActionInfo, 'assignmentStrategy' | 'defaultAssignee'>,
|
|
@@ -8588,6 +8639,8 @@ const test_ticket_automation_assignment_and_optimization = async () => {
|
|
|
8588
8639
|
closedForReason?: string,
|
|
8589
8640
|
enduser?: Enduser,
|
|
8590
8641
|
testDelayedChild?: boolean,
|
|
8642
|
+
calendarEventId?: string, // copied into journeyContext by close_ticket
|
|
8643
|
+
ticketOwner?: string, // override the seed ticket's owner, to avoid masking a previous-owner fallback
|
|
8591
8644
|
}) => {
|
|
8592
8645
|
|
|
8593
8646
|
const e = enduser || await sdk.api.endusers.createOne({ assignedTo, journeys: { [journey.id]: '' }, fields: { Tag: "tag3"} })
|
|
@@ -8625,8 +8678,9 @@ const test_ticket_automation_assignment_and_optimization = async () => {
|
|
|
8625
8678
|
enduserId: e.id,
|
|
8626
8679
|
automationStepId: PLACEHOLDER_ID,
|
|
8627
8680
|
journeyId: journey.id,
|
|
8628
|
-
owner: validOwners[0],
|
|
8681
|
+
owner: ticketOwner ?? validOwners[0],
|
|
8629
8682
|
closedForReason,
|
|
8683
|
+
...(calendarEventId ? { calendarEventId } : {}),
|
|
8630
8684
|
})
|
|
8631
8685
|
|
|
8632
8686
|
await async_test(
|
|
@@ -8759,11 +8813,13 @@ const test_ticket_automation_assignment_and_optimization = async () => {
|
|
|
8759
8813
|
info,
|
|
8760
8814
|
validOwners,
|
|
8761
8815
|
enduser,
|
|
8816
|
+
journeyContext,
|
|
8762
8817
|
} : {
|
|
8763
8818
|
assignedTo: string[]
|
|
8764
8819
|
info: Pick<CreateTicketActionInfo, 'assignmentStrategy' | 'defaultAssignee'>,
|
|
8765
8820
|
validOwners: string[],
|
|
8766
8821
|
enduser?: Enduser,
|
|
8822
|
+
journeyContext?: JourneyContext,
|
|
8767
8823
|
}) => {
|
|
8768
8824
|
const e = enduser || await sdk.api.endusers.createOne({ assignedTo, fields: { Tag: 'tag3' } })
|
|
8769
8825
|
await sdk.api.automated_actions.createOne({
|
|
@@ -8774,6 +8830,7 @@ const test_ticket_automation_assignment_and_optimization = async () => {
|
|
|
8774
8830
|
journeyId: journey.id,
|
|
8775
8831
|
status: 'active',
|
|
8776
8832
|
processAfter: Date.now(),
|
|
8833
|
+
...(journeyContext ? { journeyContext } : {}),
|
|
8777
8834
|
})
|
|
8778
8835
|
|
|
8779
8836
|
await async_test(
|
|
@@ -8874,6 +8931,115 @@ const test_ticket_automation_assignment_and_optimization = async () => {
|
|
|
8874
8931
|
validOwners: [sdkNonAdmin.userInfo.id],
|
|
8875
8932
|
})
|
|
8876
8933
|
|
|
8934
|
+
// 'Recently-Booked Appointment Host' assignment
|
|
8935
|
+
// journeyContext.calendarEventId, when it resolves to a host, takes priority over the legacy
|
|
8936
|
+
// "newest event for this enduser" lookup. one enduser per case, to avoid trigger throttling.
|
|
8937
|
+
const HOST_A = sdkNonAdmin.userInfo.id
|
|
8938
|
+
const HOST_B = sdk.userInfo.id
|
|
8939
|
+
const appointmentHostInfo = (defaultAssignee: string) => ({
|
|
8940
|
+
assignmentStrategy: { type: 'Recently-Booked Appointment Host', info: {} } as const,
|
|
8941
|
+
defaultAssignee,
|
|
8942
|
+
})
|
|
8943
|
+
// the legacy filter matches an event having *some* user attendee and *some* attendee with this
|
|
8944
|
+
// enduser's id, so each hosted event carries both
|
|
8945
|
+
const createHostedEvent = (enduserId: string, hostId: string) => sdk.api.calendar_events.createOne({
|
|
8946
|
+
title: 'appointment host test',
|
|
8947
|
+
durationInMinutes: 30,
|
|
8948
|
+
startTimeInMS: Date.now(),
|
|
8949
|
+
attendees: [{ type: 'enduser', id: enduserId }, { type: 'user', id: hostId }],
|
|
8950
|
+
})
|
|
8951
|
+
|
|
8952
|
+
// CORE PROOF: two appointments with different hosts, journey context names the OLDER one.
|
|
8953
|
+
// fails before this fix, which always took the newest-created event (HOST_B).
|
|
8954
|
+
{
|
|
8955
|
+
const e = await sdk.api.endusers.createOne({ fields: { Tag: 'tag3' } })
|
|
8956
|
+
const older = await createHostedEvent(e.id, HOST_A)
|
|
8957
|
+
const newer = await createHostedEvent(e.id, HOST_B) // higher _id, so legacy sort picks this one
|
|
8958
|
+
await testBackgroundTicket({
|
|
8959
|
+
assignedTo: [],
|
|
8960
|
+
enduser: e,
|
|
8961
|
+
info: appointmentHostInfo(HOST_B), // distinct from expected owner, so a fallback would fail
|
|
8962
|
+
validOwners: [HOST_A],
|
|
8963
|
+
journeyContext: { calendarEventId: older.id },
|
|
8964
|
+
})
|
|
8965
|
+
await Promise.all([older, newer].map(ev => sdk.api.calendar_events.deleteOne(ev.id)))
|
|
8966
|
+
}
|
|
8967
|
+
|
|
8968
|
+
// no journey context -> legacy "newest event" behavior is unchanged
|
|
8969
|
+
{
|
|
8970
|
+
const e = await sdk.api.endusers.createOne({ fields: { Tag: 'tag3' } })
|
|
8971
|
+
const older = await createHostedEvent(e.id, HOST_A)
|
|
8972
|
+
const newer = await createHostedEvent(e.id, HOST_B)
|
|
8973
|
+
await testBackgroundTicket({
|
|
8974
|
+
assignedTo: [],
|
|
8975
|
+
enduser: e,
|
|
8976
|
+
info: appointmentHostInfo(HOST_A),
|
|
8977
|
+
validOwners: [HOST_B], // newest created event's host
|
|
8978
|
+
})
|
|
8979
|
+
await Promise.all([older, newer].map(ev => sdk.api.calendar_events.deleteOne(ev.id)))
|
|
8980
|
+
}
|
|
8981
|
+
|
|
8982
|
+
// context event no longer exists -> falls back to the legacy lookup
|
|
8983
|
+
{
|
|
8984
|
+
const e = await sdk.api.endusers.createOne({ fields: { Tag: 'tag3' } })
|
|
8985
|
+
const deleted = await createHostedEvent(e.id, HOST_B)
|
|
8986
|
+
await sdk.api.calendar_events.deleteOne(deleted.id)
|
|
8987
|
+
const hosted = await createHostedEvent(e.id, HOST_A)
|
|
8988
|
+
await testBackgroundTicket({
|
|
8989
|
+
assignedTo: [],
|
|
8990
|
+
enduser: e,
|
|
8991
|
+
info: appointmentHostInfo(HOST_B),
|
|
8992
|
+
validOwners: [HOST_A],
|
|
8993
|
+
journeyContext: { calendarEventId: deleted.id },
|
|
8994
|
+
})
|
|
8995
|
+
await sdk.api.calendar_events.deleteOne(hosted.id)
|
|
8996
|
+
}
|
|
8997
|
+
|
|
8998
|
+
// context event has no user attendee (so yields no host) -> falls back to the legacy lookup
|
|
8999
|
+
{
|
|
9000
|
+
const e = await sdk.api.endusers.createOne({ fields: { Tag: 'tag3' } })
|
|
9001
|
+
const enduserOnly = await sdk.api.calendar_events.createOne({
|
|
9002
|
+
title: 'appointment host test, no host',
|
|
9003
|
+
durationInMinutes: 30,
|
|
9004
|
+
startTimeInMS: Date.now(),
|
|
9005
|
+
attendees: [{ type: 'enduser', id: e.id }],
|
|
9006
|
+
})
|
|
9007
|
+
const hosted = await createHostedEvent(e.id, HOST_A)
|
|
9008
|
+
await testBackgroundTicket({
|
|
9009
|
+
assignedTo: [],
|
|
9010
|
+
enduser: e,
|
|
9011
|
+
info: appointmentHostInfo(HOST_B),
|
|
9012
|
+
validOwners: [HOST_A],
|
|
9013
|
+
journeyContext: { calendarEventId: enduserOnly.id },
|
|
9014
|
+
})
|
|
9015
|
+
await Promise.all([enduserOnly, hosted].map(ev => sdk.api.calendar_events.deleteOne(ev.id)))
|
|
9016
|
+
}
|
|
9017
|
+
|
|
9018
|
+
// no events at all -> no resolvable host, so defaultAssignee wins
|
|
9019
|
+
await testBackgroundTicket({
|
|
9020
|
+
assignedTo: [],
|
|
9021
|
+
info: appointmentHostInfo(HOST_A),
|
|
9022
|
+
validOwners: [HOST_A],
|
|
9023
|
+
})
|
|
9024
|
+
|
|
9025
|
+
// api path: close_ticket copies the original ticket's calendarEventId into journeyContext
|
|
9026
|
+
{
|
|
9027
|
+
const e = await sdk.api.endusers.createOne({
|
|
9028
|
+
journeys: { [journey.id]: '' }, fields: { Tag: 'tag3' },
|
|
9029
|
+
})
|
|
9030
|
+
const older = await createHostedEvent(e.id, HOST_A)
|
|
9031
|
+
const newer = await createHostedEvent(e.id, HOST_B)
|
|
9032
|
+
await testForegroundTicket({
|
|
9033
|
+
assignedTo: [],
|
|
9034
|
+
enduser: e,
|
|
9035
|
+
info: appointmentHostInfo(HOST_B),
|
|
9036
|
+
validOwners: [HOST_A],
|
|
9037
|
+
calendarEventId: older.id,
|
|
9038
|
+
ticketOwner: HOST_B, // so a previous-owner style fallback would also fail
|
|
9039
|
+
})
|
|
9040
|
+
await Promise.all([older, newer].map(ev => sdk.api.calendar_events.deleteOne(ev.id)))
|
|
9041
|
+
}
|
|
9042
|
+
|
|
8877
9043
|
return Promise.all([
|
|
8878
9044
|
await sdk.api.journeys.deleteOne(journey.id),
|
|
8879
9045
|
await sdk.api.ticket_queues.deleteOne(queue.id),
|
|
@@ -9560,6 +9726,10 @@ export const formsort_tests = async () => {
|
|
|
9560
9726
|
if (!r.formsort?.length) { return false }
|
|
9561
9727
|
if (!r.responses?.length) { return false }
|
|
9562
9728
|
if (r.responses.length !== answers.length) { return false }
|
|
9729
|
+
// this response attached to a patient that already existed (created at the SDK call above), so
|
|
9730
|
+
// the webhook flags it and email/phone are withheld from the enduser update — see
|
|
9731
|
+
// authFieldIntakeDisabled in api.ts and formsort_webhook_auth_field_lock.test.ts
|
|
9732
|
+
if (!r.authFieldIntakeDisabled) { return false }
|
|
9563
9733
|
|
|
9564
9734
|
if (!validateResponse(r, 'address', JSON.stringify(address, null, 2))) { return false }
|
|
9565
9735
|
if (!validateResponse(r, 'email', answersEmail)) { return false }
|
|
@@ -9588,7 +9758,10 @@ export const formsort_tests = async () => {
|
|
|
9588
9758
|
if (submissionEnduser.fname !== 'Fname') { return false }
|
|
9589
9759
|
if (submissionEnduser.lname !== 'Lname') { return false }
|
|
9590
9760
|
if (submissionEnduser.gender !== 'Male') { return false }
|
|
9591
|
-
|
|
9761
|
+
// phone is an auth channel (OTP delivery), and this enduser was matched by a $or guess rather
|
|
9762
|
+
// than created by this submission, so the submitted phone must NOT land. Non-auth intake fields
|
|
9763
|
+
// above still flow through.
|
|
9764
|
+
if (submissionEnduser.phone) { return false }
|
|
9592
9765
|
if (submissionEnduser.defaultFromEmail !== 'from@tellescope.com') { return false }
|
|
9593
9766
|
if (submissionEnduser.useDefaultFromEmailInAutomations !== true) { return false }
|
|
9594
9767
|
if (submissionEnduser.defaultFromPhone !== '+15555555555') { return false }
|
|
@@ -13751,6 +13924,55 @@ const replace_form_field_template_values_tests = async () => {
|
|
|
13751
13924
|
) === '<p>Locations: NYC<br />SF<br />LA</p>',
|
|
13752
13925
|
'fail CRLF in substituted value', 'CRLF in substituted value'
|
|
13753
13926
|
)
|
|
13927
|
+
|
|
13928
|
+
// escapeHTMLValues: substituted values are patient-supplied (their own intake answers / enduser
|
|
13929
|
+
// record), so on any path rendered by a sanitizer that permits iframes they must be escaped —
|
|
13930
|
+
// otherwise a patient can inject a frame into an admin-authored description.
|
|
13931
|
+
const enduserWithMarkupField = {
|
|
13932
|
+
fname: "Multi",
|
|
13933
|
+
fields: { Injected: '<iframe src="https://evil.example"></iframe>' },
|
|
13934
|
+
} as Partial<Enduser>
|
|
13935
|
+
|
|
13936
|
+
const escaped = replace_form_field_template_values(
|
|
13937
|
+
'<p>{{enduser.Injected}}</p>',
|
|
13938
|
+
{ enduser: enduserWithMarkupField, escapeNewlinesAsHTMLBreaks: true, escapeHTMLValues: true }
|
|
13939
|
+
)
|
|
13940
|
+
assert(
|
|
13941
|
+
escaped.includes('<iframe') && !escaped.includes('<iframe'),
|
|
13942
|
+
'fail escapeHTMLValues escapes markup', 'escapeHTMLValues escapes markup'
|
|
13943
|
+
)
|
|
13944
|
+
|
|
13945
|
+
// Escaping must run BEFORE the newline conversion, or the injected breaks become <br />
|
|
13946
|
+
const enduserWithMarkupAndNewline = {
|
|
13947
|
+
fields: { Mixed: 'a<b\nc&d' },
|
|
13948
|
+
} as Partial<Enduser>
|
|
13949
|
+
assert(
|
|
13950
|
+
replace_form_field_template_values(
|
|
13951
|
+
'{{enduser.Mixed}}',
|
|
13952
|
+
{ enduser: enduserWithMarkupAndNewline, escapeNewlinesAsHTMLBreaks: true, escapeHTMLValues: true }
|
|
13953
|
+
) === 'a<b<br />c&d',
|
|
13954
|
+
'fail escapeHTMLValues ordering vs newline breaks', 'escapeHTMLValues ordering vs newline breaks'
|
|
13955
|
+
)
|
|
13956
|
+
|
|
13957
|
+
// Flag absent => byte-identical to today. Plain-text callers (field titles/descriptions rendered
|
|
13958
|
+
// in a Typography) rely on this: escaping there would corrupt e.g. a name containing '&'.
|
|
13959
|
+
const enduserWithAmpersand = {
|
|
13960
|
+
fields: { Practice: 'Smith & Jones <Cardiology>' },
|
|
13961
|
+
} as Partial<Enduser>
|
|
13962
|
+
assert(
|
|
13963
|
+
replace_form_field_template_values(
|
|
13964
|
+
'Practice: {{enduser.Practice}}',
|
|
13965
|
+
{ enduser: enduserWithAmpersand }
|
|
13966
|
+
) === 'Practice: Smith & Jones <Cardiology>',
|
|
13967
|
+
'fail no escaping without the flag', 'no escaping without the flag'
|
|
13968
|
+
)
|
|
13969
|
+
assert(
|
|
13970
|
+
replace_form_field_template_values(
|
|
13971
|
+
'Practice: {{enduser.Practice}}',
|
|
13972
|
+
{ enduser: enduserWithAmpersand, escapeHTMLValues: true }
|
|
13973
|
+
) === 'Practice: Smith & Jones <Cardiology>',
|
|
13974
|
+
'fail escaping with the flag', 'escaping with the flag'
|
|
13975
|
+
)
|
|
13754
13976
|
}
|
|
13755
13977
|
|
|
13756
13978
|
const inbox_threads_building_tests = async () => {
|
|
@@ -15052,6 +15274,9 @@ const ip_address_form_tests = async () => {
|
|
|
15052
15274
|
await replace_form_field_template_values_tests()
|
|
15053
15275
|
await mfa_tests()
|
|
15054
15276
|
await setup_tests(sdk, sdkNonAdmin)
|
|
15277
|
+
await allowed_paths_confinement_tests({ sdk, sdkNonAdmin })
|
|
15278
|
+
await phone_calls_conference_hold_tests({ sdk, sdkNonAdmin })
|
|
15279
|
+
await tickets_bulk_assign_care_team_tests({ sdk, sdkNonAdmin })
|
|
15055
15280
|
await custom_dashboards_tests({ sdk, sdkNonAdmin })
|
|
15056
15281
|
await register_business_id_injection_tests({ sdk, sdkNonAdmin })
|
|
15057
15282
|
await automation_trigger_tests()
|
|
@@ -15060,10 +15285,13 @@ const ip_address_form_tests = async () => {
|
|
|
15060
15285
|
await beluga_pharmacy_mappings_tests({ sdk, sdkNonAdmin })
|
|
15061
15286
|
await mdi_case_offerings_tests({ sdk, sdkNonAdmin })
|
|
15062
15287
|
await enduser_write_restrictions_tests({ sdk, sdkNonAdmin })
|
|
15288
|
+
await enduser_ai_summary_trust_gate_tests({ sdk, sdkNonAdmin })
|
|
15063
15289
|
await enduser_cross_create_tests({ sdk, sdkNonAdmin })
|
|
15064
15290
|
await globalunique_leak_tests({ sdk, sdkNonAdmin })
|
|
15065
15291
|
await load_inbox_redaction_tests({ sdk, sdkNonAdmin })
|
|
15066
15292
|
await webhook_timeout_tests({ sdk, sdkNonAdmin })
|
|
15293
|
+
await public_endpoint_auth_field_lock_tests({ sdk, sdkNonAdmin })
|
|
15294
|
+
await formsort_webhook_auth_field_lock_tests({ sdk, sdkNonAdmin })
|
|
15067
15295
|
await user_portal_settings_tests({ sdk, sdkNonAdmin })
|
|
15068
15296
|
await invite_user_enumeration_tests({ sdk, sdkNonAdmin })
|
|
15069
15297
|
await handle_incoming_communication_cross_tenant_tests({ sdk, sdkNonAdmin })
|
|
@@ -15076,6 +15304,7 @@ const ip_address_form_tests = async () => {
|
|
|
15076
15304
|
await cascade_role_rename_cross_tenant_tests({ sdk, sdkNonAdmin })
|
|
15077
15305
|
await self_admin_role_assignment_tests({ sdk, sdkNonAdmin })
|
|
15078
15306
|
await sanitize_user_html_xss_tests()
|
|
15307
|
+
await sanitize_user_html_with_iframes_tests()
|
|
15079
15308
|
await prototype_pollution_tests()
|
|
15080
15309
|
await account_switcher_tests({ sdk, sdkNonAdmin })
|
|
15081
15310
|
await totp_mfa_tests({ sdk, sdkNonAdmin })
|
|
@@ -15110,6 +15339,7 @@ const ip_address_form_tests = async () => {
|
|
|
15110
15339
|
await time_tracks_appointment_duration_tests({ sdk, sdkNonAdmin })
|
|
15111
15340
|
await calendar_event_limits_tests({ sdk, sdkNonAdmin })
|
|
15112
15341
|
await get_some_projection_tests({ sdk, sdkNonAdmin })
|
|
15342
|
+
await file_download_unicode_names_tests({ sdk, sdkNonAdmin })
|
|
15113
15343
|
await elation_user_id_tests({ sdk, sdkNonAdmin })
|
|
15114
15344
|
await concurrent_build_threads_tests({ sdk, sdkNonAdmin })
|
|
15115
15345
|
await custom_aggregation_tests({ sdk, sdkNonAdmin })
|
package/test_generated.pdf
CHANGED
|
Binary file
|
package/.env
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
TEST_EMAIL='sebastian.a.coates+test@gmail.com'
|
|
2
|
-
MFA_EMAIL='sebass+mfa@tellescope.com'
|
|
3
|
-
SUB_EMAIL='sebass+sub@tellescope.com'
|
|
4
|
-
OTHER_SUB_EMAIL='sebass+othersub@tellescope.com'
|
|
5
|
-
SUB_SUB_EMAIL='sebass+subsub@tellescope.com'
|
|
6
|
-
TEST_PASSWORD='asdfGHJK1234!@#$'
|
|
7
|
-
TEST_EMAIL_2='sebass192@gmail.com'
|
|
8
|
-
TEST_PASSWORD_2='3009SwagSwag'
|
|
9
|
-
NON_ADMIN_EMAIL='nonadmin@tellescope.com'
|
|
10
|
-
NON_ADMIN_PASSWORD='3009SwagSwag'
|
|
11
|
-
CROSS_ORG_API_KEY='cross-org-testing-api-key-manually-set'
|
|
12
|
-
CROSS_ORG_TARGET_BUSINESS_ID='69efea9b0c4d5bd1da90ca77'
|
|
13
|
-
CROSS_ORG_UNAPPROVED_BUSINESS_ID='63a0d6be40e38ba9e899a490'
|