I have an Angular 10 unit test that displays SPEC HAS NO EXPECTATIONS.
Below is a sample of the code in my app.component.ts file being tested
import {Component, HostListener, OnInit} from '@angular/core';
import {EventMessageBus, MessageBusGroup} from "@app/shared/services/message-bus/EventMessageBus";
import {CollapsePanel, ExpandPanel, ResizeMessageGrid} from "@app/shared/services/message-bus/message-bus-events";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
private messageBusGroup: MessageBusGroup;
private timeout = null;
constructor(
private eventBusService: EventMessageBus
) {
this.messageBusGroup = eventBusService.group();
}
ngOnInit() {
// Subscribe to events
this.messageBusGroup.on(CollapsePanel, this.onCollapsePanel.bind(this));
this.messageBusGroup.on(ExpandPanel, this.onExpandPanel.bind(this));
}
private onCollapsePanel(): void {
const panel = document.getElementById('left-panel');
const mainPanel = document.getElementById('content');
const prefsPanel = document.getElementById('preferences-flyout');
const wgPanel = document.getElementById('wgmgmt-flyout');
panel.classList.add('collapsed');
mainPanel.classList.add('expanded');
prefsPanel.classList.add('expanded');
wgPanel.classList.add('expanded');
this.resizeWindow();
}
private onExpandPanel(): void {
debugger
const panel = document.getElementById('left-panel');
const mainPanel = document.getElementById('content');
const prefsPanel = document.getElementById('preferences-flyout');
const wgPanel = document.getElementById('wgmgmt-flyout');
panel.classList.remove('collapsed');
mainPanel.classList.remove('expanded');
prefsPanel.classList.remove('expanded');
wgPanel.classList.remove('expanded');
this.resizeWindow();
}
private resizeWindow(): void {
setTimeout(() => {
const e = document.createEvent('Event');
e.initEvent('resize', true, true);
window.dispatchEvent(e);
this.messageBusGroup.emit(new ResizeMessageGrid());
}, 100)
}
}
Here's my unit test spec:
import {TestBed, async, ComponentFixture, fakeAsync, tick, waitForAsync} from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
// ... more imports ...
let fixture: ComponentFixture<AppComponent>;
let component: AppComponent;
// MOCK COMPONENTS
@Component({
template: `<div></div>`,
selector: 'search'
})
class SearchComponentMock {}
@Component({
template: `<div></div>`,
selector: 'mailfiles'
})
class MailfilesComponentMock {}
@Component({
template: `
<div>
<div id="wgmgmt-flyout"></div>
<div id="preferences-flyout"></div>
<div id="content"></div>
<div id="left-panel"></div>
</div>
`,
selector: 'workspace'
})
class WorkspaceComponentMock {}
@Component({
template: `<div></div>`,
selector: 'folders'
})
class FoldersComponentMock {}
describe('AppComponent', () => {
let router: Router;
let location: Location;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes([
{
path: '',
component: WorkspaceComponentMock,
//canActivate: [CurrentUserGuard, IsRegisteredGuard],
children: [
{path: 'search', component: SearchComponentMock},
{path: 'mailfiles', component: MailfilesComponentMock},
{path: 'folders', component: FoldersComponentMock},
{path: '', redirectTo: 'search/new', pathMatch: 'full'}
]
}
]),
ToasterModule.forRoot()
],
declarations: [
AppComponent,
EnvBannerComponent
],
providers: [
{ provide: 'CONFIGURATION', useValue: environment },
]
}).compileComponents();
router = TestBed.inject(Router);
location = TestBed.inject(Location);
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.ngZone.run(() => {
router.initialNavigation();
});
});
it('should create the app', () => {
expect(component).toBeTruthy();
});
describe('AppComponent DOM Tests', () => {
beforeEach(() => {
})
it('should collapse side panel when called', waitForAsync(() => {
fixture.detectChanges();
fixture.whenStable().then(() => {
const onCollapsePanelSpy = spyOn<any>(component, 'onCollapsePanel');
const resizeWindowSpy = spyOn<any>(component, 'resizeWindow');
(component as any).messageBusGroup.emit(new CollapsePanel());
const lPanel = fixture.debugElement.query(By.css('#left-panel'));
const content = fixture.debugElement.query(By.css('#content'));
const prefFlyout = fixture.debugElement.query(By.css('#preferences-flyout'));
const wgPanel = fixture.debugElement.query(By.css('#wgmgmt-flyout'));
expect(onCollapsePanelSpy).toHaveBeenCalled();
expect(lPanel.nativeElement.classList).toContain('collapsed');
expect(content.nativeElement.classList).toContain('expanded');
expect(prefFlyout.nativeElement.classList).toContain('expanded');
expect(wgPanel.nativeElement.classList).toContain('expanded');
expect(resizeWindowSpy).toHaveBeenCalled();
});
}));
it('should expand side panel when called', async((done) => {
//fixture.detectChanges();
fixture.whenStable().then(() => {
const onCollapsePanelSpy = spyOn<any>(component, 'onCollapsePanel');
const resizeWindowSpy = spyOn<any>(component, 'resizeWindow');
(component as any).messageBusGroup.emit(new ExpandPanel());
fixture.detectChanges()
const lPanel = fixture.debugElement.query(By.css('#left-panel'));
const content = fixture.debugElement.query(By.css('#content'));
const prefFlyout = fixture.debugElement.query(By.css('#preferences-flyout'));
const wgPanel = fixture.debugElement.query(By.css('#wgmgmt-flyout'));
expect(onCollapsePanelSpy).toHaveBeenCalled();
expect(lPanel.nativeElement.classList).not.toContain('collapsed');
expect(content.nativeElement.classList).not.toContain('expanded');
expect(prefFlyout.nativeElement.classList).not.toContain('expanded');
expect(wgPanel.nativeElement.classList).not.toContain('expanded');
expect(resizeWindowSpy).toHaveBeenCalled();
done()
});
}));
})
});
In the above code, I've tried using waitForAsync, async, fakeAsync without success.
Basically, in my tests I get a hold of the App Component's messagBusGroup property/function and invoke it. The library is basically an emitter/subscription service I wrote so when I make the call
(component as any).messageBusGroup.emit(new ExpandPanel())
it causes the defined event handlers to be called. This approach seems to work and the expected methods are called, but the unit tests do not seem to be aware of the 'expect' statements.
What am I doing wrong here?