@tellescope/sdk 1.254.0 → 1.255.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/sdk.d.ts +4 -0
- package/lib/cjs/sdk.d.ts.map +1 -1
- package/lib/cjs/sdk.js +5 -0
- package/lib/cjs/sdk.js.map +1 -1
- package/lib/cjs/tests/api_tests/ai_decision_summary_config.test.d.ts +16 -0
- package/lib/cjs/tests/api_tests/ai_decision_summary_config.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/ai_decision_summary_config.test.js +187 -0
- package/lib/cjs/tests/api_tests/ai_decision_summary_config.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/mdi_case_offerings.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/mdi_case_offerings.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/mdi_case_offerings.test.js +443 -0
- package/lib/cjs/tests/api_tests/mdi_case_offerings.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/order_status_equals_frequency.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/order_status_equals_frequency.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/order_status_equals_frequency.test.js +254 -0
- package/lib/cjs/tests/api_tests/order_status_equals_frequency.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/organization_api_keys.test.d.ts +6 -0
- package/lib/cjs/tests/api_tests/organization_api_keys.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/organization_api_keys.test.js +226 -0
- package/lib/cjs/tests/api_tests/organization_api_keys.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.d.ts +21 -0
- package/lib/cjs/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.js +362 -0
- package/lib/cjs/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0145-globalunique-leak.test.d.ts +20 -0
- package/lib/cjs/tests/api_tests/security/F-0145-globalunique-leak.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0145-globalunique-leak.test.js +139 -0
- package/lib/cjs/tests/api_tests/security/F-0145-globalunique-leak.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0151-load-inbox-redaction.test.d.ts +18 -0
- package/lib/cjs/tests/api_tests/security/F-0151-load-inbox-redaction.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0151-load-inbox-redaction.test.js +156 -0
- package/lib/cjs/tests/api_tests/security/F-0151-load-inbox-redaction.test.js.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0155-webhook-timeout.test.d.ts +20 -0
- package/lib/cjs/tests/api_tests/security/F-0155-webhook-timeout.test.d.ts.map +1 -0
- package/lib/cjs/tests/api_tests/security/F-0155-webhook-timeout.test.js +157 -0
- package/lib/cjs/tests/api_tests/security/F-0155-webhook-timeout.test.js.map +1 -0
- package/lib/cjs/tests/setup.d.ts.map +1 -1
- package/lib/cjs/tests/setup.js +20 -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 +543 -282
- package/lib/cjs/tests/tests.js.map +1 -1
- package/lib/esm/sdk.d.ts +6 -2
- package/lib/esm/sdk.d.ts.map +1 -1
- package/lib/esm/sdk.js +5 -0
- package/lib/esm/sdk.js.map +1 -1
- package/lib/esm/session.d.ts +1 -0
- package/lib/esm/session.d.ts.map +1 -1
- package/lib/esm/tests/api_tests/ai_decision_summary_config.test.d.ts +16 -0
- package/lib/esm/tests/api_tests/ai_decision_summary_config.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/ai_decision_summary_config.test.js +183 -0
- package/lib/esm/tests/api_tests/ai_decision_summary_config.test.js.map +1 -0
- package/lib/esm/tests/api_tests/mdi_case_offerings.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/mdi_case_offerings.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/mdi_case_offerings.test.js +439 -0
- package/lib/esm/tests/api_tests/mdi_case_offerings.test.js.map +1 -0
- package/lib/esm/tests/api_tests/order_status_equals_frequency.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/order_status_equals_frequency.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/order_status_equals_frequency.test.js +250 -0
- package/lib/esm/tests/api_tests/order_status_equals_frequency.test.js.map +1 -0
- package/lib/esm/tests/api_tests/organization_api_keys.test.d.ts +6 -0
- package/lib/esm/tests/api_tests/organization_api_keys.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/organization_api_keys.test.js +222 -0
- package/lib/esm/tests/api_tests/organization_api_keys.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.d.ts +21 -0
- package/lib/esm/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.js +358 -0
- package/lib/esm/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0145-globalunique-leak.test.d.ts +20 -0
- package/lib/esm/tests/api_tests/security/F-0145-globalunique-leak.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0145-globalunique-leak.test.js +135 -0
- package/lib/esm/tests/api_tests/security/F-0145-globalunique-leak.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0151-load-inbox-redaction.test.d.ts +18 -0
- package/lib/esm/tests/api_tests/security/F-0151-load-inbox-redaction.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0151-load-inbox-redaction.test.js +152 -0
- package/lib/esm/tests/api_tests/security/F-0151-load-inbox-redaction.test.js.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0155-webhook-timeout.test.d.ts +20 -0
- package/lib/esm/tests/api_tests/security/F-0155-webhook-timeout.test.d.ts.map +1 -0
- package/lib/esm/tests/api_tests/security/F-0155-webhook-timeout.test.js +150 -0
- package/lib/esm/tests/api_tests/security/F-0155-webhook-timeout.test.js.map +1 -0
- package/lib/esm/tests/setup.d.ts.map +1 -1
- package/lib/esm/tests/setup.js +20 -1
- 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 +543 -282
- package/lib/esm/tests/tests.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/src/sdk.ts +11 -0
- package/src/tests/api_tests/mdi_case_offerings.test.ts +414 -0
- package/src/tests/api_tests/organization_api_keys.test.ts +207 -0
- package/src/tests/api_tests/security/F-0116-F-0119-enduser-cross-create.test.ts +221 -0
- package/src/tests/api_tests/security/F-0145-globalunique-leak.test.ts +78 -0
- package/src/tests/api_tests/security/F-0151-load-inbox-redaction.test.ts +81 -0
- package/src/tests/api_tests/security/F-0155-webhook-timeout.test.ts +85 -0
- package/src/tests/setup.ts +9 -0
- package/src/tests/tests.ts +199 -2
- package/test_generated.pdf +0 -0
|
@@ -0,0 +1,183 @@
|
|
|
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, } from "@tellescope/testing";
|
|
40
|
+
import { setup_tests } from "../setup";
|
|
41
|
+
var host = process.env.API_URL || 'http://localhost:8080';
|
|
42
|
+
/**
|
|
43
|
+
* Exercises generate_ai_decision with the new `aiSummaryConfiguration` payload (CU-86e1h0j7f).
|
|
44
|
+
*
|
|
45
|
+
* The handler responds early with `{}` and then builds context + calls Bedrock in the background,
|
|
46
|
+
* so the deterministic, Bedrock-independent assertions here are:
|
|
47
|
+
* 1. A valid `aiSummaryConfiguration` payload is accepted (schema + validator wiring) → resolves.
|
|
48
|
+
* 2. The legacy `{ prompt, sources }` payload still validates (back-compat) → resolves.
|
|
49
|
+
* 3. A malformed `aiSummaryConfiguration` (invalid data source type) is rejected by the validator
|
|
50
|
+
* BEFORE the early response → throws.
|
|
51
|
+
*/
|
|
52
|
+
export var ai_decision_summary_config_tests = function (_a) {
|
|
53
|
+
var sdk = _a.sdk;
|
|
54
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
55
|
+
var enduser, journey, decisionStep;
|
|
56
|
+
return __generator(this, function (_b) {
|
|
57
|
+
switch (_b.label) {
|
|
58
|
+
case 0:
|
|
59
|
+
log_header("AI Decision — aiSummaryConfiguration payload");
|
|
60
|
+
return [4 /*yield*/, sdk.api.endusers.createOne({
|
|
61
|
+
fname: 'AIDecision',
|
|
62
|
+
lname: 'Config',
|
|
63
|
+
email: "ai-decision-config-".concat(Date.now(), "@example.com"),
|
|
64
|
+
})];
|
|
65
|
+
case 1:
|
|
66
|
+
enduser = _b.sent();
|
|
67
|
+
return [4 /*yield*/, sdk.api.journeys.createOne({ title: "AI Decision Config Journey ".concat(Date.now()) })
|
|
68
|
+
// a real aiDecision step using the new shared config shape
|
|
69
|
+
];
|
|
70
|
+
case 2:
|
|
71
|
+
journey = _b.sent();
|
|
72
|
+
return [4 /*yield*/, sdk.api.automation_steps.createOne({
|
|
73
|
+
journeyId: journey.id,
|
|
74
|
+
action: {
|
|
75
|
+
type: 'aiDecision',
|
|
76
|
+
info: {
|
|
77
|
+
outcomes: ['needs_followup', 'no_action'],
|
|
78
|
+
aiSummaryConfiguration: {
|
|
79
|
+
prompt: 'Decide whether the patient needs a follow-up based on recent activity.',
|
|
80
|
+
dataSources: [
|
|
81
|
+
{ type: 'sms_messages', limit: 5, lookbackMS: 30 * 24 * 60 * 60 * 1000 },
|
|
82
|
+
{ type: 'chats', limit: 5 },
|
|
83
|
+
{ type: 'form_responses', limit: 3 },
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
events: [{ type: 'onJourneyStart', info: {} }],
|
|
89
|
+
})];
|
|
90
|
+
case 3:
|
|
91
|
+
decisionStep = _b.sent();
|
|
92
|
+
_b.label = 4;
|
|
93
|
+
case 4:
|
|
94
|
+
_b.trys.push([4, , 8, 10]);
|
|
95
|
+
// 1. valid new-shape payload — handler accepts and returns early with {}
|
|
96
|
+
return [4 /*yield*/, async_test("generate_ai_decision accepts aiSummaryConfiguration payload", function () { return sdk.api.ai_conversations.generate_ai_decision({
|
|
97
|
+
enduserId: enduser.id,
|
|
98
|
+
automationStepId: decisionStep.id,
|
|
99
|
+
outcomes: ['needs_followup', 'no_action'],
|
|
100
|
+
aiSummaryConfiguration: {
|
|
101
|
+
prompt: 'Decide whether the patient needs a follow-up based on recent activity.',
|
|
102
|
+
dataSources: [
|
|
103
|
+
{ type: 'sms_messages', limit: 5, lookbackMS: 30 * 24 * 60 * 60 * 1000 },
|
|
104
|
+
{ type: 'chats', limit: 5 },
|
|
105
|
+
],
|
|
106
|
+
maxOutputTokens: 50,
|
|
107
|
+
},
|
|
108
|
+
}); }, { onResult: function () { return true; } })
|
|
109
|
+
// 2. legacy payload still validates (back-compat)
|
|
110
|
+
];
|
|
111
|
+
case 5:
|
|
112
|
+
// 1. valid new-shape payload — handler accepts and returns early with {}
|
|
113
|
+
_b.sent();
|
|
114
|
+
// 2. legacy payload still validates (back-compat)
|
|
115
|
+
return [4 /*yield*/, async_test("generate_ai_decision still accepts legacy prompt/sources payload", function () { return sdk.api.ai_conversations.generate_ai_decision({
|
|
116
|
+
enduserId: enduser.id,
|
|
117
|
+
automationStepId: decisionStep.id,
|
|
118
|
+
outcomes: ['needs_followup', 'no_action'],
|
|
119
|
+
prompt: 'Legacy decision prompt',
|
|
120
|
+
sources: [{ type: 'SMS', limit: 3 }],
|
|
121
|
+
}); }, { onResult: function () { return true; } })
|
|
122
|
+
// 3. malformed aiSummaryConfiguration (invalid data source type) rejected by the validator
|
|
123
|
+
];
|
|
124
|
+
case 6:
|
|
125
|
+
// 2. legacy payload still validates (back-compat)
|
|
126
|
+
_b.sent();
|
|
127
|
+
// 3. malformed aiSummaryConfiguration (invalid data source type) rejected by the validator
|
|
128
|
+
return [4 /*yield*/, async_test("generate_ai_decision rejects an invalid aiSummaryConfiguration data source", function () { return sdk.api.ai_conversations.generate_ai_decision({
|
|
129
|
+
enduserId: enduser.id,
|
|
130
|
+
automationStepId: decisionStep.id,
|
|
131
|
+
outcomes: ['needs_followup', 'no_action'],
|
|
132
|
+
aiSummaryConfiguration: {
|
|
133
|
+
prompt: 'bad config',
|
|
134
|
+
dataSources: [{ type: 'not_a_real_source', limit: 1 }],
|
|
135
|
+
},
|
|
136
|
+
}); }, { shouldError: true, onError: function () { return true; } })];
|
|
137
|
+
case 7:
|
|
138
|
+
// 3. malformed aiSummaryConfiguration (invalid data source type) rejected by the validator
|
|
139
|
+
_b.sent();
|
|
140
|
+
return [3 /*break*/, 10];
|
|
141
|
+
case 8: return [4 /*yield*/, Promise.all([
|
|
142
|
+
sdk.api.journeys.deleteOne(journey.id).catch(function () { }),
|
|
143
|
+
sdk.api.endusers.deleteOne(enduser.id).catch(function () { }),
|
|
144
|
+
])];
|
|
145
|
+
case 9:
|
|
146
|
+
_b.sent();
|
|
147
|
+
return [7 /*endfinally*/];
|
|
148
|
+
case 10:
|
|
149
|
+
console.log("✅ AI Decision aiSummaryConfiguration tests completed successfully");
|
|
150
|
+
return [2 /*return*/];
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
};
|
|
155
|
+
// Allow running this test file independently
|
|
156
|
+
if (require.main === module) {
|
|
157
|
+
console.log("\uD83C\uDF10 Using API URL: ".concat(host));
|
|
158
|
+
var sdk_1 = new Session({ host: host });
|
|
159
|
+
var sdkNonAdmin_1 = new Session({ host: host });
|
|
160
|
+
var runTests = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
161
|
+
return __generator(this, function (_a) {
|
|
162
|
+
switch (_a.label) {
|
|
163
|
+
case 0: return [4 /*yield*/, setup_tests(sdk_1, sdkNonAdmin_1)];
|
|
164
|
+
case 1:
|
|
165
|
+
_a.sent();
|
|
166
|
+
return [4 /*yield*/, ai_decision_summary_config_tests({ sdk: sdk_1, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
167
|
+
case 2:
|
|
168
|
+
_a.sent();
|
|
169
|
+
return [2 /*return*/];
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}); };
|
|
173
|
+
runTests()
|
|
174
|
+
.then(function () {
|
|
175
|
+
console.log("✅ AI Decision aiSummaryConfiguration test suite completed successfully");
|
|
176
|
+
process.exit(0);
|
|
177
|
+
})
|
|
178
|
+
.catch(function (error) {
|
|
179
|
+
console.error("❌ AI Decision aiSummaryConfiguration test suite failed:", error);
|
|
180
|
+
process.exit(1);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
//# sourceMappingURL=ai_decision_summary_config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai_decision_summary_config.test.js","sourceRoot":"","sources":["../../../../src/tests/api_tests/ai_decision_summary_config.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mdi_case_offerings.test.d.ts","sourceRoot":"","sources":["../../../../src/tests/api_tests/mdi_case_offerings.test.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AA2FnC,eAAO,MAAM,wBAAwB;SAAuC,OAAO;iBAAe,OAAO;mBA2SxG,CAAA"}
|
|
@@ -0,0 +1,439 @@
|
|
|
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, } from "@tellescope/testing";
|
|
40
|
+
import { setup_tests } from "../setup";
|
|
41
|
+
import { evaluate_conditional_logic, evaluate_string_field_comparison } from "@tellescope/utilities";
|
|
42
|
+
var host = process.env.API_URL || 'http://localhost:8080';
|
|
43
|
+
// Local replica of the API's resolve_case_offerings (md_integrations.ts), built
|
|
44
|
+
// from the same shared @tellescope/utilities helpers it uses, so we can assert
|
|
45
|
+
// the resolution behavior from the SDK test harness.
|
|
46
|
+
var is_empty_conditions = function (conditions) {
|
|
47
|
+
if (!conditions || !Object.keys(conditions).length)
|
|
48
|
+
return true;
|
|
49
|
+
var condition = conditions.condition;
|
|
50
|
+
if (condition !== undefined)
|
|
51
|
+
return !Object.keys(condition).length;
|
|
52
|
+
return false;
|
|
53
|
+
};
|
|
54
|
+
var resolve_case_offerings = function (offerings, responses) { return (offerings.filter(function (o) {
|
|
55
|
+
if (!o.conditions || is_empty_conditions(o.conditions))
|
|
56
|
+
return true;
|
|
57
|
+
return evaluate_conditional_logic(o.conditions, function (key, value) { var _a; return evaluate_string_field_comparison((_a = responses.find(function (r) { return r.externalId === key; })) === null || _a === void 0 ? void 0 : _a.value, value); });
|
|
58
|
+
})); };
|
|
59
|
+
var to_number = function (v) {
|
|
60
|
+
var n = typeof v === 'number' ? v : parseFloat(String(v !== null && v !== void 0 ? v : ''));
|
|
61
|
+
return Number.isFinite(n) ? n : undefined;
|
|
62
|
+
};
|
|
63
|
+
var enduser_height_to_cm = function (h) {
|
|
64
|
+
var inches = to_number(h === null || h === void 0 ? void 0 : h.value);
|
|
65
|
+
if (inches === undefined)
|
|
66
|
+
return undefined;
|
|
67
|
+
return Math.round(inches * 2.54);
|
|
68
|
+
};
|
|
69
|
+
var enduser_weight_to_kg = function (w) {
|
|
70
|
+
var lbs = to_number(w === null || w === void 0 ? void 0 : w.value);
|
|
71
|
+
if (lbs === undefined)
|
|
72
|
+
return undefined;
|
|
73
|
+
return Math.round(lbs * 0.45359237 * 100) / 100;
|
|
74
|
+
};
|
|
75
|
+
var PATIENT_MAPPED_EXTERNAL_IDS = new Set([
|
|
76
|
+
'fname', 'first_name', 'lname', 'last_name',
|
|
77
|
+
'email', 'dateOfBirth', 'gender', 'phone', 'address',
|
|
78
|
+
'height', 'weight',
|
|
79
|
+
'allergies', 'current_medications', 'medical_conditions', 'special_necessities', 'pregnancy',
|
|
80
|
+
'intro_video_id',
|
|
81
|
+
]);
|
|
82
|
+
// Mirrors the externalId exclusion step in form_response_to_case_questions:
|
|
83
|
+
// patient-mapped fields are dropped, everything else survives.
|
|
84
|
+
var case_question_external_ids = function (responses) { return (responses
|
|
85
|
+
.filter(function (r) { return !(r.externalId && PATIENT_MAPPED_EXTERNAL_IDS.has(r.externalId)); })
|
|
86
|
+
.map(function (r) { return r.externalId; })
|
|
87
|
+
.filter(function (id) { return id !== undefined; })); };
|
|
88
|
+
var resolve_displayed_options = function (response, formFields) {
|
|
89
|
+
var _a, _b;
|
|
90
|
+
if (formFields === void 0) { formFields = []; }
|
|
91
|
+
var field = (formFields.find(function (f) { return f._id.toString() === response.fieldId; })
|
|
92
|
+
|| formFields.find(function (f) { return response.externalId && f.externalId === response.externalId; }));
|
|
93
|
+
return ((response.answer.type === 'multiple_choice' || response.answer.type === 'Dropdown')
|
|
94
|
+
&& ((_b = (_a = field === null || field === void 0 ? void 0 : field.options) === null || _a === void 0 ? void 0 : _a.choices) === null || _b === void 0 ? void 0 : _b.length)) ? field.options.choices : undefined;
|
|
95
|
+
};
|
|
96
|
+
export var mdi_case_offerings_tests = function (_a) {
|
|
97
|
+
var sdk = _a.sdk, sdkNonAdmin = _a.sdkNonAdmin;
|
|
98
|
+
return __awaiter(void 0, void 0, void 0, function () {
|
|
99
|
+
var testFormId, MIXED_1;
|
|
100
|
+
return __generator(this, function (_b) {
|
|
101
|
+
switch (_b.label) {
|
|
102
|
+
case 0:
|
|
103
|
+
log_header("MDI Case Offerings Tests");
|
|
104
|
+
_b.label = 1;
|
|
105
|
+
case 1:
|
|
106
|
+
_b.trys.push([1, , 18, 21]);
|
|
107
|
+
// --- Schema round-trip tests ---
|
|
108
|
+
return [4 /*yield*/, async_test("Create form with mdiCaseOfferings mixing unconditional and conditional entries", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
109
|
+
var offerings, form, fetched;
|
|
110
|
+
var _a, _b, _c;
|
|
111
|
+
return __generator(this, function (_d) {
|
|
112
|
+
switch (_d.label) {
|
|
113
|
+
case 0:
|
|
114
|
+
offerings = [
|
|
115
|
+
{ offering_id: "offering-always" },
|
|
116
|
+
{ offering_id: "offering-ca", conditions: { condition: { state: "CA" } } },
|
|
117
|
+
{
|
|
118
|
+
offering_id: "offering-ca-glp",
|
|
119
|
+
conditions: { $and: [{ condition: { state: "CA" } }, { condition: { med_type: "weightLoss" } }] },
|
|
120
|
+
},
|
|
121
|
+
];
|
|
122
|
+
return [4 /*yield*/, sdk.api.forms.createOne({
|
|
123
|
+
title: 'MDI Case Offerings Test Form',
|
|
124
|
+
mdiCaseOfferings: offerings,
|
|
125
|
+
})];
|
|
126
|
+
case 1:
|
|
127
|
+
form = _d.sent();
|
|
128
|
+
testFormId = form.id;
|
|
129
|
+
return [4 /*yield*/, sdk.api.forms.getOne(form.id)];
|
|
130
|
+
case 2:
|
|
131
|
+
fetched = _d.sent();
|
|
132
|
+
return [2 /*return*/, (((_a = fetched.mdiCaseOfferings) === null || _a === void 0 ? void 0 : _a.length) === 3
|
|
133
|
+
&& fetched.mdiCaseOfferings[0].offering_id === "offering-always"
|
|
134
|
+
&& fetched.mdiCaseOfferings[0].conditions === undefined
|
|
135
|
+
&& !!((_b = fetched.mdiCaseOfferings[1].conditions) === null || _b === void 0 ? void 0 : _b.condition)
|
|
136
|
+
&& !!((_c = fetched.mdiCaseOfferings[2].conditions) === null || _c === void 0 ? void 0 : _c.$and))];
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}); }, { expectedResult: true })];
|
|
140
|
+
case 2:
|
|
141
|
+
// --- Schema round-trip tests ---
|
|
142
|
+
_b.sent();
|
|
143
|
+
return [4 /*yield*/, async_test("Backwards-compat: existing flat { offering_id } config still validates", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
144
|
+
var flat, fetched;
|
|
145
|
+
var _a;
|
|
146
|
+
return __generator(this, function (_b) {
|
|
147
|
+
switch (_b.label) {
|
|
148
|
+
case 0:
|
|
149
|
+
if (!testFormId)
|
|
150
|
+
throw new Error("No test form");
|
|
151
|
+
flat = [
|
|
152
|
+
{ offering_id: "legacy-1" },
|
|
153
|
+
{ offering_id: "legacy-2" },
|
|
154
|
+
];
|
|
155
|
+
return [4 /*yield*/, sdk.api.forms.updateOne(testFormId, { mdiCaseOfferings: flat }, { replaceObjectFields: true })];
|
|
156
|
+
case 1:
|
|
157
|
+
_b.sent();
|
|
158
|
+
return [4 /*yield*/, sdk.api.forms.getOne(testFormId)];
|
|
159
|
+
case 2:
|
|
160
|
+
fetched = _b.sent();
|
|
161
|
+
return [2 /*return*/, (((_a = fetched.mdiCaseOfferings) === null || _a === void 0 ? void 0 : _a.length) === 2
|
|
162
|
+
&& fetched.mdiCaseOfferings.every(function (o) { return o.conditions === undefined; }))];
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}); }, { expectedResult: true })];
|
|
166
|
+
case 3:
|
|
167
|
+
_b.sent();
|
|
168
|
+
return [4 /*yield*/, async_test("Save nested CompoundFilter conditions on an offering and read back", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
169
|
+
var nested, fetched;
|
|
170
|
+
var _a, _b;
|
|
171
|
+
return __generator(this, function (_c) {
|
|
172
|
+
switch (_c.label) {
|
|
173
|
+
case 0:
|
|
174
|
+
if (!testFormId)
|
|
175
|
+
throw new Error("No test form");
|
|
176
|
+
nested = [
|
|
177
|
+
{
|
|
178
|
+
offering_id: "offering-nested",
|
|
179
|
+
conditions: {
|
|
180
|
+
$and: [
|
|
181
|
+
{ $or: [{ condition: { state: "CA" } }, { condition: { state: "NY" } }] },
|
|
182
|
+
{ condition: { med_type: "weightLoss" } },
|
|
183
|
+
],
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
];
|
|
187
|
+
return [4 /*yield*/, sdk.api.forms.updateOne(testFormId, { mdiCaseOfferings: nested }, { replaceObjectFields: true })];
|
|
188
|
+
case 1:
|
|
189
|
+
_c.sent();
|
|
190
|
+
return [4 /*yield*/, sdk.api.forms.getOne(testFormId)];
|
|
191
|
+
case 2:
|
|
192
|
+
fetched = _c.sent();
|
|
193
|
+
return [2 /*return*/, (((_a = fetched.mdiCaseOfferings) === null || _a === void 0 ? void 0 : _a.length) === 1
|
|
194
|
+
&& !!((_b = fetched.mdiCaseOfferings[0].conditions) === null || _b === void 0 ? void 0 : _b.$and))];
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}); }, { expectedResult: true })
|
|
198
|
+
// --- resolve_case_offerings behavior tests ---
|
|
199
|
+
];
|
|
200
|
+
case 4:
|
|
201
|
+
_b.sent();
|
|
202
|
+
MIXED_1 = [
|
|
203
|
+
{ offering_id: "always" },
|
|
204
|
+
{ offering_id: "ca-only", conditions: { condition: { state: "CA" } } },
|
|
205
|
+
{ offering_id: "ny-only", conditions: { condition: { state: "NY" } } },
|
|
206
|
+
];
|
|
207
|
+
return [4 /*yield*/, async_test("Resolver returns exactly the matching subset plus unconditional offerings", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
208
|
+
var resolved;
|
|
209
|
+
return __generator(this, function (_a) {
|
|
210
|
+
resolved = resolve_case_offerings(MIXED_1, [{ externalId: "state", value: "CA" }]);
|
|
211
|
+
return [2 /*return*/, (resolved.length === 2
|
|
212
|
+
&& resolved.some(function (o) { return o.offering_id === "always"; })
|
|
213
|
+
&& resolved.some(function (o) { return o.offering_id === "ca-only"; })
|
|
214
|
+
&& !resolved.some(function (o) { return o.offering_id === "ny-only"; }))];
|
|
215
|
+
});
|
|
216
|
+
}); }, { expectedResult: true })];
|
|
217
|
+
case 5:
|
|
218
|
+
_b.sent();
|
|
219
|
+
return [4 /*yield*/, async_test("Send none: when conditions match nothing, only unconditional offerings remain", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
220
|
+
var allConditional, resolved;
|
|
221
|
+
return __generator(this, function (_a) {
|
|
222
|
+
allConditional = [
|
|
223
|
+
{ offering_id: "ca-only", conditions: { condition: { state: "CA" } } },
|
|
224
|
+
{ offering_id: "ny-only", conditions: { condition: { state: "NY" } } },
|
|
225
|
+
];
|
|
226
|
+
resolved = resolve_case_offerings(allConditional, [{ externalId: "state", value: "TX" }]);
|
|
227
|
+
return [2 /*return*/, resolved.length === 0];
|
|
228
|
+
});
|
|
229
|
+
}); }, { expectedResult: true })];
|
|
230
|
+
case 6:
|
|
231
|
+
_b.sent();
|
|
232
|
+
return [4 /*yield*/, async_test("Backwards compat: all-unconditional config sends everything", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
233
|
+
var allUnconditional, resolved;
|
|
234
|
+
return __generator(this, function (_a) {
|
|
235
|
+
allUnconditional = [
|
|
236
|
+
{ offering_id: "a" },
|
|
237
|
+
{ offering_id: "b" },
|
|
238
|
+
{ offering_id: "c" },
|
|
239
|
+
];
|
|
240
|
+
resolved = resolve_case_offerings(allUnconditional, [{ externalId: "state", value: "TX" }]);
|
|
241
|
+
return [2 /*return*/, resolved.length === 3];
|
|
242
|
+
});
|
|
243
|
+
}); }, { expectedResult: true })];
|
|
244
|
+
case 7:
|
|
245
|
+
_b.sent();
|
|
246
|
+
return [4 /*yield*/, async_test("Empty/blank conditions object is treated as unconditional (always sent)", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
247
|
+
var withBlank, resolved;
|
|
248
|
+
return __generator(this, function (_a) {
|
|
249
|
+
withBlank = [
|
|
250
|
+
{ offering_id: "blank", conditions: { condition: {} } },
|
|
251
|
+
];
|
|
252
|
+
resolved = resolve_case_offerings(withBlank, []);
|
|
253
|
+
return [2 /*return*/, resolved.length === 1 && resolved[0].offering_id === "blank"];
|
|
254
|
+
});
|
|
255
|
+
}); }, { expectedResult: true })];
|
|
256
|
+
case 8:
|
|
257
|
+
_b.sent();
|
|
258
|
+
return [4 /*yield*/, async_test("$or conditions: offering sent when any branch matches", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
259
|
+
var offerings, resolved;
|
|
260
|
+
return __generator(this, function (_a) {
|
|
261
|
+
offerings = [
|
|
262
|
+
{ offering_id: "ca-or-ny", conditions: { $or: [{ condition: { state: "CA" } }, { condition: { state: "NY" } }] } },
|
|
263
|
+
];
|
|
264
|
+
resolved = resolve_case_offerings(offerings, [{ externalId: "state", value: "NY" }]);
|
|
265
|
+
return [2 /*return*/, resolved.length === 1];
|
|
266
|
+
});
|
|
267
|
+
}); }, { expectedResult: true })];
|
|
268
|
+
case 9:
|
|
269
|
+
_b.sent();
|
|
270
|
+
return [4 /*yield*/, async_test("$contains operator narrows offerings by substring match", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
271
|
+
var offerings, matches, misses;
|
|
272
|
+
return __generator(this, function (_a) {
|
|
273
|
+
offerings = [
|
|
274
|
+
{ offering_id: "glp", conditions: { condition: { meds: { $contains: "GLP" } } } },
|
|
275
|
+
];
|
|
276
|
+
matches = resolve_case_offerings(offerings, [{ externalId: "meds", value: "GLP-1 agonist" }]);
|
|
277
|
+
misses = resolve_case_offerings(offerings, [{ externalId: "meds", value: "Semaglutide" }]);
|
|
278
|
+
return [2 /*return*/, matches.length === 1 && misses.length === 0];
|
|
279
|
+
});
|
|
280
|
+
}); }, { expectedResult: true })
|
|
281
|
+
// --- height/weight conversion tests ---
|
|
282
|
+
];
|
|
283
|
+
case 10:
|
|
284
|
+
_b.sent();
|
|
285
|
+
// --- height/weight conversion tests ---
|
|
286
|
+
return [4 /*yield*/, async_test("enduser_height_to_cm converts Inches → integer centimeters", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
287
|
+
return __generator(this, function (_a) {
|
|
288
|
+
return [2 /*return*/, (enduser_height_to_cm({ value: 70, unit: 'Inches' }) === 178
|
|
289
|
+
&& enduser_height_to_cm({ value: '70', unit: 'Inches' }) === 178 // string value parsed
|
|
290
|
+
&& enduser_height_to_cm(undefined) === undefined // absent → omitted
|
|
291
|
+
&& enduser_height_to_cm({ value: '', unit: 'Inches' }) === undefined)];
|
|
292
|
+
});
|
|
293
|
+
}); }, { expectedResult: true })];
|
|
294
|
+
case 11:
|
|
295
|
+
// --- height/weight conversion tests ---
|
|
296
|
+
_b.sent();
|
|
297
|
+
return [4 /*yield*/, async_test("enduser_weight_to_kg converts Pounds → kilograms (float, 2dp)", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
298
|
+
return __generator(this, function (_a) {
|
|
299
|
+
return [2 /*return*/, (enduser_weight_to_kg({ value: 200, unit: 'Pounds' }) === 90.72
|
|
300
|
+
&& enduser_weight_to_kg({ value: '200', unit: 'Pounds' }) === 90.72 // string value parsed
|
|
301
|
+
&& enduser_weight_to_kg(undefined) === undefined // absent → omitted
|
|
302
|
+
&& enduser_weight_to_kg({ value: 'not-a-number', unit: 'Pounds' }) === undefined)];
|
|
303
|
+
});
|
|
304
|
+
}); }, { expectedResult: true })
|
|
305
|
+
// --- case_questions exclusion tests ---
|
|
306
|
+
];
|
|
307
|
+
case 12:
|
|
308
|
+
_b.sent();
|
|
309
|
+
// --- case_questions exclusion tests ---
|
|
310
|
+
return [4 /*yield*/, async_test("case_questions exclude patient-mapped fields but keep non-mapped clinical answers", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
311
|
+
var responses, kept, excluded;
|
|
312
|
+
return __generator(this, function (_a) {
|
|
313
|
+
responses = [
|
|
314
|
+
{ externalId: 'fname' },
|
|
315
|
+
{ externalId: 'email' },
|
|
316
|
+
{ externalId: 'dateOfBirth' },
|
|
317
|
+
{ externalId: 'gender' },
|
|
318
|
+
{ externalId: 'phone' },
|
|
319
|
+
{ externalId: 'address' },
|
|
320
|
+
{ externalId: 'height' },
|
|
321
|
+
{ externalId: 'weight' },
|
|
322
|
+
{ externalId: 'allergies' },
|
|
323
|
+
{ externalId: 'special_necessities' },
|
|
324
|
+
{ externalId: 'symptoms' },
|
|
325
|
+
{ externalId: 'duration' }, // non-mapped clinical field → survives
|
|
326
|
+
];
|
|
327
|
+
kept = case_question_external_ids(responses);
|
|
328
|
+
excluded = ['fname', 'email', 'dateOfBirth', 'gender', 'phone', 'address', 'height', 'weight', 'allergies', 'special_necessities'];
|
|
329
|
+
return [2 /*return*/, (kept.length === 2
|
|
330
|
+
&& kept.includes('symptoms')
|
|
331
|
+
&& kept.includes('duration')
|
|
332
|
+
&& excluded.every(function (id) { return !kept.includes(id); }))];
|
|
333
|
+
});
|
|
334
|
+
}); }, { expectedResult: true })
|
|
335
|
+
// --- displayed_options tests ---
|
|
336
|
+
];
|
|
337
|
+
case 13:
|
|
338
|
+
// --- case_questions exclusion tests ---
|
|
339
|
+
_b.sent();
|
|
340
|
+
// --- displayed_options tests ---
|
|
341
|
+
return [4 /*yield*/, async_test("multiple_choice response + matching field by _id → displayed_options equals field choices", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
342
|
+
var fields, response, opts;
|
|
343
|
+
return __generator(this, function (_a) {
|
|
344
|
+
fields = [
|
|
345
|
+
{ _id: 'field-1', options: { choices: ['Yes', 'No', 'Maybe'] } },
|
|
346
|
+
];
|
|
347
|
+
response = { fieldId: 'field-1', answer: { type: 'multiple_choice' } };
|
|
348
|
+
opts = resolve_displayed_options(response, fields);
|
|
349
|
+
return [2 /*return*/, (!!opts
|
|
350
|
+
&& opts.length === 3
|
|
351
|
+
&& opts[0] === 'Yes' && opts[1] === 'No' && opts[2] === 'Maybe')];
|
|
352
|
+
});
|
|
353
|
+
}); }, { expectedResult: true })];
|
|
354
|
+
case 14:
|
|
355
|
+
// --- displayed_options tests ---
|
|
356
|
+
_b.sent();
|
|
357
|
+
return [4 /*yield*/, async_test("Dropdown response + matching field by externalId → displayed_options equals field choices", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
358
|
+
var fields, response, opts;
|
|
359
|
+
return __generator(this, function (_a) {
|
|
360
|
+
fields = [
|
|
361
|
+
{ _id: 'field-2', externalId: 'state', options: { choices: ['CA', 'NY', 'TX'] } },
|
|
362
|
+
];
|
|
363
|
+
response = { fieldId: '', externalId: 'state', answer: { type: 'Dropdown' } };
|
|
364
|
+
opts = resolve_displayed_options(response, fields);
|
|
365
|
+
return [2 /*return*/, !!opts && opts.length === 3 && opts.join(',') === 'CA,NY,TX'];
|
|
366
|
+
});
|
|
367
|
+
}); }, { expectedResult: true })];
|
|
368
|
+
case 15:
|
|
369
|
+
_b.sent();
|
|
370
|
+
return [4 /*yield*/, async_test("string/number response → displayed_options undefined even with field choices present", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
371
|
+
var fields, stringResponse, numberResponse;
|
|
372
|
+
return __generator(this, function (_a) {
|
|
373
|
+
fields = [
|
|
374
|
+
{ _id: 'field-3', options: { choices: ['Yes', 'No'] } },
|
|
375
|
+
];
|
|
376
|
+
stringResponse = { fieldId: 'field-3', answer: { type: 'string' } };
|
|
377
|
+
numberResponse = { fieldId: 'field-3', answer: { type: 'number' } };
|
|
378
|
+
return [2 /*return*/, (resolve_displayed_options(stringResponse, fields) === undefined
|
|
379
|
+
&& resolve_displayed_options(numberResponse, fields) === undefined)];
|
|
380
|
+
});
|
|
381
|
+
}); }, { expectedResult: true })];
|
|
382
|
+
case 16:
|
|
383
|
+
_b.sent();
|
|
384
|
+
return [4 /*yield*/, async_test("multiple_choice response with no matching field → displayed_options undefined (question still kept)", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
385
|
+
var fields, noMatch, emptyChoices, fieldsEmpty;
|
|
386
|
+
return __generator(this, function (_a) {
|
|
387
|
+
fields = [
|
|
388
|
+
{ _id: 'field-4', externalId: 'other', options: { choices: ['A', 'B'] } },
|
|
389
|
+
];
|
|
390
|
+
noMatch = { fieldId: 'field-unknown', externalId: 'unknown', answer: { type: 'multiple_choice' } };
|
|
391
|
+
emptyChoices = { fieldId: 'field-5', answer: { type: 'multiple_choice' } };
|
|
392
|
+
fieldsEmpty = [{ _id: 'field-5', options: { choices: [] } }];
|
|
393
|
+
return [2 /*return*/, (resolve_displayed_options(noMatch, fields) === undefined
|
|
394
|
+
&& resolve_displayed_options(emptyChoices, fieldsEmpty) === undefined)];
|
|
395
|
+
});
|
|
396
|
+
}); }, { expectedResult: true })];
|
|
397
|
+
case 17:
|
|
398
|
+
_b.sent();
|
|
399
|
+
return [3 /*break*/, 21];
|
|
400
|
+
case 18:
|
|
401
|
+
if (!testFormId) return [3 /*break*/, 20];
|
|
402
|
+
return [4 /*yield*/, sdk.api.forms.deleteOne(testFormId).catch(console.error)];
|
|
403
|
+
case 19:
|
|
404
|
+
_b.sent();
|
|
405
|
+
_b.label = 20;
|
|
406
|
+
case 20: return [7 /*endfinally*/];
|
|
407
|
+
case 21: return [2 /*return*/];
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
};
|
|
412
|
+
if (require.main === module) {
|
|
413
|
+
console.log("Using API URL: ".concat(host));
|
|
414
|
+
var sdk_1 = new Session({ host: host });
|
|
415
|
+
var sdkNonAdmin_1 = new Session({ host: host });
|
|
416
|
+
var runTests = function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
417
|
+
return __generator(this, function (_a) {
|
|
418
|
+
switch (_a.label) {
|
|
419
|
+
case 0: return [4 /*yield*/, setup_tests(sdk_1, sdkNonAdmin_1)];
|
|
420
|
+
case 1:
|
|
421
|
+
_a.sent();
|
|
422
|
+
return [4 /*yield*/, mdi_case_offerings_tests({ sdk: sdk_1, sdkNonAdmin: sdkNonAdmin_1 })];
|
|
423
|
+
case 2:
|
|
424
|
+
_a.sent();
|
|
425
|
+
return [2 /*return*/];
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
}); };
|
|
429
|
+
runTests()
|
|
430
|
+
.then(function () {
|
|
431
|
+
console.log("MDI case offerings test suite completed successfully");
|
|
432
|
+
process.exit(0);
|
|
433
|
+
})
|
|
434
|
+
.catch(function (error) {
|
|
435
|
+
console.error("MDI case offerings test suite failed:", error);
|
|
436
|
+
process.exit(1);
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
//# sourceMappingURL=mdi_case_offerings.test.js.map
|