@tellescope/sdk 1.246.1 → 1.247.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.
Files changed (52) hide show
  1. package/lib/cjs/sdk.d.ts +1 -0
  2. package/lib/cjs/sdk.d.ts.map +1 -1
  3. package/lib/cjs/sdk.js.map +1 -1
  4. package/lib/cjs/tests/api_tests/account_switcher.test.d.ts +6 -0
  5. package/lib/cjs/tests/api_tests/account_switcher.test.d.ts.map +1 -0
  6. package/lib/cjs/tests/api_tests/account_switcher.test.js +445 -0
  7. package/lib/cjs/tests/api_tests/account_switcher.test.js.map +1 -0
  8. package/lib/cjs/tests/api_tests/calendar_events_bulk_update.test.d.ts +5 -0
  9. package/lib/cjs/tests/api_tests/calendar_events_bulk_update.test.d.ts.map +1 -0
  10. package/lib/cjs/tests/api_tests/calendar_events_bulk_update.test.js +483 -0
  11. package/lib/cjs/tests/api_tests/calendar_events_bulk_update.test.js.map +1 -0
  12. package/lib/cjs/tests/api_tests/email_utils.test.d.ts +2 -0
  13. package/lib/cjs/tests/api_tests/email_utils.test.d.ts.map +1 -0
  14. package/lib/cjs/tests/api_tests/email_utils.test.js +141 -0
  15. package/lib/cjs/tests/api_tests/email_utils.test.js.map +1 -0
  16. package/lib/cjs/tests/api_tests/mdb_sort.test.d.ts +6 -0
  17. package/lib/cjs/tests/api_tests/mdb_sort.test.d.ts.map +1 -0
  18. package/lib/cjs/tests/api_tests/mdb_sort.test.js +370 -0
  19. package/lib/cjs/tests/api_tests/mdb_sort.test.js.map +1 -0
  20. package/lib/cjs/tests/tests.d.ts.map +1 -1
  21. package/lib/cjs/tests/tests.js +156 -128
  22. package/lib/cjs/tests/tests.js.map +1 -1
  23. package/lib/esm/sdk.d.ts +1 -0
  24. package/lib/esm/sdk.d.ts.map +1 -1
  25. package/lib/esm/sdk.js.map +1 -1
  26. package/lib/esm/tests/api_tests/account_switcher.test.d.ts +6 -0
  27. package/lib/esm/tests/api_tests/account_switcher.test.d.ts.map +1 -0
  28. package/lib/esm/tests/api_tests/account_switcher.test.js +438 -0
  29. package/lib/esm/tests/api_tests/account_switcher.test.js.map +1 -0
  30. package/lib/esm/tests/api_tests/calendar_events_bulk_update.test.d.ts +5 -0
  31. package/lib/esm/tests/api_tests/calendar_events_bulk_update.test.d.ts.map +1 -0
  32. package/lib/esm/tests/api_tests/calendar_events_bulk_update.test.js +479 -0
  33. package/lib/esm/tests/api_tests/calendar_events_bulk_update.test.js.map +1 -0
  34. package/lib/esm/tests/api_tests/email_utils.test.d.ts +2 -0
  35. package/lib/esm/tests/api_tests/email_utils.test.d.ts.map +1 -0
  36. package/lib/esm/tests/api_tests/email_utils.test.js +137 -0
  37. package/lib/esm/tests/api_tests/email_utils.test.js.map +1 -0
  38. package/lib/esm/tests/api_tests/mdb_sort.test.d.ts +6 -0
  39. package/lib/esm/tests/api_tests/mdb_sort.test.d.ts.map +1 -0
  40. package/lib/esm/tests/api_tests/mdb_sort.test.js +366 -0
  41. package/lib/esm/tests/api_tests/mdb_sort.test.js.map +1 -0
  42. package/lib/esm/tests/tests.d.ts.map +1 -1
  43. package/lib/esm/tests/tests.js +156 -128
  44. package/lib/esm/tests/tests.js.map +1 -1
  45. package/lib/tsconfig.tsbuildinfo +1 -1
  46. package/package.json +10 -10
  47. package/src/sdk.ts +1 -0
  48. package/src/tests/api_tests/calendar_events_bulk_update.test.ts +418 -0
  49. package/src/tests/api_tests/mdb_sort.test.ts +259 -0
  50. package/src/tests/api_tests/organization_settings_duplicates.test.ts +201 -0
  51. package/src/tests/tests.ts +30 -2
  52. package/test_generated.pdf +0 -0
