struct-fakerator 1.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.
- package/README.md +36 -0
- package/biome.json +20 -0
- package/jsconfig.json +20 -0
- package/package.json +25 -0
- package/src/config_scheme.js +45 -0
- package/src/create_config.js +109 -0
- package/src/create_config.test.js +72 -0
- package/src/create_generator_fn.js +139 -0
- package/src/create_generator_fn.test.js +132 -0
- package/src/type.js +23 -0
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# 假資料結構產生器
|
|
2
|
+
|
|
3
|
+
## 用途
|
|
4
|
+
|
|
5
|
+
使用 faker js 時是單一純值不能產生結構,需要自己手動組合結構,此專案利用撰寫設定檔的方式來產生一個特定的假資料函數,減少手動組合結構的麻煩。
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
const test = {
|
|
9
|
+
type: 'obj',
|
|
10
|
+
content: {
|
|
11
|
+
name: {
|
|
12
|
+
type: 'value',
|
|
13
|
+
generateFn: () => 'hello',
|
|
14
|
+
},
|
|
15
|
+
list: {
|
|
16
|
+
type: 'arr',
|
|
17
|
+
len: 5,
|
|
18
|
+
item: {
|
|
19
|
+
type: 'value',
|
|
20
|
+
generateFn: () => 10,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const generateFn = createGeneratorByType(test);
|
|
27
|
+
|
|
28
|
+
console.log(generateFn());
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
{
|
|
32
|
+
name: "hello"
|
|
33
|
+
list: [10, 10, 10, 10, 10,]
|
|
34
|
+
}
|
|
35
|
+
*/
|
|
36
|
+
```
|
package/biome.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/1.7.1/schema.json",
|
|
3
|
+
"organizeImports": {
|
|
4
|
+
"enabled": true
|
|
5
|
+
},
|
|
6
|
+
"linter": {
|
|
7
|
+
"enabled": true,
|
|
8
|
+
"rules": {
|
|
9
|
+
"recommended": true
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"formatter": {
|
|
13
|
+
"indentStyle": "space"
|
|
14
|
+
},
|
|
15
|
+
"javascript": {
|
|
16
|
+
"formatter": {
|
|
17
|
+
"quoteStyle": "double"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
package/jsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es6",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"baseUrl": ".",
|
|
6
|
+
"paths": {
|
|
7
|
+
"*": [
|
|
8
|
+
"node_modules/*"
|
|
9
|
+
]
|
|
10
|
+
},
|
|
11
|
+
"checkJs": true,
|
|
12
|
+
},
|
|
13
|
+
"include": [
|
|
14
|
+
"./**/*"
|
|
15
|
+
],
|
|
16
|
+
"exclude": [
|
|
17
|
+
"node_modules",
|
|
18
|
+
"**/node_modules/*"
|
|
19
|
+
]
|
|
20
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "struct-fakerator",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node src/index.js",
|
|
9
|
+
"test": "vitest"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [],
|
|
12
|
+
"author": "FizzyElt",
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@biomejs/biome": "^1.7.1",
|
|
16
|
+
"@faker-js/faker": "^8.4.1",
|
|
17
|
+
"vitest": "^1.5.2"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"zod": "^3.23.6"
|
|
21
|
+
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const valueConfigScheme = z.object({
|
|
4
|
+
type: z.string().regex(/^value$/, { message: "invalid type string" }),
|
|
5
|
+
generateFn: z.function(),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export const selectionConfigScheme = z.object({
|
|
9
|
+
type: z.string().regex(/^select$/, { message: "invalid type string" }),
|
|
10
|
+
items: z.any().array().nonempty({ message: "items can not be empty" }),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const arrayConfigScheme = z.object({
|
|
14
|
+
type: z.string().regex(/^arr$/, { message: "invalid type string" }),
|
|
15
|
+
item: z.object({}),
|
|
16
|
+
len: z.number().nonnegative(),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export const tupleConfigScheme = z.object({
|
|
20
|
+
type: z.string().regex(/^tuple$/, { message: "invalid type string" }),
|
|
21
|
+
configItems: z.any().array(),
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export const objConfigScheme = z.object({
|
|
25
|
+
type: z.string().regex(/^obj$/, { message: "invalid type string" }),
|
|
26
|
+
content: z.object({}),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const boundedSeriesScheme = z
|
|
30
|
+
.object({
|
|
31
|
+
type: z
|
|
32
|
+
.string()
|
|
33
|
+
.regex(/^bounded_series$/, { message: "invalid type string" }),
|
|
34
|
+
upperLimit: z.number().nonnegative(),
|
|
35
|
+
lowerLimit: z.number().nonnegative(),
|
|
36
|
+
createInitValue: z.function().args().returns(z.number()),
|
|
37
|
+
count: z.number().nonnegative(),
|
|
38
|
+
})
|
|
39
|
+
.refine(({ upperLimit, lowerLimit }) => upperLimit >= lowerLimit, {
|
|
40
|
+
message: "lowerLimit can not greater then upperLimit",
|
|
41
|
+
})
|
|
42
|
+
.refine(({ createInitValue }) => typeof createInitValue() === "number", {
|
|
43
|
+
message: "createInitValue is not return number",
|
|
44
|
+
path: ["createInitValue"],
|
|
45
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { faker } from "@faker-js/faker";
|
|
2
|
+
import {
|
|
3
|
+
valueConfigScheme,
|
|
4
|
+
arrayConfigScheme,
|
|
5
|
+
selectionConfigScheme,
|
|
6
|
+
tupleConfigScheme,
|
|
7
|
+
objConfigScheme,
|
|
8
|
+
boundedSeriesScheme,
|
|
9
|
+
} from "./config_scheme";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* value
|
|
13
|
+
* @param {function} generateFn - The function used to generate the value.
|
|
14
|
+
* @return {ValueConfig} The configuration object with the type "value" and the provided generate function.
|
|
15
|
+
*/
|
|
16
|
+
export const createValueConfig = (generateFn) => {
|
|
17
|
+
const config = {
|
|
18
|
+
type: "value",
|
|
19
|
+
generateFn,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
valueConfigScheme.parse(config);
|
|
23
|
+
|
|
24
|
+
return config;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* selection
|
|
29
|
+
* @param {Array} items - The array of items to choose from.
|
|
30
|
+
* @return {SelectionConfig} The configuration object with the type "select" and the provided items.
|
|
31
|
+
*/
|
|
32
|
+
export const createSelectionConfig = (items) => {
|
|
33
|
+
const config = { type: "select", items };
|
|
34
|
+
|
|
35
|
+
selectionConfigScheme.parse(config);
|
|
36
|
+
|
|
37
|
+
return config;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* object
|
|
42
|
+
* @param {object} content
|
|
43
|
+
* @return {ObjectConfig}
|
|
44
|
+
*/
|
|
45
|
+
export const createObjectConfig = (content) => {
|
|
46
|
+
const config = { type: "obj", content };
|
|
47
|
+
|
|
48
|
+
objConfigScheme.parse(config);
|
|
49
|
+
|
|
50
|
+
return config;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* array
|
|
55
|
+
* @param {object} item
|
|
56
|
+
* @param {number} len
|
|
57
|
+
* @return {ArrayConfig}
|
|
58
|
+
*/
|
|
59
|
+
export const createArrayConfig = (item, len) => {
|
|
60
|
+
const config = { type: "arr", item, len };
|
|
61
|
+
|
|
62
|
+
arrayConfigScheme.parse(config);
|
|
63
|
+
|
|
64
|
+
return config;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* tuple
|
|
69
|
+
* @param {Array} configItems
|
|
70
|
+
* @return {TupleConfig}
|
|
71
|
+
*/
|
|
72
|
+
export const createTupleConfig = (configItems) => {
|
|
73
|
+
const config = {
|
|
74
|
+
type: "tuple",
|
|
75
|
+
configItems,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
tupleConfigScheme.parse(config);
|
|
79
|
+
|
|
80
|
+
return config;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* bounded series
|
|
85
|
+
* @param {{ upperLimit: number, lowerLimit: number, createInitValue: () => number, count: number }} config
|
|
86
|
+
* @return {BoundedSeriesConfig}
|
|
87
|
+
*/
|
|
88
|
+
export const createBoundedSeriesConfig = (config) => {
|
|
89
|
+
const newConfig = {
|
|
90
|
+
type: "bounded_series",
|
|
91
|
+
...config,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
boundedSeriesScheme.parse(newConfig);
|
|
95
|
+
|
|
96
|
+
return newConfig;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// int value
|
|
100
|
+
export const createIntValueConfig = (option) =>
|
|
101
|
+
createValueConfig(() => faker.number.int(option));
|
|
102
|
+
|
|
103
|
+
// float value
|
|
104
|
+
export const createFloatValueConfig = (option) =>
|
|
105
|
+
createValueConfig(() => faker.number.float(option));
|
|
106
|
+
|
|
107
|
+
// email value
|
|
108
|
+
export const createEmailValueConfig = (option) =>
|
|
109
|
+
createValueConfig(() => faker.internet.email(option));
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { expect, expectTypeOf, test } from "vitest";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
createValueConfig,
|
|
5
|
+
createSelectionConfig,
|
|
6
|
+
createArrayConfig,
|
|
7
|
+
createTupleConfig,
|
|
8
|
+
createObjectConfig,
|
|
9
|
+
createBoundedSeriesConfig,
|
|
10
|
+
} from "./create_config";
|
|
11
|
+
import { createGeneratorByType } from "./create_generator_fn";
|
|
12
|
+
|
|
13
|
+
test("createValueConfig", () => {
|
|
14
|
+
const valueConfig = createValueConfig(() => 44);
|
|
15
|
+
|
|
16
|
+
expect(valueConfig.type).toBe("value");
|
|
17
|
+
expect(valueConfig.generateFn).toBeTypeOf("function");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("createSelectionConfig", () => {
|
|
21
|
+
const options = [1, 2, 3, 4];
|
|
22
|
+
const selectionConfig = createSelectionConfig([1, 2, 3, 4]);
|
|
23
|
+
|
|
24
|
+
expect(selectionConfig.type).toBe("select");
|
|
25
|
+
expect(selectionConfig.items).toEqual(options);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("createArrayConfig", () => {
|
|
29
|
+
const valueConfig = createValueConfig(() => 44);
|
|
30
|
+
const arrConfig = createArrayConfig(valueConfig, 20);
|
|
31
|
+
|
|
32
|
+
expect(arrConfig.type).toBe("arr");
|
|
33
|
+
expect(arrConfig.len).toBe(20);
|
|
34
|
+
expect(arrConfig.item).toEqual(valueConfig);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("createTupleConfig", () => {
|
|
38
|
+
const value1Config = createValueConfig(() => 123);
|
|
39
|
+
const value2Config = createValueConfig(() => "hello");
|
|
40
|
+
|
|
41
|
+
const tupleConfig = createTupleConfig([value1Config, value2Config]);
|
|
42
|
+
|
|
43
|
+
expect(tupleConfig.type).toBe("tuple");
|
|
44
|
+
expect(tupleConfig.configItems).toEqual([value1Config, value2Config]);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("createObjConfig", () => {
|
|
48
|
+
const value1Config = createValueConfig(() => 32);
|
|
49
|
+
const value2Config = createValueConfig(() => "frank");
|
|
50
|
+
|
|
51
|
+
const objConfig = createObjectConfig({
|
|
52
|
+
name: value2Config,
|
|
53
|
+
age: value1Config,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
expect(objConfig.type).toBe("obj");
|
|
57
|
+
expect(objConfig.content).toEqual({ name: value2Config, age: value1Config });
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("createBoundedSeriesConfig", () => {
|
|
61
|
+
const boundedSeriesConfig = createBoundedSeriesConfig({
|
|
62
|
+
count: 1,
|
|
63
|
+
upperLimit: 1.2,
|
|
64
|
+
lowerLimit: 1.0,
|
|
65
|
+
createInitValue: () => 40,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
expect(boundedSeriesConfig.type).toBe("bounded_series");
|
|
69
|
+
expect(boundedSeriesConfig.upperLimit).toBe(1.2);
|
|
70
|
+
expect(boundedSeriesConfig.lowerLimit).toBe(1.0);
|
|
71
|
+
expect(boundedSeriesConfig.createInitValue).toBeTypeOf("function");
|
|
72
|
+
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { faker } from "@faker-js/faker";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
valueConfigScheme,
|
|
5
|
+
selectionConfigScheme,
|
|
6
|
+
arrayConfigScheme,
|
|
7
|
+
objConfigScheme,
|
|
8
|
+
boundedSeriesScheme,
|
|
9
|
+
tupleConfigScheme,
|
|
10
|
+
} from "./config_scheme";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* value
|
|
14
|
+
* @param {ValueConfig} config
|
|
15
|
+
* @param {number=} level
|
|
16
|
+
* @return {function}
|
|
17
|
+
*/
|
|
18
|
+
export const createValueGenerator = (config, level = 0) => {
|
|
19
|
+
valueConfigScheme.parse(config);
|
|
20
|
+
|
|
21
|
+
return config.generateFn;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* selection
|
|
26
|
+
* @param {SelectionConfig} config
|
|
27
|
+
* @param {number=} level
|
|
28
|
+
* @return {function} The configuration object with the type "select" and the provided items.
|
|
29
|
+
*/
|
|
30
|
+
export const createSelectionGenerator = (config, level = 0) => {
|
|
31
|
+
selectionConfigScheme.parse(config);
|
|
32
|
+
|
|
33
|
+
const { items } = config;
|
|
34
|
+
|
|
35
|
+
return () => items[faker.number.int(items.length - 1)];
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* object
|
|
40
|
+
* @param {ObjectConfig} config
|
|
41
|
+
* @param {number=} level
|
|
42
|
+
* @return {() => object}
|
|
43
|
+
*/
|
|
44
|
+
export const createObjectGenerator = (config, level = 0) => {
|
|
45
|
+
objConfigScheme.parse(config);
|
|
46
|
+
|
|
47
|
+
const keyWithFns = Object.entries(config.content).map(([key, subConfig]) => [
|
|
48
|
+
key,
|
|
49
|
+
createGeneratorByType(subConfig, level + 1),
|
|
50
|
+
]);
|
|
51
|
+
|
|
52
|
+
return () => {
|
|
53
|
+
const result = {};
|
|
54
|
+
for (const [key, generateFn] of keyWithFns) {
|
|
55
|
+
result[key] = generateFn();
|
|
56
|
+
}
|
|
57
|
+
return result;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* array
|
|
63
|
+
* @param {ArrayConfig} config
|
|
64
|
+
* @param {number=} level
|
|
65
|
+
* @return {() => Array}
|
|
66
|
+
*/
|
|
67
|
+
export const createArrayGenerator = (config, level = 0) => {
|
|
68
|
+
arrayConfigScheme.parse(config);
|
|
69
|
+
|
|
70
|
+
const itemGeneratorFn = createGeneratorByType(config.item, level + 1);
|
|
71
|
+
|
|
72
|
+
return () => Array.from({ length: config.len ?? 0 }, itemGeneratorFn);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* tuple
|
|
77
|
+
* @param {TupleConfig} config
|
|
78
|
+
* @param {number=} level
|
|
79
|
+
* @return {() => Array}
|
|
80
|
+
*/
|
|
81
|
+
export const createTupleGenerator = (config, level = 0) => {
|
|
82
|
+
tupleConfigScheme.parse(config);
|
|
83
|
+
|
|
84
|
+
const itemsFns = config.configItems.map(createGeneratorByType);
|
|
85
|
+
|
|
86
|
+
return () => itemsFns.map((generateFn) => generateFn());
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* bounded series
|
|
91
|
+
* @param {BoundedSeriesConfig} config
|
|
92
|
+
* @param {number} level
|
|
93
|
+
* @return {() => Array<number>}
|
|
94
|
+
*/
|
|
95
|
+
export const createBoundedSeriesGenerator = (config, level = 0) => {
|
|
96
|
+
boundedSeriesScheme.parse(config);
|
|
97
|
+
|
|
98
|
+
const { upperLimit, lowerLimit, createInitValue, count } = config;
|
|
99
|
+
|
|
100
|
+
return () => {
|
|
101
|
+
let value = createInitValue();
|
|
102
|
+
|
|
103
|
+
const boundedSeries = [];
|
|
104
|
+
|
|
105
|
+
for (let i = 0; i < count; i++) {
|
|
106
|
+
value = faker.number.float({ max: upperLimit, min: lowerLimit }) * value;
|
|
107
|
+
boundedSeries.push(value);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return boundedSeries;
|
|
111
|
+
};
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
*
|
|
116
|
+
* @param {ValueConfig | SelectionConfig | ArrayConfig | ObjectConfig | TupleConfig | BoundedSeriesConfig} config
|
|
117
|
+
* @param {number=} level
|
|
118
|
+
* @return {function}
|
|
119
|
+
*/
|
|
120
|
+
export const createGeneratorByType = (config, level = 0) => {
|
|
121
|
+
switch (config.type) {
|
|
122
|
+
case "obj":
|
|
123
|
+
return createObjectGenerator(config, level);
|
|
124
|
+
case "arr":
|
|
125
|
+
return createArrayGenerator(config, level);
|
|
126
|
+
case "select":
|
|
127
|
+
return createSelectionGenerator(config, level);
|
|
128
|
+
case "tuple":
|
|
129
|
+
return createTupleGenerator(config, level);
|
|
130
|
+
case "value":
|
|
131
|
+
return createValueGenerator(config, level);
|
|
132
|
+
case "bounded_series":
|
|
133
|
+
return createBoundedSeriesGenerator(config, level);
|
|
134
|
+
default:
|
|
135
|
+
throw Error(
|
|
136
|
+
`level ${level} config type "${config.type}" is not supported`,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { ZodError } from "zod";
|
|
3
|
+
import {
|
|
4
|
+
createValueGenerator,
|
|
5
|
+
createSelectionGenerator,
|
|
6
|
+
createArrayGenerator,
|
|
7
|
+
createTupleGenerator,
|
|
8
|
+
createObjectGenerator,
|
|
9
|
+
createBoundedSeriesGenerator,
|
|
10
|
+
} from "./create_generator_fn";
|
|
11
|
+
|
|
12
|
+
describe("createValueGenerator", () => {
|
|
13
|
+
test("normal", () => {
|
|
14
|
+
const value = createValueGenerator({
|
|
15
|
+
type: "value",
|
|
16
|
+
generateFn: () => 50,
|
|
17
|
+
})();
|
|
18
|
+
|
|
19
|
+
expect(value).toBe(50);
|
|
20
|
+
|
|
21
|
+
const value2 = createValueGenerator({
|
|
22
|
+
type: "value",
|
|
23
|
+
generateFn: () => ({ age: 100, name: "hello" }),
|
|
24
|
+
})();
|
|
25
|
+
|
|
26
|
+
expect(value2).toEqual({ age: 100, name: "hello" });
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe("createSelectionGenerator", () => {
|
|
31
|
+
test("normal", () => {
|
|
32
|
+
const value = createSelectionGenerator({
|
|
33
|
+
type: "select",
|
|
34
|
+
items: [1],
|
|
35
|
+
})();
|
|
36
|
+
|
|
37
|
+
expect(value).toBe(1);
|
|
38
|
+
|
|
39
|
+
const value2 = createSelectionGenerator({
|
|
40
|
+
type: "select",
|
|
41
|
+
items: [30, 30, 30, 30],
|
|
42
|
+
})();
|
|
43
|
+
|
|
44
|
+
expect(value2).toBe(30);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe("createArrayGenerator", () => {
|
|
49
|
+
test("normal", () => {
|
|
50
|
+
const list = createArrayGenerator({
|
|
51
|
+
type: "arr",
|
|
52
|
+
len: 5,
|
|
53
|
+
item: { type: "value", generateFn: () => ({ age: 42 }) },
|
|
54
|
+
})();
|
|
55
|
+
|
|
56
|
+
expect(list).toEqual([
|
|
57
|
+
{ age: 42 },
|
|
58
|
+
{ age: 42 },
|
|
59
|
+
{ age: 42 },
|
|
60
|
+
{ age: 42 },
|
|
61
|
+
{ age: 42 },
|
|
62
|
+
]);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe("createTupleGenerator", () => {
|
|
67
|
+
test("normal", () => {
|
|
68
|
+
const tuple = createTupleGenerator({
|
|
69
|
+
type: "tuple",
|
|
70
|
+
configItems: [
|
|
71
|
+
{ type: "value", generateFn: () => 225 },
|
|
72
|
+
{ type: "value", generateFn: () => "hello world" },
|
|
73
|
+
],
|
|
74
|
+
})();
|
|
75
|
+
|
|
76
|
+
expect(tuple.length).toBe(2);
|
|
77
|
+
const [num, str] = tuple;
|
|
78
|
+
expect(num).toBe(225);
|
|
79
|
+
expect(str).toBe("hello world");
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe("createObjectGenerator", () => {
|
|
84
|
+
test("normal", () => {
|
|
85
|
+
const obj = createObjectGenerator({
|
|
86
|
+
type: "obj",
|
|
87
|
+
content: {
|
|
88
|
+
name: { type: "value", generateFn: () => "John" },
|
|
89
|
+
age: { type: "value", generateFn: () => 50 },
|
|
90
|
+
location: { type: "value", generateFn: () => "Taiwan" },
|
|
91
|
+
},
|
|
92
|
+
})();
|
|
93
|
+
|
|
94
|
+
expect(obj).toEqual({ name: "John", age: 50, location: "Taiwan" });
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe("createBoundedSeriesGenerator", () => {
|
|
99
|
+
test("normal", () => {
|
|
100
|
+
const upperLimit = 1.1;
|
|
101
|
+
const lowerLimit = 0.9;
|
|
102
|
+
const initValue = 100;
|
|
103
|
+
const count = 100;
|
|
104
|
+
|
|
105
|
+
const list = createBoundedSeriesGenerator({
|
|
106
|
+
type: "bounded_series",
|
|
107
|
+
upperLimit,
|
|
108
|
+
lowerLimit,
|
|
109
|
+
createInitValue: () => initValue,
|
|
110
|
+
count,
|
|
111
|
+
})();
|
|
112
|
+
|
|
113
|
+
for (let i = 0; i < count; i++) {
|
|
114
|
+
const value = list[i];
|
|
115
|
+
if (i === 0) {
|
|
116
|
+
const ratio = value / initValue;
|
|
117
|
+
|
|
118
|
+
expect(ratio).toBeLessThanOrEqual(upperLimit);
|
|
119
|
+
expect(ratio).toBeGreaterThanOrEqual(lowerLimit);
|
|
120
|
+
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const prevValue = list[i - 1];
|
|
125
|
+
|
|
126
|
+
const ratio = value / prevValue;
|
|
127
|
+
|
|
128
|
+
expect(ratio).toBeLessThanOrEqual(upperLimit);
|
|
129
|
+
expect(ratio).toBeGreaterThanOrEqual(lowerLimit);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
});
|
package/src/type.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {{ type: 'value', generateFn: Function}} ValueConfig
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @typedef {{ type: 'select', items: Array }} SelectionConfig
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {{ type: 'arr', item: Object, len: number }} ArrayConfig
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {{ type: 'tuple', configItems: Array }} TupleConfig
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @typedef {{ type: 'obj', content: Object }} ObjectConfig
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {{ type: 'bounded_series', upperLimit: number, lowerLimit: number, createInitValue: function, count: number }} BoundedSeriesConfig
|
|
23
|
+
*/
|