@tellescope/sdk 1.251.0 → 1.252.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/tests/api_tests/calendar_event_webhook_template.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/calendar_event_webhook_template.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/calendar_event_webhook_template.test.js +337 -0
- package/lib/cjs/tests/api_tests/calendar_event_webhook_template.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.js +287 -0
- package/lib/cjs/tests/api_tests/enduser_login_rate_limits.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/push_forms_to_portal_group_completion.test.d.ts.map +1 -1
- package/lib/cjs/tests/api_tests/push_forms_to_portal_group_completion.test.js +234 -198
- package/lib/cjs/tests/api_tests/push_forms_to_portal_group_completion.test.js.map +1 -1
- package/lib/cjs/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.d.ts +28 -0
- package/lib/cjs/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.js +349 -0
- package/lib/cjs/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts +28 -0
- package/lib/cjs/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js +247 -0
- package/lib/cjs/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0007-invite-user-enumeration.test.d.ts +29 -0
- package/lib/cjs/tests/api_tests/security/F-0007-invite-user-enumeration.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0007-invite-user-enumeration.test.js +278 -0
- package/lib/cjs/tests/api_tests/security/F-0007-invite-user-enumeration.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.d.ts +24 -0
- package/lib/cjs/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.js +201 -0
- package/lib/cjs/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html.test.d.ts +2 -0
- package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html.test.js +148 -0
- package/lib/cjs/tests/api_tests/security/F-0013-sanitize-user-html.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0016-prototype-pollution.test.d.ts +2 -0
- package/lib/cjs/tests/api_tests/security/F-0016-prototype-pollution.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0016-prototype-pollution.test.js +88 -0
- package/lib/cjs/tests/api_tests/security/F-0016-prototype-pollution.test.js.map +1 -0
- package/lib/cjs/tests/tests.d.ts.map +1 -1
- package/lib/cjs/tests/tests.js +186 -151
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/tests/api_tests/calendar_event_webhook_template.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/calendar_event_webhook_template.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/calendar_event_webhook_template.test.js +333 -0
- package/lib/esm/tests/api_tests/calendar_event_webhook_template.test.js.map +1 -0
- package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.js +280 -0
- package/lib/esm/tests/api_tests/enduser_login_rate_limits.test.js.map +1 -0
- package/lib/esm/tests/api_tests/push_forms_to_portal_group_completion.test.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/push_forms_to_portal_group_completion.test.js +235 -199
- package/lib/esm/tests/api_tests/push_forms_to_portal_group_completion.test.js.map +1 -1
- package/lib/esm/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.d.ts +28 -0
- package/lib/esm/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.js +345 -0
- package/lib/esm/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts +28 -0
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js +243 -0
- package/lib/esm/tests/api_tests/security/F-0005-ai-conversations-rbac.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0007-invite-user-enumeration.test.d.ts +29 -0
- package/lib/esm/tests/api_tests/security/F-0007-invite-user-enumeration.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0007-invite-user-enumeration.test.js +271 -0
- package/lib/esm/tests/api_tests/security/F-0007-invite-user-enumeration.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.d.ts +24 -0
- package/lib/esm/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.js +194 -0
- package/lib/esm/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html.test.d.ts +2 -0
- package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html.test.js +144 -0
- package/lib/esm/tests/api_tests/security/F-0013-sanitize-user-html.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0016-prototype-pollution.test.d.ts +2 -0
- package/lib/esm/tests/api_tests/security/F-0016-prototype-pollution.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0016-prototype-pollution.test.js +84 -0
- package/lib/esm/tests/api_tests/security/F-0016-prototype-pollution.test.js.map +1 -0
- package/lib/esm/tests/tests.d.ts.map +1 -1
- package/lib/esm/tests/tests.js +186 -151
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/tests/api_tests/calendar_event_webhook_template.test.ts +204 -0
- package/src/tests/api_tests/enduser_login_rate_limits.test.ts +178 -0
- package/src/tests/api_tests/push_forms_to_portal_group_completion.test.ts +113 -88
- package/src/tests/api_tests/security/F-0001-data-sync-redaction-bypass.test.ts +236 -0
- package/src/tests/api_tests/security/F-0005-ai-conversations-rbac.test.ts +154 -0
- package/src/tests/api_tests/security/F-0007-invite-user-enumeration.test.ts +198 -0
- package/src/tests/api_tests/security/F-0008-handle-incoming-communication-cross-tenant.test.ts +130 -0
- package/src/tests/api_tests/security/F-0013-sanitize-user-html.test.ts +109 -0
- package/src/tests/api_tests/security/F-0016-prototype-pollution.test.ts +50 -0
- package/src/tests/tests.ts +19 -2
- package/test_generated.pdf +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar_event_webhook_template.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/api_tests/calendar_event_webhook_template.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AA4BnC,eAAO,MAAM,qCAAqC;SAClB,OAAO;iBAAe,OAAO;mBAsJ5D,CAAA"}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
11
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
12
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
13
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
14
|
+
function step(op) {
|
|
15
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
16
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
17
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
18
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
19
|
+
switch (op[0]) {
|
|
20
|
+
case 0: case 1: t = op; break;
|
|
21
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
22
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
23
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
24
|
+
default:
|
|
25
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
26
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
27
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
28
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
29
|
+
if (t[2]) _.ops.pop();
|
|
30
|
+
_.trys.pop(); continue;
|
|
31
|
+
}
|
|
32
|
+
op = body.call(thisArg, _);
|
|
33
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
34
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
require('source-map-support').install();
|
|
38
|
+
import { Session } from "../../sdk";
|
|
39
|
+
import { async_test, log_header, wait, } from "@tellescope/testing";
|
|
40
|
+
import { setup_tests } from "../setup";
|
|
41
|
+
var host = process.env.API_URL || 'http://localhost:8080';
|
|
42
|
+
var HEALTHIE_TITLE = 'Healthie'; // mirror @tellescope/constants HEALTHIE_TITLE
|
|
43
|
+
// Unreachable webhook target — the request will fail quickly but the API still writes
|
|
44
|
+
// the resolved payload to webhook_logs, which is what we're verifying.
|
|
45
|
+
var WEBHOOK_TARGET_URL = 'http://127.0.0.1:9';
|
|
46
|
+
var find_log_for_url = function (sdk, url, expectedHealthieId) { return __awaiter(void 0, void 0, void 0, function () {
|
|
47
|
+
var start, logs, match;
|
|
48
|
+
return __generator(this, function (_a) {
|
|
49
|
+
switch (_a.label) {
|
|
50
|
+
case 0:
|
|
51
|
+
start = Date.now();
|
|
52
|
+
_a.label = 1;
|
|
53
|
+
case 1:
|
|
54
|
+
if (!(Date.now() - start < 10000)) return [3 /*break*/, 4];
|
|
55
|
+
return [4 /*yield*/, sdk.api.webhook_logs.getSome({ limit: 50, sort: 'newFirst' })];
|
|
56
|
+
case 2:
|
|
57
|
+
logs = _a.sent();
|
|
58
|
+
match = logs.find(function (l) { var _a; return l.url === url && ((_a = l.payload) === null || _a === void 0 ? void 0 : _a.healthieId) === expectedHealthieId; });
|
|
59
|
+
if (match)
|
|
60
|
+
return [2 /*return*/, match];
|
|
61
|
+
return [4 /*yield*/, wait(undefined, 500)];
|
|
62
|
+
case 3:
|
|
63
|
+
_a.sent();
|
|
64
|
+
return [3 /*break*/, 1];
|
|
65
|
+
case 4: return [2 /*return*/, null];
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}); };
|
|
69
|
+
// Main test function that can be called independently
|
|
70
|
+
export var calendar_event_webhook_template_tests = function (_a) {
|
|
71
|
+
var sdk = _a.sdk, sdkNonAdmin = _a.sdkNonAdmin;
|
|
72
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
73
|
+
var enduser, externalIdEvent, referencesEvent, journey, step, _b, _c, _d, _e, _f;
|
|
74
|
+
return __generator(this, function (_g) {
|
|
75
|
+
switch (_g.label) {
|
|
76
|
+
case 0:
|
|
77
|
+
log_header("Calendar Event Webhook Template Tests");
|
|
78
|
+
return [4 /*yield*/, sdk.api.endusers.createOne({})
|
|
79
|
+
// Case 1: Healthie ID resolved via source + externalId
|
|
80
|
+
];
|
|
81
|
+
case 1:
|
|
82
|
+
enduser = _g.sent();
|
|
83
|
+
return [4 /*yield*/, sdk.api.calendar_events.createOne({
|
|
84
|
+
title: 'External ID Calendar Event',
|
|
85
|
+
durationInMinutes: 30,
|
|
86
|
+
startTimeInMS: Date.now(),
|
|
87
|
+
attendees: [{ type: 'enduser', id: enduser.id }],
|
|
88
|
+
source: HEALTHIE_TITLE,
|
|
89
|
+
externalId: 'evt_HEALTHIE_123',
|
|
90
|
+
})
|
|
91
|
+
// Case 2: Healthie ID resolved via references
|
|
92
|
+
];
|
|
93
|
+
case 2:
|
|
94
|
+
externalIdEvent = _g.sent();
|
|
95
|
+
return [4 /*yield*/, sdk.api.calendar_events.createOne({
|
|
96
|
+
title: 'References Calendar Event',
|
|
97
|
+
durationInMinutes: 30,
|
|
98
|
+
startTimeInMS: Date.now(),
|
|
99
|
+
attendees: [{ type: 'enduser', id: enduser.id }],
|
|
100
|
+
references: [{ type: HEALTHIE_TITLE, id: 'evt_REF_456' }],
|
|
101
|
+
})
|
|
102
|
+
// create an automation step to satisfy schema validation (automationStepId is required)
|
|
103
|
+
];
|
|
104
|
+
case 3:
|
|
105
|
+
referencesEvent = _g.sent();
|
|
106
|
+
return [4 /*yield*/, sdk.api.journeys.createOne({
|
|
107
|
+
title: 'Calendar Event Webhook Template Tests',
|
|
108
|
+
defaultState: 'State 1',
|
|
109
|
+
})];
|
|
110
|
+
case 4:
|
|
111
|
+
journey = _g.sent();
|
|
112
|
+
return [4 /*yield*/, sdk.api.automation_steps.createOne({
|
|
113
|
+
journeyId: journey.id,
|
|
114
|
+
events: [{ type: 'onJourneyStart', info: {} }],
|
|
115
|
+
action: {
|
|
116
|
+
type: 'sendWebhook',
|
|
117
|
+
info: {
|
|
118
|
+
message: 'placeholder',
|
|
119
|
+
url: WEBHOOK_TARGET_URL,
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
})];
|
|
123
|
+
case 5:
|
|
124
|
+
step = _g.sent();
|
|
125
|
+
_g.label = 6;
|
|
126
|
+
case 6:
|
|
127
|
+
_g.trys.push([6, , 10, 26]);
|
|
128
|
+
return [4 /*yield*/, async_test('Send Webhook resolves {{calendar_event.Healthie ID}} from source+externalId', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
129
|
+
var url, log, payload;
|
|
130
|
+
return __generator(this, function (_a) {
|
|
131
|
+
switch (_a.label) {
|
|
132
|
+
case 0:
|
|
133
|
+
url = "".concat(WEBHOOK_TARGET_URL, "/external/").concat(externalIdEvent.id);
|
|
134
|
+
return [4 /*yield*/, sdk.api.webhooks.send_automation_webhook({
|
|
135
|
+
message: 'placeholder',
|
|
136
|
+
enduserId: enduser.id,
|
|
137
|
+
automationStepId: step.id,
|
|
138
|
+
action: {
|
|
139
|
+
type: 'sendWebhook',
|
|
140
|
+
info: {
|
|
141
|
+
message: 'placeholder',
|
|
142
|
+
url: url,
|
|
143
|
+
fields: [
|
|
144
|
+
{ field: 'healthieId', value: '{{calendar_event.Healthie ID}}' },
|
|
145
|
+
{ field: 'title', value: '{{calendar_event.title}}' },
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
context: { calendarEventId: externalIdEvent.id },
|
|
150
|
+
}).catch(function () { })]; // the unreachable URL is expected to error after logging
|
|
151
|
+
case 1:
|
|
152
|
+
_a.sent(); // the unreachable URL is expected to error after logging
|
|
153
|
+
return [4 /*yield*/, find_log_for_url(sdk, url, 'evt_HEALTHIE_123')];
|
|
154
|
+
case 2:
|
|
155
|
+
log = _a.sent();
|
|
156
|
+
if (!log)
|
|
157
|
+
return [2 /*return*/, false];
|
|
158
|
+
payload = log.payload;
|
|
159
|
+
return [2 /*return*/, (payload === null || payload === void 0 ? void 0 : payload.healthieId) === 'evt_HEALTHIE_123'
|
|
160
|
+
&& (payload === null || payload === void 0 ? void 0 : payload.title) === externalIdEvent.title];
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}); }, { onResult: function (r) { return r === true; } })];
|
|
164
|
+
case 7:
|
|
165
|
+
_g.sent();
|
|
166
|
+
return [4 /*yield*/, async_test('Send Webhook resolves {{calendar_event.Healthie ID}} from references', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
167
|
+
var url, log, payload;
|
|
168
|
+
return __generator(this, function (_a) {
|
|
169
|
+
switch (_a.label) {
|
|
170
|
+
case 0:
|
|
171
|
+
url = "".concat(WEBHOOK_TARGET_URL, "/refs/").concat(referencesEvent.id);
|
|
172
|
+
return [4 /*yield*/, sdk.api.webhooks.send_automation_webhook({
|
|
173
|
+
message: 'placeholder',
|
|
174
|
+
enduserId: enduser.id,
|
|
175
|
+
automationStepId: step.id,
|
|
176
|
+
action: {
|
|
177
|
+
type: 'sendWebhook',
|
|
178
|
+
info: {
|
|
179
|
+
message: 'placeholder',
|
|
180
|
+
url: url,
|
|
181
|
+
fields: [
|
|
182
|
+
{ field: 'healthieId', value: '{{calendar_event.Healthie ID}}' },
|
|
183
|
+
{ field: 'title', value: '{{calendar_event.title}}' },
|
|
184
|
+
],
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
context: { calendarEventId: referencesEvent.id },
|
|
188
|
+
}).catch(function () { })];
|
|
189
|
+
case 1:
|
|
190
|
+
_a.sent();
|
|
191
|
+
return [4 /*yield*/, find_log_for_url(sdk, url, 'evt_REF_456')];
|
|
192
|
+
case 2:
|
|
193
|
+
log = _a.sent();
|
|
194
|
+
if (!log)
|
|
195
|
+
return [2 /*return*/, false];
|
|
196
|
+
payload = log.payload;
|
|
197
|
+
return [2 /*return*/, (payload === null || payload === void 0 ? void 0 : payload.healthieId) === 'evt_REF_456'
|
|
198
|
+
&& (payload === null || payload === void 0 ? void 0 : payload.title) === referencesEvent.title];
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}); }, { onResult: function (r) { return r === true; } })];
|
|
202
|
+
case 8:
|
|
203
|
+
_g.sent();
|
|
204
|
+
return [4 /*yield*/, async_test('Send Webhook leaves {{calendar_event.Healthie ID}} blank when no calendarEventId in context', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
205
|
+
var url, start, logs, match, payload;
|
|
206
|
+
return __generator(this, function (_a) {
|
|
207
|
+
switch (_a.label) {
|
|
208
|
+
case 0:
|
|
209
|
+
url = "".concat(WEBHOOK_TARGET_URL, "/nocontext");
|
|
210
|
+
return [4 /*yield*/, sdk.api.webhooks.send_automation_webhook({
|
|
211
|
+
message: 'placeholder',
|
|
212
|
+
enduserId: enduser.id,
|
|
213
|
+
automationStepId: step.id,
|
|
214
|
+
action: {
|
|
215
|
+
type: 'sendWebhook',
|
|
216
|
+
info: {
|
|
217
|
+
message: 'placeholder',
|
|
218
|
+
url: url,
|
|
219
|
+
fields: [
|
|
220
|
+
{ field: 'healthieId', value: '{{calendar_event.Healthie ID}}' },
|
|
221
|
+
],
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
// no calendarEventId
|
|
225
|
+
}).catch(function () { })
|
|
226
|
+
// Without a calendar event in context, the templating helper returns the input
|
|
227
|
+
// unchanged, so the literal template string remains in the payload.
|
|
228
|
+
];
|
|
229
|
+
case 1:
|
|
230
|
+
_a.sent();
|
|
231
|
+
start = Date.now();
|
|
232
|
+
_a.label = 2;
|
|
233
|
+
case 2:
|
|
234
|
+
if (!(Date.now() - start < 10000)) return [3 /*break*/, 5];
|
|
235
|
+
return [4 /*yield*/, sdk.api.webhook_logs.getSome({ limit: 50, sort: 'newFirst' })];
|
|
236
|
+
case 3:
|
|
237
|
+
logs = _a.sent();
|
|
238
|
+
match = logs.find(function (l) { return l.url === url; });
|
|
239
|
+
if (match) {
|
|
240
|
+
payload = match.payload;
|
|
241
|
+
return [2 /*return*/, (payload === null || payload === void 0 ? void 0 : payload.healthieId) === '{{calendar_event.Healthie ID}}'];
|
|
242
|
+
}
|
|
243
|
+
return [4 /*yield*/, wait(undefined, 500)];
|
|
244
|
+
case 4:
|
|
245
|
+
_a.sent();
|
|
246
|
+
return [3 /*break*/, 2];
|
|
247
|
+
case 5: return [2 /*return*/, false];
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}); }, { onResult: function (r) { return r === true; } })];
|
|
251
|
+
case 9:
|
|
252
|
+
_g.sent();
|
|
253
|
+
return [3 /*break*/, 26];
|
|
254
|
+
case 10:
|
|
255
|
+
_g.trys.push([10, 12, , 13]);
|
|
256
|
+
return [4 /*yield*/, sdk.api.calendar_events.deleteOne(externalIdEvent.id)];
|
|
257
|
+
case 11:
|
|
258
|
+
_g.sent();
|
|
259
|
+
return [3 /*break*/, 13];
|
|
260
|
+
case 12:
|
|
261
|
+
_b = _g.sent();
|
|
262
|
+
return [3 /*break*/, 13];
|
|
263
|
+
case 13:
|
|
264
|
+
_g.trys.push([13, 15, , 16]);
|
|
265
|
+
return [4 /*yield*/, sdk.api.calendar_events.deleteOne(referencesEvent.id)];
|
|
266
|
+
case 14:
|
|
267
|
+
_g.sent();
|
|
268
|
+
return [3 /*break*/, 16];
|
|
269
|
+
case 15:
|
|
270
|
+
_c = _g.sent();
|
|
271
|
+
return [3 /*break*/, 16];
|
|
272
|
+
case 16:
|
|
273
|
+
_g.trys.push([16, 18, , 19]);
|
|
274
|
+
return [4 /*yield*/, sdk.api.automation_steps.deleteOne(step.id)];
|
|
275
|
+
case 17:
|
|
276
|
+
_g.sent();
|
|
277
|
+
return [3 /*break*/, 19];
|
|
278
|
+
case 18:
|
|
279
|
+
_d = _g.sent();
|
|
280
|
+
return [3 /*break*/, 19];
|
|
281
|
+
case 19:
|
|
282
|
+
_g.trys.push([19, 21, , 22]);
|
|
283
|
+
return [4 /*yield*/, sdk.api.journeys.deleteOne(journey.id)];
|
|
284
|
+
case 20:
|
|
285
|
+
_g.sent();
|
|
286
|
+
return [3 /*break*/, 22];
|
|
287
|
+
case 21:
|
|
288
|
+
_e = _g.sent();
|
|
289
|
+
return [3 /*break*/, 22];
|
|
290
|
+
case 22:
|
|
291
|
+
_g.trys.push([22, 24, , 25]);
|
|
292
|
+
return [4 /*yield*/, sdk.api.endusers.deleteOne(enduser.id)];
|
|
293
|
+
case 23:
|
|
294
|
+
_g.sent();
|
|
295
|
+
return [3 /*break*/, 25];
|
|
296
|
+
case 24:
|
|
297
|
+
_f = _g.sent();
|
|
298
|
+
return [3 /*break*/, 25];
|
|
299
|
+
case 25: return [7 /*endfinally*/];
|
|
300
|
+
case 26: return [2 /*return*/];
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
};
|
|
305
|
+
// Allow running this test file independently
|
|
306
|
+
if (require.main === module) {
|
|
307
|
+
console.log("\uD83C\uDF10 Using API URL: ".concat(host));
|
|
308
|
+
var sdk_1 = new Session({ host: host });
|
|
309
|
+
var sdkNonAdmin_1 = new Session({ host: host });
|
|
310
|
+
var runTests = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
311
|
+
return __generator(this, function (_a) {
|
|
312
|
+
switch (_a.label) {
|
|
313
|
+
case 0: return [4 /*yield*/, setup_tests(sdk_1, sdkNonAdmin_1)];
|
|
314
|
+
case 1:
|
|
315
|
+
_a.sent();
|
|
316
|
+
return [4 /*yield*/, calendar_event_webhook_template_tests({ sdk: sdk_1, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
317
|
+
case 2:
|
|
318
|
+
_a.sent();
|
|
319
|
+
return [2 /*return*/];
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
}); };
|
|
323
|
+
runTests()
|
|
324
|
+
.then(function () {
|
|
325
|
+
console.log("✅ Calendar event webhook template test suite completed successfully");
|
|
326
|
+
process.exit(0);
|
|
327
|
+
})
|
|
328
|
+
.catch(function (error) {
|
|
329
|
+
console.error("❌ Calendar event webhook template test suite failed:", error);
|
|
330
|
+
process.exit(1);
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
//# sourceMappingURL=calendar_event_webhook_template.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar_event_webhook_template.test.js","sourceRoot":"","sources":["../../../../src/tests/api_tests/calendar_event_webhook_template.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enduser_login_rate_limits.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/api_tests/enduser_login_rate_limits.test.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAoCnC,eAAO,MAAM,+BAA+B;SAAwC,OAAO;iBAAe,OAAO;mBAoHhH,CAAA"}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
11
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
12
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
13
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
14
|
+
function step(op) {
|
|
15
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
16
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
17
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
18
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
19
|
+
switch (op[0]) {
|
|
20
|
+
case 0: case 1: t = op; break;
|
|
21
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
22
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
23
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
24
|
+
default:
|
|
25
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
26
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
27
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
28
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
29
|
+
if (t[2]) _.ops.pop();
|
|
30
|
+
_.trys.pop(); continue;
|
|
31
|
+
}
|
|
32
|
+
op = body.call(thisArg, _);
|
|
33
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
34
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
require('source-map-support').install();
|
|
38
|
+
import axios from "axios";
|
|
39
|
+
import { Session } from "../../sdk";
|
|
40
|
+
import { async_test, log_header, } from "@tellescope/testing";
|
|
41
|
+
import { setup_tests } from "../setup";
|
|
42
|
+
var host = process.env.API_URL || 'http://localhost:8080';
|
|
43
|
+
// Per-IP rate limits applied to enduser public endpoints:
|
|
44
|
+
// POST /v1/login-enduser 20 / min, 100 / hour
|
|
45
|
+
// POST /v1/begin-enduser-login-flow 10 / min, 50 / hour
|
|
46
|
+
// POST /v1/endusers/send-otp-code 5 / min, 30 / hour
|
|
47
|
+
// Plus a per-identifier limit on begin_login_flow: 5 / 10 min per email|phone.
|
|
48
|
+
var post = function (path, body) { return __awaiter(void 0, void 0, void 0, function () {
|
|
49
|
+
var res, err_1;
|
|
50
|
+
var _a, _b;
|
|
51
|
+
return __generator(this, function (_c) {
|
|
52
|
+
switch (_c.label) {
|
|
53
|
+
case 0:
|
|
54
|
+
_c.trys.push([0, 2, , 3]);
|
|
55
|
+
return [4 /*yield*/, axios.post("".concat(host).concat(path), body, { validateStatus: function () { return true; } })];
|
|
56
|
+
case 1:
|
|
57
|
+
res = _c.sent();
|
|
58
|
+
return [2 /*return*/, { status: res.status, data: res.data }];
|
|
59
|
+
case 2:
|
|
60
|
+
err_1 = _c.sent();
|
|
61
|
+
return [2 /*return*/, { status: (_a = err_1 === null || err_1 === void 0 ? void 0 : err_1.response) === null || _a === void 0 ? void 0 : _a.status, data: (_b = err_1 === null || err_1 === void 0 ? void 0 : err_1.response) === null || _b === void 0 ? void 0 : _b.data }];
|
|
62
|
+
case 3: return [2 /*return*/];
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}); };
|
|
66
|
+
var fire_until_429 = function (cap, send) { return __awaiter(void 0, void 0, void 0, function () {
|
|
67
|
+
var triggeredAt, i, status_1;
|
|
68
|
+
return __generator(this, function (_a) {
|
|
69
|
+
switch (_a.label) {
|
|
70
|
+
case 0:
|
|
71
|
+
triggeredAt = -1;
|
|
72
|
+
i = 0;
|
|
73
|
+
_a.label = 1;
|
|
74
|
+
case 1:
|
|
75
|
+
if (!(i < cap + 5)) return [3 /*break*/, 4];
|
|
76
|
+
return [4 /*yield*/, send(i)];
|
|
77
|
+
case 2:
|
|
78
|
+
status_1 = (_a.sent()).status;
|
|
79
|
+
if (status_1 === 429) {
|
|
80
|
+
triggeredAt = i;
|
|
81
|
+
return [3 /*break*/, 4];
|
|
82
|
+
}
|
|
83
|
+
_a.label = 3;
|
|
84
|
+
case 3:
|
|
85
|
+
i++;
|
|
86
|
+
return [3 /*break*/, 1];
|
|
87
|
+
case 4: return [2 /*return*/, triggeredAt];
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}); };
|
|
91
|
+
export var enduser_login_rate_limits_tests = function (_a) {
|
|
92
|
+
var sdk = _a.sdk, sdkNonAdmin = _a.sdkNonAdmin;
|
|
93
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
94
|
+
var businessId, loginTrip, beginIpTrip, fixedEmail, beginIdTrip, fakeToken, sendOtpTrip, tripped, ts, enduser, goodLogin_1, goodLoginRetry_1;
|
|
95
|
+
return __generator(this, function (_b) {
|
|
96
|
+
switch (_b.label) {
|
|
97
|
+
case 0:
|
|
98
|
+
log_header("Enduser Login Rate Limit Tests");
|
|
99
|
+
businessId = sdk.userInfo.businessId;
|
|
100
|
+
// Ensure throttled_events from prior tests don't bleed in.
|
|
101
|
+
return [4 /*yield*/, sdk.reset_db()
|
|
102
|
+
// ---- /v1/login-enduser per-IP cap (20/min) ----
|
|
103
|
+
// Bogus emails ensure we never reach the actual DB lookup / login work.
|
|
104
|
+
];
|
|
105
|
+
case 1:
|
|
106
|
+
// Ensure throttled_events from prior tests don't bleed in.
|
|
107
|
+
_b.sent();
|
|
108
|
+
return [4 /*yield*/, fire_until_429(20, function (i) { return post('/v1/login-enduser', {
|
|
109
|
+
email: "rl-login-".concat(Date.now(), "-").concat(i, "@tellescope.com"),
|
|
110
|
+
password: 'NotARealPassword!2025',
|
|
111
|
+
businessId: businessId,
|
|
112
|
+
}); })];
|
|
113
|
+
case 2:
|
|
114
|
+
loginTrip = _b.sent();
|
|
115
|
+
return [4 /*yield*/, async_test('login per-IP throttle trips within first 21 requests', function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
116
|
+
return [2 /*return*/, (loginTrip >= 0 && loginTrip <= 20) ? 'tripped' : "not-tripped:".concat(loginTrip)];
|
|
117
|
+
}); }); }, { expectedResult: 'tripped' })];
|
|
118
|
+
case 3:
|
|
119
|
+
_b.sent();
|
|
120
|
+
return [4 /*yield*/, sdk.reset_db()
|
|
121
|
+
// ---- /v1/begin-enduser-login-flow per-IP cap (10/min) ----
|
|
122
|
+
// Use distinct emails so the per-identifier limit (5/10min) does NOT trip first;
|
|
123
|
+
// we want the IP cap to be the first thing to fire.
|
|
124
|
+
];
|
|
125
|
+
case 4:
|
|
126
|
+
_b.sent();
|
|
127
|
+
return [4 /*yield*/, fire_until_429(10, function (i) { return post('/v1/begin-enduser-login-flow', {
|
|
128
|
+
email: "rl-begin-ip-".concat(Date.now(), "-").concat(i, "@tellescope.com"),
|
|
129
|
+
businessId: businessId,
|
|
130
|
+
}); })];
|
|
131
|
+
case 5:
|
|
132
|
+
beginIpTrip = _b.sent();
|
|
133
|
+
return [4 /*yield*/, async_test('begin_login_flow per-IP throttle trips within first 11 requests', function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
134
|
+
return [2 /*return*/, (beginIpTrip >= 0 && beginIpTrip <= 10) ? 'tripped' : "not-tripped:".concat(beginIpTrip)];
|
|
135
|
+
}); }); }, { expectedResult: 'tripped' })];
|
|
136
|
+
case 6:
|
|
137
|
+
_b.sent();
|
|
138
|
+
return [4 /*yield*/, sdk.reset_db()
|
|
139
|
+
// ---- /v1/begin-enduser-login-flow per-identifier cap (5 / 10 min per email) ----
|
|
140
|
+
// Hit a single email below the per-IP cap.
|
|
141
|
+
];
|
|
142
|
+
case 7:
|
|
143
|
+
_b.sent();
|
|
144
|
+
fixedEmail = "rl-begin-id-".concat(Date.now(), "@tellescope.com");
|
|
145
|
+
return [4 /*yield*/, fire_until_429(5, function () { return post('/v1/begin-enduser-login-flow', {
|
|
146
|
+
email: fixedEmail,
|
|
147
|
+
businessId: businessId,
|
|
148
|
+
}); })];
|
|
149
|
+
case 8:
|
|
150
|
+
beginIdTrip = _b.sent();
|
|
151
|
+
return [4 /*yield*/, async_test('begin_login_flow per-identifier throttle trips within first 6 requests', function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
152
|
+
return [2 /*return*/, (beginIdTrip >= 0 && beginIdTrip <= 5) ? 'tripped' : "not-tripped:".concat(beginIdTrip)];
|
|
153
|
+
}); }); }, { expectedResult: 'tripped' })];
|
|
154
|
+
case 9:
|
|
155
|
+
_b.sent();
|
|
156
|
+
return [4 /*yield*/, sdk.reset_db()
|
|
157
|
+
// ---- /v1/endusers/send-otp-code per-IP cap (5/min) ----
|
|
158
|
+
// Use a bogus JWT-shaped token so we trip the IP guard first (it runs before any DB work).
|
|
159
|
+
];
|
|
160
|
+
case 10:
|
|
161
|
+
_b.sent();
|
|
162
|
+
fakeToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCJ9.sig';
|
|
163
|
+
return [4 /*yield*/, fire_until_429(5, function () { return post('/v1/endusers/send-otp-code', {
|
|
164
|
+
token: fakeToken,
|
|
165
|
+
method: 'email',
|
|
166
|
+
}); })];
|
|
167
|
+
case 11:
|
|
168
|
+
sendOtpTrip = _b.sent();
|
|
169
|
+
return [4 /*yield*/, async_test('send_otp per-IP throttle trips within first 6 requests', function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
|
|
170
|
+
return [2 /*return*/, (sendOtpTrip >= 0 && sendOtpTrip <= 5) ? 'tripped' : "not-tripped:".concat(sendOtpTrip)];
|
|
171
|
+
}); }); }, { expectedResult: 'tripped' })
|
|
172
|
+
// Confirm 429 response does not leak the keying strategy (no mention of "ip" or "address").
|
|
173
|
+
];
|
|
174
|
+
case 12:
|
|
175
|
+
_b.sent();
|
|
176
|
+
return [4 /*yield*/, post('/v1/endusers/send-otp-code', { token: fakeToken, method: 'email' })];
|
|
177
|
+
case 13:
|
|
178
|
+
tripped = _b.sent();
|
|
179
|
+
return [4 /*yield*/, async_test('429 response does not mention "ip" or "address"', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
180
|
+
var msg;
|
|
181
|
+
var _a, _b;
|
|
182
|
+
return __generator(this, function (_c) {
|
|
183
|
+
msg = ((_b = (_a = tripped.data) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : '').toLowerCase();
|
|
184
|
+
return [2 /*return*/, (msg.includes('ip') || msg.includes('address')) ? 'leaked' : 'safe'];
|
|
185
|
+
});
|
|
186
|
+
}); }, { expectedResult: 'safe' })
|
|
187
|
+
// ---- Legitimate-login regression: a single successful login should still go through ----
|
|
188
|
+
// Reset state, then create a real enduser with a password and confirm one login succeeds.
|
|
189
|
+
];
|
|
190
|
+
case 14:
|
|
191
|
+
_b.sent();
|
|
192
|
+
// ---- Legitimate-login regression: a single successful login should still go through ----
|
|
193
|
+
// Reset state, then create a real enduser with a password and confirm one login succeeds.
|
|
194
|
+
return [4 /*yield*/, sdk.reset_db()];
|
|
195
|
+
case 15:
|
|
196
|
+
// ---- Legitimate-login regression: a single successful login should still go through ----
|
|
197
|
+
// Reset state, then create a real enduser with a password and confirm one login succeeds.
|
|
198
|
+
_b.sent();
|
|
199
|
+
ts = Date.now();
|
|
200
|
+
return [4 /*yield*/, sdk.api.endusers.createOne({
|
|
201
|
+
fname: 'RateLimitOk', lname: 'Enduser',
|
|
202
|
+
email: "rl-legit-".concat(ts, "@tellescope.com"),
|
|
203
|
+
})];
|
|
204
|
+
case 16:
|
|
205
|
+
enduser = _b.sent();
|
|
206
|
+
_b.label = 17;
|
|
207
|
+
case 17:
|
|
208
|
+
_b.trys.push([17, , 23, 26]);
|
|
209
|
+
return [4 /*yield*/, sdk.api.endusers.set_password({ id: enduser.id, password: 'CorrectPassword123!' })];
|
|
210
|
+
case 18:
|
|
211
|
+
_b.sent();
|
|
212
|
+
return [4 /*yield*/, post('/v1/login-enduser', {
|
|
213
|
+
email: enduser.email,
|
|
214
|
+
password: 'CorrectPassword123!',
|
|
215
|
+
businessId: businessId,
|
|
216
|
+
})];
|
|
217
|
+
case 19:
|
|
218
|
+
goodLogin_1 = _b.sent();
|
|
219
|
+
return [4 /*yield*/, async_test('legitimate login still succeeds (returns authToken, not 429)', function () { return __awaiter(void 0, void 0, void 0, function () { var _a; return __generator(this, function (_b) {
|
|
220
|
+
return [2 /*return*/, goodLogin_1.status === 200 && !!((_a = goodLogin_1.data) === null || _a === void 0 ? void 0 : _a.authToken) ? 'ok' : "failed:".concat(goodLogin_1.status)];
|
|
221
|
+
}); }); }, { expectedResult: 'ok' })
|
|
222
|
+
// A subsequent successful login by the same user/IP should also succeed —
|
|
223
|
+
// a single legitimate user retrying must not trip the per-IP cap.
|
|
224
|
+
];
|
|
225
|
+
case 20:
|
|
226
|
+
_b.sent();
|
|
227
|
+
return [4 /*yield*/, post('/v1/login-enduser', {
|
|
228
|
+
email: enduser.email,
|
|
229
|
+
password: 'CorrectPassword123!',
|
|
230
|
+
businessId: businessId,
|
|
231
|
+
})];
|
|
232
|
+
case 21:
|
|
233
|
+
goodLoginRetry_1 = _b.sent();
|
|
234
|
+
return [4 /*yield*/, async_test('legitimate login retry still succeeds', function () { return __awaiter(void 0, void 0, void 0, function () { var _a; return __generator(this, function (_b) {
|
|
235
|
+
return [2 /*return*/, goodLoginRetry_1.status === 200 && !!((_a = goodLoginRetry_1.data) === null || _a === void 0 ? void 0 : _a.authToken) ? 'ok' : "failed:".concat(goodLoginRetry_1.status)];
|
|
236
|
+
}); }); }, { expectedResult: 'ok' })];
|
|
237
|
+
case 22:
|
|
238
|
+
_b.sent();
|
|
239
|
+
return [3 /*break*/, 26];
|
|
240
|
+
case 23: return [4 /*yield*/, sdk.api.endusers.deleteOne(enduser.id).catch(function () { return null; })];
|
|
241
|
+
case 24:
|
|
242
|
+
_b.sent();
|
|
243
|
+
return [4 /*yield*/, sdk.reset_db().catch(function () { return null; })];
|
|
244
|
+
case 25:
|
|
245
|
+
_b.sent();
|
|
246
|
+
return [7 /*endfinally*/];
|
|
247
|
+
case 26: return [2 /*return*/];
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
};
|
|
252
|
+
// Allow running this test file independently
|
|
253
|
+
if (require.main === module) {
|
|
254
|
+
console.log("\uD83C\uDF10 Using API URL: ".concat(host));
|
|
255
|
+
var sdk_1 = new Session({ host: host });
|
|
256
|
+
var sdkNonAdmin_1 = new Session({ host: host });
|
|
257
|
+
var runTests = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
258
|
+
return __generator(this, function (_a) {
|
|
259
|
+
switch (_a.label) {
|
|
260
|
+
case 0: return [4 /*yield*/, setup_tests(sdk_1, sdkNonAdmin_1)];
|
|
261
|
+
case 1:
|
|
262
|
+
_a.sent();
|
|
263
|
+
return [4 /*yield*/, enduser_login_rate_limits_tests({ sdk: sdk_1, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
264
|
+
case 2:
|
|
265
|
+
_a.sent();
|
|
266
|
+
return [2 /*return*/];
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
}); };
|
|
270
|
+
runTests()
|
|
271
|
+
.then(function () {
|
|
272
|
+
console.log("✅ Enduser login rate limit test suite completed successfully");
|
|
273
|
+
process.exit(0);
|
|
274
|
+
})
|
|
275
|
+
.catch(function (error) {
|
|
276
|
+
console.error("❌ Enduser login rate limit test suite failed:", error);
|
|
277
|
+
process.exit(1);
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
//# sourceMappingURL=enduser_login_rate_limits.test.js.map
|