Skip to content

Commit

Permalink
fix: repair memoization of promotion selectors (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
dhhyi authored Dec 18, 2019
1 parent 11d729d commit 3ea5ee9
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 23 deletions.
4 changes: 2 additions & 2 deletions src/app/core/facades/shopping.facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,13 @@ export class ShoppingFacade {
// PROMOTIONS
promotion$(promotionId: string) {
this.store.dispatch(new LoadPromotion({ promoId: promotionId }));
return this.store.pipe(select(getPromotion, { promoId: promotionId }));
return this.store.pipe(select(getPromotion(), { promoId: promotionId }));
}

promotions$(promotionIds: string[]) {
promotionIds.forEach(promotionId => {
this.store.dispatch(new LoadPromotion({ promoId: promotionId }));
});
return this.store.pipe(select(getPromotions, { promotionIds }));
return this.store.pipe(select(getPromotions(), { promotionIds }));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -63,16 +63,39 @@ describe('Promotions Selectors', () => {
describe('state with a promotion', () => {
beforeEach(() => {
store$.dispatch(new LoadPromotionSuccess({ promotion: promo }));
store$.dispatch(new LoadPromotionSuccess({ promotion: promo1 }));
});

describe('but no current router state', () => {
it('should return the promotion information when used', () => {
expect(getPromotionEntities(store$.state)).toEqual({ [promo.id]: promo });
expect(getPromotionEntities(store$.state)).toMatchInlineSnapshot(`
Object {
"id": Object {
"id": "id",
},
"id1": Object {
"id": "id1",
},
}
`);
});

it('should return a promotion stub if promotion is selected', () => {
expect(getPromotion(store$.state, { promoId: promo.id })).toBeTruthy();
expect(getPromotions(store$.state, { promotionIds: [promo.id, promo1.id] })).toBeTruthy();
expect(getPromotion()(store$.state, { promoId: promo.id })).toMatchInlineSnapshot(`
Object {
"id": "id",
}
`);
expect(getPromotions()(store$.state, { promotionIds: [promo.id, promo1.id] })).toMatchInlineSnapshot(`
Array [
Object {
"id": "id",
},
Object {
"id": "id1",
},
]
`);
});
});
});
Expand Down
39 changes: 24 additions & 15 deletions src/app/core/store/shopping/promotions/promotions.selectors.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { createSelector } from '@ngrx/store';
import { memoize } from 'lodash-es';
import {
DefaultProjectorFn,
MemoizedSelectorWithProps,
createSelector,
createSelectorFactory,
defaultMemoize,
} from '@ngrx/store';
import { isEqual } from 'lodash-es';

import { Promotion } from 'ish-core/models/promotion/promotion.model';
import { ShoppingState, getShoppingState } from 'ish-core/store/shopping/shopping-store';
Expand All @@ -15,17 +21,20 @@ export const { selectEntities: getPromotionEntities, selectAll: getAllPromotions
getPromotionsState
);

export const getPromotion = createSelector(
getPromotionEntities,
(entities, props: { promoId: string }) => entities[props.promoId]
);
export const getPromotion = () =>
createSelector(
getPromotionEntities,
(entities, props: { promoId: string }): Promotion => entities[props.promoId]
);

export const getPromotions = createSelector(
getAllPromotions,
memoize(
(promotions, props): Promotion[] =>
props.promotionIds.map(id => promotions.find(p => p.id === id)).filter(x => !!x),
(promotions: Promotion[], props: { promotionIds: string[] }) =>
`${props.promotionIds.join()}#${promotions.map(p => p.id).join()}`
)
);
export const getPromotions = (): MemoizedSelectorWithProps<
object,
{ promotionIds: string[] },
Promotion[],
DefaultProjectorFn<Promotion[]>
> =>
createSelectorFactory(projector => defaultMemoize(projector, isEqual, isEqual))(
getAllPromotions,
(promotions: Promotion[], props: { promotionIds: string[] }): Promotion[] =>
props.promotionIds.map(id => promotions.find(p => p.id === id)).filter(x => !!x)
);
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { instance, mock, when } from 'ts-mockito';
import { ServerHtmlDirective } from 'ish-core/directives/server-html.directive';
import { ShoppingFacade } from 'ish-core/facades/shopping.facade';
import { BasketRebate } from 'ish-core/models/basket-rebate/basket-rebate.model';
import { Promotion } from 'ish-core/models/promotion/promotion.model';
import { getICMBaseURL } from 'ish-core/store/configuration';
import { PromotionDetailsComponent } from 'ish-shared/components/promotion/promotion-details/promotion-details.component';

Expand Down Expand Up @@ -51,7 +52,7 @@ describe('Basket Promotion Component', () => {
id: 'PROMO_UUID',
title: 'MyPromotionTitle',
disableMessages: false,
})
} as Promotion)
);

component.rebate = {
Expand All @@ -74,7 +75,7 @@ describe('Basket Promotion Component', () => {
id: 'PROMO_UUID',
title: 'MyPromotionTitle',
disableMessages: true,
})
} as Promotion)
);

component.rebate = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
import { MockComponent } from 'ng-mocks';
import { of } from 'rxjs';
import { EMPTY, of } from 'rxjs';
import { anything, instance, mock, when } from 'ts-mockito';

import { ServerHtmlDirective } from 'ish-core/directives/server-html.directive';
Expand All @@ -19,6 +19,7 @@ describe('Product Promotion Component', () => {

beforeEach(async(() => {
shoppingFacade = mock(ShoppingFacade);
when(shoppingFacade.promotions$(anything())).thenReturn(EMPTY);

TestBed.configureTestingModule({
declarations: [
Expand Down

0 comments on commit 3ea5ee9

Please sign in to comment.