Platform: [@ngrx/store/testing] overrideSelector with props

Created on 23 Oct 2019  路  5Comments  路  Source: ngrx/platform

Currently we can override selectors in the MockStore with the overrideSelector method. This method treats MemoizedSelector and MemoizedSelectorWithProps exactly the same way : by providing an hardcoded return value.

It would be really is usefull to be able to provide a callback for MemoizedSelectorWithProps in order to return different values depending on the props.

Describe any alternatives/workarounds you're currently using

None

Other information:

I am testing a router guard that can check multiple access rights, accessed via a selector, and I want to test when the user has some rights but not all.

If accepted, I would be willing to submit a PR for this feature

[ ] Yes (Assistance is provided if you need help submitting a pull request)
[x] No

Store

Most helpful comment

@louie-succio it works fine overriding MemoizedSelectorWithProps statically - the mock value can't be conditional based on passed prop.

The scenario that is not possible to mock today would be similar to this:

it('should allow conditionally mocking of store.select with a memoized selector with Prop using provideMockStore', () => {
  const expectedValue = [100, 200];

  const selectorWithPropMocked = createSelector(
    () => initialState,
    (state: typeof initialState, add: number) => state.counter1 + add
  );

  // This override should be applied when prop is 1
  mockStore.overrideSelector(selectorWithPropMocked, 100);

  // This override should be applied when prop is 2
  mockStore.overrideSelector(selectorWithPropMocked, 200);

  // Idea for mocking #1:
  // mockStore.overrideSelector(selectorWithPropMocked, 1, 100);
  // mockStore.overrideSelector(selectorWithPropMocked, 2, 200);

  // Idea for mocking #2:
  // mockStore.overrideSelector(selectorWithPropMocked, (prop) => {
  //   switch (prop) {
  //     case 1:
  //       return 100;
  //     case 2:
  //       return 200;
  //   }
  // });

  combineLatest([
    mockStore.select(selectorWithPropMocked, 1),
    mockStore.select(selectorWithPropMocked, 2),
  ]).subscribe((result) => expect(result).toBe(expectedValue));
});

All 5 comments

+1

Is anyone looking into this already?
I have same issue and would be willing to submit a PR.

Is there any update on this?

A work around for this I just found. I was looking through the tests for ngrx-store and if you override your MemoizedSelectorWithProps within provideMockStore you'll be able to accomplish what you need. An example of how it's done here

I have it working for my case where I use a MemoizedSelectorWithProps. The one caveat I'm unsure of is if you'd be able to alter the override later in the tests, or if this is done once during the test file
initialization and then that's it.

@louie-succio it works fine overriding MemoizedSelectorWithProps statically - the mock value can't be conditional based on passed prop.

The scenario that is not possible to mock today would be similar to this:

it('should allow conditionally mocking of store.select with a memoized selector with Prop using provideMockStore', () => {
  const expectedValue = [100, 200];

  const selectorWithPropMocked = createSelector(
    () => initialState,
    (state: typeof initialState, add: number) => state.counter1 + add
  );

  // This override should be applied when prop is 1
  mockStore.overrideSelector(selectorWithPropMocked, 100);

  // This override should be applied when prop is 2
  mockStore.overrideSelector(selectorWithPropMocked, 200);

  // Idea for mocking #1:
  // mockStore.overrideSelector(selectorWithPropMocked, 1, 100);
  // mockStore.overrideSelector(selectorWithPropMocked, 2, 200);

  // Idea for mocking #2:
  // mockStore.overrideSelector(selectorWithPropMocked, (prop) => {
  //   switch (prop) {
  //     case 1:
  //       return 100;
  //     case 2:
  //       return 200;
  //   }
  // });

  combineLatest([
    mockStore.select(selectorWithPropMocked, 1),
    mockStore.select(selectorWithPropMocked, 2),
  ]).subscribe((result) => expect(result).toBe(expectedValue));
});

Is there any update on this?

Was this page helpful?
0 / 5 - 0 ratings