mirror of
https://github.com/tenrok/OverlayScrollbars.git
synced 2026-06-06 03:12:27 +03:00
rework cache
This commit is contained in:
@@ -5,8 +5,8 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"test": "jest --coverage --runInBand --detectOpenHandles",
|
||||
"test:jsdom": "jest --coverage --runInBand --detectOpenHandles --selectProjects jsdom",
|
||||
"test:pptr": "jest --coverage --runInBand --detectOpenHandles --selectProjects puppeteer",
|
||||
"test:jsdom": "jest --coverage --runInBand --detectOpenHandles --selectProjects jsdom --testPathPattern",
|
||||
"test:pptr": "jest --coverage --runInBand --detectOpenHandles --selectProjects puppeteer --testPathPattern",
|
||||
"build": "rollup -c"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
import {
|
||||
CacheUpdateInfo,
|
||||
CachePropsToUpdate,
|
||||
CacheUpdated,
|
||||
Cache,
|
||||
OptionsWithOptionsTemplate,
|
||||
OptionsValidated,
|
||||
transformOptions,
|
||||
validateOptions,
|
||||
assignDeep,
|
||||
createCache,
|
||||
isEmptyObject,
|
||||
isBoolean,
|
||||
keys,
|
||||
} from 'support';
|
||||
import { PlainObject } from 'typings';
|
||||
|
||||
interface LifecycleUpdateHints<O, C> {
|
||||
_force?: boolean;
|
||||
_changedOptions?: OptionsValidated<O>;
|
||||
_changedOptions?: CachePropsToUpdate<O>;
|
||||
_changedCache?: CachePropsToUpdate<C>;
|
||||
}
|
||||
|
||||
@@ -46,7 +45,7 @@ export const createLifecycleBase = <O, C>(
|
||||
defaultOptionsWithTemplate: OptionsWithOptionsTemplate<Required<O>>,
|
||||
cacheUpdateInfo: CacheUpdateInfo<C>,
|
||||
initialOptions: O | undefined,
|
||||
updateFunction: (changedOptions: OptionsValidated<O>, changedCache: CacheUpdated<C>) => any
|
||||
updateFunction: (changedOptions: Cache<O>, changedCache: Cache<C>) => any
|
||||
): LifecycleBase<O, C> => {
|
||||
const { _template: optionsTemplate, _options: defaultOptions } = transformOptions<Required<O>>(defaultOptionsWithTemplate);
|
||||
const options: Required<O> = assignDeep(
|
||||
@@ -55,15 +54,16 @@ export const createLifecycleBase = <O, C>(
|
||||
validateOptions<O>(initialOptions || ({} as O), optionsTemplate, null, true)._validated
|
||||
);
|
||||
const cacheChange = createCache<C>(cacheUpdateInfo);
|
||||
const cacheOptions = createCache<O>(options, true);
|
||||
|
||||
const update = (hints: LifecycleUpdateHints<O, C>) => {
|
||||
const hasForce = isBoolean(hints._force);
|
||||
const force = hints._force === true;
|
||||
|
||||
const changedCache = cacheChange(force ? null : hints._changedCache || (hasForce ? null : []), force);
|
||||
const changedOptions = force ? options : hints._changedOptions || ({} as O);
|
||||
const changedOptions = cacheOptions(force ? null : hints._changedOptions, !!hints._changedOptions || force);
|
||||
|
||||
if (!isEmptyObject(changedOptions) || !isEmptyObject(changedCache)) {
|
||||
if (changedOptions._anythingChanged || changedCache._anythingChanged) {
|
||||
updateFunction(changedOptions, changedCache);
|
||||
}
|
||||
};
|
||||
@@ -76,7 +76,7 @@ export const createLifecycleBase = <O, C>(
|
||||
const { _validated: changedOptions } = validateOptions(newOptions, optionsTemplate, options, true);
|
||||
assignDeep(options, changedOptions);
|
||||
|
||||
update({ _changedOptions: changedOptions });
|
||||
update({ _changedOptions: keys(changedOptions) as CachePropsToUpdate<O> });
|
||||
}
|
||||
return options;
|
||||
},
|
||||
|
||||
@@ -1,14 +1,4 @@
|
||||
import {
|
||||
cssProperty,
|
||||
runEach,
|
||||
topRightBottomLeft,
|
||||
TRBL,
|
||||
equalTRBL,
|
||||
optionsTemplateTypes as oTypes,
|
||||
OptionsTemplateValue,
|
||||
style,
|
||||
hasOwnProperty,
|
||||
} from 'support';
|
||||
import { cssProperty, runEach, topRightBottomLeft, TRBL, equalTRBL, optionsTemplateTypes as oTypes, OptionsTemplateValue, style } from 'support';
|
||||
import { OSTargetObject } from 'typings';
|
||||
import { createLifecycleBase, Lifecycle } from 'lifecycles/lifecycleBase';
|
||||
import { getEnvironment, Environment } from 'environment';
|
||||
@@ -61,9 +51,10 @@ export const createStructureLifecycle = (
|
||||
},
|
||||
initialOptions,
|
||||
(changedOptions, changedCache) => {
|
||||
if (hasOwnProperty(changedOptions, 'paddingAbsolute') || hasOwnProperty(changedCache, 'padding')) {
|
||||
const { padding } = changedCache;
|
||||
const { paddingAbsolute } = changedOptions;
|
||||
const { _value: paddingAbsolute, _changed: paddingAbsoluteChanged } = changedOptions.paddingAbsolute;
|
||||
const { _value: padding, _changed: paddingChanged } = changedCache.padding;
|
||||
|
||||
if (paddingAbsoluteChanged || paddingChanged) {
|
||||
const paddingStyle: TRBL = {
|
||||
t: 0,
|
||||
r: 0,
|
||||
|
||||
+33
-31
@@ -1,31 +1,29 @@
|
||||
import { isArray, isString } from 'support/utils/types';
|
||||
import { keys } from 'support/utils/object';
|
||||
import { assignDeep, keys } from 'support/utils/object';
|
||||
import { each } from 'support/utils/array';
|
||||
|
||||
interface CacheEntry<T> {
|
||||
_current?: T;
|
||||
_previous?: T;
|
||||
_changed?: boolean;
|
||||
}
|
||||
|
||||
type Cache<T> = {
|
||||
[P in keyof T]: CacheEntry<T[P]>;
|
||||
};
|
||||
|
||||
type UpdateCacheProp<T> = <P extends keyof T>(prop: P, value: T[P], compare: EqualCachePropFunction<T, P> | null) => void;
|
||||
|
||||
type UpdateCachePropFunction<T, P extends keyof T> = (current?: T[P], previous?: T[P]) => T[P];
|
||||
|
||||
type EqualCachePropFunction<T, P extends keyof T> = (a?: T[P], b?: T[P]) => boolean;
|
||||
|
||||
export interface CacheEntry<T> {
|
||||
_value?: T;
|
||||
_previous?: T;
|
||||
_changed: boolean;
|
||||
}
|
||||
|
||||
export type Cache<T> = {
|
||||
[P in keyof T]: CacheEntry<T[P]>;
|
||||
};
|
||||
|
||||
export type CacheUpdated<T> = Cache<T> & { _anythingChanged: boolean };
|
||||
|
||||
export type CachePropsToUpdate<T> = Array<keyof T> | keyof T;
|
||||
|
||||
export type CacheUpdate<T> = (propsToUpdate?: CachePropsToUpdate<T> | null, force?: boolean) => CacheUpdated<T>;
|
||||
|
||||
export type CacheUpdated<T> = {
|
||||
[P in keyof T]?: T[P];
|
||||
};
|
||||
|
||||
export type CacheUpdateInfo<T> = {
|
||||
[P in keyof T]: UpdateCachePropFunction<T, P> | [UpdateCachePropFunction<T, P>, EqualCachePropFunction<T, P>];
|
||||
};
|
||||
@@ -46,31 +44,34 @@ export type CacheUpdateInfo<T> = {
|
||||
* If no equal function is passed a shallow comparison is carried out between the values.
|
||||
*
|
||||
* @returns A function which can be called with wither one ar an array of properties which shall be updated. Optionally it can be called with the force param.
|
||||
* This function returns a object which contains all changed cache properties, if a property isn't in this object it means that it didn't change.
|
||||
* This function returns a object which represents the cache and its state at the time of updating (changed to previous value, current value and previous value).
|
||||
*/
|
||||
export const createCache = <T>(cacheUpdateInfo: CacheUpdateInfo<T>): CacheUpdate<T> => {
|
||||
const cache: Cache<T> = {} as T;
|
||||
export function createCache<T>(cacheUpdateInfo: CacheUpdateInfo<T>): CacheUpdate<T>;
|
||||
export function createCache<T>(referenceObj: T, isReference: true): CacheUpdate<T>;
|
||||
export function createCache<T>(cacheUpdateInfo: CacheUpdateInfo<T> | T, isReference?: true): CacheUpdate<T> {
|
||||
const cache: Cache<T> = {} as any;
|
||||
const allProps: Array<keyof T> = keys(cacheUpdateInfo) as Array<keyof T>;
|
||||
|
||||
each(allProps, (prop) => {
|
||||
cache[prop] = {};
|
||||
cache[prop] = { _changed: false, _value: isReference ? cacheUpdateInfo[prop] : undefined } as any;
|
||||
});
|
||||
|
||||
const updateCacheProp: UpdateCacheProp<T> = (prop, value, equal): void => {
|
||||
const curr = cache[prop]._current;
|
||||
const curr = cache[prop]._value;
|
||||
|
||||
cache[prop]._current = value;
|
||||
cache[prop]._value = value;
|
||||
cache[prop]._previous = curr;
|
||||
cache[prop]._changed = equal ? !equal(curr, value) : curr !== value;
|
||||
};
|
||||
|
||||
const flush = (force?: boolean): CacheUpdated<T> => {
|
||||
const result: CacheUpdated<T> = {} as CacheUpdated<T>;
|
||||
const flush = (props: Array<keyof T>, force?: boolean): CacheUpdated<T> => {
|
||||
const result: CacheUpdated<T> = assignDeep({}, cache, { _anythingChanged: false });
|
||||
|
||||
each(allProps, (prop: keyof T) => {
|
||||
if (cache[prop]._changed || force) {
|
||||
result[prop] = cache[prop]._current;
|
||||
}
|
||||
each(props, (prop: keyof T) => {
|
||||
const changed = force || cache[prop]._changed;
|
||||
result._anythingChanged = result._anythingChanged || changed;
|
||||
|
||||
result[prop]._changed = changed;
|
||||
cache[prop]._changed = false;
|
||||
});
|
||||
|
||||
@@ -83,11 +84,12 @@ export const createCache = <T>(cacheUpdateInfo: CacheUpdateInfo<T>): CacheUpdate
|
||||
each(finalPropsToUpdate, (prop) => {
|
||||
const cacheVal = cache[prop];
|
||||
const curr = cacheUpdateInfo[prop];
|
||||
const arr = isArray(curr);
|
||||
|
||||
const arr = isReference ? false : isArray(curr);
|
||||
const value = arr ? curr[0] : curr;
|
||||
const equal = arr ? curr[1] : null;
|
||||
updateCacheProp(prop, value(cacheVal._current, cacheVal._previous), equal);
|
||||
updateCacheProp(prop, isReference ? value : value(cacheVal._value, cacheVal._previous), equal);
|
||||
});
|
||||
return flush(force);
|
||||
return flush(finalPropsToUpdate, force);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { optionsTemplateTypes as oTypes } from 'support';
|
||||
import { optionsTemplateTypes as oTypes, Cache } from 'support';
|
||||
import { createLifecycleBase } from 'lifecycles/lifecycleBase';
|
||||
|
||||
interface TestLifecycleOptions {
|
||||
@@ -37,6 +37,19 @@ const createLifecycle = (initalOptions?: TestLifecycleOptions, updateFn?: () =>
|
||||
updateFn || (() => {})
|
||||
);
|
||||
|
||||
const createOptionsUnchangedObj = (exc?: Cache<TestLifecycleOptions>) =>
|
||||
expect.objectContaining({
|
||||
number: exc?.number || expect.objectContaining({ _changed: false }),
|
||||
string: exc?.string || expect.objectContaining({ _changed: false }),
|
||||
nested: exc?.nested || expect.objectContaining({ _changed: false }),
|
||||
});
|
||||
const createCacheUnchangedObj = (exc?: Cache<TestLifecycleCache>) =>
|
||||
expect.objectContaining({
|
||||
number: exc?.number || expect.objectContaining({ _changed: false }),
|
||||
constant: exc?.constant || expect.objectContaining({ _changed: false }),
|
||||
object: exc?.object || expect.objectContaining({ _changed: false }),
|
||||
});
|
||||
|
||||
describe('lifecycleBase', () => {
|
||||
describe('options', () => {
|
||||
test('correct default options', () => {
|
||||
@@ -106,7 +119,19 @@ describe('lifecycleBase', () => {
|
||||
|
||||
_updateCache('number');
|
||||
expect(updateFn).toBeCalledTimes(2);
|
||||
expect(updateFn).toBeCalledWith({}, { number: 2 });
|
||||
expect(updateFn).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({}),
|
||||
expect.objectContaining({
|
||||
number: {
|
||||
_value: 2,
|
||||
_changed: true,
|
||||
_previous: 1,
|
||||
},
|
||||
constant: expect.objectContaining({
|
||||
_changed: false,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
_updateCache('constant');
|
||||
expect(updateFn).toBeCalledTimes(2);
|
||||
@@ -118,11 +143,37 @@ describe('lifecycleBase', () => {
|
||||
|
||||
_updateCache(['number', 'object']);
|
||||
expect(updateFn).toBeCalledTimes(2);
|
||||
expect(updateFn).toBeCalledWith({}, { number: 2, object: { string: 'hihi', boolean: false } });
|
||||
expect(updateFn).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({}),
|
||||
expect.objectContaining({
|
||||
number: {
|
||||
_value: 2,
|
||||
_previous: 1,
|
||||
_changed: true,
|
||||
},
|
||||
object: {
|
||||
_value: { string: 'hihi', boolean: false },
|
||||
_previous: { string: 'hi', boolean: true },
|
||||
_changed: true,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
_updateCache(['number', 'constant']);
|
||||
expect(updateFn).toBeCalledTimes(3);
|
||||
expect(updateFn).toBeCalledWith({}, { number: 3 });
|
||||
expect(updateFn).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({}),
|
||||
expect.objectContaining({
|
||||
number: {
|
||||
_value: 3,
|
||||
_previous: 2,
|
||||
_changed: true,
|
||||
},
|
||||
constant: expect.objectContaining({
|
||||
_changed: false,
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
_updateCache(['constant']);
|
||||
expect(updateFn).toBeCalledTimes(3);
|
||||
@@ -135,23 +186,41 @@ describe('lifecycleBase', () => {
|
||||
createLifecycle({}, updateFn);
|
||||
|
||||
expect(updateFn).toBeCalledTimes(1);
|
||||
expect(updateFn).toBeCalledWith(
|
||||
{
|
||||
number: 0,
|
||||
string: 'hi',
|
||||
nested: {
|
||||
boolean: false,
|
||||
number: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
number: 1,
|
||||
constant: false,
|
||||
object: {
|
||||
string: 'hi',
|
||||
boolean: true,
|
||||
},
|
||||
}
|
||||
expect(updateFn).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({
|
||||
number: expect.objectContaining({
|
||||
_value: 0,
|
||||
_changed: true,
|
||||
}),
|
||||
string: expect.objectContaining({
|
||||
_value: 'hi',
|
||||
_changed: true,
|
||||
}),
|
||||
nested: expect.objectContaining({
|
||||
_value: {
|
||||
boolean: false,
|
||||
number: 0,
|
||||
},
|
||||
_changed: true,
|
||||
}),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
number: expect.objectContaining({
|
||||
_value: 1,
|
||||
_changed: true,
|
||||
}),
|
||||
constant: expect.objectContaining({
|
||||
_value: false,
|
||||
_changed: true,
|
||||
}),
|
||||
object: expect.objectContaining({
|
||||
_value: {
|
||||
string: 'hi',
|
||||
boolean: true,
|
||||
},
|
||||
_changed: true,
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
@@ -161,13 +230,36 @@ describe('lifecycleBase', () => {
|
||||
|
||||
_options({ number: 5 });
|
||||
expect(updateFn).toBeCalledTimes(2);
|
||||
expect(updateFn).toBeCalledWith({ number: 5 }, {});
|
||||
expect(updateFn).toHaveBeenLastCalledWith(
|
||||
createOptionsUnchangedObj({
|
||||
number: {
|
||||
_value: 5,
|
||||
_previous: 0,
|
||||
_changed: true,
|
||||
},
|
||||
}),
|
||||
createCacheUnchangedObj()
|
||||
);
|
||||
|
||||
_options({ number: 5, string: 'test', nested: { number: 3 } });
|
||||
expect(updateFn).toBeCalledTimes(3);
|
||||
expect(updateFn).toBeCalledWith({ string: 'test', nested: { number: 3 } }, {});
|
||||
expect(updateFn).toHaveBeenLastCalledWith(
|
||||
createOptionsUnchangedObj({
|
||||
string: {
|
||||
_value: 'test',
|
||||
_previous: 'hi',
|
||||
_changed: true,
|
||||
},
|
||||
nested: {
|
||||
_value: expect.objectContaining({ number: 3 }),
|
||||
_previous: expect.objectContaining({ number: 3 }), // because reference, number is 3 instead of expected 0
|
||||
_changed: true,
|
||||
},
|
||||
}),
|
||||
createCacheUnchangedObj()
|
||||
);
|
||||
|
||||
_options({ number: 5, string: 'test', nested: { number: 3 } });
|
||||
_options({ string: 'test', nested: { number: 3 } });
|
||||
expect(updateFn).toBeCalledTimes(3);
|
||||
});
|
||||
|
||||
@@ -177,11 +269,34 @@ describe('lifecycleBase', () => {
|
||||
|
||||
_updateCache('number');
|
||||
expect(updateFn).toBeCalledTimes(2);
|
||||
expect(updateFn).toBeCalledWith({}, { number: 2 });
|
||||
expect(updateFn).toHaveBeenLastCalledWith(
|
||||
createOptionsUnchangedObj(),
|
||||
createCacheUnchangedObj({
|
||||
number: {
|
||||
_value: 2,
|
||||
_previous: 1,
|
||||
_changed: true,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
_updateCache(['number', 'object', 'constant']);
|
||||
expect(updateFn).toBeCalledTimes(3);
|
||||
expect(updateFn).toBeCalledWith({}, { number: 3, object: { string: 'hihi', boolean: false } });
|
||||
expect(updateFn).toHaveBeenLastCalledWith(
|
||||
createOptionsUnchangedObj(),
|
||||
createCacheUnchangedObj({
|
||||
number: {
|
||||
_value: 3,
|
||||
_previous: 2,
|
||||
_changed: true,
|
||||
},
|
||||
object: {
|
||||
_value: { string: 'hihi', boolean: false },
|
||||
_previous: { string: 'hi', boolean: true },
|
||||
_changed: true,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
_updateCache('constant');
|
||||
expect(updateFn).toBeCalledTimes(3);
|
||||
@@ -193,49 +308,198 @@ describe('lifecycleBase', () => {
|
||||
|
||||
_update();
|
||||
expect(updateFn).toBeCalledTimes(2);
|
||||
expect(updateFn).toBeCalledWith({}, { number: 2, object: { string: 'hihi', boolean: false } });
|
||||
expect(updateFn).toHaveBeenLastCalledWith(
|
||||
createOptionsUnchangedObj(),
|
||||
createCacheUnchangedObj({
|
||||
number: {
|
||||
_value: 2,
|
||||
_previous: 1,
|
||||
_changed: true,
|
||||
},
|
||||
object: {
|
||||
_value: { string: 'hihi', boolean: false },
|
||||
_previous: { string: 'hi', boolean: true },
|
||||
_changed: true,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
_update(true);
|
||||
expect(updateFn).toBeCalledTimes(3);
|
||||
expect(updateFn).toBeCalledWith(
|
||||
{
|
||||
number: 0,
|
||||
string: 'hi',
|
||||
nested: {
|
||||
boolean: false,
|
||||
number: 0,
|
||||
expect(updateFn).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({
|
||||
number: expect.objectContaining({
|
||||
_value: 0,
|
||||
_changed: true,
|
||||
}),
|
||||
string: expect.objectContaining({
|
||||
_value: 'hi',
|
||||
_changed: true,
|
||||
}),
|
||||
nested: expect.objectContaining({
|
||||
_value: {
|
||||
boolean: false,
|
||||
number: 0,
|
||||
},
|
||||
_changed: true,
|
||||
}),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
number: {
|
||||
_value: 3,
|
||||
_previous: 2,
|
||||
_changed: true,
|
||||
},
|
||||
constant: {
|
||||
_value: false,
|
||||
_previous: false,
|
||||
_changed: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
number: 3,
|
||||
constant: false,
|
||||
object: {
|
||||
string: 'hihihi',
|
||||
boolean: true,
|
||||
_value: {
|
||||
string: 'hihihi',
|
||||
boolean: true,
|
||||
},
|
||||
_previous: {
|
||||
string: 'hihi',
|
||||
boolean: false,
|
||||
},
|
||||
_changed: true,
|
||||
},
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
_options({ number: 3, nested: { boolean: true } });
|
||||
_update(true);
|
||||
expect(updateFn).toBeCalledTimes(5);
|
||||
expect(updateFn).toBeCalledWith(
|
||||
{
|
||||
number: 3,
|
||||
string: 'hi',
|
||||
nested: {
|
||||
boolean: true,
|
||||
number: 0,
|
||||
expect(updateFn).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({
|
||||
number: expect.objectContaining({
|
||||
_value: 3,
|
||||
_changed: true,
|
||||
}),
|
||||
string: expect.objectContaining({
|
||||
_value: 'hi',
|
||||
_changed: true,
|
||||
}),
|
||||
nested: expect.objectContaining({
|
||||
_value: {
|
||||
boolean: true,
|
||||
number: 0,
|
||||
},
|
||||
_changed: true,
|
||||
}),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
number: {
|
||||
_value: 4,
|
||||
_previous: 3,
|
||||
_changed: true,
|
||||
},
|
||||
constant: {
|
||||
_value: false,
|
||||
_previous: false,
|
||||
_changed: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
number: 4,
|
||||
constant: false,
|
||||
object: {
|
||||
string: 'hihihihi',
|
||||
boolean: false,
|
||||
_value: {
|
||||
string: 'hihihihi',
|
||||
boolean: false,
|
||||
},
|
||||
_previous: {
|
||||
string: 'hihihi',
|
||||
boolean: true,
|
||||
},
|
||||
_changed: true,
|
||||
},
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
_options({ number: 3, nested: { boolean: true } });
|
||||
_update();
|
||||
expect(updateFn).toBeCalledTimes(6);
|
||||
expect(updateFn).toHaveBeenLastCalledWith(
|
||||
createOptionsUnchangedObj({
|
||||
number: expect.objectContaining({
|
||||
_value: 3,
|
||||
_changed: false,
|
||||
}),
|
||||
string: expect.objectContaining({
|
||||
_value: 'hi',
|
||||
_changed: false,
|
||||
}),
|
||||
nested: expect.objectContaining({
|
||||
_value: {
|
||||
boolean: true,
|
||||
number: 0,
|
||||
},
|
||||
_changed: false,
|
||||
}),
|
||||
}),
|
||||
createCacheUnchangedObj({
|
||||
number: {
|
||||
_value: 5,
|
||||
_previous: 4,
|
||||
_changed: true,
|
||||
},
|
||||
object: {
|
||||
_value: { string: 'hihihihihi', boolean: true },
|
||||
_previous: { string: 'hihihihi', boolean: false },
|
||||
_changed: true,
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
_options({ number: 4, nested: { boolean: false }, string: 'hi' });
|
||||
expect(updateFn).toBeCalledTimes(7);
|
||||
expect(updateFn).toHaveBeenLastCalledWith(
|
||||
createOptionsUnchangedObj({
|
||||
number: expect.objectContaining({
|
||||
_value: 4,
|
||||
_changed: true,
|
||||
}),
|
||||
string: expect.objectContaining({
|
||||
_value: 'hi',
|
||||
_changed: false,
|
||||
}),
|
||||
nested: expect.objectContaining({
|
||||
_value: {
|
||||
boolean: false,
|
||||
number: 0,
|
||||
},
|
||||
_changed: true,
|
||||
}),
|
||||
}),
|
||||
createCacheUnchangedObj()
|
||||
);
|
||||
_update();
|
||||
expect(updateFn).toBeCalledTimes(8);
|
||||
expect(updateFn).toHaveBeenLastCalledWith(
|
||||
createOptionsUnchangedObj({
|
||||
number: expect.objectContaining({
|
||||
_value: 4,
|
||||
_changed: false,
|
||||
}),
|
||||
string: expect.objectContaining({
|
||||
_value: 'hi',
|
||||
_changed: false,
|
||||
}),
|
||||
nested: expect.objectContaining({
|
||||
_value: {
|
||||
boolean: false,
|
||||
number: 0,
|
||||
},
|
||||
_changed: false,
|
||||
}),
|
||||
}),
|
||||
createCacheUnchangedObj({
|
||||
number: expect.objectContaining({
|
||||
_changed: true,
|
||||
}),
|
||||
object: expect.objectContaining({
|
||||
_changed: true,
|
||||
}),
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
+229
-79
@@ -13,7 +13,7 @@ const createUpdater = <T>(updaterReturn: (i: number) => T) => {
|
||||
};
|
||||
|
||||
describe('cache', () => {
|
||||
describe('createCache', () => {
|
||||
describe('cache with cacheUpdateInfo object', () => {
|
||||
test('creates and updates simple cache', () => {
|
||||
interface Test {
|
||||
number: number;
|
||||
@@ -33,69 +33,81 @@ describe('cache', () => {
|
||||
object: updateObj,
|
||||
});
|
||||
|
||||
expect(updateCache('number').number).toBe(1);
|
||||
expect(updateCache('number').number._value).toBe(1);
|
||||
expect(updateNumberFn).toHaveBeenCalledTimes(1);
|
||||
expect(updateNumberFn).toHaveBeenCalledWith(undefined, undefined);
|
||||
expect(updateNumberFn).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
|
||||
expect(updateCache('number').number).toBe(2);
|
||||
expect(updateCache('number').number._value).toBe(2);
|
||||
expect(updateNumberFn).toHaveBeenCalledTimes(2);
|
||||
expect(updateNumberFn).toHaveBeenCalledWith(1, undefined);
|
||||
expect(updateNumberFn).toHaveBeenLastCalledWith(1, undefined);
|
||||
|
||||
expect(updateCache('number').number).toBe(3);
|
||||
expect(updateCache('number').number._value).toBe(3);
|
||||
expect(updateNumberFn).toHaveBeenCalledTimes(3);
|
||||
expect(updateNumberFn).toHaveBeenCalledWith(2, 1);
|
||||
expect(updateNumberFn).toHaveBeenLastCalledWith(2, 1);
|
||||
|
||||
let { string, boolean, object, number } = updateCache('number');
|
||||
expect(string).toBe(undefined);
|
||||
expect(boolean).toBe(undefined);
|
||||
expect(object).toBe(undefined);
|
||||
expect(number).toBe(4);
|
||||
expect(string._value).toBe(undefined);
|
||||
expect(string._changed).toBe(false);
|
||||
expect(boolean._value).toBe(undefined);
|
||||
expect(boolean._changed).toBe(false);
|
||||
expect(object._value).toBe(undefined);
|
||||
expect(object._changed).toBe(false);
|
||||
expect(number._value).toBe(4);
|
||||
expect(number._changed).toBe(true);
|
||||
|
||||
expect(updateBooleanFn).not.toHaveBeenCalled();
|
||||
expect(updateStringFn).not.toHaveBeenCalled();
|
||||
expect(updateObjFn).not.toHaveBeenCalled();
|
||||
|
||||
({ string, boolean, object, number } = updateCache(['string', 'boolean', 'object']));
|
||||
expect(string).toBe('1');
|
||||
expect(boolean).toBe(!!(1 % 2));
|
||||
expect(object).toEqual({ 1: 1 });
|
||||
expect(number).toBe(undefined);
|
||||
expect(string._value).toBe('1');
|
||||
expect(string._changed).toBe(true);
|
||||
expect(boolean._value).toBe(!!(1 % 2));
|
||||
expect(boolean._changed).toBe(true);
|
||||
expect(object._value).toEqual({ 1: 1 });
|
||||
expect(object._changed).toEqual(true);
|
||||
expect(number._value).toBe(4);
|
||||
expect(number._changed).toBe(false);
|
||||
|
||||
expect(updateBooleanFn).toHaveBeenCalledTimes(1);
|
||||
expect(updateBooleanFn).toHaveBeenCalledWith(undefined, undefined);
|
||||
expect(updateBooleanFn).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
|
||||
expect(updateStringFn).toHaveBeenCalledTimes(1);
|
||||
expect(updateStringFn).toHaveBeenCalledWith(undefined, undefined);
|
||||
expect(updateStringFn).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
|
||||
expect(updateObjFn).toHaveBeenCalledTimes(1);
|
||||
expect(updateObjFn).toHaveBeenCalledWith(undefined, undefined);
|
||||
expect(updateObjFn).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
|
||||
updateCache(['string', 'boolean', 'object']);
|
||||
expect(updateBooleanFn).toHaveBeenCalledTimes(2);
|
||||
expect(updateBooleanFn).toHaveBeenCalledWith(!!(1 % 2), undefined);
|
||||
expect(updateBooleanFn).toHaveBeenLastCalledWith(!!(1 % 2), undefined);
|
||||
|
||||
expect(updateStringFn).toHaveBeenCalledTimes(2);
|
||||
expect(updateStringFn).toHaveBeenCalledWith('1', undefined);
|
||||
expect(updateStringFn).toHaveBeenLastCalledWith('1', undefined);
|
||||
|
||||
expect(updateObjFn).toHaveBeenCalledTimes(2);
|
||||
expect(updateObjFn).toHaveBeenCalledWith({ 1: 1 }, undefined);
|
||||
expect(updateObjFn).toHaveBeenLastCalledWith({ 1: 1 }, undefined);
|
||||
|
||||
updateCache(['string', 'boolean', 'object']);
|
||||
expect(updateBooleanFn).toHaveBeenCalledTimes(3);
|
||||
expect(updateBooleanFn).toHaveBeenCalledWith(!!(2 % 2), !!(1 % 2));
|
||||
expect(updateBooleanFn).toHaveBeenLastCalledWith(!!(2 % 2), !!(1 % 2));
|
||||
|
||||
expect(updateStringFn).toHaveBeenCalledTimes(3);
|
||||
expect(updateStringFn).toHaveBeenCalledWith('2', '1');
|
||||
expect(updateStringFn).toHaveBeenLastCalledWith('2', '1');
|
||||
|
||||
expect(updateObjFn).toHaveBeenCalledTimes(3);
|
||||
expect(updateObjFn).toHaveBeenCalledWith({ 2: 2 }, { 1: 1 });
|
||||
expect(updateObjFn).toHaveBeenLastCalledWith({ 2: 2 }, { 1: 1 });
|
||||
|
||||
updateCache(['string', 'boolean', 'object']);
|
||||
({ string, boolean, object, number } = updateCache());
|
||||
expect(string).toBe('5');
|
||||
expect(boolean).toBe(!!(5 % 2));
|
||||
expect(object).toEqual({ 5: 5 });
|
||||
expect(number).toBe(5);
|
||||
expect(string._value).toBe('5');
|
||||
expect(string._changed).toBe(true);
|
||||
expect(boolean._value).toBe(!!(5 % 2));
|
||||
expect(boolean._changed).toBe(true);
|
||||
expect(object._value).toEqual({ 5: 5 });
|
||||
expect(object._changed).toEqual(true);
|
||||
expect(number._value).toBe(5);
|
||||
expect(number._changed).toBe(true);
|
||||
|
||||
expect(updateBooleanFn).toHaveBeenCalledTimes(5);
|
||||
expect(updateStringFn).toHaveBeenCalledTimes(5);
|
||||
@@ -109,17 +121,24 @@ describe('cache', () => {
|
||||
number: updateNumber,
|
||||
});
|
||||
|
||||
expect(updateCache('number').number).toBe(0);
|
||||
expect(updateNumberFn).toHaveBeenCalledWith(undefined, undefined);
|
||||
let { _value, _changed } = updateCache('number').number;
|
||||
expect(_value).toBe(0);
|
||||
expect(_changed).toBe(true);
|
||||
expect(updateNumberFn).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
|
||||
expect(updateCache('number').number).toBe(undefined);
|
||||
expect(updateNumberFn).toHaveBeenCalledWith(0, undefined);
|
||||
({ _value, _changed } = updateCache('number').number);
|
||||
expect(_value).toBe(0);
|
||||
expect(_changed).toBe(false);
|
||||
expect(updateNumberFn).toHaveBeenLastCalledWith(0, undefined);
|
||||
|
||||
expect(updateCache('number').number).toBe(undefined);
|
||||
expect(updateNumberFn).toHaveBeenCalledWith(0, 0);
|
||||
({ _value, _changed } = updateCache('number').number);
|
||||
expect(_value).toBe(0);
|
||||
expect(_changed).toBe(false);
|
||||
expect(updateNumberFn).toHaveBeenLastCalledWith(0, 0);
|
||||
|
||||
const changed = updateCache('number');
|
||||
expect(Object.prototype.hasOwnProperty.call(changed, 'changed')).toBe(false);
|
||||
expect(Object.prototype.hasOwnProperty.call(changed, 'number')).toBe(true);
|
||||
});
|
||||
|
||||
test('doesnt update if nothing changes with non primitives', () => {
|
||||
@@ -136,45 +155,91 @@ describe('cache', () => {
|
||||
],
|
||||
});
|
||||
|
||||
expect(updateCache('constObj').constObj).toBe(constObj);
|
||||
expect(updateConstObjFn).toHaveBeenCalledWith(undefined, undefined);
|
||||
expect(updateCache('constObj').constObj).toBe(undefined);
|
||||
expect(updateConstObjFn).toHaveBeenCalledWith(constObj, undefined);
|
||||
expect(updateCache('constObj').constObj).toBe(undefined);
|
||||
expect(updateConstObjFn).toHaveBeenCalledWith(constObj, constObj);
|
||||
expect(Object.prototype.hasOwnProperty.call(updateCache('constObj'), 'constObj')).toBe(false);
|
||||
let { _value, _changed } = updateCache('constObj').constObj;
|
||||
expect(_value).toEqual(constObj);
|
||||
expect(_changed).toBe(true);
|
||||
expect(updateConstObjFn).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
|
||||
expect(updateCache('similarObj').similarObj).toEqual(constObj);
|
||||
expect(updateSimilarObjFn).toHaveBeenCalledWith(undefined, undefined);
|
||||
expect(updateCache('similarObj').similarObj).toEqual(constObj);
|
||||
expect(updateSimilarObjFn).toHaveBeenCalledWith(constObj, undefined);
|
||||
expect(updateCache('similarObj').similarObj).toEqual(constObj);
|
||||
expect(updateSimilarObjFn).toHaveBeenCalledWith(constObj, constObj);
|
||||
expect(Object.prototype.hasOwnProperty.call(updateCache('similarObj'), 'similarObj')).toBe(true);
|
||||
({ _value, _changed } = updateCache('constObj').constObj);
|
||||
expect(_value).toEqual(constObj);
|
||||
expect(_changed).toBe(false);
|
||||
expect(updateConstObjFn).toHaveBeenLastCalledWith(constObj, undefined);
|
||||
|
||||
expect(updateCache('comparisonObj').comparisonObj).toEqual(constObj);
|
||||
expect(updateComparisonObjFn).toHaveBeenCalledWith(undefined, undefined);
|
||||
expect(updateCache('comparisonObj').comparisonObj).toBe(undefined);
|
||||
expect(updateComparisonObjFn).toHaveBeenCalledWith(constObj, undefined);
|
||||
expect(updateCache('comparisonObj').comparisonObj).toBe(undefined);
|
||||
expect(updateComparisonObjFn).toHaveBeenCalledWith(constObj, constObj);
|
||||
expect(Object.prototype.hasOwnProperty.call(updateCache('comparisonObj'), 'comparisonObj')).toBe(false);
|
||||
({ _value, _changed } = updateCache('constObj').constObj);
|
||||
expect(_value).toEqual(constObj);
|
||||
expect(_changed).toBe(false);
|
||||
expect(updateConstObjFn).toHaveBeenLastCalledWith(constObj, constObj);
|
||||
|
||||
({ _value, _changed } = updateCache('similarObj').similarObj);
|
||||
expect(_value).toEqual(constObj);
|
||||
expect(_changed).toBe(true);
|
||||
expect(updateSimilarObjFn).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
|
||||
({ _value, _changed } = updateCache('similarObj').similarObj);
|
||||
expect(_value).toEqual(constObj);
|
||||
expect(_changed).toBe(true);
|
||||
expect(updateSimilarObjFn).toHaveBeenLastCalledWith(constObj, undefined);
|
||||
|
||||
({ _value, _changed } = updateCache('similarObj').similarObj);
|
||||
expect(_value).toEqual(constObj);
|
||||
expect(_changed).toBe(true);
|
||||
expect(updateSimilarObjFn).toHaveBeenLastCalledWith(constObj, constObj);
|
||||
|
||||
({ _value, _changed } = updateCache('comparisonObj').comparisonObj);
|
||||
expect(_value).toEqual(constObj);
|
||||
expect(_changed).toBe(true);
|
||||
expect(updateComparisonObjFn).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
|
||||
({ _value, _changed } = updateCache('comparisonObj').comparisonObj);
|
||||
expect(_value).toEqual(constObj);
|
||||
expect(_changed).toBe(false);
|
||||
expect(updateComparisonObjFn).toHaveBeenLastCalledWith(constObj, undefined);
|
||||
|
||||
({ _value, _changed } = updateCache('comparisonObj').comparisonObj);
|
||||
expect(_value).toEqual(constObj);
|
||||
expect(_changed).toBe(false);
|
||||
expect(updateComparisonObjFn).toHaveBeenLastCalledWith(constObj, constObj);
|
||||
|
||||
const result = updateCache();
|
||||
expect(Object.prototype.hasOwnProperty.call(result, 'constObj')).toBe(true);
|
||||
expect(Object.prototype.hasOwnProperty.call(result, 'similarObj')).toBe(true);
|
||||
expect(Object.prototype.hasOwnProperty.call(result, 'comparisonObj')).toBe(true);
|
||||
});
|
||||
|
||||
test('updates definitely with force', () => {
|
||||
const [updateNumberFn, updateNumber] = createUpdater<number>(() => 0);
|
||||
const [, updateString] = createUpdater<number>(() => 0);
|
||||
const updateCache = createCache({
|
||||
number: updateNumber,
|
||||
string: updateString,
|
||||
});
|
||||
|
||||
expect(updateCache('number', true).number).toBe(0);
|
||||
expect(updateNumberFn).toHaveBeenCalledWith(undefined, undefined);
|
||||
let { _value, _changed } = updateCache('number', true).number;
|
||||
expect(_value).toBe(0);
|
||||
expect(_changed).toBe(true);
|
||||
expect(updateNumberFn).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
|
||||
expect(updateCache('number', true).number).toBe(0);
|
||||
expect(updateNumberFn).toHaveBeenCalledWith(0, undefined);
|
||||
({ _value, _changed } = updateCache('number', true).number);
|
||||
expect(_value).toBe(0);
|
||||
expect(_changed).toBe(true);
|
||||
expect(updateNumberFn).toHaveBeenLastCalledWith(0, undefined);
|
||||
|
||||
expect(updateCache('number', true).number).toBe(0);
|
||||
expect(updateNumberFn).toHaveBeenCalledWith(0, 0);
|
||||
({ _value, _changed } = updateCache('number', true).number);
|
||||
expect(_value).toBe(0);
|
||||
expect(_changed).toBe(true);
|
||||
expect(updateNumberFn).toHaveBeenLastCalledWith(0, 0);
|
||||
|
||||
let { number, string } = updateCache('number', true);
|
||||
expect(number._changed).toBe(true);
|
||||
expect(string._changed).toBe(false);
|
||||
|
||||
({ number, string } = updateCache(['number', 'string'], true));
|
||||
expect(number._changed).toBe(true);
|
||||
expect(string._changed).toBe(true);
|
||||
|
||||
({ number, string } = updateCache('string', true));
|
||||
expect(number._changed).toBe(false);
|
||||
expect(string._changed).toBe(true);
|
||||
});
|
||||
|
||||
test('custom comparison on primitves', () => {
|
||||
@@ -185,21 +250,35 @@ describe('cache', () => {
|
||||
number: [updateNumber, () => true],
|
||||
});
|
||||
|
||||
expect(updateCache('string').string).toBe('hi');
|
||||
expect(updateStringFn).toHaveBeenCalledWith(undefined, undefined);
|
||||
expect(updateCache('string').string).toBe('hi');
|
||||
expect(updateStringFn).toHaveBeenCalledWith('hi', undefined);
|
||||
expect(updateCache('string').string).toBe('hi');
|
||||
expect(updateStringFn).toHaveBeenCalledWith('hi', 'hi');
|
||||
expect(Object.prototype.hasOwnProperty.call(updateCache('string'), 'string')).toBe(true);
|
||||
let { _value, _changed } = updateCache('string').string;
|
||||
expect(_value).toBe('hi');
|
||||
expect(_changed).toBe(true);
|
||||
expect(updateStringFn).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
|
||||
expect(updateCache('number').number).toBe(undefined);
|
||||
expect(updateNumberFn).toHaveBeenCalledWith(undefined, undefined);
|
||||
expect(updateCache('number').number).toBe(undefined);
|
||||
expect(updateNumberFn).toHaveBeenCalledWith(1, undefined);
|
||||
expect(updateCache('number').number).toBe(undefined);
|
||||
expect(updateNumberFn).toHaveBeenCalledWith(2, 1);
|
||||
expect(Object.prototype.hasOwnProperty.call(updateCache('number'), 'number')).toBe(false);
|
||||
({ _value, _changed } = updateCache('string').string);
|
||||
expect(_value).toBe('hi');
|
||||
expect(_changed).toBe(true);
|
||||
expect(updateStringFn).toHaveBeenLastCalledWith('hi', undefined);
|
||||
|
||||
({ _value, _changed } = updateCache('string').string);
|
||||
expect(_value).toBe('hi');
|
||||
expect(_changed).toBe(true);
|
||||
expect(updateStringFn).toHaveBeenLastCalledWith('hi', 'hi');
|
||||
|
||||
({ _value, _changed } = updateCache('number').number);
|
||||
expect(_value).toBe(1);
|
||||
expect(_changed).toBe(false);
|
||||
expect(updateNumberFn).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
|
||||
({ _value, _changed } = updateCache('number').number);
|
||||
expect(_value).toBe(2);
|
||||
expect(_changed).toBe(false);
|
||||
expect(updateNumberFn).toHaveBeenLastCalledWith(1, undefined);
|
||||
|
||||
({ _value, _changed } = updateCache('number').number);
|
||||
expect(_value).toBe(3);
|
||||
expect(_changed).toBe(false);
|
||||
expect(updateNumberFn).toHaveBeenLastCalledWith(2, 1);
|
||||
});
|
||||
|
||||
test('updates all entries with null or undefined as argument', () => {
|
||||
@@ -211,12 +290,83 @@ describe('cache', () => {
|
||||
});
|
||||
|
||||
updateCache();
|
||||
expect(updateNumberFn).toHaveBeenCalledWith(undefined, undefined);
|
||||
expect(updateNumberFn2).toHaveBeenCalledWith(undefined, undefined);
|
||||
expect(updateNumberFn).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
expect(updateNumberFn2).toHaveBeenLastCalledWith(undefined, undefined);
|
||||
|
||||
updateCache(null);
|
||||
expect(updateNumberFn).toHaveBeenCalledWith(1, undefined);
|
||||
expect(updateNumberFn2).toHaveBeenCalledWith(1, undefined);
|
||||
expect(updateNumberFn).toHaveBeenLastCalledWith(1, undefined);
|
||||
expect(updateNumberFn2).toHaveBeenLastCalledWith(1, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('cache with reference object', () => {
|
||||
test('creates and updates simple cache', () => {
|
||||
interface Test {
|
||||
number: number;
|
||||
boolean: boolean;
|
||||
string: string;
|
||||
object: {};
|
||||
}
|
||||
const refObj: Test = {
|
||||
number: 0,
|
||||
boolean: false,
|
||||
string: 'hi',
|
||||
object: {},
|
||||
};
|
||||
|
||||
const updateCache = createCache<Test>(refObj, true);
|
||||
|
||||
let { _value, _changed, _previous } = updateCache('number').number;
|
||||
expect(_value).toBe(0);
|
||||
expect(_changed).toBe(false);
|
||||
|
||||
refObj.number = 1;
|
||||
({ _value, _changed } = updateCache('number').number);
|
||||
expect(_value).toBe(1);
|
||||
expect(_changed).toBe(true);
|
||||
|
||||
refObj.number = 2;
|
||||
({ _value, _changed } = updateCache('string').number);
|
||||
expect(_value).toBe(1);
|
||||
expect(_changed).toBe(false);
|
||||
|
||||
refObj.number = 3;
|
||||
({ _value, _changed, _previous } = updateCache('number').number);
|
||||
expect(_value).toBe(3);
|
||||
expect(_previous).toBe(1);
|
||||
expect(_changed).toBe(true);
|
||||
|
||||
let { number, boolean, string, object } = updateCache();
|
||||
expect(number._value).toBe(3);
|
||||
expect(number._changed).toBe(false);
|
||||
expect(boolean._value).toBe(false);
|
||||
expect(boolean._changed).toBe(false);
|
||||
expect(string._value).toBe('hi');
|
||||
expect(string._changed).toBe(false);
|
||||
expect(object._value).toEqual({});
|
||||
expect(object._changed).toBe(false);
|
||||
|
||||
refObj.string = 'hi2';
|
||||
refObj.boolean = true;
|
||||
({ number, boolean, string, object } = updateCache());
|
||||
expect(number._value).toBe(3);
|
||||
expect(number._changed).toBe(false);
|
||||
expect(boolean._value).toBe(true);
|
||||
expect(boolean._changed).toBe(true);
|
||||
expect(string._value).toBe('hi2');
|
||||
expect(string._changed).toBe(true);
|
||||
expect(object._value).toEqual({});
|
||||
expect(object._changed).toBe(false);
|
||||
|
||||
({ number, boolean, string, object } = updateCache(null, true));
|
||||
expect(number._value).toBe(3);
|
||||
expect(number._changed).toBe(true);
|
||||
expect(boolean._value).toBe(true);
|
||||
expect(boolean._changed).toBe(true);
|
||||
expect(string._value).toBe('hi2');
|
||||
expect(string._changed).toBe(true);
|
||||
expect(object._value).toEqual({});
|
||||
expect(object._changed).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user