UNPKG

@spencejs/spence-factories

Version:

Spence Factories - An opinionated Factory Framework for testing db entities

82 lines (69 loc) 2.53 kB
const _ = require("lodash/fp"); const { randomUUID } = require("node:crypto"); function register(name, ...args) { let defaultRepo; let baseFactory; if (args.length === 1) { [baseFactory] = args; } else { [defaultRepo, baseFactory] = args; } const capitalizedName = `${_.capitalize(name[0])}${name.slice(1)}`; const commonFactory = commonFactoryType(baseFactory, defaultRepo); return { name, capitalizedName, [`new${capitalizedName}`]: async (...commonFactoryArgs) => { const { item } = await commonFactory("created")(...commonFactoryArgs); return item; }, [`created${capitalizedName}`]: createdFactoryType(commonFactory), [`persist${capitalizedName}`]: persistFactoryType(commonFactory), }; } function commonFactoryType(baseFactory, defaultRepo) { return (itemType) => async (rawOverrides = {}) => { const manualProperties = []; async function getOrBuild(property, valFactory, ...valFactoryArgs) { if (rawOverrides[property] != null) { manualProperties.push(property); return rawOverrides[property]; } if (_.isFunction(valFactory)) { return valFactory(...valFactoryArgs); } return valFactory[`${itemType}${valFactory.capitalizedName}`](...valFactoryArgs); } function overrides() { return _.pickBy((v, k) => v != null && !_.includes(k, manualProperties), rawOverrides); } const val = await baseFactory(overrides, { getOrBuild }, rawOverrides); if (val.repo) { return val; } return { item: val, repo: defaultRepo }; }; } function createdFactoryType(commonFactory) { return async (overrides = {}) => { const { item, repo } = await commonFactory("created")(overrides); const idKey = _.getOr("id", "collection.idKey", repo); const mockIdGenerator = _.getOr(randomUUID, "collection.mockIdGenerator", repo); const timestampKeys = _.getOr({ createdAt: "createdAt", updatedAt: "updatedAt" }, "collection.timestampKeys", repo); return { [idKey]: mockIdGenerator(), [timestampKeys.createdAt]: new Date().toISOString(), [timestampKeys.updatedAt]: new Date().toISOString(), ...item, }; }; } function persistFactoryType(commonFactory) { return async (overrides = {}) => { const { item, repo } = await commonFactory("persist")(overrides); const value = await repo.insert(item); return JSON.parse(JSON.stringify(value)); }; } module.exports = { register };