@@ -0,0 +1,201 @@
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
+ export const organization_settings_duplicates_tests = async ({ sdk, sdkNonAdmin } : { sdk: Session, sdkNonAdmin: Session }) => {
13
+ log_header("Organization Settings Duplicate Validation Tests")
14
+
15
+ const orgId = sdk.userInfo.businessId
16
+
17
+ // === A. replaceObjectFields: false (merge/push behavior) ===
18
+
19
+ // A1. Duplicate tags via merge
20
+ await sdk.api.organizations.updateOne(orgId, {
21
+ settings: { endusers: { tags: ['tag1', 'tag2'] } }
22
+ }, { replaceObjectFields: true })
23
+
24
+ await async_test(
25
+ "Merge tags rejects duplicates (tag2 appears in both old and new)",
26
+ () => sdk.api.organizations.updateOne(orgId, {
27
+ settings: { endusers: { tags: ['tag2', 'tag3'] } }
28
+ }),
29
+ { shouldError: true, onError: (e: { message: string }) => e.message.includes('Duplicate value in settings.endusers.tags') }
30
+ )
31
+
32
+ // A2. Duplicate customFields via merge
33
+ await sdk.api.organizations.updateOne(orgId, {
34
+ settings: { endusers: { customFields: [{ type: 'Text' as const, field: 'myField', info: {} }] } }
35
+ }, { replaceObjectFields: true })
36
+
37
+ await async_test(
38
+ "Merge customFields rejects duplicate field name",
39
+ () => sdk.api.organizations.updateOne(orgId, {
40
+ settings: { endusers: { customFields: [{ type: 'Text' as const, field: 'myField', info: {} }] } }
41
+ }),
42
+ { shouldError: true, onError: (e: { message: string }) => e.message.includes('Duplicate field in settings.endusers.customFields') }
43
+ )
44
+
45
+ // A3. Duplicate builtinFields via merge
46
+ await sdk.api.organizations.updateOne(orgId, {
47
+ settings: { endusers: { builtinFields: [{ field: 'fname', label: 'First Name' }] } }
48
+ }, { replaceObjectFields: true })
49
+
50
+ await async_test(
51
+ "Merge builtinFields rejects duplicate field name",
52
+ () => sdk.api.organizations.updateOne(orgId, {
53
+ settings: { endusers: { builtinFields: [{ field: 'fname', label: 'First Name Copy' }] } }
54
+ }),
55
+ { shouldError: true, onError: (e: { message: string }) => e.message.includes('Duplicate field in settings.endusers.builtinFields') }
56
+ )
57
+
58
+ // A4. Duplicate dontRecordCallsToPhone via merge
59
+ await sdk.api.organizations.updateOne(orgId, {
60
+ settings: { endusers: { dontRecordCallsToPhone: ['+15551234567'] } }
61
+ }, { replaceObjectFields: true })
62
+
63
+ await async_test(
64
+ "Merge dontRecordCallsToPhone rejects duplicates",
65
+ () => sdk.api.organizations.updateOne(orgId, {
66
+ settings: { endusers: { dontRecordCallsToPhone: ['+15551234567'] } }
67
+ }),
68
+ { shouldError: true, onError: (e: { message: string }) => e.message.includes('Duplicate value in settings.endusers.dontRecordCallsToPhone') }
69
+ )
70
+
71
+ // A5. Duplicate cancelReasons via merge
72
+ await sdk.api.organizations.updateOne(orgId, {
73
+ settings: { calendar: { cancelReasons: ['No show'] } }
74
+ }, { replaceObjectFields: true })
75
+
76
+ await async_test(
77
+ "Merge cancelReasons rejects duplicates",
78
+ () => sdk.api.organizations.updateOne(orgId, {
79
+ settings: { calendar: { cancelReasons: ['No show'] } }
80
+ }),
81
+ { shouldError: true, onError: (e: { message: string }) => e.message.includes('Duplicate value in settings.calendar.cancelReasons') }
82
+ )
83
+
84
+ // === B. replaceObjectFields: true (full replacement) ===
85
+
86
+ // B1. Replace that grows the array with dupes should be rejected
87
+ await sdk.api.organizations.updateOne(orgId, {
88
+ settings: { endusers: { tags: ['tag1'] } }
89
+ }, { replaceObjectFields: true })
90
+
91
+ await async_test(
92
+ "Replace tags rejects duplicates when array grows",
93
+ () => sdk.api.organizations.updateOne(orgId, {
94
+ settings: { endusers: { tags: ['tag1', 'tag1', 'tag2'] } }
95
+ }, { replaceObjectFields: true }),
96
+ { shouldError: true, onError: (e: { message: string }) => e.message.includes('Duplicate value in settings.endusers.tags') }
97
+ )
98
+
99
+ // B2. Replace with dupes that shrinks the array should be allowed
100
+ await sdk.api.organizations.updateOne(orgId, {
101
+ settings: { endusers: { tags: ['a', 'b', 'c'] } }
102
+ }, { replaceObjectFields: true })
103
+
104
+ await async_test(
105
+ "Replace with dupes that shrinks array succeeds",
106
+ () => sdk.api.organizations.updateOne(orgId, {
107
+ settings: { endusers: { tags: ['a', 'a'] } }
108
+ }, { replaceObjectFields: true }),
109
+ { shouldError: false, onResult: () => true }
110
+ )
111
+
112
+ // B3. Replace with unique values always succeeds
113
+ await async_test(
114
+ "Replace tags succeeds with unique values",
115
+ () => sdk.api.organizations.updateOne(orgId, {
116
+ settings: { endusers: { tags: ['tag1', 'tag2'] } }
117
+ }, { replaceObjectFields: true }),
118
+ { shouldError: false, onResult: () => true }
119
+ )
120
+
121
+ // === C. Non-duplicate updates still succeed ===
122
+
123
+ // C1. Set initial tags then add different tags via merge
124
+ await sdk.api.organizations.updateOne(orgId, {
125
+ settings: { endusers: { tags: ['tagA', 'tagB'] } }
126
+ }, { replaceObjectFields: true })
127
+
128
+ await async_test(
129
+ "Merge with unique new tags succeeds",
130
+ () => sdk.api.organizations.updateOne(orgId, {
131
+ settings: { endusers: { tags: ['tagC', 'tagD'] } }
132
+ }),
133
+ { shouldError: false, onResult: () => true }
134
+ )
135
+
136
+ // C2. Replace with unique values
137
+ await async_test(
138
+ "Replace customFields with unique values succeeds",
139
+ () => sdk.api.organizations.updateOne(orgId, {
140
+ settings: { endusers: { customFields: [
141
+ { type: 'Text' as const, field: 'field1', info: {} },
142
+ { type: 'Text' as const, field: 'field2', info: {} },
143
+ ] } }
144
+ }, { replaceObjectFields: true }),
145
+ { shouldError: false, onResult: () => true }
146
+ )
147
+
148
+ // C3. Updating another settings field preserves pre-existing duplicates
149
+ // First set tags to a longer array, then shrink to a dupe array (shrinking is allowed)
150
+ await sdk.api.organizations.updateOne(orgId, {
151
+ settings: { endusers: { tags: ['dupeTag', 'otherTag', 'anotherTag'] } }
152
+ }, { replaceObjectFields: true })
153
+ await sdk.api.organizations.updateOne(orgId, {
154
+ settings: { endusers: { tags: ['dupeTag', 'dupeTag'] } }
155
+ }, { replaceObjectFields: true })
156
+
157
+ await async_test(
158
+ "Updating cancelReasons succeeds even when tags has pre-existing duplicates",
159
+ () => sdk.api.organizations.updateOne(orgId, {
160
+ settings: { calendar: { cancelReasons: ['new reason'] } }
161
+ }, { replaceObjectFields: true }),
162
+ { shouldError: false, onResult: () => true }
163
+ )
164
+
165
+ // Clean up settings to avoid affecting other tests
166
+ await sdk.api.organizations.updateOne(orgId, {
167
+ settings: {
168
+ endusers: {
169
+ tags: [],
170
+ customFields: [],
171
+ builtinFields: [],
172
+ dontRecordCallsToPhone: [],
173
+ },
174
+ calendar: {
175
+ cancelReasons: [],
176
+ },
177
+ }
178
+ }, { replaceObjectFields: true })
179
+ }
180
+
181
+ // Allow running this test file independently
182
+ if (require.main === module) {
183
+ console.log(`Using API URL: ${host}`)
184
+ const sdk = new Session({ host })
185
+ const sdkNonAdmin = new Session({ host })
186
+
187
+ const runTests = async () => {
188
+ await setup_tests(sdk, sdkNonAdmin)
189
+ await organization_settings_duplicates_tests({ sdk, sdkNonAdmin })
190
+ }
191
+
192
+ runTests()
193
+ .then(() => {
194
+ console.log("✅ Organization settings duplicate validation tests completed successfully")
195
+ process.exit(0)
196
+ })
197
+ .catch((error) => {
198
+ console.error("❌ Organization settings duplicate validation tests failed:", error)
199
+ process.exit(1)
200
+ })
201
+ }
@@ -37,6 +37,7 @@ import {
37
37
  import { Session, APIQuery, EnduserSession } from "../sdk"
38
38
  import { enduser_observations_acknowledge_tests } from "./api_tests/enduser_observations_acknowledge.test"
39
39
  import { get_some_projection_tests } from "./api_tests/get_some_projection.test"
40
+ import { mdb_sort_tests } from "./api_tests/mdb_sort.test"
40
41
  import { create_user_notifications_trigger_tests } from "./api_tests/create_user_notifications_trigger.test"
41
42
  import { inbox_thread_assignment_updates_tests } from "./api_tests/inbox_thread_assignment_updates.test"
42
43
  import { inbox_thread_draft_scheduled_tests } from "./api_tests/inbox_thread_draft_scheduled.test"
@@ -88,6 +89,8 @@ import { load_team_chat_tests } from "./api_tests/load_team_chat.test";
88
89
  import { form_started_trigger_tests } from "./api_tests/form_started_trigger.test";
89
90
  import { medication_added_trigger_tests } from "./api_tests/medication_added_trigger.test";
90
91
  import { elation_user_id_tests } from "./api_tests/elation_user_id.test";
92
+ import { organization_settings_duplicates_tests } from "./api_tests/organization_settings_duplicates.test";
93
+ import { calendar_events_bulk_update_tests } from "./api_tests/calendar_events_bulk_update.test";
91
94
  import { openloop_webhooks_tests } from "./api_tests/openloop_webhooks.test";
92
95
  import { beluga_pharmacy_mappings_tests } from "./api_tests/beluga_pharmacy_mappings.test";
93
96
 
@@ -5212,7 +5215,29 @@ const search_tests = async () => {
5212
5215
  `Search by email`,
5213
5216
  () => sdk.api.endusers.getSome({ search: { query: 'search@tellescope'} }),
5214
5217
  { onResult: es => es.length === 2 },
5215
- )
5218
+ )
5219
+
5220
+ // minSearchScore parameter tests
5221
+ await async_test(
5222
+ `Search with minSearchScore accepted`,
5223
+ () => sdk.api.endusers.getSome({ search: { query: 'john', minSearchScore: 0.5 } }),
5224
+ { onResult: es => es.length === 1 && es[0].id === e1.id },
5225
+ )
5226
+ await async_test(
5227
+ `Search with minSearchScore 0 accepted`,
5228
+ () => sdk.api.endusers.getSome({ search: { query: 'john', minSearchScore: 0 } }),
5229
+ { onResult: es => es.length === 1 && es[0].id === e1.id },
5230
+ )
5231
+ await async_test(
5232
+ `Search with negative minSearchScore rejected`,
5233
+ () => sdk.api.endusers.getSome({ search: { query: 'john', minSearchScore: -1 } }),
5234
+ handleAnyError,
5235
+ )
5236
+ await async_test(
5237
+ `Search with string minSearchScore rejected`,
5238
+ () => sdk.api.endusers.getSome({ search: { query: 'john', minSearchScore: 'high' as any } }),
5239
+ handleAnyError,
5240
+ )
5216
5241
 
