custom-app
Version:
ITIMS��Ʒ�鿪��ר��React���,�Dz��ý��ּ�dhcc-app���������
430 lines (425 loc) • 11.8 kB
JavaScript
import test from 'ava'
import merge from '../dist/index.cjs'
import { concatArrays } from '../dist/index.cjs'
import copy from 'copy-anything'
import { isDate, isFunction, isString, isArray, isObject } from 'is-what'
function cloneFn (originVal, targetVal) {
if (isObject(targetVal)) return JSON.parse(JSON.stringify(targetVal))
return targetVal
}
test('1. origin & target stays the same | 2. works with dates', t => {
let res, origin, target
const nd = new Date()
origin = {body: 'a'}
target = {dueDate: nd}
res = merge(origin, target)
t.deepEqual(res, {body: 'a', dueDate: nd})
t.deepEqual(origin, {body: 'a'})
t.deepEqual(target, {dueDate: nd})
})
test('adding a prop on target1|target2|mergedObj', t => {
let res, origin, target
origin = {nested: {}}
target = {nested: {}}
res = merge(origin, target)
t.deepEqual(res, {nested: {}})
origin.nested.a = ''
target.nested.b = ''
res.nested.c = ''
t.deepEqual(origin, {nested: {a: ''}})
t.deepEqual(target, {nested: {b: ''}})
t.deepEqual(res, {nested: {c: ''}})
})
test('changing a prop on target1|target2|mergedObj', t => {
let res, origin, target
// failing example
origin = {nested: {a: 1}}
target = {}
res = merge(origin, target)
t.deepEqual(res, {nested: {a: 1}})
origin.nested.a = 2
t.deepEqual(origin, {nested: {a: 2}}) // linked
t.deepEqual(target, {})
t.deepEqual(res, {nested: {a: 2}}) // linked
target.nested = {a: 3}
t.deepEqual(origin, {nested: {a: 2}}) // not changed
t.deepEqual(target, {nested: {a: 3}})
t.deepEqual(res, {nested: {a: 2}}) // not changed
res.nested.a = 4
t.deepEqual(origin, {nested: {a: 4}}) // linked
t.deepEqual(target, {nested: {a: 3}})
t.deepEqual(res, {nested: {a: 4}}) // linked
// working
origin = {nested: {a: 1}}
target = {}
res = copy(merge(origin, target))
t.deepEqual(res, {nested: {a: 1}})
origin.nested.a = 2
t.deepEqual(origin, {nested: {a: 2}}) // not linked
t.deepEqual(target, {})
t.deepEqual(res, {nested: {a: 1}}) // not linked
target.nested = {a: 3}
t.deepEqual(origin, {nested: {a: 2}}) // not changed
t.deepEqual(target, {nested: {a: 3}})
t.deepEqual(res, {nested: {a: 1}}) // not changed
res.nested.a = 4
t.deepEqual(origin, {nested: {a: 2}}) // not linked
t.deepEqual(target, {nested: {a: 3}})
t.deepEqual(res, {nested: {a: 4}}) // not linked
})
test('1. works with multiple levels | 2. overwrites entire object with null', t => {
let res, origin, target
origin = {body: '', head: null, toes: {big: true}, fingers: {'12': false}}
target = {body: {}, head: {}, toes: {}, fingers: null}
res = merge(origin, target)
t.deepEqual(res, {body: {}, head: {}, toes: {big: true}, fingers: null})
})
test('origin and target are not modified', t => {
let res, origin, target
origin = {body: '', head: null, toes: {big: true}, fingers: {'12': false}}
target = {body: {}, head: {}, toes: {}, fingers: null}
res = merge(origin, target)
t.deepEqual(res, {body: {}, head: {}, toes: {big: true}, fingers: null})
t.deepEqual(origin, {body: '', head: null, toes: {big: true}, fingers: {'12': false}})
t.deepEqual(target, {body: {}, head: {}, toes: {}, fingers: null})
origin.body = 'a'
origin.head = 'a'
origin.toes.big = 'a'
origin.fingers['12'] = 'a'
target.body = 'b'
target.head = 'b'
target.toes = 'b'
target.fingers = 'b'
t.deepEqual(res, {body: {}, head: {}, toes: {big: true}, fingers: null})
t.deepEqual(origin, {body: 'a', head: 'a', toes: {big: 'a'}, fingers: {'12': 'a'}})
t.deepEqual(target, {body: 'b', head: 'b', toes: 'b', fingers: 'b'})
})
test('origin and target are not modified - with completely different props', t => {
let res, origin, target
// extend to clone vals
origin = {body: '', head: null, toes: {big: true}, fingers: {'12': false}}
target = {a: 'a', b: 'b', c: {d: {e: 'e'}}}
res = merge({extensions: [cloneFn]}, origin, target)
t.deepEqual(res, {body: '', head: null, toes: {big: true}, fingers: {'12': false}, a: 'a', b: 'b', c: {d: {e: 'e'}}})
t.deepEqual(origin, {body: '', head: null, toes: {big: true}, fingers: {'12': false}})
t.deepEqual(target, {a: 'a', b: 'b', c: {d: {e: 'e'}}})
origin.body = 'a'
origin.head = 'a'
origin.toes.big = 'a'
origin.fingers['12'] = 'a'
target.a = 'x'
target.b = 'x'
target.c.d.e = 'x'
t.deepEqual(origin, {body: 'a', head: 'a', toes: {big: 'a'}, fingers: {'12': 'a'}})
t.deepEqual(target, {a: 'x', b: 'x', c: {d: {e: 'x'}}})
t.deepEqual(res, {body: '', head: null, toes: {big: true}, fingers: {'12': false}, a: 'a', b: 'b', c: {d: {e: 'e'}}})
})
test('Clone Objects', t => {
let clone, origin, target
origin = {body: '', head: null, toes: {big: true}, fingers: {'12': false}}
clone = merge({extensions: [cloneFn]}, origin)
t.deepEqual(clone, {body: '', head: null, toes: {big: true}, fingers: {'12': false}})
t.deepEqual(origin, {body: '', head: null, toes: {big: true}, fingers: {'12': false}})
origin.body = 'a'
origin.head = 'a'
origin.toes.big = 'a'
origin.fingers['12'] = 'a'
t.deepEqual(clone, {body: '', head: null, toes: {big: true}, fingers: {'12': false}})
t.deepEqual(origin, {body: 'a', head: 'a', toes: {big: 'a'}, fingers: {'12': 'a'}})
})
test('Overwrite arrays', t => {
let res, origin, target
origin = {array: ['a']}
target = {array: ['b']}
res = merge(origin, target)
t.deepEqual(res, {array: ['b']})
})
test('Extend conversion', t => {
let res, origin, target
function convertTimestamps (originVal, targetVal) {
if (
originVal === '%convertTimestamp%' &&
isString(targetVal) &&
isDate(new Date(targetVal))
) {
return new Date(targetVal)
}
return targetVal
}
origin = {
date: '%convertTimestamp%'
}
target = {
date: '1990-06-22'
}
res = merge({extensions: [convertTimestamps]}, origin, target)
t.deepEqual(res, {date: new Date('1990-06-22')})
res = merge({extensions: [convertTimestamps]}, '%convertTimestamp%', '1990-06-22')
t.deepEqual(res, new Date('1990-06-22'))
})
test('Extend concat arrays', t => {
let res, origin, target
function concatArr (originVal, targetVal) {
if (isArray(originVal) && isArray(targetVal)) {
return originVal.concat(targetVal)
}
return targetVal
}
origin = {
someArray: ['a'],
a: {b: {c: ['x']}}
}
target = {
someArray: ['b'],
a: {b: {c: ['y']}}
}
res = merge({extensions: [concatArr]}, origin, target)
t.deepEqual(res, {someArray: ['a', 'b'], a: {b: {c: ['x', 'y']}}})
// also works on base lvl
res = merge({extensions: [concatArr]}, ['a'], ['b'])
t.deepEqual(res, ['a', 'b'])
})
test('import concat array extension', t => {
let res, origin, target
origin = {
someArray: ['a'],
a: {b: {c: ['x']}}
}
target = {
someArray: ['b'],
a: {b: {c: ['y']}}
}
res = merge({extensions: [concatArrays]}, origin, target)
t.deepEqual(res, {someArray: ['a', 'b'], a: {b: {c: ['x', 'y']}}})
// also works on base lvl
res = merge({extensions: [concatArrays]}, ['a'], ['b'])
t.deepEqual(res, ['a', 'b'])
})
test('overwrites null with empty object', t => {
let res, origin, target
origin = {
body: null
}
target = {
body: {}
}
res = merge(origin, target)
t.deepEqual(res, {body: {}})
})
test('overwrites null with object with props', t => {
let res, origin, target
origin = {
body: null
}
target = {
body: {props: true}
}
res = merge(origin, target)
t.deepEqual(res, {body: {props: true}})
})
test('overwrites string values', t => {
let res, origin, target
origin = {body: 'a'}
target = {body: 'b'}
res = merge(origin, target)
t.deepEqual(res, {body: 'b'})
t.deepEqual(origin, {body: 'a'})
t.deepEqual(target, {body: 'b'})
})
test('works with very deep props & dates', t => {
let res, origin, target
const newDate = new Date()
origin = {
info: {
time: 'now',
newDate,
very: {
deep: {
prop: false
}
}
}
}
target = {
info: {
date: 'tomorrow',
very: {
deep: {
prop: true
}
}
}
}
res = merge(origin, target)
t.deepEqual(res, {
info: {
time: 'now',
newDate,
date: 'tomorrow',
very: {
deep: {
prop: true
}
}
}
})
t.deepEqual(origin, {
info: {
time: 'now',
newDate,
very: {
deep: {prop: false}
}
}
})
t.deepEqual(target, {
info: {
date: 'tomorrow',
very: {
deep: {prop: true}
}
}
})
t.true(isDate(res.info.newDate))
})
test('1. does not overwrite origin prop if target prop is an empty object | 2. properly merges deep props', t => {
let res, origin, target
origin = {
info: {
time: {when: 'now'},
very: {
deep: {prop: false}
}
}
}
target = {
info: {
time: {},
very: {whole: 1}
}
}
res = merge(origin, target)
t.deepEqual(res, {
info: {
time: {when: 'now'},
very: {
deep: {prop: false},
whole: 1
}
}
})
})
test('overwrites any origin prop when target prop is an object with props', t => {
let res, origin, target
origin = {
body: 'a',
body2: {head: false},
tail: {}
}
target = {
body: {head: true},
body2: {head: {eyes: true}},
}
res = merge(origin, target)
t.deepEqual(res, {
body: {head: true},
body2: {head: {eyes: true}},
tail: {}
})
t.deepEqual(origin, {
body: 'a',
body2: {head: false},
tail: {}
})
t.deepEqual(target, {
body: {head: true},
body2: {head: {eyes: true}},
})
})
test('overwrites entire objects when target val is a simple string', t => {
let res, origin, target
origin = {
body: 'a',
body2: {head: false},
tail: {}
}
target = 'a'
res = merge(origin, target)
t.is(res, 'a')
t.deepEqual(origin, {
body: 'a',
body2: {head: false},
tail: {}
})
})
test('works with unlimited depth', t => {
let res, origin, t1, t2, t3, t4
const date = new Date()
origin = {origin: 'a', t2: false, t3: {}, t4: 'false'}
t1 = {t1: date}
t2 = {t2: 'new'}
t3 = {t3: 'new'}
t4 = {t4: 'new', t3: {}}
res = merge(origin, t1, t2, t3, t4)
t.deepEqual(res, {origin: 'a', t1: date, t2: 'new', t3: {}, t4: 'new'})
t.deepEqual(origin, {origin: 'a', t2: false, t3: {}, t4: 'false'})
t.deepEqual(t1, {t1: date})
t.deepEqual(t2, {t2: 'new'})
t.deepEqual(t3, {t3: 'new'})
t.deepEqual(t4, {t4: 'new', t3: {}})
})
test('symbols as keys', t => {
let res, x, y
const mySymbol = Symbol('mySymbol')
x = { value: 42, [mySymbol]: 'hello' }
y = { other: 33 }
res = merge(x, y)
t.is(res.value, 42)
t.is(res.other, 33)
t.is(res[mySymbol], 'hello')
x = { value: 42 }
y = { other: 33, [mySymbol]: 'hello' }
res = merge(x, y)
t.is(res.value, 42)
t.is(res.other, 33)
t.is(res[mySymbol], 'hello')
})
test('nonenumerable keys', t => {
let x, y, res
const mySymbol = Symbol('mySymbol')
x = { value: 42 }
y = { other: 33 }
Object.defineProperty(x, 'xid', {
value: 1,
writable: true,
enumerable: false,
configurable: true
})
Object.defineProperty(x, mySymbol, {
value: 'original',
writable: true,
enumerable: false,
configurable: true
})
Object.defineProperty(y, 'yid', {
value: 2,
writable: true,
enumerable: false,
configurable: true
})
Object.defineProperty(y, mySymbol, {
value: 'new',
writable: true,
enumerable: false,
configurable: true
})
res = merge(x, y)
t.is(res.value, 42)
t.is(res.other, 33)
t.is(res.xid, 1)
t.is(res.yid, 2)
t.is(res[mySymbol], 'new')
t.is(Object.keys(res).length, 2)
t.true(Object.keys(res).includes('value'))
t.true(Object.keys(res).includes('other'))
})