0

I'm implementing tests for a simple canActivate guard. See below:

// guard
export const hasGraphResultsCanActiveGuard: CanActivateFn = (
  route: ActivatedRouteSnapshot,
  routerState: RouterStateSnapshot
) => {
  return inject(Store)
    .select(selectGraphResults)
    .pipe(
      map((results) => {
        return results.length > 0;
      }),
      tap((hasResults) => {
        if (!hasResults) {
          inject(Router).navigate(['/app/map']);
        }
      })
    );
};

// routes in the module where its used
const routes: Routes = [
  {
    path: 'analysis',
    component: AnalysisComponent,
    canActivate: [hasGraphResultsCanActiveGuard],
  },
  {
    path: '**',
    pathMatch: 'full',
    redirectTo: 'analysis',
  },
];

// Test
describe('HasGraphResultsGuard', () => {
  beforeEach(() => {
    return (
      MockBuilder(
        [
          RouterModule,
          RouterTestingModule.withRoutes([]),
          NG_MOCKS_ROOT_PROVIDERS,
        ],
        DisruptionPageModule
      )
        .exclude(NG_MOCKS_GUARDS)
        .keep(hasGraphResultsCanActiveGuard)
        .provide(
          provideMockStore({
            initialState: {
              graph: cloneDeep(initialGraphState),
            },
          })
        )
    );
  });

  it('Redirects to /app/map', fakeAsync(() => {
    const fixture = MockRender(RouterOutlet, {});
    const router = ngMocks.get(Router);
    const location = ngMocks.get(Location);

    // Initialize navigation
    if (fixture.ngZone) {
      fixture.ngZone.run(() => router.initialNavigation());
      tick();
    }

    // The initial state has no graph results so it should redirect
    expect(location.path()).toEqual('/app/map');
  }));
});

Unless I've missed something I believe I've implemented the test exactly as the docs suggest. Heres the error I get:

Error: MockBuilder has found a missing dependency: hasGraphResultsCanActiveGuard. It means no module provides it. Please, use the "export" flag if you want to add it explicitly. https://ng-mocks.sudo.eu/api/MockBuilder#export-flag

I've tried adding the export flag and then it says it cant resolve the parameters.

The guard works as intended in my app but I cant connect things correctly in the test. Am I missing something or are the docs incomplete?

JDillon522
  • 19,046
  • 15
  • 47
  • 81
  • First time I see a CanActivateFn. Any reason you don't use a CanActivate Service instead ? – Random Jun 29 '23 at 09:09
  • Im not familiar with that pattern. The docs (both ng-mocks and angular) only use pure functions. – JDillon522 Jun 29 '23 at 12:20
  • indeed, CanActivate interface [is deprecated](https://angular.io/api/router/CanActivate), ty – Random Jun 29 '23 at 15:11
  • I guess I wasnt clear. I'm not using the CanActivate interface in a class, I'm using the CanActivateFn https://angular.io/api/router/CanActivateFn – JDillon522 Jun 29 '23 at 16:32
  • Yep, I'm the one using the deprecated pattern. About your issue, I don't know ngMock (I use Jasmine or Jest), but what I would do is test the `hasGraphResultsCanActiveGuard` alone, without the router. So I would call this function with my mocked services and router, and check wether it returns true of false (and if `navigate(['/app/map'])` has been called). It makes the test easier. Checking if the guard is correctly applied would be an integration test, not a unit test IMO. – Random Jun 30 '23 at 07:36

1 Answers1

0

had the same issue, i think a ng-mocks update to 14.11.0 solved it