From ffdc2b01c5823f615ece6a528a5b6ad37a09f4a0 Mon Sep 17 00:00:00 2001 From: Adam Wathan Date: Fri, 1 Feb 2019 10:37:36 -0500 Subject: [PATCH] Intelligently deep merge user's config --- __tests__/mergeConfigWithDefaults.test.js | 329 +++++++++++++++++++++- src/util/mergeConfigWithDefaults.js | 5 +- 2 files changed, 318 insertions(+), 16 deletions(-) diff --git a/__tests__/mergeConfigWithDefaults.test.js b/__tests__/mergeConfigWithDefaults.test.js index 135681356..1b1655479 100644 --- a/__tests__/mergeConfigWithDefaults.test.js +++ b/__tests__/mergeConfigWithDefaults.test.js @@ -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: {}, }) }) diff --git a/src/util/mergeConfigWithDefaults.js b/src/util/mergeConfigWithDefaults.js index 4be7a1f99..ea229fd3b 100644 --- a/src/util/mergeConfigWithDefaults.js +++ b/src/util/mergeConfigWithDefaults.js @@ -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) }