@tellescope/sdk 1.255.8 → 1.255.10
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/enduser.d.ts +1 -0
- package/lib/cjs/enduser.d.ts.map +1 -1
- package/lib/cjs/sdk.d.ts +3 -2
- package/lib/cjs/sdk.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/calendar_event_limits.test.js +1 -1
- package/lib/cjs/tests/api_tests/calendar_event_limits.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/dont_sync_to_elation_form_submission.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/dont_sync_to_elation_form_submission.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/dont_sync_to_elation_form_submission.test.js +166 -0
- package/lib/cjs/tests/api_tests/dont_sync_to_elation_form_submission.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/enduser_cross_access_isolation.test.js +8 -8
- package/lib/cjs/tests/api_tests/enduser_cross_access_isolation.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/nutrition_tracking.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/nutrition_tracking.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/nutrition_tracking.test.js +483 -0
- package/lib/cjs/tests/api_tests/nutrition_tracking.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/webhook_error_handling.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/webhook_error_handling.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/webhook_error_handling.test.js +324 -0
- package/lib/cjs/tests/api_tests/webhook_error_handling.test.js.map +1 -0
- package/lib/cjs/tests/setup.d.ts +11 -1
- package/lib/cjs/tests/setup.d.ts.map +1 -1
- package/lib/cjs/tests/setup.js +19 -1
- package/lib/cjs/tests/setup.js.map +1 -1
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +207 -192
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/sdk.d.ts +2 -2
- package/lib/esm/tests/api_tests/calendar_event_limits.test.js +2 -2
- package/lib/esm/tests/api_tests/calendar_event_limits.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 +259 -33
- package/lib/esm/tests/api_tests/custom_dashboards.test.js.map +1 -1
- package/lib/esm/tests/api_tests/dont_sync_to_elation_form_submission.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/dont_sync_to_elation_form_submission.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/dont_sync_to_elation_form_submission.test.js +162 -0
- package/lib/esm/tests/api_tests/dont_sync_to_elation_form_submission.test.js.map +1 -0
- package/lib/esm/tests/api_tests/enduser_cross_access_isolation.test.js +9 -9
- package/lib/esm/tests/api_tests/enduser_cross_access_isolation.test.js.map +1 -1
- package/lib/esm/tests/api_tests/medication_added_trigger.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/medication_added_trigger.test.js +206 -136
- package/lib/esm/tests/api_tests/medication_added_trigger.test.js.map +1 -1
- package/lib/esm/tests/api_tests/nutrition_tracking.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/nutrition_tracking.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/nutrition_tracking.test.js +479 -0
- package/lib/esm/tests/api_tests/nutrition_tracking.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts +10 -0
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js +184 -41
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js.map +1 -1
- package/lib/esm/tests/api_tests/webhook_error_handling.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/webhook_error_handling.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/webhook_error_handling.test.js +317 -0
- package/lib/esm/tests/api_tests/webhook_error_handling.test.js.map +1 -0
- package/lib/esm/tests/setup.d.ts +11 -1
- package/lib/esm/tests/setup.d.ts.map +1 -1
- package/lib/esm/tests/setup.js +17 -0
- package/lib/esm/tests/setup.js.map +1 -1
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +233 -206
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/src/tests/api_tests/calendar_event_limits.test.ts +2 -2
- package/src/tests/api_tests/dont_sync_to_elation_form_submission.test.ts +91 -0
- package/src/tests/api_tests/enduser_cross_access_isolation.test.ts +6 -6
- package/src/tests/api_tests/nutrition_tracking.test.ts +425 -0
- package/src/tests/api_tests/webhook_error_handling.test.ts +190 -0
- package/src/tests/setup.ts +13 -0
- package/src/tests/tests.ts +29 -18
- package/test_generated.pdf +0 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
require('source-map-support').install();
|
|
2
|
+
|
|
3
|
+
import express from "express"
|
|
4
|
+
import bodyParser from "body-parser"
|
|
5
|
+
import crypto from "crypto"
|
|
6
|
+
import http from "http"
|
|
7
|
+
|
|
8
|
+
import { Session } from "../../sdk"
|
|
9
|
+
import {
|
|
10
|
+
assert,
|
|
11
|
+
async_test,
|
|
12
|
+
log_header,
|
|
13
|
+
wait,
|
|
14
|
+
} from "@tellescope/testing"
|
|
15
|
+
import { setup_tests } from "../setup"
|
|
16
|
+
|
|
17
|
+
const host = process.env.API_URL || 'http://localhost:8080' as const
|
|
18
|
+
|
|
19
|
+
const TEST_SECRET = "this is a test secret for verifying integrity of web hooks"
|
|
20
|
+
const sha256 = (s: string) => crypto.createHash('sha256').update(s).digest('hex')
|
|
21
|
+
|
|
22
|
+
// DNS resolution for the reserved .invalid TLD always fails => axios ENOTFOUND (no err.response)
|
|
23
|
+
const ENOTFOUND_URL = `http://webhook-error-handling-test.invalid/hook`
|
|
24
|
+
|
|
25
|
+
const POLL_TIMEOUT_MS = 10_000
|
|
26
|
+
const POLL_INTERVAL_MS = 500
|
|
27
|
+
|
|
28
|
+
const find_log_for_url = async (sdk: Session, url: string) => {
|
|
29
|
+
const start = Date.now()
|
|
30
|
+
while (Date.now() - start < POLL_TIMEOUT_MS) {
|
|
31
|
+
const logs = await sdk.api.webhook_logs.getSome({ limit: 50, sort: 'newFirst' as any }) as Array<any>
|
|
32
|
+
const match = logs.find(l => l.url === url)
|
|
33
|
+
if (match) return match
|
|
34
|
+
await wait(undefined, POLL_INTERVAL_MS)
|
|
35
|
+
}
|
|
36
|
+
return null
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const get_failure_count = async (sdk: Session) => {
|
|
40
|
+
const configs = await sdk.api.webhooks.getSome() as Array<any>
|
|
41
|
+
return (configs[0]?.deliveryFailureCount ?? 0) as number
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// the $inc on the webhook config is fire-and-forget — poll until it lands
|
|
45
|
+
const wait_for_failure_count = async (sdk: Session, expected: number) => {
|
|
46
|
+
const start = Date.now()
|
|
47
|
+
let count = -1
|
|
48
|
+
while (Date.now() - start < POLL_TIMEOUT_MS) {
|
|
49
|
+
count = await get_failure_count(sdk)
|
|
50
|
+
if (count === expected) return count
|
|
51
|
+
await wait(undefined, POLL_INTERVAL_MS)
|
|
52
|
+
}
|
|
53
|
+
return count
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Main test function that can be called independently
|
|
57
|
+
export const webhook_error_handling_tests = async ({ sdk, sdkNonAdmin } : { sdk: Session, sdkNonAdmin: Session }) => {
|
|
58
|
+
log_header("Webhook Error Handling Tests")
|
|
59
|
+
|
|
60
|
+
// local receiver: error paths for failure scenarios, a healthy path that verifies integrity
|
|
61
|
+
const app = express()
|
|
62
|
+
app.use(bodyParser.json({ limit: '25mb' }))
|
|
63
|
+
|
|
64
|
+
let successIntegrityVerified = false
|
|
65
|
+
app.post('/fail-400', (_, res) => { res.status(400).json({ error: 'bad request' }) })
|
|
66
|
+
app.post('/fail-500', (_, res) => { res.status(500).json({ error: 'server error' }) })
|
|
67
|
+
app.post('/success', (req, res) => {
|
|
68
|
+
const { records, timestamp, integrity } = req.body
|
|
69
|
+
successIntegrityVerified = (
|
|
70
|
+
sha256((records ?? []).map((r: { id: string }) => r.id).join('') + timestamp + TEST_SECRET) === integrity
|
|
71
|
+
)
|
|
72
|
+
res.status(200).json({})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
const server: http.Server = await new Promise(resolve => {
|
|
76
|
+
const s = app.listen(0, '127.0.0.1', () => resolve(s))
|
|
77
|
+
})
|
|
78
|
+
const receiverBase = `http://127.0.0.1:${(server.address() as any).port}`
|
|
79
|
+
|
|
80
|
+
const enduserIds: string[] = []
|
|
81
|
+
const trigger_delivery = async (label: string) => {
|
|
82
|
+
const enduser = await sdk.api.endusers.createOne({ email: `webhook-error-${label}-${Date.now()}@tellescope.com` })
|
|
83
|
+
enduserIds.push(enduser.id)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
await async_test(
|
|
88
|
+
'configure webhook',
|
|
89
|
+
() => sdk.api.webhooks.configure({ url: ENOTFOUND_URL, secret: TEST_SECRET }),
|
|
90
|
+
{ shouldError: false, onResult: () => true },
|
|
91
|
+
)
|
|
92
|
+
await sdk.api.webhooks.update({ subscriptionUpdates: { endusers: { create: true, update: false, delete: false } } })
|
|
93
|
+
|
|
94
|
+
const initialCount = await get_failure_count(sdk)
|
|
95
|
+
|
|
96
|
+
// Scenario 1: ENOTFOUND — no HTTP response at all
|
|
97
|
+
await trigger_delivery('enotfound')
|
|
98
|
+
const enotfoundLog = await find_log_for_url(sdk, ENOTFOUND_URL)
|
|
99
|
+
assert(!!enotfoundLog, 'no webhook_logs entry for ENOTFOUND delivery', 'ENOTFOUND failure logged to webhook_logs')
|
|
100
|
+
assert(
|
|
101
|
+
typeof enotfoundLog?.response === 'string' && enotfoundLog.response.length > 0,
|
|
102
|
+
`expected string error message response, got: ${JSON.stringify(enotfoundLog?.response)}`,
|
|
103
|
+
'ENOTFOUND log has error message as response'
|
|
104
|
+
)
|
|
105
|
+
assert(enotfoundLog?.responseCode === undefined, 'unexpected responseCode for ENOTFOUND', 'ENOTFOUND log has no responseCode')
|
|
106
|
+
assert(
|
|
107
|
+
await wait_for_failure_count(sdk, initialCount + 1) === initialCount + 1,
|
|
108
|
+
'deliveryFailureCount not incremented after ENOTFOUND',
|
|
109
|
+
'deliveryFailureCount incremented after ENOTFOUND'
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
// Scenario 2a: HTTP 400 from the receiver
|
|
113
|
+
await sdk.api.webhooks.update({ url: `${receiverBase}/fail-400` })
|
|
114
|
+
await trigger_delivery('http400')
|
|
115
|
+
const log400 = await find_log_for_url(sdk, `${receiverBase}/fail-400`)
|
|
116
|
+
assert(log400?.responseCode === 400, `expected responseCode 400, got ${log400?.responseCode}`, 'HTTP 400 responseCode recorded')
|
|
117
|
+
assert(
|
|
118
|
+
await wait_for_failure_count(sdk, initialCount + 2) === initialCount + 2,
|
|
119
|
+
'deliveryFailureCount not incremented after HTTP 400',
|
|
120
|
+
'deliveryFailureCount incremented after HTTP 400'
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
// Scenario 2b: HTTP 500 from the receiver
|
|
124
|
+
await sdk.api.webhooks.update({ url: `${receiverBase}/fail-500` })
|
|
125
|
+
await trigger_delivery('http500')
|
|
126
|
+
const log500 = await find_log_for_url(sdk, `${receiverBase}/fail-500`)
|
|
127
|
+
assert(log500?.responseCode === 500, `expected responseCode 500, got ${log500?.responseCode}`, 'HTTP 500 responseCode recorded')
|
|
128
|
+
assert(
|
|
129
|
+
await wait_for_failure_count(sdk, initialCount + 3) === initialCount + 3,
|
|
130
|
+
'deliveryFailureCount not incremented after HTTP 500',
|
|
131
|
+
'deliveryFailureCount incremented after HTTP 500'
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
// Scenario 3 (timeout): skipped — WEBHOOK_TIMEOUT_MS is a constant (15s), not env-overridable,
|
|
135
|
+
// and a 15s+ non-responding receiver would make this suite unacceptably slow.
|
|
136
|
+
// Covered by security/F-0155-webhook-timeout.test.ts via send_automation_webhook.
|
|
137
|
+
|
|
138
|
+
// Scenario 4: success path unchanged — 200 logged, counter untouched
|
|
139
|
+
await sdk.api.webhooks.update({ url: `${receiverBase}/success` })
|
|
140
|
+
await trigger_delivery('success')
|
|
141
|
+
const successLog = await find_log_for_url(sdk, `${receiverBase}/success`)
|
|
142
|
+
assert(successLog?.responseCode === 200, `expected responseCode 200, got ${successLog?.responseCode}`, 'success responseCode recorded')
|
|
143
|
+
assert(successIntegrityVerified, 'integrity check failed on success delivery', 'success delivery integrity verified')
|
|
144
|
+
await wait(undefined, 1000) // allow any (erroneous) counter update to land before checking
|
|
145
|
+
assert(
|
|
146
|
+
await get_failure_count(sdk) === initialCount + 3,
|
|
147
|
+
'deliveryFailureCount changed on successful delivery',
|
|
148
|
+
'deliveryFailureCount untouched on success'
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
// deliveryFailureCount is server-managed: not settable through the public update endpoint
|
|
152
|
+
const configs = await sdk.api.webhooks.getSome() as Array<any>
|
|
153
|
+
const webhookId = configs[0]?.id
|
|
154
|
+
await sdk.api.webhooks.updateOne(webhookId, { deliveryFailureCount: 9999 } as any).catch(() => {}) // may reject (readonly)
|
|
155
|
+
assert(
|
|
156
|
+
await get_failure_count(sdk) === initialCount + 3,
|
|
157
|
+
'customer was able to overwrite deliveryFailureCount',
|
|
158
|
+
'deliveryFailureCount not customer-settable'
|
|
159
|
+
)
|
|
160
|
+
} finally {
|
|
161
|
+
// stop deliveries for subsequent tests and shut down the local receiver
|
|
162
|
+
await sdk.api.webhooks.update({ subscriptionUpdates: { endusers: { create: false, update: false, delete: false } } }).catch(() => {})
|
|
163
|
+
server.close()
|
|
164
|
+
for (const id of enduserIds) {
|
|
165
|
+
try { await sdk.api.endusers.deleteOne(id) } catch {}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Allow running this test file independently
|
|
171
|
+
if (require.main === module) {
|
|
172
|
+
console.log(`🌐 Using API URL: ${host}`)
|
|
173
|
+
const sdk = new Session({ host })
|
|
174
|
+
const sdkNonAdmin = new Session({ host })
|
|
175
|
+
|
|
176
|
+
const runTests = async () => {
|
|
177
|
+
await setup_tests(sdk, sdkNonAdmin)
|
|
178
|
+
await webhook_error_handling_tests({ sdk, sdkNonAdmin })
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
runTests()
|
|
182
|
+
.then(() => {
|
|
183
|
+
console.log("✅ Webhook error handling test suite completed successfully")
|
|
184
|
+
process.exit(0)
|
|
185
|
+
})
|
|
186
|
+
.catch((error) => {
|
|
187
|
+
console.error("❌ Webhook error handling test suite failed:", error)
|
|
188
|
+
process.exit(1)
|
|
189
|
+
})
|
|
190
|
+
}
|
package/src/tests/setup.ts
CHANGED
|
@@ -159,4 +159,17 @@ export const setup_tests = async (sdk: Session, sdkNonAdmin: Session) => {
|
|
|
159
159
|
sdk.api.users.updateOne(sdk.userInfo.id, { notificationEmailsDisabled: true }),
|
|
160
160
|
sdk.api.users.updateOne(sdkNonAdmin.userInfo.id, { notificationEmailsDisabled: true }),
|
|
161
161
|
]).catch(console.error)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Establishes an enduser session WITHOUT hitting the IP-rate-limited /login-enduser endpoint
|
|
165
|
+
// (throttleByIp: 20/min + 100/hr per IP — the full suite shares one IP and can exceed both).
|
|
166
|
+
// Use for test setup; reserve enduserSDK.authenticate for tests OF the login flow itself.
|
|
167
|
+
export const authenticate_enduser_via_token = async (
|
|
168
|
+
sdk: Session,
|
|
169
|
+
enduserSDK: EnduserSession,
|
|
170
|
+
filter: { id?: string, email?: string, externalId?: string },
|
|
171
|
+
) => {
|
|
172
|
+
const { authToken, enduser } = await sdk.api.endusers.generate_auth_token(filter)
|
|
173
|
+
await enduserSDK.handle_new_session({ authToken, enduser })
|
|
174
|
+
return enduser
|
|
162
175
|
}
|
package/src/tests/tests.ts
CHANGED
|
@@ -56,7 +56,7 @@ import { journey_error_branching_tests } from "./api_tests/journey_error_branchi
|
|
|
56
56
|
import { journey_delete_cancels_actions_tests } from "./api_tests/journey_delete_cancels_actions.test"
|
|
57
57
|
import { afteraction_day_of_month_delay_tests } from "./api_tests/afteraction_day_of_month_delay.test"
|
|
58
58
|
import { push_forms_to_portal_group_completion_tests } from "./api_tests/push_forms_to_portal_group_completion.test"
|
|
59
|
-
import { setup_tests } from "./setup"
|
|
59
|
+
import { authenticate_enduser_via_token, setup_tests } from "./setup"
|
|
60
60
|
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"
|
|
61
61
|
import { DEFAULT_OPERATIONS, PLACEHOLDER_ID, ZENDESK_INTEGRATIONS_TITLE, ZOOM_TITLE } from "@tellescope/constants"
|
|
62
62
|
import {
|
|
@@ -94,6 +94,7 @@ import { monthly_availability_restrictions_tests } from "./api_tests/monthly_ava
|
|
|
94
94
|
import { calendar_event_limits_tests } from "./api_tests/calendar_event_limits.test";
|
|
95
95
|
import { custom_aggregation_tests } from "./api_tests/custom_aggregation.test";
|
|
96
96
|
import { chats_analytics_tests } from "./api_tests/chats_analytics.test";
|
|
97
|
+
import { nutrition_tracking_tests } from "./api_tests/nutrition_tracking.test";
|
|
97
98
|
import { no_access_permission_checks_tests } from "./api_tests/no_access_permission_checks.test";
|
|
98
99
|
import { resource_access_tags_tests } from "./api_tests/resource_access_tags.test";
|
|
99
100
|
import { field_redaction_tests } from "./api_tests/field_redaction.test";
|
|
@@ -120,6 +121,7 @@ import { ai_conversations_tests } from "./api_tests/ai_conversations.test";
|
|
|
120
121
|
import { load_team_chat_tests } from "./api_tests/load_team_chat.test";
|
|
121
122
|
import { form_started_trigger_tests } from "./api_tests/form_started_trigger.test";
|
|
122
123
|
import { form_submitted_trigger_tests } from "./api_tests/form_submitted_trigger.test";
|
|
124
|
+
import { dont_sync_to_elation_form_submission_tests } from "./api_tests/dont_sync_to_elation_form_submission.test";
|
|
123
125
|
import { medication_added_trigger_tests } from "./api_tests/medication_added_trigger.test";
|
|
124
126
|
import { conditional_logic_medication_unit_tests } from "./unit_tests/conditional_logic_medication.test";
|
|
125
127
|
import { elation_user_id_tests } from "./api_tests/elation_user_id.test";
|
|
@@ -136,6 +138,7 @@ import { date_string_validation_tests } from "./api_tests/date_string_validation
|
|
|
136
138
|
import { enduser_session_invalidation_tests } from "./api_tests/enduser_session_invalidation.test";
|
|
137
139
|
import { enduser_cross_access_isolation_tests } from "./api_tests/enduser_cross_access_isolation.test";
|
|
138
140
|
import { calendar_event_webhook_template_tests } from "./api_tests/calendar_event_webhook_template.test";
|
|
141
|
+
import { webhook_error_handling_tests } from "./api_tests/webhook_error_handling.test";
|
|
139
142
|
|
|
140
143
|
const UniquenessViolationMessage = 'Uniqueness Violation'
|
|
141
144
|
|
|
@@ -282,7 +285,7 @@ const sub_organization_tests = async() => {
|
|
|
282
285
|
await async_test(`subsub get subsub`, () => sdkSubSub.api.endusers.getOne(subSubEnduser.id), passOnAnyResult)
|
|
283
286
|
|
|
284
287
|
await sdk.api.endusers.set_password({ id: rootEnduser.id, password })
|
|
285
|
-
await enduserSDK
|
|
288
|
+
await authenticate_enduser_via_token(sdk, enduserSDK, { id: rootEnduser.id })
|
|
286
289
|
await async_test(
|
|
287
290
|
`root enduser create`,
|
|
288
291
|
() => enduserSDK.api.engagement_events.createOne({ significance: 1, type: 'test', enduserId: rootEnduser.id }),
|
|
@@ -294,7 +297,7 @@ const sub_organization_tests = async() => {
|
|
|
294
297
|
|
|
295
298
|
|
|
296
299
|
await sdk.api.endusers.set_password({ id: subEnduser.id, password })
|
|
297
|
-
await enduserSDK
|
|
300
|
+
await authenticate_enduser_via_token(sdk, enduserSDK, { id: subEnduser.id })
|
|
298
301
|
await async_test(
|
|
299
302
|
`sub enduser create`,
|
|
300
303
|
() => enduserSDK.api.engagement_events.createOne({ significance: 1, type: 'test', enduserId: subEnduser.id }),
|
|
@@ -302,7 +305,7 @@ const sub_organization_tests = async() => {
|
|
|
302
305
|
)
|
|
303
306
|
|
|
304
307
|
await sdk.api.endusers.set_password({ id: subSubEnduser.id, password })
|
|
305
|
-
await enduserSDK
|
|
308
|
+
await authenticate_enduser_via_token(sdk, enduserSDK, { id: subSubEnduser.id })
|
|
306
309
|
await async_test(
|
|
307
310
|
`subSub enduser create`,
|
|
308
311
|
() => enduserSDK.api.engagement_events.createOne({ significance: 1, type: 'test', enduserId: subSubEnduser.id }),
|
|
@@ -826,9 +829,14 @@ const enduser_tests = async (queries=sdk.api.endusers) => {
|
|
|
826
829
|
)
|
|
827
830
|
await async_test(
|
|
828
831
|
`enduser registered can log in`,
|
|
829
|
-
() => enduserSDK.authenticate('test3@gmail.com', 'testenduserpassword'),
|
|
832
|
+
() => enduserSDK.authenticate('test3@gmail.com', 'testenduserpassword'),
|
|
830
833
|
{ onResult: e => !!e.authToken && e.enduser.email === 'test3@gmail.com' },
|
|
831
834
|
)
|
|
835
|
+
await async_test(
|
|
836
|
+
`enduser login rejects a wrong password`,
|
|
837
|
+
() => new EnduserSession({ host, businessId }).authenticate('test3@gmail.com', 'wrong-password'),
|
|
838
|
+
handleAnyError,
|
|
839
|
+
)
|
|
832
840
|
|
|
833
841
|
await async_test(
|
|
834
842
|
`update-enduser email conflict`,
|
|
@@ -1378,7 +1386,7 @@ const chat_tests = async() => {
|
|
|
1378
1386
|
|
|
1379
1387
|
const enduser = await sdk.api.endusers.createOne({ email })
|
|
1380
1388
|
await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
|
|
1381
|
-
await
|
|
1389
|
+
await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id }).catch(console.error)
|
|
1382
1390
|
|
|
1383
1391
|
const room = await sdk.api.chat_rooms.createOne({ type: 'internal', userIds: [userId] })
|
|
1384
1392
|
const chat = await sdk.api.chats.createOne({ roomId: room.id, message: "Hello!" })
|
|
@@ -1521,7 +1529,7 @@ const enduserAccessTests = async () => {
|
|
|
1521
1529
|
const enduser = await sdk.api.endusers.createOne({ email })
|
|
1522
1530
|
const enduser2 = await sdk.api.endusers.createOne({ email: 'hi' + email })
|
|
1523
1531
|
await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
|
|
1524
|
-
await
|
|
1532
|
+
await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id }).catch(console.error)
|
|
1525
1533
|
|
|
1526
1534
|
await wait(undefined, 1000) // wait so that refresh_session generates a new authToken (different timestamp)
|
|
1527
1535
|
|
|
@@ -1706,7 +1714,7 @@ const files_tests = async () => {
|
|
|
1706
1714
|
log_header("Files")
|
|
1707
1715
|
const enduser = await sdk.api.endusers.createOne({ email })
|
|
1708
1716
|
await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
|
|
1709
|
-
await
|
|
1717
|
+
await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id }).catch(console.error)
|
|
1710
1718
|
await sdkNonAdmin.authenticate(nonAdminEmail, nonAdminPassword) // to use new role, handle logout on role change
|
|
1711
1719
|
|
|
1712
1720
|
const buff = buffer.Buffer.from('test file data')
|
|
@@ -1817,7 +1825,7 @@ const enduser_session_tests = async () => {
|
|
|
1817
1825
|
|
|
1818
1826
|
const enduser = await sdk.api.endusers.createOne({ email })
|
|
1819
1827
|
await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
|
|
1820
|
-
await
|
|
1828
|
+
await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id }).catch(console.error)
|
|
1821
1829
|
|
|
1822
1830
|
const users = await enduserSDK.api.users.display_info()
|
|
1823
1831
|
assert(users && users.length > 0, 'No users returned', 'Get user display info for enduser')
|
|
@@ -5839,7 +5847,7 @@ export const meetings_tests = async () => {
|
|
|
5839
5847
|
|
|
5840
5848
|
const enduser = await sdk.api.endusers.createOne({ email })
|
|
5841
5849
|
await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
|
|
5842
|
-
await
|
|
5850
|
+
await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id }).catch(console.error)
|
|
5843
5851
|
|
|
5844
5852
|
const privateMeeting = await sdk.api.meetings.start_meeting({ })
|
|
5845
5853
|
const publicMeeting = await sdk.api.meetings.start_meeting({ publicRead: true })
|
|
@@ -6205,7 +6213,7 @@ const community_tests = async () => {
|
|
|
6205
6213
|
|
|
6206
6214
|
const enduser = await sdk.api.endusers.createOne({ email })
|
|
6207
6215
|
await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
|
|
6208
|
-
await
|
|
6216
|
+
await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id }).catch(console.error)
|
|
6209
6217
|
|
|
6210
6218
|
const forum = await sdk.api.forums.createOne({ title: 'test', publicRead: true })
|
|
6211
6219
|
const privateForum = await sdk.api.forums.createOne({ title: 'test 2', publicRead: false })
|
|
@@ -6352,7 +6360,7 @@ const redaction_tests = async () => {
|
|
|
6352
6360
|
unredactedFields: [{ field: 'testField', value: 'testValue' }] as any,
|
|
6353
6361
|
})
|
|
6354
6362
|
await sdk.api.endusers.set_password({ id: enduser.id, password }).catch(console.error)
|
|
6355
|
-
await
|
|
6363
|
+
await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id }).catch(console.error)
|
|
6356
6364
|
|
|
6357
6365
|
const endusers = await enduserSDK.api.endusers.getSome()
|
|
6358
6366
|
const forUser = await sdk.api.endusers.getSome()
|
|
@@ -6599,7 +6607,7 @@ export const calendar_event_RSVPs_tests = async () => {
|
|
|
6599
6607
|
log_header("Calendar Event RSVPs")
|
|
6600
6608
|
|
|
6601
6609
|
await enduserSDK.register({ email: 'rsvps@tellescope.com', password: "testenduserpassword" })
|
|
6602
|
-
await enduserSDK
|
|
6610
|
+
await authenticate_enduser_via_token(sdk, enduserSDK, { email: 'rsvps@tellescope.com' })
|
|
6603
6611
|
|
|
6604
6612
|
const event = await sdk.api.calendar_events.createOne({
|
|
6605
6613
|
title: "RSVP Event",
|
|
@@ -6684,7 +6692,7 @@ const post_comments_tests = async () => {
|
|
|
6684
6692
|
log_header("Post Comments")
|
|
6685
6693
|
|
|
6686
6694
|
await enduserSDK.register({ email: 'rsvps@tellescope.com', password: "testenduserpassword" })
|
|
6687
|
-
await enduserSDK
|
|
6695
|
+
await authenticate_enduser_via_token(sdk, enduserSDK, { email: 'rsvps@tellescope.com' })
|
|
6688
6696
|
|
|
6689
6697
|
const forumId = (await sdk.api.forums.createOne({ title: "RSVP Event", publicRead: true })).id
|
|
6690
6698
|
const postId = (await sdk.api.forum_posts.createOne({ forumId, title: 'Post', htmlContent: '', textContent: '', })).id
|
|
@@ -6902,13 +6910,13 @@ export const self_serve_appointment_booking_tests = async () => {
|
|
|
6902
6910
|
})
|
|
6903
6911
|
|
|
6904
6912
|
const enduserSDK2 = new EnduserSession({ host, businessId })
|
|
6905
|
-
await enduserSDK2
|
|
6913
|
+
await authenticate_enduser_via_token(sdk, enduserSDK2, { email: 'sebass+ca@tellescope.com' }).catch(console.error)
|
|
6906
6914
|
|
|
6907
6915
|
const enduserSDK3 = new EnduserSession({ host, businessId })
|
|
6908
|
-
await enduserSDK3
|
|
6916
|
+
await authenticate_enduser_via_token(sdk, enduserSDK3, { email: 'sebass+3@tellescope.com' }).catch(console.error)
|
|
6909
6917
|
|
|
6910
6918
|
// NY Enduser Tests
|
|
6911
|
-
await enduserSDK
|
|
6919
|
+
await authenticate_enduser_via_token(sdk, enduserSDK, { email: 'sebass+ny@tellescope.com' }).catch(console.error)
|
|
6912
6920
|
await async_test(
|
|
6913
6921
|
'30 minute slots for state restriction',
|
|
6914
6922
|
() => enduserSDK.api.calendar_events.get_appointment_availability({
|
|
@@ -7569,7 +7577,7 @@ const run_autoreply_test = async (title: string, { expectingAutoreply, autoreply
|
|
|
7569
7577
|
|
|
7570
7578
|
const enduser = await sdk.api.endusers.createOne({ fname: 'Autoreply', lname: "Test", email: "autoreply@tellescope.com" })
|
|
7571
7579
|
await sdk.api.endusers.set_password({ id: enduser.id, password })
|
|
7572
|
-
await enduserSDK
|
|
7580
|
+
await authenticate_enduser_via_token(sdk, enduserSDK, { id: enduser.id })
|
|
7573
7581
|
|
|
7574
7582
|
const room = await sdk.api.chat_rooms.createOne({
|
|
7575
7583
|
userIds: [sdk.userInfo.id],
|
|
@@ -15054,6 +15062,7 @@ const ip_address_form_tests = async () => {
|
|
|
15054
15062
|
await invite_user_enumeration_tests({ sdk, sdkNonAdmin })
|
|
15055
15063
|
await handle_incoming_communication_cross_tenant_tests({ sdk, sdkNonAdmin })
|
|
15056
15064
|
await calendar_event_webhook_template_tests({ sdk, sdkNonAdmin })
|
|
15065
|
+
await webhook_error_handling_tests({ sdk, sdkNonAdmin })
|
|
15057
15066
|
await outbound_chat_sent_trigger_tests({ sdk })
|
|
15058
15067
|
await enduser_login_rate_limits_tests({ sdk, sdkNonAdmin })
|
|
15059
15068
|
await data_sync_redaction_bypass_tests({ sdk, sdkNonAdmin })
|
|
@@ -15074,6 +15083,7 @@ const ip_address_form_tests = async () => {
|
|
|
15074
15083
|
await chats_analytics_tests({ sdk, sdkNonAdmin })
|
|
15075
15084
|
await field_redaction_tests({ sdk, sdkNonAdmin })
|
|
15076
15085
|
await form_submitted_trigger_tests({ sdk, sdkNonAdmin })
|
|
15086
|
+
await dont_sync_to_elation_form_submission_tests({ sdk, sdkNonAdmin })
|
|
15077
15087
|
await date_string_validation_tests({ sdk, sdkNonAdmin })
|
|
15078
15088
|
await openloop_webhooks_tests({ sdk, sdkNonAdmin })
|
|
15079
15089
|
await mdi_webhooks_tests({ sdk, sdkNonAdmin })
|
|
@@ -15120,6 +15130,7 @@ const ip_address_form_tests = async () => {
|
|
|
15120
15130
|
await inbox_threads_loading_tests()
|
|
15121
15131
|
await load_inbox_data_tests({ sdk, sdkNonAdmin })
|
|
15122
15132
|
await enduser_observations_acknowledge_tests({ sdk, sdkNonAdmin })
|
|
15133
|
+
await nutrition_tracking_tests({ sdk, sdkNonAdmin })
|
|
15123
15134
|
await translations_tests({ sdk, sdkNonAdmin })
|
|
15124
15135
|
await create_user_notifications_trigger_tests({ sdk })
|
|
15125
15136
|
await group_mms_active_tests()
|
package/test_generated.pdf
CHANGED
|
Binary file
|