@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.
@@ -40,6 +40,7 @@ export declare class MockRunner {
40
40
  inputs: {
41
41
  id?: string | undefined;
42
42
  jsonSchema?: any;
43
+ sampleData?: any;
43
44
  };
44
45
  formHtml?: string | undefined;
45
46
  };
@@ -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 {};
@@ -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
- if (step.type === "HTML_FORM" ||
210
+ const isFormStep = step.type === "HTML_FORM" ||
210
211
  step.type === "DYNAMIC_FORM" ||
211
- step.type === "FORM") {
212
- continue;
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
- let stepPayload = payloads.findIndex((p) => p.context.action === step.type);
215
- const payload = stepPayload === -1 ? {} : payloads[stepPayload];
216
- if (stepPayload !== -1) {
217
- payloads.splice(stepPayload, 1); // remove used payload
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
- stepConfig.mock.inputs = cityInputs;
226
- }
227
- else {
228
- stepConfig.mock.inputs = {};
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
  });
@@ -4,3 +4,4 @@ export declare function validateConfigWithErrors(config: MockPlaygroundConfigTyp
4
4
  success: boolean;
5
5
  errors?: z.core.$ZodIssue[];
6
6
  };
7
+ export declare function validateGoodConfig(config: MockPlaygroundConfigType): void;
@@ -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
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ondc/automation-mock-runner",
3
- "version": "1.3.20",
3
+ "version": "1.3.22",
4
4
  "description": "A TypeScript library for ONDC automation mock runner",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",