Jeremy Thomas
Jeremy Thomas

Reputation: 6684

Angular testbed testing route cannot find module

I am trying to test a simple redirect using TestBed but keep seeing the following error:

Error: Uncaught (in promise): Error: Cannot find module ./pages/login/login.module#LoginPageModule

My test is as follows:

describe('AppComponent', () => {

  let statusBarSpy, splashScreenSpy, platformReadySpy, platformSpy, platformIsSpy, storageSpy;
  let router: Router;
  let location: Location;
  let fixture, loginFixture;
  let comp: AppComponent;

  beforeEach(async(() => {
    statusBarSpy = jasmine.createSpyObj('StatusBar', ['styleDefault']);
    splashScreenSpy = jasmine.createSpyObj('SplashScreen', ['hide']);
    platformReadySpy = Promise.resolve();
    platformIsSpy = Promise.resolve('ipad');
    platformSpy = jasmine.createSpyObj('Platform', { ready: platformReadySpy, is: platformIsSpy })
    storageSpy = jasmine.createSpyObj('Storage', ['get', 'set', 'clear', 'remove', 'ready']);

    TestBed.configureTestingModule({
      declarations: [AppComponent],
      imports: [

        IonicStorageModule.forRoot(),
        HttpClientTestingModule,
        LoginPageModule,
        RouterTestingModule.withRoutes(routes),

      ],
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
      providers: [
        { provide: Storage, useClass: StorageMock },
        { provide: StatusBar, useValue: statusBarSpy },
        { provide: SplashScreen, useValue: splashScreenSpy },
        { provide: Platform, useValue: platformSpy },
      ],
    }).compileComponents();

    router = TestBed.get(Router);
    location = TestBed.get(Location);
    fixture = TestBed.createComponent(AppComponent);
    loginFixture = TestBed.createComponent
    comp = fixture.componentInstance;
    router.initialNavigation();
  }));

  it('navigates to "" redirects you to /login', fakeAsync(() => {
    router.navigate(['/login']);
    tick();
    expect(location.path()).toBe('/login')
  }));
});

And my routes in app-routing.module.ts is:

export const routes: Routes = [
  {
    path: '',
    redirectTo: 'login',
    pathMatch: 'full'
  },
  {
    path: 'login', 
    loadChildren: './pages/login/login.module#LoginPageModule'
    // component: LoginPage
  },
  {
    path: 'manager-dashboard',
    canActivate: [AuthGuard],
    loadChildren: './pages/manager-dashboard/manager-dashboard.module#ManagerDashboardPageModule'
  },
];

And my LoginPageModule is:

const routes: Routes = [
  {
    path: '',
    component: LoginPage
  }
];

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    IonicModule,
    RouterModule.forChild(routes)
  ],
  declarations: [LoginPage]
})
export class LoginPageModule {}

Is there something I need to do to make this work?

Upvotes: 2

Views: 2224

Answers (1)

Sumit Parakh
Sumit Parakh

Reputation: 1143

You need to stub out lazy loaded module while testing. Add following line in the beforeEach function:-

const loader = TestBed.get(NgModuleFactoryLoader);

Then in your test case, before navigation code, add this:-

loader.stubbedModules = {lazyModule: LoginPageModule};

eg:

@Component({ template: '' })
class LazyLoadedComponent { }

@NgModule({ declarations: [ LazyLoadedComponent ]})
class LazyModule { }

it('navigates to "" redirects you to /login', fakeAsync(() => {
    const loader = TestBed.get(NgModuleFactoryLoader);

    loader.stubbedModules = {
       './pages/login/login.module#LoginPageModule': LazyModule,
    };

    router.navigate(['/login']);
    tick();
    expect(location.path()).toBe('/login')
}));

For more details you can read about testing lazy loaded modules here:- https://angular.io/api/router/testing/SpyNgModuleFactoryLoader https://github.com/angular/angular/issues/17902

I hope it helps.

Upvotes: 3

Related Questions