@jackfranklin/test-data-bot
Advanced tools
Comparing version 1.2.0 to 1.3.0
@@ -35,5 +35,13 @@ /// <reference types="faker" /> | ||
map?: (builtThing: FactoryResultType) => FactoryResultType; | ||
traits?: string | string[]; | ||
} | ||
interface TraitsConfiguration<FactoryResultType> { | ||
readonly [traitName: string]: { | ||
overrides?: Overrides<FactoryResultType>; | ||
postBuild?: (builtThing: FactoryResultType) => FactoryResultType; | ||
}; | ||
} | ||
interface BuildConfiguration<FactoryResultType> { | ||
readonly fields: FieldsConfiguration<FactoryResultType>; | ||
readonly traits?: TraitsConfiguration<FactoryResultType>; | ||
readonly postBuild?: (x: FactoryResultType) => FactoryResultType; | ||
@@ -40,0 +48,0 @@ } |
@@ -18,2 +18,6 @@ "use strict"; | ||
const identity = (x) => x; | ||
const buildTimeTraitsArray = (buildTimeConfig) => { | ||
const { traits = [] } = buildTimeConfig; | ||
return Array.isArray(traits) ? traits : [traits]; | ||
}; | ||
exports.build = (factoryNameOrConfig, configObject) => { | ||
@@ -27,3 +31,14 @@ const config = (typeof factoryNameOrConfig === 'string' | ||
const overrides = buildTimeConfig.overrides || {}; | ||
const valueOrOverride = overrides[fieldKey] || fieldValue; | ||
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 = overrides[fieldKey] || traitOverrides[fieldKey] || fieldValue; | ||
/* eslint-disable-next-line @typescript-eslint/no-use-before-define */ | ||
@@ -77,5 +92,14 @@ return expandConfigField(valueOrOverride); | ||
const fieldsToReturn = expandConfigFields(config.fields, buildTimeConfig); | ||
const traitsArray = buildTimeTraitsArray(buildTimeConfig); | ||
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(fieldsToReturn)); | ||
return buildTimeMapFunc(postBuild(afterTraitPostBuildFields)); | ||
}; | ||
@@ -82,0 +106,0 @@ }; |
@@ -0,1 +1,6 @@ | ||
### 1.3.0 - 13 May 2020 | ||
- Added traits to test-data-bot. See the README for examples. | ||
### 1.2.0 - 09 May 2020 | ||
@@ -2,0 +7,0 @@ |
{ | ||
"name": "@jackfranklin/test-data-bot", | ||
"version": "1.2.0", | ||
"version": "1.3.0", | ||
"license": "MIT", | ||
@@ -37,3 +37,3 @@ "description": "Generate test data for your tests easily.", | ||
"@types/lodash": "^4.14.150", | ||
"@types/node": "^13.13.5", | ||
"@types/node": "^14.0.1", | ||
"@typescript-eslint/eslint-plugin": "^2.31.0", | ||
@@ -40,0 +40,0 @@ "@typescript-eslint/parser": "^2.31.0", |
@@ -261,2 +261,60 @@ # @jackfranklin/test-data-bot | ||
## Traits (*new in v1.3*) | ||
Traits let you define a set of overrides for a factory that can easily be re-applied. Let's imagine you've got a users factory where users can be admins: | ||
```js | ||
interface User { | ||
name: string; | ||
admin: boolean; | ||
} | ||
const userBuilder = build<User>({ | ||
fields: { | ||
name: 'jack', | ||
admin: perBuild(() => false), | ||
}, | ||
traits: { | ||
admin: { | ||
overrides: { admin: perBuild(() => true) }, | ||
}, | ||
}, | ||
}); | ||
``` | ||
Notice that we've defined the `admin` trait here. You don't need to do this; you could easily override the `admin` field each time: | ||
```js | ||
const adminUser = userBuilder({ overrides: { admin: perBuild(() => true) } }); | ||
``` | ||
But imagine that the field changes, or the way you represent admins changes. Or imagine setting an admin is not just one field but a few fields that need to change. Maybe an admin's email address always has to be a certain domain. We can define that behaviour once as a trait: | ||
```js | ||
const userBuilder = build<User>({ | ||
fields: { | ||
name: 'jack', | ||
admin: perBuild(() => false), | ||
}, | ||
traits: { | ||
admin: { | ||
overrides: { admin: perBuild(() => true) }, | ||
}, | ||
}, | ||
}); | ||
``` | ||
And now building an admin user is easy: | ||
```js | ||
const admin = userBuilder({ traits: 'admin' }); | ||
``` | ||
You can define and use multiple traits when building an object. Be aware that if two traits override the same value, the one passed in last wins: | ||
``` | ||
// any properties defined in other-trait will override any that admin sets | ||
const admin = userBuilder({ traits: ['admin', 'other-trait'] }); | ||
``` | ||
## TypeScript support | ||
@@ -263,0 +321,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
32269
195
466