Intelligently deep merge user's config

This commit is contained in:
Adam Wathan 2019-02-01 10:37:36 -05:00
parent b036cac4b5
commit ffdc2b01c5
2 changed files with 318 additions and 16 deletions

View File

@ -1,47 +1,346 @@
import mergeConfigWithDefaults from '../src/util/mergeConfigWithDefaults'
test('user top-level keys override default top-level keys', () => {
test('prefix key overrides default prefix', () => {
const userConfig = {
prefix: 'tw-',
}
const defaultConfig = {
prefix: '',
important: false,
separator: ':',
theme: {
screens: {
mobile: '400px',
},
},
variants: {
appearance: ['responsive'],
borderCollapse: [],
borderColors: ['responsive', 'hover', 'focus'],
}
}
const result = mergeConfigWithDefaults(userConfig, defaultConfig)
expect(result).toEqual({
prefix: 'tw-',
important: false,
separator: ':',
theme: {
screens: {
mobile: '400px',
},
},
variants: {
appearance: ['responsive'],
borderCollapse: [],
borderColors: ['responsive', 'hover', 'focus'],
}
})
})
test('important key overrides default important', () => {
const userConfig = {
important: true,
}
const defaultConfig = {
prefix: '',
important: false,
separator: ':',
theme: {
screens: {
mobile: '400px',
},
},
variants: {
appearance: ['responsive'],
borderCollapse: [],
borderColors: ['responsive', 'hover', 'focus'],
}
}
const result = mergeConfigWithDefaults(userConfig, defaultConfig)
expect(result).toEqual({
prefix: '',
important: true,
separator: ':',
theme: {
screens: {
mobile: '400px',
},
},
variants: {
appearance: ['responsive'],
borderCollapse: [],
borderColors: ['responsive', 'hover', 'focus'],
}
})
})
test('separator key overrides default separator', () => {
const userConfig = {
separator: '__',
}
const defaultConfig = {
prefix: '',
important: false,
separator: ':',
theme: {
screens: {
mobile: '400px',
},
},
variants: {
appearance: ['responsive'],
borderCollapse: [],
borderColors: ['responsive', 'hover', 'focus'],
}
}
const result = mergeConfigWithDefaults(userConfig, defaultConfig)
expect(result).toEqual({
prefix: '',
important: false,
separator: '__',
theme: {
screens: {
mobile: '400px',
},
},
variants: {
appearance: ['responsive'],
borderCollapse: [],
borderColors: ['responsive', 'hover', 'focus'],
}
})
})
test('theme key is merged instead of replaced', () => {
const userConfig = {
theme: {
screens: {
mobile: '400px',
},
},
}
const defaultConfig = {
prefix: '-',
important: false,
separator: ':',
theme: {
colors: {
'grey-darker': '#606f7b',
'grey-dark': '#8795a1',
'grey': '#b8c2cc',
'grey-light': '#dae1e7',
'grey-lighter': '#f1f5f8',
},
fonts: {
sans: [
'system-ui',
'BlinkMacSystemFont',
'-apple-system',
'Roboto',
'sans-serif',
],
serif: [
'Constantia',
'Lucida Bright',
'Georgia',
'serif',
],
},
screens: {
sm: '500px',
md: '750px',
lg: '1000px',
},
},
variants: {
appearance: ['responsive'],
borderCollapse: [],
borderColors: ['responsive', 'hover', 'focus'],
}
}
const result = mergeConfigWithDefaults(userConfig, defaultConfig)
expect(result).toEqual({
prefix: 'tw-',
important: true,
prefix: '-',
important: false,
separator: ':',
theme: {
colors: {
'grey-darker': '#606f7b',
'grey-dark': '#8795a1',
'grey': '#b8c2cc',
'grey-light': '#dae1e7',
'grey-lighter': '#f1f5f8',
},
fonts: {
sans: [
'system-ui',
'BlinkMacSystemFont',
'-apple-system',
'Roboto',
'sans-serif',
],
serif: [
'Constantia',
'Lucida Bright',
'Georgia',
'serif',
],
},
screens: {
mobile: '400px',
},
},
variants: {
appearance: ['responsive'],
borderCollapse: [],
borderColors: ['responsive', 'hover', 'focus'],
}
})
})
test('variants key is merged instead of replaced', () => {
const userConfig = {
variants: {
backgroundAttachment: [],
borderColors: ['responsive', 'hover', 'focus', 'active'],
}
}
const defaultConfig = {
prefix: '-',
important: false,
separator: ':',
theme: {
colors: {
'grey-darker': '#606f7b',
'grey-dark': '#8795a1',
'grey': '#b8c2cc',
'grey-light': '#dae1e7',
'grey-lighter': '#f1f5f8',
},
fonts: {
sans: [
'system-ui',
'BlinkMacSystemFont',
'-apple-system',
'Roboto',
'sans-serif',
],
serif: [
'Constantia',
'Lucida Bright',
'Georgia',
'serif',
],
},
screens: {
sm: '500px',
md: '750px',
lg: '1000px',
},
},
variants: {
appearance: ['responsive'],
backgroundAttachment: ['responsive'],
borderCollapse: [],
borderColors: ['responsive', 'hover', 'focus'],
borderRadius: ['responsive'],
}
}
const result = mergeConfigWithDefaults(userConfig, defaultConfig)
expect(result).toEqual({
prefix: '-',
important: false,
separator: ':',
theme: {
colors: {
'grey-darker': '#606f7b',
'grey-dark': '#8795a1',
'grey': '#b8c2cc',
'grey-light': '#dae1e7',
'grey-lighter': '#f1f5f8',
},
fonts: {
sans: [
'system-ui',
'BlinkMacSystemFont',
'-apple-system',
'Roboto',
'sans-serif',
],
serif: [
'Constantia',
'Lucida Bright',
'Georgia',
'serif',
],
},
screens: {
sm: '500px',
md: '750px',
lg: '1000px',
},
},
variants: {
appearance: ['responsive'],
backgroundAttachment: [],
borderCollapse: [],
borderColors: ['responsive', 'hover', 'focus', 'active'],
borderRadius: ['responsive'],
}
})
})
test('missing top level keys are pulled from the default config', () => {
const userConfig = {
colors: { red: '#ff0000' },
modules: {},
}
const userConfig = {}
const defaultConfig = {
colors: { green: '#00ff00' },
screens: {
sm: '576px',
prefix: '-',
important: false,
separator: ':',
theme: {
colors: { green: '#00ff00' },
screens: {
mobile: '400px',
},
},
variants: {
appearance: ['responsive'],
borderCollapse: [],
borderColors: ['responsive', 'hover', 'focus'],
},
modules: {},
}
const result = mergeConfigWithDefaults(userConfig, defaultConfig)
expect(result).toEqual({
colors: { red: '#ff0000' },
screens: {
sm: '576px',
prefix: '-',
important: false,
separator: ':',
theme: {
colors: { green: '#00ff00' },
screens: {
mobile: '400px',
},
},
variants: {
appearance: ['responsive'],
borderCollapse: [],
borderColors: ['responsive', 'hover', 'focus'],
},
modules: {},
})
})

View File

@ -1,5 +1,8 @@
import _ from 'lodash'
export default function(userConfig, defaultConfig) {
return _.defaults(userConfig, defaultConfig)
return _.defaults({
theme: _.defaults(userConfig.theme, defaultConfig.theme),
variants: _.defaults(userConfig.variants, defaultConfig.variants),
}, userConfig, defaultConfig)
}