@tellescope/sdk 1.248.0 → 1.249.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/.env +3 -0
  2. package/lib/cjs/sdk.d.ts +1 -0
  3. package/lib/cjs/sdk.d.ts.map +1 -1
  4. package/lib/cjs/sdk.js +1 -0
  5. package/lib/cjs/sdk.js.map +1 -1
  6. package/lib/cjs/tests/api_tests/chats_analytics.test.d.ts +6 -0
  7. package/lib/cjs/tests/api_tests/chats_analytics.test.d.ts.map +1 -0
  8. package/lib/cjs/tests/api_tests/chats_analytics.test.js +256 -0
  9. package/lib/cjs/tests/api_tests/chats_analytics.test.js.map +1 -0
  10. package/lib/cjs/tests/api_tests/cross_org_api_key.test.d.ts +6 -0
  11. package/lib/cjs/tests/api_tests/cross_org_api_key.test.d.ts.map +1 -0
  12. package/lib/cjs/tests/api_tests/cross_org_api_key.test.js +748 -0
  13. package/lib/cjs/tests/api_tests/cross_org_api_key.test.js.map +1 -0
  14. package/lib/cjs/tests/api_tests/enduser_session_invalidation.test.d.ts.map +1 -1
  15. package/lib/cjs/tests/api_tests/enduser_session_invalidation.test.js +426 -2
  16. package/lib/cjs/tests/api_tests/enduser_session_invalidation.test.js.map +1 -1
  17. package/lib/cjs/tests/api_tests/eom_billing_codes.test.d.ts +6 -0
  18. package/lib/cjs/tests/api_tests/eom_billing_codes.test.d.ts.map +1 -0
  19. package/lib/cjs/tests/api_tests/eom_billing_codes.test.js +162 -0
  20. package/lib/cjs/tests/api_tests/eom_billing_codes.test.js.map +1 -0
  21. package/lib/cjs/tests/api_tests/eom_procedure_codes.test.d.ts +6 -0
  22. package/lib/cjs/tests/api_tests/eom_procedure_codes.test.d.ts.map +1 -0
  23. package/lib/cjs/tests/api_tests/eom_procedure_codes.test.js +339 -0
  24. package/lib/cjs/tests/api_tests/eom_procedure_codes.test.js.map +1 -0
  25. package/lib/cjs/tests/api_tests/managed_content_file_access.test.d.ts +13 -0
  26. package/lib/cjs/tests/api_tests/managed_content_file_access.test.d.ts.map +1 -0
  27. package/lib/cjs/tests/api_tests/managed_content_file_access.test.js +385 -0
  28. package/lib/cjs/tests/api_tests/managed_content_file_access.test.js.map +1 -0
  29. package/lib/cjs/tests/api_tests/organization_settings_duplicates.test.d.ts.map +1 -1
  30. package/lib/cjs/tests/api_tests/organization_settings_duplicates.test.js +25 -2
  31. package/lib/cjs/tests/api_tests/organization_settings_duplicates.test.js.map +1 -1
  32. package/lib/cjs/tests/tests.d.ts.map +1 -1
  33. package/lib/cjs/tests/tests.js +185 -134
  34. package/lib/cjs/tests/tests.js.map +1 -1
  35. package/lib/esm/sdk.d.ts +3 -2
  36. package/lib/esm/sdk.d.ts.map +1 -1
  37. package/lib/esm/sdk.js +1 -0
  38. package/lib/esm/sdk.js.map +1 -1
  39. package/lib/esm/tests/api_tests/chats_analytics.test.d.ts +6 -0
  40. package/lib/esm/tests/api_tests/chats_analytics.test.d.ts.map +1 -0
  41. package/lib/esm/tests/api_tests/chats_analytics.test.js +252 -0
  42. package/lib/esm/tests/api_tests/chats_analytics.test.js.map +1 -0
  43. package/lib/esm/tests/api_tests/cross_org_api_key.test.d.ts +6 -0
  44. package/lib/esm/tests/api_tests/cross_org_api_key.test.d.ts.map +1 -0
  45. package/lib/esm/tests/api_tests/cross_org_api_key.test.js +744 -0
  46. package/lib/esm/tests/api_tests/cross_org_api_key.test.js.map +1 -0
  47. package/lib/esm/tests/api_tests/enduser_session_invalidation.test.d.ts.map +1 -1
  48. package/lib/esm/tests/api_tests/enduser_session_invalidation.test.js +426 -2
  49. package/lib/esm/tests/api_tests/enduser_session_invalidation.test.js.map +1 -1
  50. package/lib/esm/tests/api_tests/eom_billing_codes.test.d.ts +6 -0
  51. package/lib/esm/tests/api_tests/eom_billing_codes.test.d.ts.map +1 -0
  52. package/lib/esm/tests/api_tests/eom_billing_codes.test.js +158 -0
  53. package/lib/esm/tests/api_tests/eom_billing_codes.test.js.map +1 -0
  54. package/lib/esm/tests/api_tests/eom_procedure_codes.test.d.ts +6 -0
  55. package/lib/esm/tests/api_tests/eom_procedure_codes.test.d.ts.map +1 -0
  56. package/lib/esm/tests/api_tests/eom_procedure_codes.test.js +335 -0
  57. package/lib/esm/tests/api_tests/eom_procedure_codes.test.js.map +1 -0
  58. package/lib/esm/tests/api_tests/managed_content_file_access.test.d.ts +13 -0
  59. package/lib/esm/tests/api_tests/managed_content_file_access.test.d.ts.map +1 -0
  60. package/lib/esm/tests/api_tests/managed_content_file_access.test.js +358 -0
  61. package/lib/esm/tests/api_tests/managed_content_file_access.test.js.map +1 -0
  62. package/lib/esm/tests/api_tests/organization_settings_duplicates.test.d.ts.map +1 -1
  63. package/lib/esm/tests/api_tests/organization_settings_duplicates.test.js +25 -2
  64. package/lib/esm/tests/api_tests/organization_settings_duplicates.test.js.map +1 -1
  65. package/lib/esm/tests/tests.d.ts.map +1 -1
  66. package/lib/esm/tests/tests.js +186 -135
  67. package/lib/esm/tests/tests.js.map +1 -1
  68. package/lib/tsconfig.tsbuildinfo +1 -1
  69. package/package.json +10 -10
  70. package/src/sdk.ts +4 -0
  71. package/src/tests/api_tests/chats_analytics.test.ts +182 -0
  72. package/src/tests/api_tests/cross_org_api_key.test.ts +665 -0
  73. package/src/tests/api_tests/enduser_session_invalidation.test.ts +223 -0
  74. package/src/tests/api_tests/eom_procedure_codes.test.ts +296 -0
  75. package/src/tests/api_tests/managed_content_file_access.test.ts +214 -0
  76. package/src/tests/api_tests/organization_settings_duplicates.test.ts +14 -0
  77. package/src/tests/tests.ts +93 -3
  78. 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
