@schmock/faker 1.10.0 → 1.13.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/dist/field-name-matcher.d.ts.map +1 -1
- package/dist/field-name-matcher.js +9 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/jsf-config.d.ts +8 -5
- package/dist/jsf-config.d.ts.map +1 -1
- package/dist/jsf-config.js +19 -42
- package/dist/schema-enhancement.js +4 -0
- package/dist/test-utils.d.ts +5 -5
- package/dist/test-utils.d.ts.map +1 -1
- package/dist/test-utils.js +25 -13
- package/package.json +7 -7
- package/src/advanced-features.test.ts +72 -71
- package/src/data-quality.test.ts +38 -38
- package/src/error-handling.test.ts +54 -56
- package/src/field-mappings.test.ts +74 -63
- package/src/field-name-matcher.ts +12 -2
- package/src/index.test.ts +145 -135
- package/src/index.ts +8 -6
- package/src/integration.test.ts +30 -28
- package/src/jsf-config.ts +21 -37
- package/src/performance.test.ts +45 -43
- package/src/plugin-integration.test.ts +46 -46
- package/src/real-world.test.ts +22 -22
- package/src/schema-enhancement.ts +5 -0
- package/src/steps/deterministic-seeds.steps.ts +24 -21
- package/src/steps/faker-plugin.steps.ts +190 -142
- package/src/test-utils.ts +38 -22
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describeFeature, loadFeature } from "@amiceli/vitest-cucumber";
|
|
2
2
|
import { expect } from "vitest";
|
|
3
|
-
import {
|
|
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(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
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
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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 =
|
|
121
|
-
|
|
122
|
-
|
|
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 =
|
|
126
|
-
|
|
127
|
-
()
|
|
128
|
-
|
|
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>(
|
|
250
|
-
|
|
251
|
-
|
|
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(
|
|
298
|
+
expectValid: async (schema: JSONSchema7): Promise<void> => {
|
|
299
|
+
await expect(generateFromSchema({ schema })).resolves.not.toThrow();
|
|
293
300
|
},
|
|
294
301
|
|
|
295
|
-
expectInvalid: (
|
|
302
|
+
expectInvalid: async (
|
|
303
|
+
schema: any,
|
|
304
|
+
errorMessage?: string | RegExp,
|
|
305
|
+
): Promise<void> => {
|
|
296
306
|
if (errorMessage) {
|
|
297
|
-
expect(
|
|
307
|
+
await expect(generateFromSchema({ schema })).rejects.toThrow(
|
|
308
|
+
errorMessage,
|
|
309
|
+
);
|
|
298
310
|
} else {
|
|
299
|
-
expect(
|
|
311
|
+
await expect(generateFromSchema({ schema })).rejects.toThrow();
|
|
300
312
|
}
|
|
301
313
|
},
|
|
302
314
|
|
|
303
|
-
expectSchemaError: (
|
|
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");
|