5217
5242
  await Promise.all([
5218
5243
  sdk.api.endusers.deleteOne(e1.id),
@@ -14101,6 +14126,9 @@ const ip_address_form_tests = async () => {
14101
14126
  await replace_enduser_template_values_tests()
14102
14127
  await mfa_tests()
14103
14128
  await setup_tests(sdk, sdkNonAdmin)
14129
+ await mdb_sort_tests({ sdk, sdkNonAdmin })
14130
+ await organization_settings_duplicates_tests({ sdk, sdkNonAdmin })
14131
+ await search_tests()
14104
14132
  await time_tracks_tests({ sdk, sdkNonAdmin })
14105
14133
  await time_tracks_historical_tests({ sdk, sdkNonAdmin })
14106
14134
  await time_tracks_correction_tests({ sdk, sdkNonAdmin })
@@ -14147,6 +14175,7 @@ const ip_address_form_tests = async () => {
14147
14175
  await rate_limit_tests()
14148
14176
  await ip_address_form_tests()
14149
14177
  await bulk_update_tests()
14178
+ await calendar_events_bulk_update_tests({ sdk })
14150
14179
  await cancel_upcoming_appointments_journey_action_test()
14151
14180
  await multi_tenant_tests() // should come right after setup tests
14152
14181
  await sync_tests_with_access_tags() // should come directly after setup to avoid extra sync values
@@ -14185,7 +14214,6 @@ const ip_address_form_tests = async () => {
14185
14214
  await role_based_access_tests()
14186
14215
  await enduser_session_tests()
14187
14216
  await nextReminderInMS_tests()
14188
- await search_tests()
14189
14217
  await wait_for_trigger_tests()
14190
14218
  await pdf_generation()
14191
14219
  await remove_from_journey_on_incoming_comms_tests().catch(console.error) // timing is unreliable, uncomment if changing logic
Binary file