Platform: Impossible to test selectors which uses router store

Created on 23 Mar 2018  路  6Comments  路  Source: ngrx/platform

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x] Question
[ ] Feature request
[x] Documentation issue or request

What is the current behavior?

Some selectors can use the routerStore, for example:

export const isSomeIdParamValid = createSelector(
  getRouterState,
  (routerS) => {
    return routerS.state.params && routerS.state.params.someId;
  }
);

The fact is in tests, it's almost impossible to get a proper setup where we can test the behavior of these selectors.

As current setup where we can dig around the web / demo app (since no documentation is provided at all for testing purpose), we result to get only nested structure instead of flat. Running the app works and we can retrieve value as expected. But Test setup with actual tool is quite impossible it seems.

Minimal reproduction of the problem with instructions:

Find stackblitz here:
https://stackblitz.com/edit/ngrx-router-testing?file=app%2Fstore%2Frouter.selec.spec.ts

I put here the return value.

As you can see, by using a testBed setup like:

RouterTestingModule.withRoutes([{
          path: 'list/:someId',
          component: ListMockComponent
        }]),
        StoreModule.forRoot({
          router: combineReducers(reducers)
        }),
        StoreRouterConnectingModule.forRoot({
          stateKey: 'router',
        }),

we manage to get a nested structure when we try to select using getRouterState selector:

{
auth: { unwanted AuthState here },
router: { state: { routerStateUrl here } } 
}

How to get a proper setup where getRouterState and so getRouterStateUrl and children selector can get routerState directly without reaching a nested state structure.

The problem seems to come from the fact when setuping store for selector testing, we use StoreModule.forRoot() and then combineReducers which push all state chunks (even unwanted Auth state here) in the store state and returns it as the key here "router".

So when we use getRouterState selector, we get something like: { router: {state: {} }, auth: {}}intsead of getting directly the inner part router: {state:{}}. So of course, state doesn't exist on this returned state object.

What is the proper way to test such behavior and selectors using router store?

If using real router Store in test (note we should'nt have to do that), how to Spy on and "bypass" the getRouterState / getRouterStateUrl? Spying on store.select seems not the solution since we want to be able to test other real selectors and we only want to spy and return mocked data on 'store.select(getRouterState)` exactly.

Since testing cannot be ran here, please only find test setup and working app.

Version of affected browser(s),operating system(s), npm, node and ngrx:

ngrx 5.2.0, angular 5.2.0, node 8.9.4

Most helpful comment

@brandonroberts the stackblitz link you shared seem to not work anymore. Is there any documentation on how to set up router state in tests properly?

All 6 comments

Here is a working example of testing with router-store. https://stackblitz.com/edit/angular-testing-template-xcvbz9?file=app%2Frouting.spec.ts

The proper way to test composed selectors is to use the projector function and use the arguments and assert against the output. Recently documented here https://github.com/ngrx/platform/blob/master/docs/store/testing.md#testing-selectors

Thanks @brandonroberts hope to see better documentation in the future about router-store. Will dive into your example.

@brandonroberts on the stackblitz you linked, please could you explain why the skip(1) is necessary when getting router State?

@brandonroberts the stackblitz link you shared seem to not work anymore. Is there any documentation on how to set up router state in tests properly?

@brandonroberts - As above, please can you fix your stackblitz example?

The test sample has been updated

Was this page helpful?
0 / 5 - 0 ratings

Related issues

oxiumio picture oxiumio  路  3Comments

mappedinn picture mappedinn  路  3Comments

gperdomor picture gperdomor  路  3Comments

sandangel picture sandangel  路  3Comments

brandonroberts picture brandonroberts  路  3Comments