+ }
@@ -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
@@ -50,7 +50,7 @@ import { appointment_rescheduled_trigger_tests } from "./api_tests/appointment_r
50
50
  import { journey_error_branching_tests } from "./api_tests/journey_error_branching.test"
51
51
  import { afteraction_day_of_month_delay_tests } from "./api_tests/afteraction_day_of_month_delay.test"
52
52
  import { setup_tests } from "./setup"
53
- import { evaluate_conditional_logic_for_enduser_fields, FORM_LOGIC_CALCULATED_FIELDS, get_care_team_primary, get_flattened_fields, get_next_reminder_timestamp, object_is_empty, replace_enduser_template_values, responses_satisfy_conditions, truncate_string, weighted_round_robin, YYYY_MM_DD_to_MM_DD_YYYY } from "@tellescope/utilities"
53
+ import { evaluate_conditional_logic_for_enduser_fields, FORM_LOGIC_CALCULATED_FIELDS, get_care_team_primary, get_flattened_fields, get_next_reminder_timestamp, object_is_empty, replace_enduser_template_values, replace_form_field_template_values, responses_satisfy_conditions, truncate_string, weighted_round_robin, YYYY_MM_DD_to_MM_DD_YYYY } from "@tellescope/utilities"
54
54
  import { DEFAULT_OPERATIONS, PLACEHOLDER_ID, ZENDESK_INTEGRATIONS_TITLE, ZOOM_TITLE } from "@tellescope/constants"
