Skip to content

Commit

Permalink
fix(data): mergeQuerySet uses mergeStrategy (#2430)
Browse files Browse the repository at this point in the history
Closes #2368
  • Loading branch information
AdditionAddict authored Jun 6, 2020
1 parent 0b41c71 commit e1720b4
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 1 deletion.
172 changes: 172 additions & 0 deletions modules/data/spec/reducers/entity-cache-reducer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import {
ChangeSet,
ChangeSetOperation,
Logger,
MergeStrategy,
ChangeType,
} from '../..';

class Hero {
Expand Down Expand Up @@ -286,6 +288,121 @@ describe('EntityCacheReducer', () => {
expect(heroCollection.ids).toEqual(expectedIds);
expect(heroCollection.entities[42]).toEqual({ id: 42, name: 'Bobby' });
});

it('should use default preserve changes merge strategy', () => {
const {
unchangedHero,
unchangedHeroServerUpdated,
updatedHero,
locallyUpdatedHero,
serverUpdatedHero,
initialCache,
} = createInitialCacheForMerges();
const querySet: EntityCacheQuerySet = {
Hero: [unchangedHeroServerUpdated, serverUpdatedHero],
};
const action = new MergeQuerySet(querySet);

const state = entityCacheReducer(initialCache, action);
expect(state['Hero'].entities[unchangedHero.id]).toEqual(
unchangedHeroServerUpdated,
'Updates current value for unchanged entity'
);
expect(state['Hero'].entities[updatedHero.id]).toEqual(
locallyUpdatedHero,
'Preserves the current value for changed entity'
);
expect(
state['Hero'].changeState[updatedHero.id]!.originalValue
).toEqual(
serverUpdatedHero,
'Overwrites the originalValue with the merge entity'
);
});

it('should be able to use ignore changes merge strategy', () => {
const {
updatedHero,
serverUpdatedHero,
initialCache,
} = createInitialCacheForMerges();
const querySet: EntityCacheQuerySet = {
Hero: [serverUpdatedHero],
};
const action = new MergeQuerySet(querySet, MergeStrategy.IgnoreChanges);

const state = entityCacheReducer(initialCache, action);
expect(state['Hero'].entities[updatedHero.id]).toEqual(
serverUpdatedHero,
'Update the collection entity'
);
expect(
state['Hero'].changeState[updatedHero.id]!.originalValue
).toEqual(updatedHero, 'changeState is untouched');
});

it('should be able to use preserve changes merge strategy', () => {
const {
unchangedHero,
unchangedHeroServerUpdated,
updatedHero,
locallyUpdatedHero,
serverUpdatedHero,
initialCache,
} = createInitialCacheForMerges();
const querySet: EntityCacheQuerySet = {
Hero: [unchangedHeroServerUpdated, serverUpdatedHero],
};
const action = new MergeQuerySet(
querySet,
MergeStrategy.PreserveChanges
);

const state = entityCacheReducer(initialCache, action);
expect(state['Hero'].entities[unchangedHero.id]).toEqual(
unchangedHeroServerUpdated,
'Updates current value for unchanged entity'
);
expect(state['Hero'].entities[updatedHero.id]).toEqual(
locallyUpdatedHero,
'Preserves the current value for changed entity'
);
expect(
state['Hero'].changeState[updatedHero.id]!.originalValue
).toEqual(
serverUpdatedHero,
'Overwrites the originalValue with the merge entity'
);
});

it('should be able to use overwrite changes merge strategy', () => {
const {
unchangedHero,
unchangedHeroServerUpdated,
updatedHero,
serverUpdatedHero,
initialCache,
} = createInitialCacheForMerges();
const querySet: EntityCacheQuerySet = {
Hero: [unchangedHeroServerUpdated, serverUpdatedHero],
};
const action = new MergeQuerySet(
querySet,
MergeStrategy.OverwriteChanges
);

const state = entityCacheReducer(initialCache, action);
expect(state['Hero'].entities[unchangedHero.id]).toEqual(
unchangedHeroServerUpdated,
'Replace the current collection entity for unchanged entity'
);
expect(state['Hero'].changeState[unchangedHero.id]).toBeUndefined();
expect(state['Hero'].entities[updatedHero.id]).toEqual(
serverUpdatedHero,
'Replace the current collection entity for changed entity'
);
expect(state['Hero'].changeState[updatedHero.id]).toBeUndefined();
});
});

describe('SET_ENTITY_CACHE', () => {
Expand Down Expand Up @@ -592,6 +709,61 @@ describe('EntityCacheReducer', () => {
return cache;
}

function createInitialCacheForMerges() {
// general test data for testing mergeStrategy
const unchangedHero = { id: 1, name: 'Unchanged', power: 'Hammer' };
const unchangedHeroServerUpdated = {
id: 1,
name: 'UnchangedUpdated',
power: 'Bish',
};
const deletedHero = { id: 2, name: 'Deleted', power: 'Bash' };
const addedHero = { id: 3, name: 'Added', power: 'Tiny' };
const updatedHero = { id: 4, name: 'Pre Updated', power: 'Tech' };
const locallyUpdatedHero = {
id: 4,
name: 'Locally Updated',
power: 'Suit',
};
const serverUpdatedHero = { id: 4, name: 'Server Updated', power: 'Nano' };
const ids = [unchangedHero.id, addedHero.id, updatedHero.id];
const initialCache = {
Hero: {
ids,
entities: {
[unchangedHero.id]: unchangedHero,
[addedHero.id]: addedHero,
[updatedHero.id]: locallyUpdatedHero,
},
entityName: 'Hero',
filter: '',
loaded: true,
loading: false,
changeState: {
[deletedHero.id]: {
changeType: ChangeType.Deleted,
originalValue: deletedHero,
},
[updatedHero.id]: {
changeType: ChangeType.Updated,
originalValue: updatedHero,
},
[addedHero.id]: { changeType: ChangeType.Added },
},
},
};
return {
unchangedHero,
unchangedHeroServerUpdated,
deletedHero,
addedHero,
updatedHero,
locallyUpdatedHero,
serverUpdatedHero,
initialCache,
};
}

function createInitialSaveTestEntities() {
const entities: { [entityName: string]: any[] } = {
Fool: [
Expand Down
2 changes: 1 addition & 1 deletion modules/data/src/reducers/entity-cache-reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ export class EntityCacheReducerFactory {
let { mergeStrategy, querySet, tag } = action.payload;
mergeStrategy =
mergeStrategy === null ? MergeStrategy.PreserveChanges : mergeStrategy;
const entityOp = EntityOp.UPSERT_MANY;
const entityOp = EntityOp.QUERY_MANY_SUCCESS;

const entityNames = Object.keys(querySet);
entityCache = entityNames.reduce((newCache, entityName) => {
Expand Down

0 comments on commit e1720b4

Please sign in to comment.