In my route config each route has some custom data regarding page/theme colors
export const appRoutes: Array<Route> = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{
path: 'dashboard',
component: DashboardComponent,
canActivate: [AuthGuard],
data: { areaColorName: 'default' },
},
{
path: 'question-library',
component: QuestionLibraryComponent,
canActivate: [AuthGuard],
data: { areaColorName: 'questions' },
}
//etc...
];
In my app.component.ts I read that data like this where I then set a CSS class on the body with the received data
private readonly destroyRef = inject(DestroyRef);
private readonly router = inject(Router);
ngOnInit(): void {
this.router.events.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((event) => {
if (event instanceof NavigationEnd) {
const routeData = this.router.routerState.root.firstChild?.snapshot.data;
console.log(this.router.routerState.root.firstChild)
let areaName = 'default';
if (routeData && Boolean(routeData['areaColorName'])) {
areaName = routeData['areaColorName'] as string;
}
//remove any CSS class that begin with the BG status prefix
this.document.body.className = this.document.body.className
.split(' ')
.filter((c) => !c.startsWith(this.bgClassPrefix))
.join(' ')
.trim();
//Add a new class to indicate the status
this.document.body.classList.add(this.bgClassPrefix + areaName);
}
});
}
How can I go about testing this behavior? Here's what I have so far:
describe('AppComponent', () => {
let app: AppComponent;
let fixture: ComponentFixture<AppComponent>;
let injectedDocument: Document;
let injectedRouter: Router;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes([
{
path: 'dashboard',
component: DashboardComponent,
data: { areaColorName: 'foo' },
},
]),
HttpClientTestingModule,
AppComponent,
],
});
fixture = TestBed.createComponent(AppComponent);
app = fixture.componentInstance;
injectedDocument = TestBed.inject(DOCUMENT);
injectedRouter = TestBed.inject(Router);
});
it('should change the body class when navigating to different routes', () => {
fixture.detectChanges(); // triggers ngOnInit()
const event = new NavigationEnd(1, '/dashboard', '/dashboard');
const ev = injectedRouter.events as Subject<Event>;
ev.next(event);
fixture.detectChanges();
expect(injectedDocument.body.classList).not.toContain('app-area-default');
expect(injectedDocument.body.classList).toContain('app-area-foo');
});
}
This does trigger a routing event, but when console.log(this.router.routerState.root.firstChild) (inside ngOnInit) is called from within the component it just returns null. What do I need to do to be able to extract the custom route data from within a test?
You are not performing any navigation in your test. You should call
initialNavigationmethod over the router like this: