@ondc/automation-mock-runner 1.3.20 → 1.3.22
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/dist/lib/MockRunner.d.ts +1 -0
- package/dist/lib/MockRunner.js +8 -4
- package/dist/lib/configHelper.d.ts +2 -0
- package/dist/lib/configHelper.js +26 -18
- package/dist/lib/types/mock-config.d.ts +3 -0
- package/dist/lib/types/mock-config.js +1 -0
- package/dist/lib/utils/validateConfig.d.ts +1 -0
- package/dist/lib/utils/validateConfig.js +32 -0
- package/dist/test/helper-config.test.js +0 -65
- package/package.json +1 -1
package/dist/lib/MockRunner.d.ts
CHANGED
package/dist/lib/MockRunner.js
CHANGED
|
@@ -290,10 +290,7 @@ class MockRunner {
|
|
|
290
290
|
}
|
|
291
291
|
}
|
|
292
292
|
getDefaultStep(api, actionId, formType) {
|
|
293
|
-
if (formType === "html_form") {
|
|
294
|
-
throw new Error("HTML form generation is not implemented yet");
|
|
295
|
-
}
|
|
296
|
-
if (formType === "dynamic_form") {
|
|
293
|
+
if (formType === "dynamic_form" || formType === "html_form") {
|
|
297
294
|
return {
|
|
298
295
|
api: api,
|
|
299
296
|
action_id: actionId,
|
|
@@ -376,6 +373,13 @@ class MockRunner {
|
|
|
376
373
|
required: ["email", "password"],
|
|
377
374
|
additionalProperties: false,
|
|
378
375
|
},
|
|
376
|
+
sampleData: {
|
|
377
|
+
email: "john.doe@example.com",
|
|
378
|
+
age: 28,
|
|
379
|
+
password: "SecurePass1",
|
|
380
|
+
website: "https://example.com",
|
|
381
|
+
country: "US",
|
|
382
|
+
},
|
|
379
383
|
},
|
|
380
384
|
},
|
|
381
385
|
};
|
|
@@ -67,6 +67,7 @@ export declare function generatePlaygroundConfigFromFlowConfig(payloads: Payload
|
|
|
67
67
|
inputs: {
|
|
68
68
|
id?: string | undefined;
|
|
69
69
|
jsonSchema?: any;
|
|
70
|
+
sampleData?: any;
|
|
70
71
|
};
|
|
71
72
|
formHtml?: string | undefined;
|
|
72
73
|
};
|
|
@@ -81,4 +82,5 @@ export declare function generatePlaygroundConfigFromFlowConfig(payloads: Payload
|
|
|
81
82
|
validationLib: string;
|
|
82
83
|
helperLib: string;
|
|
83
84
|
}>;
|
|
85
|
+
export declare function validateConfigForDeployment(config: MockPlaygroundConfigType): void;
|
|
84
86
|
export {};
|
package/dist/lib/configHelper.js
CHANGED
|
@@ -5,9 +5,11 @@ exports.convertToFlowConfig = convertToFlowConfig;
|
|
|
5
5
|
exports.createOptimizedMockConfig = createOptimizedMockConfig;
|
|
6
6
|
exports.getMinifiedCode = getMinifiedCode;
|
|
7
7
|
exports.generatePlaygroundConfigFromFlowConfig = generatePlaygroundConfigFromFlowConfig;
|
|
8
|
+
exports.validateConfigForDeployment = validateConfigForDeployment;
|
|
8
9
|
const MockRunner_1 = require("./MockRunner");
|
|
9
10
|
const uuid_1 = require("uuid");
|
|
10
11
|
const terser_1 = require("terser");
|
|
12
|
+
const validateConfig_1 = require("./utils/validateConfig");
|
|
11
13
|
function createInitialMockConfig(domain, version, flowId) {
|
|
12
14
|
return {
|
|
13
15
|
meta: {
|
|
@@ -197,7 +199,6 @@ async function getMinifiedCode(base64Code) {
|
|
|
197
199
|
*/
|
|
198
200
|
async function generatePlaygroundConfigFromFlowConfig(payloads, flowConfig) {
|
|
199
201
|
flowConfig = JSON.parse(JSON.stringify(flowConfig));
|
|
200
|
-
flowConfig.sequence = flowConfig.sequence.filter((step) => step.type !== "HTML_FORM" && step.type !== "DYNAMIC_FORM");
|
|
201
202
|
payloads = payloads.sort((a, b) => new Date(a.context.timestamp).getTime() -
|
|
202
203
|
new Date(b.context.timestamp).getTime());
|
|
203
204
|
const domain = payloads[0].context.domain;
|
|
@@ -206,33 +207,37 @@ async function generatePlaygroundConfigFromFlowConfig(payloads, flowConfig) {
|
|
|
206
207
|
const mockRunner = new MockRunner_1.MockRunner(config);
|
|
207
208
|
let index = 0;
|
|
208
209
|
for (const step of flowConfig.sequence) {
|
|
209
|
-
|
|
210
|
+
const isFormStep = step.type === "HTML_FORM" ||
|
|
210
211
|
step.type === "DYNAMIC_FORM" ||
|
|
211
|
-
step.type === "FORM"
|
|
212
|
-
|
|
212
|
+
step.type === "FORM";
|
|
213
|
+
let stepConfig;
|
|
214
|
+
if (isFormStep) {
|
|
215
|
+
// HTML_FORM is not yet fully implemented — fall back to dynamic_form default
|
|
216
|
+
stepConfig = mockRunner.getDefaultStep(step.type, step.key, "dynamic_form");
|
|
213
217
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
219
|
-
const stepConfig = mockRunner.getDefaultStep(step.type, step.key);
|
|
220
|
-
if (index === 0) {
|
|
221
|
-
stepConfig.mock.generate = MockRunner_1.MockRunner.encodeBase64(`async function generate(defaultPayload, sessionData) {
|
|
218
|
+
else {
|
|
219
|
+
stepConfig = mockRunner.getDefaultStep(step.type, step.key);
|
|
220
|
+
if (index === 0) {
|
|
221
|
+
stepConfig.mock.generate = MockRunner_1.MockRunner.encodeBase64(`async function generate(defaultPayload, sessionData) {
|
|
222
222
|
setCityFromInputs(defaultPayload, sessionData.user_inputs);
|
|
223
223
|
return defaultPayload;
|
|
224
224
|
}`);
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
225
|
+
stepConfig.mock.inputs = cityInputs;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
stepConfig.mock.inputs = {};
|
|
229
|
+
}
|
|
230
|
+
const stepPayloadIndex = payloads.findIndex((p) => p.context.action === step.type);
|
|
231
|
+
if (stepPayloadIndex !== -1) {
|
|
232
|
+
stepConfig.mock.defaultPayload = payloads[stepPayloadIndex];
|
|
233
|
+
payloads.splice(stepPayloadIndex, 1); // remove used payload
|
|
234
|
+
}
|
|
235
|
+
index++;
|
|
229
236
|
}
|
|
230
|
-
stepConfig.mock.defaultPayload = payload;
|
|
231
237
|
const findResponseFor = flowConfig.sequence.find((s) => s.pair === step.key);
|
|
232
238
|
stepConfig.responseFor = findResponseFor ? findResponseFor.key : null;
|
|
233
239
|
stepConfig.unsolicited = step.unsolicited;
|
|
234
240
|
config.steps.push(stepConfig);
|
|
235
|
-
index++;
|
|
236
241
|
}
|
|
237
242
|
return config;
|
|
238
243
|
}
|
|
@@ -250,3 +255,6 @@ const cityInputs = {
|
|
|
250
255
|
required: ["city_code"],
|
|
251
256
|
},
|
|
252
257
|
};
|
|
258
|
+
function validateConfigForDeployment(config) {
|
|
259
|
+
(0, validateConfig_1.validateGoodConfig)(config);
|
|
260
|
+
}
|
|
@@ -26,6 +26,7 @@ export declare const MockConfigSchema: z.ZodObject<{
|
|
|
26
26
|
inputs: z.ZodObject<{
|
|
27
27
|
id: z.ZodOptional<z.ZodString>;
|
|
28
28
|
jsonSchema: z.ZodOptional<z.ZodAny>;
|
|
29
|
+
sampleData: z.ZodOptional<z.ZodAny>;
|
|
29
30
|
}, z.core.$strip>;
|
|
30
31
|
formHtml: z.ZodOptional<z.ZodBase64>;
|
|
31
32
|
}, z.core.$strip>;
|
|
@@ -49,6 +50,7 @@ export declare const PlaygroundActionStepSchema: z.ZodObject<{
|
|
|
49
50
|
inputs: z.ZodObject<{
|
|
50
51
|
id: z.ZodOptional<z.ZodString>;
|
|
51
52
|
jsonSchema: z.ZodOptional<z.ZodAny>;
|
|
53
|
+
sampleData: z.ZodOptional<z.ZodAny>;
|
|
52
54
|
}, z.core.$strip>;
|
|
53
55
|
formHtml: z.ZodOptional<z.ZodBase64>;
|
|
54
56
|
}, z.core.$strip>;
|
|
@@ -94,6 +96,7 @@ export declare const MockPlaygroundConfigSchema: z.ZodObject<{
|
|
|
94
96
|
inputs: z.ZodObject<{
|
|
95
97
|
id: z.ZodOptional<z.ZodString>;
|
|
96
98
|
jsonSchema: z.ZodOptional<z.ZodAny>;
|
|
99
|
+
sampleData: z.ZodOptional<z.ZodAny>;
|
|
97
100
|
}, z.core.$strip>;
|
|
98
101
|
formHtml: z.ZodOptional<z.ZodBase64>;
|
|
99
102
|
}, z.core.$strip>;
|
|
@@ -27,6 +27,7 @@ exports.MockConfigSchema = zod_1.z.object({
|
|
|
27
27
|
inputs: zod_1.z.object({
|
|
28
28
|
id: zod_1.z.string().min(1, "Input ID is required").optional(),
|
|
29
29
|
jsonSchema: zod_1.z.any().optional(),
|
|
30
|
+
sampleData: zod_1.z.any().optional(),
|
|
30
31
|
}),
|
|
31
32
|
formHtml: zod_1.z.base64().optional(),
|
|
32
33
|
});
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.validateConfigWithErrors = validateConfigWithErrors;
|
|
4
|
+
exports.validateGoodConfig = validateGoodConfig;
|
|
4
5
|
const mock_config_1 = require("../types/mock-config");
|
|
6
|
+
const errors_1 = require("./errors");
|
|
5
7
|
function validateConfigWithErrors(config) {
|
|
6
8
|
const result = mock_config_1.MockPlaygroundConfigSchema.safeParse(config);
|
|
7
9
|
if (result.success) {
|
|
@@ -14,3 +16,33 @@ function validateConfigWithErrors(config) {
|
|
|
14
16
|
};
|
|
15
17
|
}
|
|
16
18
|
}
|
|
19
|
+
function validateGoodConfig(config) {
|
|
20
|
+
// 1. Validate base schema
|
|
21
|
+
const baseResult = validateConfigWithErrors(config);
|
|
22
|
+
if (!baseResult.success && baseResult.errors) {
|
|
23
|
+
const messages = baseResult.errors.map((e) => `[${e.path.join(".") || "root"}] ${e.message}`);
|
|
24
|
+
throw new errors_1.ValidationError(`Config schema validation failed with ${messages.length} error(s)`, messages, { flowId: config?.meta?.flowId });
|
|
25
|
+
}
|
|
26
|
+
const errors = [];
|
|
27
|
+
// 2. If inputs.id is present, both sampleData and jsonSchema must also be present
|
|
28
|
+
config.steps.forEach((step, index) => {
|
|
29
|
+
const { id, sampleData, jsonSchema } = step.mock.inputs;
|
|
30
|
+
if (id !== undefined) {
|
|
31
|
+
if (sampleData === undefined || sampleData === null) {
|
|
32
|
+
errors.push(`steps[${index}] (action_id: "${step.action_id}"): inputs.sampleData is required when inputs.id is set`);
|
|
33
|
+
}
|
|
34
|
+
if (jsonSchema === undefined || jsonSchema === null) {
|
|
35
|
+
errors.push(`steps[${index}] (action_id: "${step.action_id}"): inputs.jsonSchema is required when inputs.id is set`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
// 3. Length of steps must equal length of transaction_history
|
|
40
|
+
// if (config.steps.length !== config.transaction_history.length) {
|
|
41
|
+
// errors.push(
|
|
42
|
+
// `steps length (${config.steps.length}) must equal transaction_history length (${config.transaction_history.length})`,
|
|
43
|
+
// );
|
|
44
|
+
// }
|
|
45
|
+
if (errors.length > 0) {
|
|
46
|
+
throw new errors_1.ValidationError(`Config validation failed with ${errors.length} error(s)`, errors, { flowId: config.meta.flowId });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -686,71 +686,6 @@ describe("configHelper", () => {
|
|
|
686
686
|
expect(onSearchStepConfig.unsolicited).toBe(false);
|
|
687
687
|
expect(onSearchStepConfig.mock.defaultPayload).toBe(onSearchPayload);
|
|
688
688
|
});
|
|
689
|
-
it("should ignore HTML_FORM and DYNAMIC_FORM steps and preserve unsolicited flag", async () => {
|
|
690
|
-
const payloads = [
|
|
691
|
-
{
|
|
692
|
-
context: {
|
|
693
|
-
action: "search",
|
|
694
|
-
timestamp: "2025-01-01T09:00:00.000Z",
|
|
695
|
-
domain: "ONDC:RET10",
|
|
696
|
-
version: "2.0.0",
|
|
697
|
-
},
|
|
698
|
-
},
|
|
699
|
-
{
|
|
700
|
-
context: {
|
|
701
|
-
action: "on_status",
|
|
702
|
-
timestamp: "2025-01-01T10:00:00.000Z",
|
|
703
|
-
domain: "ONDC:RET10",
|
|
704
|
-
version: "2.0.0",
|
|
705
|
-
},
|
|
706
|
-
},
|
|
707
|
-
];
|
|
708
|
-
const flowConfig = {
|
|
709
|
-
id: "flow_with_forms",
|
|
710
|
-
sequence: [
|
|
711
|
-
{
|
|
712
|
-
key: "search_step",
|
|
713
|
-
type: "search",
|
|
714
|
-
unsolicited: false,
|
|
715
|
-
description: "Search step",
|
|
716
|
-
pair: null,
|
|
717
|
-
owner: "BAP",
|
|
718
|
-
},
|
|
719
|
-
{
|
|
720
|
-
key: "html_form_step",
|
|
721
|
-
type: "HTML_FORM",
|
|
722
|
-
unsolicited: false,
|
|
723
|
-
description: "HTML form step",
|
|
724
|
-
pair: null,
|
|
725
|
-
owner: "BAP",
|
|
726
|
-
},
|
|
727
|
-
{
|
|
728
|
-
key: "dynamic_form_step",
|
|
729
|
-
type: "DYNAMIC_FORM",
|
|
730
|
-
unsolicited: false,
|
|
731
|
-
description: "Dynamic form step",
|
|
732
|
-
pair: null,
|
|
733
|
-
owner: "BAP",
|
|
734
|
-
},
|
|
735
|
-
{
|
|
736
|
-
key: "on_status_step",
|
|
737
|
-
type: "on_status",
|
|
738
|
-
unsolicited: true,
|
|
739
|
-
description: "Unsolicited status",
|
|
740
|
-
pair: null,
|
|
741
|
-
owner: "BPP",
|
|
742
|
-
},
|
|
743
|
-
],
|
|
744
|
-
};
|
|
745
|
-
const config = await (0, configHelper_1.generatePlaygroundConfigFromFlowConfig)(payloads, flowConfig);
|
|
746
|
-
// Only non-form steps should be present
|
|
747
|
-
expect(config.steps.map((s) => s.action_id)).toEqual([
|
|
748
|
-
"search_step",
|
|
749
|
-
"on_status_step",
|
|
750
|
-
]);
|
|
751
|
-
const onStatusStep = config.steps.find((s) => s.action_id === "on_status_step");
|
|
752
|
-
expect(onStatusStep?.unsolicited).toBe(true);
|
|
753
|
-
});
|
|
754
689
|
it("should derive version from core_version when version is missing", async () => {
|
|
755
690
|
const payloads = [
|
|
756
691
|
{
|