55
55
  import {
56
56
  schema,
@@ -74,16 +74,20 @@ import {
74
74
 
75
75
  import fs from "fs"
76
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";
77
79
  import { custom_dashboards_tests } from "./api_tests/custom_dashboards.test";
78
80
  import { message_assignment_trigger_tests } from "./api_tests/message_assignment_trigger.test";
79
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";
80
82
  import { monthly_availability_restrictions_tests } from "./api_tests/monthly_availability_restrictions.test";
81
83
  import { calendar_event_limits_tests } from "./api_tests/calendar_event_limits.test";
82
84
  import { custom_aggregation_tests } from "./api_tests/custom_aggregation.test";
85
+ import { chats_analytics_tests } from "./api_tests/chats_analytics.test";
83
86
  import { no_access_permission_checks_tests } from "./api_tests/no_access_permission_checks.test";
84
87
  import { field_redaction_tests } from "./api_tests/field_redaction.test";
85
88
  import { bulk_assignment_tests } from "./api_tests/bulk_assignment.test";
86
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";
87
91
  import { auto_merge_form_submission_tests } from "./api_tests/auto_merge_form_submission.test";
88
92
  import { database_cascade_delete_tests } from "./api_tests/database_cascade_delete.test";
89
93
  import { ai_conversations_tests } from "./api_tests/ai_conversations.test";
@@ -12903,6 +12907,87 @@ const replace_enduser_template_values_tests = async () => {
12903
12907
  await sdk.api.endusers.deleteOne(enduser.id)
12904
12908
  }
12905
12909
 
12910
+ const replace_form_field_template_values_tests = async () => {
12911
+ log_header("Replace Form Field Template Values Tests")
12912
+
12913
+ const enduserWithMultilineField = {
12914
+ fname: "Multi",
12915
+ lname: "Line",
12916
+ fields: { Locations: 'NYC\nSF\nLA' },
12917
+ } as Partial<Enduser>
12918
+
12919
+ // With escapeNewlinesAsHTMLBreaks: true — newlines in substituted value become <br />
12920
+ assert(
12921
+ replace_form_field_template_values(
12922
+ '<p>Locations: {{enduser.Locations}}</p>',
12923
+ { enduser: enduserWithMultilineField, escapeNewlinesAsHTMLBreaks: true }
12924
+ ) === '<p>Locations: NYC<br />SF<br />LA</p>',
12925
+ 'fail escapeNewlinesAsHTMLBreaks true', 'escapeNewlinesAsHTMLBreaks true'
12926
+ )
12927
+
12928
+ // Default (option absent) — newlines preserved as \n
12929
+ assert(
12930
+ replace_form_field_template_values(
12931
+ '<p>Locations: {{enduser.Locations}}</p>',
12932
+ { enduser: enduserWithMultilineField }
12933
+ ) === '<p>Locations: NYC\nSF\nLA</p>',
12934
+ 'fail default newline preserved', 'default newline preserved'
12935
+ )
12936
+
12937
+ // Explicit false — same as default
12938
+ assert(
12939
+ replace_form_field_template_values(
12940
+ '<p>Locations: {{enduser.Locations}}</p>',
12941
+ { enduser: enduserWithMultilineField, escapeNewlinesAsHTMLBreaks: false }
12942
+ ) === '<p>Locations: NYC\nSF\nLA</p>',
12943
+ 'fail escapeNewlinesAsHTMLBreaks false', 'escapeNewlinesAsHTMLBreaks false'
12944
+ )
12945
+
12946
+ // \n in original template (not in substituted value) is left alone
12947
+ assert(
12948
+ replace_form_field_template_values(
12949
+ '<p>Header</p>\n<p>{{enduser.fname}}</p>',
12950
+ { enduser: enduserWithMultilineField, escapeNewlinesAsHTMLBreaks: true }
12951
+ ) === '<p>Header</p>\n<p>Multi</p>',
12952
+ 'fail template newline untouched', 'template newline untouched'
12953
+ )
12954
+
12955
+ // Single-line value unaffected when option is enabled
12956
+ assert(
12957
+ replace_form_field_template_values(
12958
+ '<p>Hello {{enduser.fname}}</p>',
12959
+ { enduser: enduserWithMultilineField, escapeNewlinesAsHTMLBreaks: true }
12960
+ ) === '<p>Hello Multi</p>',
12961
+ 'fail single-line value', 'single-line value'
12962
+ )
12963
+
12964
+ // Substituted value containing literal two-char \n escape sequence is also converted
12965
+ const enduserWithLiteralEscapeField = {
12966
+ fname: "Multi",
12967
+ fields: { Locations: 'NYC\\nSF\\nLA' },
12968
+ } as Partial<Enduser>
12969
+ assert(
12970
+ replace_form_field_template_values(
12971
+ '<p>Locations: {{enduser.Locations}}</p>',
12972
+ { enduser: enduserWithLiteralEscapeField, escapeNewlinesAsHTMLBreaks: true }
12973
+ ) === '<p>Locations: NYC<br />SF<br />LA</p>',
12974
+ 'fail literal \\n escape in substituted value', 'literal \\n escape in substituted value'
12975
+ )
12976
+
12977
+ // Substituted value with \r\n is also converted (single break per CRLF, not two)
12978
+ const enduserWithCRLFField = {
12979
+ fname: "Multi",
12980
+ fields: { Locations: 'NYC\r\nSF\r\nLA' },
12981
+ } as Partial<Enduser>
12982
+ assert(
12983
+ replace_form_field_template_values(
12984
+ '<p>Locations: {{enduser.Locations}}</p>',
12985
+ { enduser: enduserWithCRLFField, escapeNewlinesAsHTMLBreaks: true }
12986
+ ) === '<p>Locations: NYC<br />SF<br />LA</p>',
12987
+ 'fail CRLF in substituted value', 'CRLF in substituted value'
12988
+ )
12989
+ }
12990
+
12906
12991
  const inbox_threads_building_tests = async () => {
12907
12992
  log_header("Inbox Thread Building Tests")
12908
12993
 
@@ -14199,8 +14284,14 @@ const ip_address_form_tests = async () => {
14199
14284
 
14200
14285
  await enduser_conditional_logic_tests()
14201
14286
  await replace_enduser_template_values_tests()
14287
+ await replace_form_field_template_values_tests()
14202
14288
  await mfa_tests()
14203
14289
  await setup_tests(sdk, sdkNonAdmin)
14290
+ await eom_procedure_codes_tests({ sdk, sdkNonAdmin })
14291
+ await cross_org_api_key_tests({ sdk, sdkNonAdmin })
14292
+ await organization_settings_duplicates_tests({ sdk, sdkNonAdmin })
14293
+ await enduser_session_invalidation_tests({ sdk, sdkNonAdmin })
14294
+ await chats_analytics_tests({ sdk, sdkNonAdmin })
14204
14295
  await field_redaction_tests({ sdk, sdkNonAdmin })
14205
14296
  await form_submitted_trigger_tests({ sdk, sdkNonAdmin })
14206
14297
  await date_string_validation_tests({ sdk, sdkNonAdmin })
@@ -14208,7 +14299,6 @@ const ip_address_form_tests = async () => {
14208
14299
  await automation_trigger_tests()
14209
14300
  await integrations_redacted_tests({ sdk, sdkNonAdmin })
14210
14301
  await mdb_sort_tests({ sdk, sdkNonAdmin })
14211
- await organization_settings_duplicates_tests({ sdk, sdkNonAdmin })
14212
14302
  await search_tests()
14213
14303
  await time_tracks_tests({ sdk, sdkNonAdmin })
14214
14304
  await time_tracks_historical_tests({ sdk, sdkNonAdmin })
@@ -14235,6 +14325,7 @@ const ip_address_form_tests = async () => {
14235
14325
  await beluga_pharmacy_mappings_tests({ sdk, sdkNonAdmin })
14236
14326
  await threadKeyTests()
14237
14327
  await managed_content_enduser_access_tests({ sdk, sdkNonAdmin })
14328
+ await managed_content_file_access_tests({ sdk, sdkNonAdmin })
14238
14329
  await afteraction_day_of_month_delay_tests({ sdk, sdkNonAdmin })
14239
14330
  await bulk_assignment_tests({ sdk, sdkNonAdmin })
14240
14331
  await formsort_tests()
@@ -14247,7 +14338,6 @@ const ip_address_form_tests = async () => {
14247
14338
  await inbox_threads_loading_tests()
14248
14339
  await load_inbox_data_tests({ sdk, sdkNonAdmin })
14249
14340
  await enduser_observations_acknowledge_tests({ sdk, sdkNonAdmin })
14250
- await enduser_session_invalidation_tests({ sdk, sdkNonAdmin })
14251
14341
  await create_user_notifications_trigger_tests({ sdk })
14252
14342
  await group_mms_active_tests()
14253
14343
  await auto_reply_tests()
Binary file