I have a navbar that displays a link if you're on the login page (which directs you to the next page) and a select drop-down that displays instead once you've navigated to the next page. A minimal working component example would be something like
@Component({
selector: 'app-navbar',
template: '''
<ul>
<ng-container *ngIf="isLogin$ | async else selector">
<li><a routerLink="/next">Next page</a></li>
</ng-container>
<ng-template #selector><li>You\'re here on Next</li></ng-template>
</ul>
'''
})
export class NavComponent implements OnInit {
isLogin$!: Observable<boolean>
constructor(private router: Router) { }
ngOnInit(): void {
this.isLogin$ = router.events.pipe(
filter((e): e is NavigationEnd => e instanceOf NavigationEnd),
map((e) => e.urlAfterRedirect === '/login')
);
}
}
It seems as if the async pipe isn't subscribing to the isLogin$ observable at any point during my test, even after calling detectChanges on the component fixture.
The basic test looks something like
describe('AppComponent', () => {
let app: AppComponent;
let fixture: ComponentFixture<AppComponent>;
let nav: NavComponent;
let navFixture: ComponentFixture<NavComponent>;
let router: Router;
let location: Location;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes(routes),
HttpClientTestingModule
],
declarations: [
AppComponent,
LoginComponent,
NextComponent,
NavComponent
]
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
app = fixture.debugElement.componentInstance;
navFixture = TestBed.createComponent(DomHeaderComponent);
nav = headerFixture.debugElement.componentInstance;
location = TestBed.inject(Location);
router = TestBed.inject(Router);
router.initialNavigation();
});
it('should navigate to the next page on link click', waitForAsync(() => {
fixture.detectChanges();
navFixture.detectChanges();
navFixture.whenStable().then(() => {
expect(location.path()).toBe('/login');
const de = navFixture.debugElement.query(By.css('a'));
const ne = de.nativeElement as HTMLAnchorElement;
ne.click(); // fails
expect(location.path()).toBe('/next');
});
}));
However, the native element is null. The isLogin$ observable fires (I can subscribe to it directly in tests and check its value), the location is updated, but the async pipe never seems to subscribe and update the DOM with the link. Thus, it seems as if the link doesn't exist. I'm perplexed. Cheers.