I'm writing a minifier for lexical nodes. Writing unit tests and after taking a quick look at the options for generating test data (factory-girl
, faker.js
, casual.js
, etc) I saw that there wasn't one that would allow me to quickly define different values per property and generate a list of objects that use those values.
I am sharing a small utility to generate a list of objects from a shape, that iterates through the different possibilities for each property.
type Shape<T> = {
[key in keyof T]: any;
};
function* oneOf(...args: any[]) {
let index = 0;
while (index < args.length) {
if (index < args.length - 1) {
yield args[index];
} else {
return args[index];
}
index++;
}
}
function isGenerator(obj: any): obj is Generator {
return (
!Array.isArray(obj) &&
typeof obj === "object" &&
typeof obj[Symbol.iterator] === "function"
);
}
function create<T>(shape: Shape<T>): T[] {
const values: T[] = [];
let shouldContinue = true;
let item: any = {};
while (shouldContinue) {
shouldContinue = false;
Object.entries(shape).forEach(([key, def]: [string, any]) => {
if (isGenerator(def)) {
const { value, done } = def.next();
if (done === false) {
shouldContinue = true;
item[key] = value;
} else if (typeof value !== "undefined") {
item[key] = value;
}
} else {
item[key] = def;
}
});
values.push(<T>{ ...item });
}
return values;
}
const paragraphs = create<SerializedParagraphNode>({
children: [],
direction: oneOf("ltr", "rtl", null),
format: oneOf("left", "start", "center", "right", "end", "justify", ""),
indent: oneOf(0, 1, 2),
type: "paragraph",
version: 1,
});
/* output:
[{
children: [],
direction: 'ltr',
format: 'left',
indent: 0,
type: 'paragraph',
version: 1
},
{
children: [],
direction: 'rtl',
format: 'start',
indent: 1,
type: 'paragraph',
version: 1
},
{
children: [],
direction: null,
format: 'center',
indent: 2,
type: 'paragraph',
version: 1
},
{
children: [],
direction: null,
format: 'right',
indent: 2,
type: 'paragraph',
version: 1
},
{
children: [],
direction: null,
format: 'end',
indent: 2,
type: 'paragraph',
version: 1
},
{
children: [],
direction: null,
format: 'justify',
indent: 2,
type: 'paragraph',
version: 1
},
{
children: [],
direction: null,
format: '',
indent: 2,
type: 'paragraph',
version: 1
}]
*/
Here's the JavaScript version: