@schmock/faker 1.12.0 → 2.0.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.
@@ -1,6 +1,6 @@
1
1
  import { describeFeature, loadFeature } from "@amiceli/vitest-cucumber";
2
2
  import { expect } from "vitest";
3
- import { generateFromSchema, fakerPlugin } from "../index";
3
+ import { fakerPlugin, generateFromSchema } from "../index";
4
4
 
5
5
  const feature = await loadFeature("../../features/faker-plugin.feature");
6
6
 
@@ -8,153 +8,201 @@ describeFeature(feature, ({ Scenario }) => {
8
8
  let generated: any;
9
9
  let error: Error | null = null;
10
10
 
11
- Scenario("Generate object from simple schema", ({ Given, When, Then, And }) => {
12
- let schema: any;
13
-
14
- Given("I create a schema plugin with:", (_, docString: string) => {
15
- schema = JSON.parse(docString);
16
- });
17
-
18
- When("I generate data from the schema", () => {
19
- generated = generateFromSchema({ schema });
20
- });
21
-
22
- Then("the generated data should have property {string} of type {string}", (_, prop: string, type: string) => {
23
- expect(generated).toHaveProperty(prop);
24
- expect(typeof generated[prop]).toBe(type);
25
- });
26
-
27
- And("the generated data should have property {string} of type {string}", (_, prop: string, type: string) => {
28
- expect(generated).toHaveProperty(prop);
29
- expect(typeof generated[prop]).toBe(type);
30
- });
31
- });
32
-
33
- Scenario("Generate array of items with explicit count", ({ Given, When, Then }) => {
34
- let schema: any;
35
- let count: number;
36
-
37
- Given("I create a schema plugin for array with count {int}:", (_, cnt: number, docString: string) => {
38
- schema = JSON.parse(docString);
39
- count = cnt;
40
- });
41
-
42
- When("I generate data from the schema", () => {
43
- generated = generateFromSchema({ schema, count });
44
- });
45
-
46
- Then("the generated data should be an array of length {int}", (_, length: number) => {
47
- expect(Array.isArray(generated)).toBe(true);
48
- expect(generated).toHaveLength(length);
49
- });
50
- });
51
-
52
- Scenario("Template preserves string values for mixed templates", ({ Given, When, Then }) => {
53
- let template: string;
54
- let result: any;
55
-
56
- Given("I create a schema plugin with template override {string}", (_, tmpl: string) => {
57
- template = tmpl;
58
- });
59
-
60
- When("I generate data with param {string} set to {string}", (_, paramName: string, paramValue: string) => {
61
- const schema = {
62
- type: "object" as const,
63
- properties: {
64
- value: { type: "string" as const },
11
+ Scenario(
12
+ "Generate object from simple schema",
13
+ ({ Given, When, Then, And }) => {
14
+ let schema: any;
15
+
16
+ Given("I create a schema plugin with:", (_, docString: string) => {
17
+ schema = JSON.parse(docString);
18
+ });
19
+
20
+ When("I generate data from the schema", async () => {
21
+ generated = await generateFromSchema({ schema });
22
+ });
23
+
24
+ Then(
25
+ "the generated data should have property {string} of type {string}",
26
+ (_, prop: string, type: string) => {
27
+ expect(generated).toHaveProperty(prop);
28
+ expect(typeof generated[prop]).toBe(type);
29
+ },
30
+ );
31
+
32
+ And(
33
+ "the generated data should have property {string} of type {string}",
34
+ (_, prop: string, type: string) => {
35
+ expect(generated).toHaveProperty(prop);
36
+ expect(typeof generated[prop]).toBe(type);
65
37
  },
66
- };
67
- result = generateFromSchema({
68
- schema,
69
- overrides: { value: template },
70
- params: { [paramName]: paramValue },
38
+ );
39
+ },
40
+ );
41
+
42
+ Scenario(
43
+ "Generate array of items with explicit count",
44
+ ({ Given, When, Then }) => {
45
+ let schema: any;
46
+ let count: number;
47
+
48
+ Given(
49
+ "I create a schema plugin for array with count {int}:",
50
+ (_, cnt: number, docString: string) => {
51
+ schema = JSON.parse(docString);
52
+ count = cnt;
53
+ },
54
+ );
55
+
56
+ When("I generate data from the schema", async () => {
57
+ generated = await generateFromSchema({ schema, count });
71
58
  });
72
- });
73
-
74
- Then("the template result should be the string {string}", (_, expected: string) => {
75
- expect(result.value).toBe(expected);
76
- expect(typeof result.value).toBe("string");
77
- });
78
- });
79
-
80
- Scenario("Multiple schema plugin instances do not share state", ({ Given, When, Then }) => {
81
- let plugin1: any;
82
- let plugin2: any;
83
- let data1: any;
84
- let data2: any;
85
-
86
- Given("I create two separate schema plugin instances", () => {
87
- const schema = {
88
- type: "object" as const,
89
- properties: {
90
- name: { type: "string" as const },
59
+
60
+ Then(
61
+ "the generated data should be an array of length {int}",
62
+ (_, length: number) => {
63
+ expect(Array.isArray(generated)).toBe(true);
64
+ expect(generated).toHaveLength(length);
91
65
  },
92
- required: ["name"],
93
- };
94
- plugin1 = fakerPlugin({ schema });
95
- plugin2 = fakerPlugin({ schema });
96
- });
97
-
98
- When("I generate data from both instances", async () => {
99
- const ctx = {
100
- path: "/test",
101
- route: {},
102
- method: "GET" as const,
103
- params: {},
104
- query: {},
105
- headers: {},
106
- state: new Map(),
107
- };
108
- const result1 = await plugin1.process(ctx);
109
- const result2 = await plugin2.process(ctx);
110
- data1 = result1.response;
111
- data2 = result2.response;
112
- });
113
-
114
- Then("the data from each instance should be independently generated", () => {
115
- expect(data1).toBeDefined();
116
- expect(data2).toBeDefined();
117
- expect(typeof data1.name).toBe("string");
118
- expect(typeof data2.name).toBe("string");
119
- });
120
- });
121
-
122
- Scenario("Invalid schema is rejected at plugin creation time", ({ Given, Then }) => {
123
- Given("I attempt to create a schema plugin with invalid schema", () => {
124
- error = null;
125
- try {
126
- fakerPlugin({ schema: {} as any });
127
- } catch (e) {
128
- error = e as Error;
129
- }
130
- });
131
-
132
- Then("it should throw a SchemaValidationError", () => {
133
- expect(error).not.toBeNull();
134
- expect(error!.name).toBe("SchemaValidationError");
135
- });
136
- });
137
-
138
- Scenario("Faker method validation checks actual method existence", ({ Given, Then }) => {
139
- Given("I attempt to create a schema with faker method {string}", (_, fakerMethod: string) => {
140
- error = null;
141
- try {
66
+ );
67
+ },
68
+ );
69
+
70
+ Scenario(
71
+ "Template preserves string values for mixed templates",
72
+ ({ Given, When, Then }) => {
73
+ let template: string;
74
+ let result: any;
75
+
76
+ Given(
77
+ "I create a schema plugin with template override {string}",
78
+ (_, tmpl: string) => {
79
+ template = tmpl;
80
+ },
81
+ );
82
+
83
+ When(
84
+ "I generate data with param {string} set to {string}",
85
+ async (_, paramName: string, paramValue: string) => {
86
+ const schema = {
87
+ type: "object" as const,
88
+ properties: {
89
+ value: { type: "string" as const },
90
+ },
91
+ };
92
+ result = await generateFromSchema({
93
+ schema,
94
+ overrides: { value: template },
95
+ params: { [paramName]: paramValue },
96
+ });
97
+ },
98
+ );
99
+
100
+ Then(
101
+ "the template result should be the string {string}",
102
+ (_, expected: string) => {
103
+ expect(result.value).toBe(expected);
104
+ expect(typeof result.value).toBe("string");
105
+ },
106
+ );
107
+ },
108
+ );
109
+
110
+ Scenario(
111
+ "Multiple schema plugin instances do not share state",
112
+ ({ Given, When, Then }) => {
113
+ let plugin1: any;
114
+ let plugin2: any;
115
+ let data1: any;
116
+ let data2: any;
117
+
118
+ Given("I create two separate schema plugin instances", () => {
142
119
  const schema = {
143
120
  type: "object" as const,
144
121
  properties: {
145
- field: { type: "string" as const, faker: fakerMethod },
122
+ name: { type: "string" as const },
146
123
  },
124
+ required: ["name"],
125
+ };
126
+ plugin1 = fakerPlugin({ schema });
127
+ plugin2 = fakerPlugin({ schema });
128
+ });
129
+
130
+ When("I generate data from both instances", async () => {
131
+ const ctx = {
132
+ path: "/test",
133
+ route: {},
134
+ method: "GET" as const,
135
+ params: {},
136
+ query: {},
137
+ headers: {},
138
+ state: new Map(),
147
139
  };
148
- fakerPlugin({ schema: schema as any });
149
- } catch (e) {
150
- error = e as Error;
151
- }
152
- });
153
-
154
- Then("it should throw a SchemaValidationError with message {string}", (_, message: string) => {
155
- expect(error).not.toBeNull();
156
- expect(error!.name).toBe("SchemaValidationError");
157
- expect(error!.message).toContain(message);
158
- });
159
- });
140
+ const result1 = await plugin1.process(ctx);
141
+ const result2 = await plugin2.process(ctx);
142
+ data1 = result1.response;
143
+ data2 = result2.response;
144
+ });
145
+
146
+ Then(
147
+ "the data from each instance should be independently generated",
148
+ () => {
149
+ expect(data1).toBeDefined();
150
+ expect(data2).toBeDefined();
151
+ expect(typeof data1.name).toBe("string");
152
+ expect(typeof data2.name).toBe("string");
153
+ },
154
+ );
155
+ },
156
+ );
157
+
158
+ Scenario(
159
+ "Invalid schema is rejected at plugin creation time",
160
+ ({ Given, Then }) => {
161
+ Given("I attempt to create a schema plugin with invalid schema", () => {
162
+ error = null;
163
+ try {
164
+ fakerPlugin({ schema: {} as any });
165
+ } catch (e) {
166
+ error = e as Error;
167
+ }
168
+ });
169
+
170
+ Then("it should throw a SchemaValidationError", () => {
171
+ expect(error).not.toBeNull();
172
+ expect(error?.name).toBe("SchemaValidationError");
173
+ });
174
+ },
175
+ );
176
+
177
+ Scenario(
178
+ "Faker method validation checks actual method existence",
179
+ ({ Given, Then }) => {
180
+ Given(
181
+ "I attempt to create a schema with faker method {string}",
182
+ (_, fakerMethod: string) => {
183
+ error = null;
184
+ try {
185
+ const schema = {
186
+ type: "object" as const,
187
+ properties: {
188
+ field: { type: "string" as const, faker: fakerMethod },
189
+ },
190
+ };
191
+ fakerPlugin({ schema: schema as any });
192
+ } catch (e) {
193
+ error = e as Error;
194
+ }
195
+ },
196
+ );
197
+
198
+ Then(
199
+ "it should throw a SchemaValidationError with message {string}",
200
+ (_, message: string) => {
201
+ expect(error).not.toBeNull();
202
+ expect(error?.name).toBe("SchemaValidationError");
203
+ expect(error?.message).toContain(message);
204
+ },
205
+ );
206
+ },
207
+ );
160
208
  });
package/src/test-utils.ts CHANGED
@@ -117,16 +117,17 @@ export const validators = {
117
117
  };
118
118
 
119
119
  // Generate multiple samples to check for patterns
120
- const mappedSamples = Array.from(
121
- { length: 10 },
122
- () => generateFromSchema({ schema: mappedSchema })[fieldName],
123
- );
120
+ const mappedSamples: any[] = [];
121
+ for (let i = 0; i < 10; i++) {
122
+ const result = await generateFromSchema({ schema: mappedSchema });
123
+ mappedSamples.push(result[fieldName]);
124
+ }
124
125
 
125
- const unmappedSamples = Array.from(
126
- { length: 10 },
127
- () =>
128
- generateFromSchema({ schema: unmappedSchema }).unmappedRandomField12345,
129
- );
126
+ const unmappedSamples: any[] = [];
127
+ for (let i = 0; i < 10; i++) {
128
+ const result = await generateFromSchema({ schema: unmappedSchema });
129
+ unmappedSamples.push(result.unmappedRandomField12345);
130
+ }
130
131
 
131
132
  // If field is mapped to a specific faker method, it should have different characteristics
132
133
  // than the generic unmapped field
@@ -246,16 +247,22 @@ export const performance = {
246
247
 
247
248
  // Test Data Generators
248
249
  export const generate = {
249
- samples: <T>(schema: JSONSchema7, count = 10, options?: any): T[] => {
250
- return Array.from({ length: count }, () =>
251
- generateFromSchema({ schema, ...options }),
252
- );
250
+ samples: async <T>(
251
+ schema: JSONSchema7,
252
+ count = 10,
253
+ options?: any,
254
+ ): Promise<T[]> => {
255
+ const results: T[] = [];
256
+ for (let i = 0; i < count; i++) {
257
+ results.push(await generateFromSchema({ schema, ...options }));
258
+ }
259
+ return results;
253
260
  },
254
261
 
255
- withSeed: (schema: JSONSchema7, _seed?: number): any => {
262
+ withSeed: async (schema: JSONSchema7, _seed?: number): Promise<any> => {
256
263
  // Note: faker.js doesn't support seeding in the same way,
257
264
  // but we can at least ensure consistent test behavior
258
- return generateFromSchema({ schema });
265
+ return await generateFromSchema({ schema });
259
266
  },
260
267
  };
261
268
 
@@ -288,21 +295,30 @@ export const stats = {
288
295
 
289
296
  // Schema Validation Test Helpers
290
297
  export const schemaTests = {
291
- expectValid: (schema: JSONSchema7): void => {
292
- expect(() => generateFromSchema({ schema })).not.toThrow();
298
+ expectValid: async (schema: JSONSchema7): Promise<void> => {
299
+ await expect(generateFromSchema({ schema })).resolves.not.toThrow();
293
300
  },
294
301
 
295
- expectInvalid: (schema: any, errorMessage?: string | RegExp): void => {
302
+ expectInvalid: async (
303
+ schema: any,
304
+ errorMessage?: string | RegExp,
305
+ ): Promise<void> => {
296
306
  if (errorMessage) {
297
- expect(() => generateFromSchema({ schema })).toThrow(errorMessage);
307
+ await expect(generateFromSchema({ schema })).rejects.toThrow(
308
+ errorMessage,
309
+ );
298
310
  } else {
299
- expect(() => generateFromSchema({ schema })).toThrow();
311
+ await expect(generateFromSchema({ schema })).rejects.toThrow();
300
312
  }
301
313
  },
302
314
 
303
- expectSchemaError: (schema: any, path: string, issue?: string): void => {
315
+ expectSchemaError: async (
316
+ schema: any,
317
+ path: string,
318
+ issue?: string,
319
+ ): Promise<void> => {
304
320
  try {
305
- generateFromSchema({ schema });
321
+ await generateFromSchema({ schema });
306
322
  throw new Error("Expected schema validation to fail");
307
323
  } catch (error: any) {
308
324
  expect(error.name).toBe("SchemaValidationError");