@jackfranklin/test-data-bot
Version:
Generate test data for your tests easily.
156 lines • 6.09 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.perBuild = exports.sequence = exports.bool = exports.oneOf = exports.build = void 0;
const isGenerator = (field) => {
if (!field)
return false;
return field.generatorType !== undefined;
};
const identity = (x) => x;
const buildTimeTraitsArray = (buildTimeConfig) => {
const { traits = [] } = buildTimeConfig;
return Array.isArray(traits) ? traits : [traits];
};
const getValueOrOverride = (overrides, traitOverrides, fieldValue, fieldKey) => {
if (Object.keys(overrides).includes(fieldKey)) {
return overrides[fieldKey];
}
if (Object.keys(traitOverrides).includes(fieldKey)) {
return traitOverrides[fieldKey];
}
return fieldValue;
};
function mapValues(object, callback) {
return Object.keys(object).reduce((total, key) => {
total[key] = callback(object[key], key);
return total;
}, {});
}
const build = (factoryNameOrConfig, configObject) => {
const config = (typeof factoryNameOrConfig === 'string' ? configObject : factoryNameOrConfig);
let sequenceCounter = 0;
const expandConfigFields = (fields, buildTimeConfig = {}) => {
const finalBuiltThing = mapValues(fields, (fieldValue, fieldKey) => {
const overrides = buildTimeConfig.overrides || {};
const traitsArray = buildTimeTraitsArray(buildTimeConfig);
const traitOverrides = traitsArray.reduce((overrides, currentTraitKey) => {
const hasTrait = config.traits && config.traits[currentTraitKey];
if (!hasTrait) {
console.warn(`Warning: trait '${currentTraitKey}' not found.`);
}
const traitsConfig = config.traits
? config.traits[currentTraitKey]
: {};
return Object.assign(Object.assign({}, overrides), (traitsConfig.overrides || {}));
}, {});
const valueOrOverride = getValueOrOverride(overrides, traitOverrides, fieldValue, fieldKey);
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */
return expandConfigField(valueOrOverride);
});
return finalBuiltThing;
};
const expandConfigField = (fieldValue) => {
if (isGenerator(fieldValue)) {
switch (fieldValue.generatorType) {
case 'sequence': {
return fieldValue.call(++sequenceCounter);
}
case 'oneOf':
case 'perBuild': {
return fieldValue.call();
}
}
}
if (Array.isArray(fieldValue)) {
return fieldValue.map((v) => expandConfigField(v));
}
if (fieldValue === null || fieldValue === undefined) {
// has to be before typeof fieldValue === 'object'
// as typeof null === 'object'
return fieldValue;
}
if (fieldValue instanceof Date) {
return fieldValue;
}
if (typeof fieldValue === 'object') {
return expandConfigFields(fieldValue);
}
return fieldValue;
};
const builder = (buildTimeConfig = {}) => {
const fieldsToReturn = expandConfigFields(config.fields, buildTimeConfig);
const traitsArray = buildTimeTraitsArray(buildTimeConfig);
// A user might define a value in a trait that doesn't exist in the base
// set of fields. So we need to check now if the traits set any values that
// aren't in the base, and set them too.
traitsArray.forEach((traitName) => {
const traitConfig = (config.traits && config.traits[traitName]) || {};
if (!traitConfig.overrides) {
return;
}
for (const stringKey of Object.keys(traitConfig.overrides)) {
const key = stringKey;
// If the key already exists in the base fields, we'll have defined it,
// so we don't need to worry about it.
if (key in config.fields === false) {
fieldsToReturn[key] = expandConfigField(traitConfig.overrides[key]);
}
}
});
const traitPostBuilds = traitsArray.map((traitName) => {
const traitConfig = (config.traits && config.traits[traitName]) || {};
const postBuild = traitConfig.postBuild || identity;
return postBuild;
});
const afterTraitPostBuildFields = traitPostBuilds.reduce((fields, traitPostBuild) => {
return traitPostBuild(fields);
}, fieldsToReturn);
const postBuild = config.postBuild || identity;
const buildTimeMapFunc = buildTimeConfig.map || identity;
return buildTimeMapFunc(postBuild(afterTraitPostBuildFields));
};
builder.reset = () => {
sequenceCounter = 0;
};
builder.one = (buildTimeConfig) => {
return builder(buildTimeConfig);
};
builder.many = (times, buildTimeConfig) => {
return new Array(times).fill(0).map(() => builder(buildTimeConfig));
};
return builder;
};
exports.build = build;
const oneOf = (...options) => {
return {
generatorType: 'oneOf',
call: () => {
const randomIndex = Math.floor(Math.random() * options.length);
return options[randomIndex];
},
};
};
exports.oneOf = oneOf;
const bool = () => (0, exports.oneOf)(true, false);
exports.bool = bool;
exports.sequence = ((userProvidedFunction) => {
return {
generatorType: 'sequence',
call: (counter) => {
if (typeof userProvidedFunction === 'undefined') {
return counter;
}
return userProvidedFunction(counter);
},
};
});
const perBuild = (func) => {
return {
generatorType: 'perBuild',
call: () => {
return func();
},
};
};
exports.perBuild = perBuild;
//# sourceMappingURL=index.js.map