From 38901435bef68481d53a6eabfedd1610c563f881 Mon Sep 17 00:00:00 2001 From: Benno Kohrs Date: Fri, 12 Mar 2021 15:57:17 +0100 Subject: [PATCH 1/9] added set option in update method --- packages/core/src/collection/index.ts | 32 +++++++++++++------ .../tests/unit/collection/collection.test.ts | 2 +- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/packages/core/src/collection/index.ts b/packages/core/src/collection/index.ts index b4d8bf32..12d7f9e7 100644 --- a/packages/core/src/collection/index.ts +++ b/packages/core/src/collection/index.ts @@ -122,7 +122,7 @@ export class Collection { */ public Group( initialItems?: Array, - config?: GroupConfigInterface + config: GroupConfigInterface = {} ): Group { if (this.isInstantiated) { const key = config?.key || generateId(); @@ -150,7 +150,7 @@ export class Collection { */ public Selector( initialKey: ItemKey, - config?: SelectorConfigInterface + config: SelectorConfigInterface = {} ): Selector { if (this.isInstantiated) { const key = config?.key || generateId(); @@ -305,7 +305,7 @@ export class Collection { const item = this.getItem(itemKey, { notExisting: true }); const primaryKey = this.config.primaryKey; config = defineConfig(config, { - addNewProperties: true, + patch: true, background: false, }); @@ -335,11 +335,23 @@ export class Collection { background: config.background, }); - // Apply changes to Item - item.patch(changes as any, { - background: config.background, - addNewProperties: config.addNewProperties, - }); + if (config.patch) { + let patchConfig: { addNewProperties?: boolean } = + typeof config.patch === 'object' ? config.patch : {}; + patchConfig = defineConfig(patchConfig, { + addNewProperties: true, + }); + + // Apply changes to Item + item.patch(changes as any, { + background: config.background, + addNewProperties: patchConfig.addNewProperties, + }); + } else { + item.set(changes as any, { + background: config.background, + }); + } return item; } @@ -1205,11 +1217,11 @@ export interface CollectConfigInterface { } /** - * @param addNewProperties - If properties that doesn't exist in base ItemData get added + * @param patch - If Data gets merged into the current Data * @param background - If updating an Item happens in the background (-> not causing any rerender) */ export interface UpdateConfigInterface { - addNewProperties?: boolean; + patch?: boolean | { addNewProperties?: boolean }; background?: boolean; } diff --git a/packages/core/tests/unit/collection/collection.test.ts b/packages/core/tests/unit/collection/collection.test.ts index 22cefdfc..4a5fd1e7 100644 --- a/packages/core/tests/unit/collection/collection.test.ts +++ b/packages/core/tests/unit/collection/collection.test.ts @@ -732,7 +732,7 @@ describe('Collection Tests', () => { 'dummyItem', { name: 'hans' }, { - addNewProperties: true, + patch: true, background: true, } ); From 190589cdbeebf4244945829288dcd0b6087c8296 Mon Sep 17 00:00:00 2001 From: Benno Kohrs Date: Fri, 12 Mar 2021 20:06:18 +0100 Subject: [PATCH 2/9] return this in reset method --- packages/core/src/collection/index.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core/src/collection/index.ts b/packages/core/src/collection/index.ts index 12d7f9e7..e4dc2074 100644 --- a/packages/core/src/collection/index.ts +++ b/packages/core/src/collection/index.ts @@ -859,7 +859,7 @@ export class Collection { * @public * Resets this Collection */ - public reset() { + public reset(): this { // Reset Data this.data = {}; this.size = 0; @@ -869,6 +869,8 @@ export class Collection { // Reset Selectors for (const key in this.selectors) this.getSelector(key)?.reset(); + + return this; } //========================================================================================================= From b115409462e879ebb6870d1aeda9788969c08e52 Mon Sep 17 00:00:00 2001 From: Benno Kohrs Date: Sat, 13 Mar 2021 15:18:54 +0100 Subject: [PATCH 3/9] fixed state tests --- packages/core/src/collection/index.ts | 4 +- packages/core/src/state/index.ts | 42 +++++++++--- packages/core/src/state/state.observer.ts | 4 +- .../core/tests/unit/collection/group.test.ts | 9 ++- .../core/tests/unit/collection/item.test.ts | 6 +- .../tests/unit/collection/selector.test.ts | 9 ++- .../core/tests/unit/computed/computed.test.ts | 6 +- .../tests/unit/state/state.observer.test.ts | 2 +- packages/core/tests/unit/state/state.test.ts | 68 +++++++++++++++---- 9 files changed, 116 insertions(+), 34 deletions(-) diff --git a/packages/core/src/collection/index.ts b/packages/core/src/collection/index.ts index e4dc2074..4cd53d2b 100644 --- a/packages/core/src/collection/index.ts +++ b/packages/core/src/collection/index.ts @@ -887,7 +887,7 @@ export class Collection { itemKeys: ItemKey | Array, groupKeys: GroupKey | Array, config: GroupAddConfig = {} - ) { + ): this { const _itemKeys = normalizeArray(itemKeys); const _groupKeys = normalizeArray(groupKeys); @@ -895,6 +895,8 @@ export class Collection { _groupKeys.forEach((groupKey) => { this.getGroup(groupKey)?.add(_itemKeys, config); }); + + return this; } //========================================================================================================= diff --git a/packages/core/src/state/index.ts b/packages/core/src/state/index.ts index 83268e40..55f9bc32 100644 --- a/packages/core/src/state/index.ts +++ b/packages/core/src/state/index.ts @@ -15,7 +15,6 @@ import { PersistentKey, ComputedTracker, StateIngestConfigInterface, - StateRuntimeJobConfigInterface, } from '../internal'; export class State { @@ -34,7 +33,8 @@ export class State { public sideEffects: { [key: string]: SideEffectInterface>; } = {}; // SideEffects of State (will be executed in Runtime) - public computeMethod?: ComputeMethod; + public computeValueMethod?: ComputeValueMethod; + public computeExistsMethod: ComputeExistsMethod; public isPersisted = false; // If State can be stored in Agile Storage (-> successfully integrated persistent) public persistent: StatePersistent | undefined; // Manages storing State Value into Storage @@ -68,6 +68,9 @@ export class State { this.previousStateValue = copy(initialValue); this.nextStateValue = copy(initialValue); this.isPlaceholder = true; + this.computeExistsMethod = (v) => { + return v != null; + }; // Initial Set if (!config.isPlaceholder) this.set(initialValue, { overwrite: true }); @@ -476,7 +479,25 @@ export class State { * Checks if State exists */ public get exists(): boolean { - return !this.isPlaceholder; + return !this.isPlaceholder && this.computeExistsMethod(this.value); + } + + //========================================================================================================= + // Compute Exists + //========================================================================================================= + /** + * @public + * Function that computes the exists status of the State + * @param method - Computed Function + */ + public computeExists(method: ComputeExistsMethod): this { + if (!isFunction(method)) { + Agile.logger.error(`A 'computeExistsMethod' has to be a function!`); + return this; + } + this.computeExistsMethod = method; + + return this; } //========================================================================================================= @@ -521,19 +542,23 @@ export class State { } //========================================================================================================= - // Compute + // Compute Value //========================================================================================================= /** * @public * Function that recomputes State Value if it changes * @param method - Computed Function */ - public compute(method: ComputeMethod): this { + public computeValue(method: ComputeValueMethod): this { if (!isFunction(method)) { - Agile.logger.error('A computeMethod has to be a function!'); + Agile.logger.error(`A 'computeValueMethod' has to be a function!`); return this; } - this.computeMethod = method; + this.computeValueMethod = method; + + // Initial compute + this.set(method(this.nextStateValue)); + return this; } @@ -662,7 +687,8 @@ export interface StatePersistentConfigInterface { } export type StateWatcherCallback = (value: T, key: string) => void; -export type ComputeMethod = (value: T) => T; +export type ComputeValueMethod = (value: T) => T; +export type ComputeExistsMethod = (value: T) => boolean; export type SideEffectFunctionType> = ( instance: Instance, diff --git a/packages/core/src/state/state.observer.ts b/packages/core/src/state/state.observer.ts index 1c168454..cc33e88c 100644 --- a/packages/core/src/state/state.observer.ts +++ b/packages/core/src/state/state.observer.ts @@ -86,8 +86,8 @@ export class StateObserver extends Observer { } // Assign next State Value and compute it if necessary - this.nextStateValue = state.computeMethod - ? copy(state.computeMethod(newStateValue)) + this.nextStateValue = state.computeValueMethod + ? copy(state.computeValueMethod(newStateValue)) : copy(newStateValue); // Check if State Value and new/next Value are equals diff --git a/packages/core/tests/unit/collection/group.test.ts b/packages/core/tests/unit/collection/group.test.ts index dff4258b..689f0ad2 100644 --- a/packages/core/tests/unit/collection/group.test.ts +++ b/packages/core/tests/unit/collection/group.test.ts @@ -56,7 +56,8 @@ describe('Group Tests', () => { expect(group.observer.dependents.size).toBe(0); expect(group.observer._key).toBeUndefined(); expect(group.sideEffects).toStrictEqual({}); - expect(group.computeMethod).toBeUndefined(); + expect(group.computeValueMethod).toBeUndefined(); + expect(group.computeExistsMethod).toBeInstanceOf(Function); expect(group.isPersisted).toBeFalsy(); expect(group.persistent).toBeUndefined(); expect(group.watchers).toStrictEqual({}); @@ -89,7 +90,8 @@ describe('Group Tests', () => { expect(group.observer.dependents.size).toBe(0); expect(group.observer._key).toBe('dummyKey'); expect(group.sideEffects).toStrictEqual({}); - expect(group.computeMethod).toBeUndefined(); + expect(group.computeValueMethod).toBeUndefined(); + expect(group.computeExistsMethod).toBeInstanceOf(Function); expect(group.isPersisted).toBeFalsy(); expect(group.persistent).toBeUndefined(); expect(group.watchers).toStrictEqual({}); @@ -119,7 +121,8 @@ describe('Group Tests', () => { expect(group.observer.dependents.size).toBe(0); expect(group.observer._key).toBeUndefined(); expect(group.sideEffects).toStrictEqual({}); - expect(group.computeMethod).toBeUndefined(); + expect(group.computeValueMethod).toBeUndefined(); + expect(group.computeExistsMethod).toBeInstanceOf(Function); expect(group.isPersisted).toBeFalsy(); expect(group.persistent).toBeUndefined(); expect(group.watchers).toStrictEqual({}); diff --git a/packages/core/tests/unit/collection/item.test.ts b/packages/core/tests/unit/collection/item.test.ts index 5e82d9f2..1b99a39c 100644 --- a/packages/core/tests/unit/collection/item.test.ts +++ b/packages/core/tests/unit/collection/item.test.ts @@ -41,7 +41,8 @@ describe('Item Tests', () => { dummyData[dummyCollection.config.primaryKey] ); expect(item.sideEffects).toStrictEqual({}); - expect(item.computeMethod).toBeUndefined(); + expect(item.computeValueMethod).toBeUndefined(); + expect(item.computeExistsMethod).toBeInstanceOf(Function); expect(item.isPersisted).toBeFalsy(); expect(item.persistent).toBeUndefined(); expect(item.watchers).toStrictEqual({}); @@ -78,7 +79,8 @@ describe('Item Tests', () => { dummyData[dummyCollection.config.primaryKey] ); expect(item.sideEffects).toStrictEqual({}); - expect(item.computeMethod).toBeUndefined(); + expect(item.computeValueMethod).toBeUndefined(); + expect(item.computeExistsMethod).toBeInstanceOf(Function); expect(item.isPersisted).toBeFalsy(); expect(item.persistent).toBeUndefined(); expect(item.watchers).toStrictEqual({}); diff --git a/packages/core/tests/unit/collection/selector.test.ts b/packages/core/tests/unit/collection/selector.test.ts index 27673b59..7b583406 100644 --- a/packages/core/tests/unit/collection/selector.test.ts +++ b/packages/core/tests/unit/collection/selector.test.ts @@ -43,7 +43,8 @@ describe('Selector Tests', () => { expect(selector.observer.dependents.size).toBe(0); expect(selector.observer._key).toBeUndefined(); expect(selector.sideEffects).toStrictEqual({}); - expect(selector.computeMethod).toBeUndefined(); + expect(selector.computeValueMethod).toBeUndefined(); + expect(selector.computeExistsMethod).toBeInstanceOf(Function); expect(selector.isPersisted).toBeFalsy(); expect(selector.persistent).toBeUndefined(); expect(selector.watchers).toStrictEqual({}); @@ -76,7 +77,8 @@ describe('Selector Tests', () => { expect(selector.observer.dependents.size).toBe(0); expect(selector.observer._key).toBe('dummyKey'); expect(selector.sideEffects).toStrictEqual({}); - expect(selector.computeMethod).toBeUndefined(); + expect(selector.computeValueMethod).toBeUndefined(); + expect(selector.computeExistsMethod).toBeInstanceOf(Function); expect(selector.isPersisted).toBeFalsy(); expect(selector.persistent).toBeUndefined(); expect(selector.watchers).toStrictEqual({}); @@ -107,7 +109,8 @@ describe('Selector Tests', () => { expect(selector.observer.dependents.size).toBe(0); expect(selector.observer._key).toBeUndefined(); expect(selector.sideEffects).toStrictEqual({}); - expect(selector.computeMethod).toBeUndefined(); + expect(selector.computeValueMethod).toBeUndefined(); + expect(computed.computeExistsMethod).toBeInstanceOf(Function); expect(selector.isPersisted).toBeFalsy(); expect(selector.persistent).toBeUndefined(); expect(selector.watchers).toStrictEqual({}); diff --git a/packages/core/tests/unit/computed/computed.test.ts b/packages/core/tests/unit/computed/computed.test.ts index e6cee1f8..c82f50c3 100644 --- a/packages/core/tests/unit/computed/computed.test.ts +++ b/packages/core/tests/unit/computed/computed.test.ts @@ -37,7 +37,8 @@ describe('Computed Tests', () => { expect(computed.observer.dependents.size).toBe(0); expect(computed.observer._key).toBeUndefined(); expect(computed.sideEffects).toStrictEqual({}); - expect(computed.computeMethod).toBeUndefined(); + expect(computed.computeValueMethod).toBeUndefined(); + expect(computed.computeExistsMethod).toBeInstanceOf(Function); expect(computed.isPersisted).toBeFalsy(); expect(computed.persistent).toBeUndefined(); expect(computed.watchers).toStrictEqual({}); @@ -78,7 +79,8 @@ describe('Computed Tests', () => { expect(computed.observer.dependents.has(dummyObserver1)).toBeTruthy(); // x expect(computed.observer._key).toBe('coolComputed'); // x expect(computed.sideEffects).toStrictEqual({}); - expect(computed.computeMethod).toBeUndefined(); + expect(computed.computeValueMethod).toBeUndefined(); + expect(computed.computeExistsMethod).toBeInstanceOf(Function); expect(computed.isPersisted).toBeFalsy(); expect(computed.persistent).toBeUndefined(); expect(computed.watchers).toStrictEqual({}); diff --git a/packages/core/tests/unit/state/state.observer.test.ts b/packages/core/tests/unit/state/state.observer.test.ts index ce2a081c..7b95ac5d 100644 --- a/packages/core/tests/unit/state/state.observer.test.ts +++ b/packages/core/tests/unit/state/state.observer.test.ts @@ -265,7 +265,7 @@ describe('StateObserver Tests', () => { }); it('should ingest State into Runtime and compute newStateValue if State compute Function is set (default config)', () => { - dummyState.computeMethod = (value) => `cool value '${value}'`; + dummyState.computeValueMethod = (value) => `cool value '${value}'`; stateObserver.ingestValue('updatedDummyValue'); diff --git a/packages/core/tests/unit/state/state.test.ts b/packages/core/tests/unit/state/state.test.ts index da41eff3..58731002 100644 --- a/packages/core/tests/unit/state/state.test.ts +++ b/packages/core/tests/unit/state/state.test.ts @@ -42,7 +42,8 @@ describe('State Tests', () => { expect(state.observer.dependents.size).toBe(0); expect(state.observer._key).toBeUndefined(); expect(state.sideEffects).toStrictEqual({}); - expect(state.computeMethod).toBeUndefined(); + expect(state.computeValueMethod).toBeUndefined(); + expect(state.computeExistsMethod).toBeInstanceOf(Function); expect(state.isPersisted).toBeFalsy(); expect(state.persistent).toBeUndefined(); expect(state.watchers).toStrictEqual({}); @@ -73,7 +74,8 @@ describe('State Tests', () => { expect(state.observer.dependents.has(dummyObserver)).toBeTruthy(); expect(state.observer._key).toBe('coolState'); expect(state.sideEffects).toStrictEqual({}); - expect(state.computeMethod).toBeUndefined(); + expect(state.computeValueMethod).toBeUndefined(); + expect(state.computeExistsMethod).toBeInstanceOf(Function); expect(state.isPersisted).toBeFalsy(); expect(state.persistent).toBeUndefined(); expect(state.watchers).toStrictEqual({}); @@ -98,7 +100,8 @@ describe('State Tests', () => { expect(state.observer.dependents.size).toBe(0); expect(state.observer._key).toBeUndefined(); expect(state.sideEffects).toStrictEqual({}); - expect(state.computeMethod).toBeUndefined(); + expect(state.computeValueMethod).toBeUndefined(); + expect(state.computeExistsMethod).toBeInstanceOf(Function); expect(state.isPersisted).toBeFalsy(); expect(state.persistent).toBeUndefined(); expect(state.watchers).toStrictEqual({}); @@ -739,16 +742,51 @@ describe('State Tests', () => { }); describe('exists get function tests', () => { - it('should return true if State is no placeholder', () => { + it('should return true if State is no placeholder and computeExistsMethod returns true', () => { + numberState.computeExistsMethod = jest.fn().mockReturnValueOnce(true); numberState.isPlaceholder = false; expect(numberState.exists).toBeTruthy(); + expect(numberState.computeExistsMethod).toHaveBeenCalledWith( + numberState.value + ); + }); + + it('should return false if State is no placeholder and computeExistsMethod returns false', () => { + numberState.computeExistsMethod = jest.fn().mockReturnValueOnce(false); + numberState.isPlaceholder = false; + + expect(numberState.exists).toBeFalsy(); + expect(numberState.computeExistsMethod).toHaveBeenCalledWith( + numberState.value + ); }); it('should return false if State is placeholder"', () => { + numberState.computeExistsMethod = jest.fn(() => true); numberState.isPlaceholder = true; expect(numberState.exists).toBeFalsy(); + expect(numberState.computeExistsMethod).not.toHaveBeenCalled(); // since isPlaceholder gets checked first + }); + }); + + describe('computeExists function tests', () => { + it('should assign passed function to computeExistsMethod', () => { + const computeMethod = (value) => value === null; + + numberState.computeExists(computeMethod); + + expect(numberState.computeExistsMethod).toBe(computeMethod); + }); + + it("shouldn't assign passed invalid function to computeExistsMethod", () => { + numberState.computeExists(10 as any); + + expect(numberState.computeExistsMethod).toBeInstanceOf(Function); + expect(console.error).toHaveBeenCalledWith( + "Agile Error: A 'computeExistsMethod' has to be a function!" + ); }); }); @@ -814,21 +852,27 @@ describe('State Tests', () => { }); }); - describe('compute function tests', () => { - it('should assign passed function to computeMethod', () => { + describe('computeValue function tests', () => { + beforeEach(() => { + numberState.set = jest.fn(); + }); + + it('should assign passed function to computeValueMethod and compute State value initially', () => { const computeMethod = () => 10; - numberState.compute(computeMethod); + numberState.computeValue(computeMethod); - expect(numberState.computeMethod).toBe(computeMethod); + expect(numberState.set).toHaveBeenCalledWith(10); + expect(numberState.computeValueMethod).toBe(computeMethod); }); - it("shouldn't assign passed invalid function to computeMethod", () => { - numberState.compute(10 as any); + it("shouldn't assign passed invalid function to computeValueMethod", () => { + numberState.computeValue(10 as any); - expect(numberState.computeMethod).toBeUndefined(); + expect(numberState.set).not.toHaveBeenCalled(); + expect(numberState.computeValueMethod).toBeUndefined(); expect(console.error).toHaveBeenCalledWith( - 'Agile Error: A computeMethod has to be a function!' + "Agile Error: A 'computeValueMethod' has to be a function!" ); }); }); From db2252a9ecaddd4b453c26682a207d06c7419f16 Mon Sep 17 00:00:00 2001 From: Benno Kohrs Date: Sat, 13 Mar 2021 15:19:18 +0100 Subject: [PATCH 4/9] fixed typo --- packages/core/tests/unit/collection/selector.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/tests/unit/collection/selector.test.ts b/packages/core/tests/unit/collection/selector.test.ts index 7b583406..d318d30f 100644 --- a/packages/core/tests/unit/collection/selector.test.ts +++ b/packages/core/tests/unit/collection/selector.test.ts @@ -110,7 +110,7 @@ describe('Selector Tests', () => { expect(selector.observer._key).toBeUndefined(); expect(selector.sideEffects).toStrictEqual({}); expect(selector.computeValueMethod).toBeUndefined(); - expect(computed.computeExistsMethod).toBeInstanceOf(Function); + expect(selector.computeExistsMethod).toBeInstanceOf(Function); expect(selector.isPersisted).toBeFalsy(); expect(selector.persistent).toBeUndefined(); expect(selector.watchers).toStrictEqual({}); From 97f22ae973ce4104168fc165c00869ac509c1d04 Mon Sep 17 00:00:00 2001 From: Benno Kohrs Date: Sat, 13 Mar 2021 16:11:51 +0100 Subject: [PATCH 5/9] optimized update function tests --- packages/core/src/collection/index.ts | 21 ++++- .../tests/unit/collection/collection.test.ts | 80 ++++++++++++++++++- 2 files changed, 93 insertions(+), 8 deletions(-) diff --git a/packages/core/src/collection/index.ts b/packages/core/src/collection/index.ts index 4cd53d2b..2923ffdd 100644 --- a/packages/core/src/collection/index.ts +++ b/packages/core/src/collection/index.ts @@ -326,16 +326,17 @@ export class Collection { const newItemKey = changes[primaryKey] || oldItemKey; const updateItemKey = oldItemKey !== newItemKey; - // Delete primaryKey from 'changes' because if it has changed, it gets properly updated in 'updateItemKey' (below) - if (changes[primaryKey]) delete changes[primaryKey]; - // Update ItemKey if (updateItemKey) this.updateItemKey(oldItemKey, newItemKey, { background: config.background, }); + // Patch changes into Item if (config.patch) { + // Delete primaryKey from 'changes' because if it has changed, it gets properly updated in 'updateItemKey' (see above) + if (changes[primaryKey]) delete changes[primaryKey]; + let patchConfig: { addNewProperties?: boolean } = typeof config.patch === 'object' ? config.patch : {}; patchConfig = defineConfig(patchConfig, { @@ -347,7 +348,19 @@ export class Collection { background: config.background, addNewProperties: patchConfig.addNewProperties, }); - } else { + } + + // Set changes into Item + if (!config.patch) { + // To make sure that the primaryKey doesn't differ from the changes object primaryKey + if (changes[this.config.primaryKey] !== itemKey) { + changes[this.config.primaryKey] = itemKey; + Agile.logger.warn( + `By overwriting the whole Item don't forget passing the correct primaryKey!`, changes + ); + } + + // Apply changes to Item item.set(changes as any, { background: config.background, }); diff --git a/packages/core/tests/unit/collection/collection.test.ts b/packages/core/tests/unit/collection/collection.test.ts index 4a5fd1e7..9d71b274 100644 --- a/packages/core/tests/unit/collection/collection.test.ts +++ b/packages/core/tests/unit/collection/collection.test.ts @@ -707,14 +707,16 @@ describe('Collection Tests', () => { }; dummyItem.patch = jest.fn(); + dummyItem.set = jest.fn(); collection.updateItemKey = jest.fn(); }); - it('should update existing Item with valid changes Object (default config)', () => { + it('should update existing Item by patching valid changes Object (default config)', () => { const response = collection.update('dummyItem', { name: 'hans' }); expect(response).toBe(dummyItem); expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); expect(dummyItem.patch).toHaveBeenCalledWith( { name: 'hans', @@ -724,21 +726,22 @@ describe('Collection Tests', () => { addNewProperties: true, } ); + expect(dummyItem.set).not.toHaveBeenCalled(); expect(collection.updateItemKey).not.toHaveBeenCalled(); }); - it('should update existing Item with valid changes Object (specific config)', () => { + it('should update existing Item by patching valid changes Object (specific config)', () => { const response = collection.update( 'dummyItem', { name: 'hans' }, { - patch: true, background: true, } ); expect(response).toBe(dummyItem); expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); expect(dummyItem.patch).toHaveBeenCalledWith( { name: 'hans', @@ -748,16 +751,18 @@ describe('Collection Tests', () => { addNewProperties: true, } ); + expect(dummyItem.set).not.toHaveBeenCalled(); expect(collection.updateItemKey).not.toHaveBeenCalled(); }); - it('should update existing placeholder Item with valid changes Object (default config)', () => { + it('should update existing placeholder Item by patching valid changes Object (default config)', () => { dummyItem.isPlaceholder = true; const response = collection.update('dummyItem', { name: 'hans' }); expect(response).toBe(dummyItem); expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); expect(dummyItem.patch).toHaveBeenCalledWith( { name: 'hans', @@ -767,6 +772,67 @@ describe('Collection Tests', () => { addNewProperties: true, } ); + expect(dummyItem.set).not.toHaveBeenCalled(); + expect(collection.updateItemKey).not.toHaveBeenCalled(); + }); + + it('should update existing Item by setting valid changes Object (default config)', () => { + const response = collection.update( + 'dummyItem', + { id: 'dummyItem', name: 'hans' }, + { patch: false } + ); + + expect(response).toBe(dummyItem); + expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); + expect(dummyItem.patch).not.toHaveBeenCalled(); + expect(dummyItem.set).toHaveBeenCalledWith( + { id: 'dummyItem', name: 'hans' }, + { background: false } + ); + expect(collection.updateItemKey).not.toHaveBeenCalled(); + }); + + it('should update existing Item by setting valid changes Object (specific config)', () => { + const response = collection.update( + 'dummyItem', + { id: 'dummyItem', name: 'hans' }, + { + patch: false, + background: true, + } + ); + + expect(response).toBe(dummyItem); + expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); + expect(dummyItem.patch).not.toHaveBeenCalled(); + expect(dummyItem.set).toHaveBeenCalledWith( + { id: 'dummyItem', name: 'hans' }, + { background: true } + ); + expect(collection.updateItemKey).not.toHaveBeenCalled(); + }); + + it('should update existing Item by setting valid changes Object without primaryKey and should print warning (default config)', () => { + const response = collection.update( + 'dummyItem', + { name: 'hans' }, + { patch: false } + ); + + expect(response).toBe(dummyItem); + expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).toHaveBeenCalledWith( + "Agile Warn: By overwriting the Item don't forget passing the primaryKey!" + , {id: 'dummyItem', name: 'hans'} + ); + expect(dummyItem.patch).not.toHaveBeenCalled(); + expect(dummyItem.set).toHaveBeenCalledWith( + { id: 'dummyItem', name: 'hans' }, + { background: false } + ); expect(collection.updateItemKey).not.toHaveBeenCalled(); }); @@ -777,7 +843,9 @@ describe('Collection Tests', () => { expect(console.error).toHaveBeenCalledWith( `Agile Error: Item with key/name 'notExisting' doesn't exist in Collection '${collection._key}'!` ); + expect(console.warn).not.toHaveBeenCalled(); expect(dummyItem.patch).not.toHaveBeenCalled(); + expect(dummyItem.set).not.toHaveBeenCalled(); expect(collection.updateItemKey).not.toHaveBeenCalled(); }); @@ -791,7 +859,9 @@ describe('Collection Tests', () => { expect(console.error).toHaveBeenCalledWith( `Agile Error: You have to pass an valid Changes Object to update 'dummyItem' in '${collection._key}'!` ); + expect(console.warn).not.toHaveBeenCalled(); expect(dummyItem.patch).not.toHaveBeenCalled(); + expect(dummyItem.set).not.toHaveBeenCalled(); expect(collection.updateItemKey).not.toHaveBeenCalled(); }); @@ -803,6 +873,7 @@ describe('Collection Tests', () => { expect(response).toBe(dummyItem); expect(console.error).not.toHaveBeenCalled(); + expect(console.warn).not.toHaveBeenCalled(); expect(dummyItem.patch).toHaveBeenCalledWith( { name: 'hans', @@ -812,6 +883,7 @@ describe('Collection Tests', () => { addNewProperties: true, } ); + expect(dummyItem.set).not.toHaveBeenCalled(); expect(collection.updateItemKey).toHaveBeenCalledWith( 'dummyItem', 'newDummyItemKey', From cfd9a0f2e7d4ff10f86f522c9bf7cbbadc4ae063 Mon Sep 17 00:00:00 2001 From: Benno Kohrs Date: Sat, 13 Mar 2021 17:22:27 +0100 Subject: [PATCH 6/9] fixed compute issue --- packages/core/src/computed/index.ts | 6 +++--- packages/core/src/state/state.observer.ts | 2 +- packages/core/tests/unit/computed/computed.test.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/core/src/computed/index.ts b/packages/core/src/computed/index.ts index 707b761f..55d9f6b4 100644 --- a/packages/core/src/computed/index.ts +++ b/packages/core/src/computed/index.ts @@ -109,13 +109,13 @@ export class Computed extends State< } //========================================================================================================= - // Compute Values + // Compute //========================================================================================================= /** * @internal - * Computes Value and adds missing Dependencies to Computed + * Recomputes value and adds missing dependencies to Computed */ - public computeValue(): ComputedValueType { + public compute(): ComputedValueType { // Auto track Observers the computeFunction might depend on ComputedTracker.track(); const computedValue = this.computeFunction(); diff --git a/packages/core/src/state/state.observer.ts b/packages/core/src/state/state.observer.ts index cc33e88c..52bb5301 100644 --- a/packages/core/src/state/state.observer.ts +++ b/packages/core/src/state/state.observer.ts @@ -47,7 +47,7 @@ export class StateObserver extends Observer { const state = this.state(); let newStateValue: ValueType; - if (state instanceof Computed) newStateValue = state.computeValue(); + if (state instanceof Computed) newStateValue = state.compute(); else newStateValue = state.nextStateValue; this.ingestValue(newStateValue, config); diff --git a/packages/core/tests/unit/computed/computed.test.ts b/packages/core/tests/unit/computed/computed.test.ts index c82f50c3..1cb5eb62 100644 --- a/packages/core/tests/unit/computed/computed.test.ts +++ b/packages/core/tests/unit/computed/computed.test.ts @@ -217,7 +217,7 @@ describe('Computed Tests', () => { }); }); - describe('computeValue function tests', () => { + describe('compute function tests', () => { let dummyObserver1: Observer; let dummyObserver2: Observer; let dummyObserver3: Observer; @@ -242,7 +242,7 @@ describe('Computed Tests', () => { dummyObserver2, ]); - const response = computed.computeValue(); + const response = computed.compute(); expect(response).toBe('newComputedValue'); expect(dummyComputeFunction).toHaveBeenCalled(); From 983782609f584753ec693d5c2dac9b49e7770fdd Mon Sep 17 00:00:00 2001 From: Benno Kohrs Date: Sat, 13 Mar 2021 17:28:56 +0100 Subject: [PATCH 7/9] fixed typo --- packages/multieditor/src/multieditor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/multieditor/src/multieditor.ts b/packages/multieditor/src/multieditor.ts index 15c69268..77404c50 100644 --- a/packages/multieditor/src/multieditor.ts +++ b/packages/multieditor/src/multieditor.ts @@ -85,7 +85,7 @@ export class MultiEditor< item.validate(); if (Object.prototype.hasOwnProperty.call(this.computeMethods, key)) { const computeMethod = this.computeMethods[key]; - item.compute(computeMethod); + item.computeValue(computeMethod); } } } From a52620beaf9e130657526862bd65ee831e4607c0 Mon Sep 17 00:00:00 2001 From: Benno Kohrs Date: Sat, 13 Mar 2021 17:29:48 +0100 Subject: [PATCH 8/9] fixed typo again --- packages/multieditor/src/multieditor.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/multieditor/src/multieditor.ts b/packages/multieditor/src/multieditor.ts index 77404c50..573ca0ce 100644 --- a/packages/multieditor/src/multieditor.ts +++ b/packages/multieditor/src/multieditor.ts @@ -1,6 +1,6 @@ import { Agile, - ComputeMethod, + ComputeValueMethod, copy, defineConfig, getAgileInstance, @@ -30,7 +30,7 @@ export class MultiEditor< public validateMethods: DataObject< ValidationMethodInterface | Validator > = {}; - public computeMethods: DataObject> = {}; + public computeMethods: DataObject> = {}; public onSubmit: ( preparedData: DataObject, config?: OnSubmitConfigType @@ -514,7 +514,7 @@ export interface CreateEditorConfigInterface< validateMethods?: DataObject< ValidationMethodInterface | Validator >; - computeMethods?: DataObject>; + computeMethods?: DataObject>; onSubmit: ( preparedData: DataObject, config?: onSubmitConfig From fe697219327d6dacd19e4ed802eb224424681662 Mon Sep 17 00:00:00 2001 From: Benno Kohrs Date: Sat, 13 Mar 2021 17:41:43 +0100 Subject: [PATCH 9/9] fixed tests --- packages/core/tests/unit/collection/collection.test.ts | 8 +++++--- packages/core/tests/unit/state/state.observer.test.ts | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/core/tests/unit/collection/collection.test.ts b/packages/core/tests/unit/collection/collection.test.ts index 9d71b274..46bade21 100644 --- a/packages/core/tests/unit/collection/collection.test.ts +++ b/packages/core/tests/unit/collection/collection.test.ts @@ -824,9 +824,11 @@ describe('Collection Tests', () => { expect(response).toBe(dummyItem); expect(console.error).not.toHaveBeenCalled(); - expect(console.warn).toHaveBeenCalledWith( - "Agile Warn: By overwriting the Item don't forget passing the primaryKey!" - , {id: 'dummyItem', name: 'hans'} + expect( + console.warn + ).toHaveBeenCalledWith( + "Agile Warn: By overwriting the whole Item don't forget passing the correct primaryKey!", + { id: 'dummyItem', name: 'hans' } ); expect(dummyItem.patch).not.toHaveBeenCalled(); expect(dummyItem.set).toHaveBeenCalledWith( diff --git a/packages/core/tests/unit/state/state.observer.test.ts b/packages/core/tests/unit/state/state.observer.test.ts index 7b95ac5d..ebfc1c09 100644 --- a/packages/core/tests/unit/state/state.observer.test.ts +++ b/packages/core/tests/unit/state/state.observer.test.ts @@ -121,7 +121,7 @@ describe('StateObserver Tests', () => { }); it('should call ingestValue with computedValue if Observer belongs to a ComputedState (default config)', () => { - dummyComputed.computeValue = jest.fn(() => 'computedValue'); + dummyComputed.compute = jest.fn(() => 'computedValue'); computedObserver.ingest(); @@ -129,7 +129,7 @@ describe('StateObserver Tests', () => { 'computedValue', {} ); - expect(dummyComputed.computeValue).toHaveBeenCalled(); + expect(dummyComputed.compute).toHaveBeenCalled(); }); });