UNPKG

@jackfranklin/test-data-bot

Version:
156 lines 6.09 kB
"use strict"; 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