Reputation: 79
I have a component :
@Component({
selector: 'app-sidenav',
standalone: true,
imports: [
MatSidenavModule
],
templateUrl: './sidenav.component.html',
styleUrl: './sidenav.component.scss'
})
export class SidenavComponent implements OnInit {
openingService = inject(SidenavOpeningService);
opened: BooleanInput;
#injector = inject(Injector);
constructor() {
}
ngOnInit():void {
runInInjectionContext(this.#injector, () => {
effect(() => {
this.opened = this.openingService.isOpen();
});
});
}
}
<mat-sidenav-container>
<mat-sidenav #sidenav [opened]="opened" (openedChange)="openingService.isOpen.set($event)" mode="over">Start</mat-sidenav>
<mat-sidenav-content>
<p>test</p>
</mat-sidenav-content>
</mat-sidenav-container>
and a service :
import {Injectable, signal} from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class SidenavOpeningService {
isOpen = signal(false);
constructor() { }
toggle() {
this.isOpen.update(value => !value);
}
}
This test pass :
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SidenavComponent } from './sidenav.component';
import {SidenavOpeningService} from "../../services/sidenav-opening.service";
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import {MatSidenavModule} from "@angular/material/sidenav";
describe('SidenavComponent', () => {
let component: SidenavComponent;
let fixture: ComponentFixture<SidenavComponent>;
let mockService: jasmine.SpyObj<SidenavOpeningService> = jasmine.createSpyObj('SidenavOpeningService', ['isOpen', 'toggle']);
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SidenavComponent,MatSidenavModule, NoopAnimationsModule],
providers: [{ provide: SidenavOpeningService, useValue: mockService }]
})
.compileComponents();
fixture = TestBed.createComponent(SidenavComponent);
component = fixture.componentInstance;
mockService.isOpen.and.returnValue(true);
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should update "opened" based on SidenavOpeningService', () => {
expect(component.opened).toBeTrue();
});
});
but this test doesn't pass :
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SidenavComponent } from './sidenav.component';
import {SidenavOpeningService} from "../../services/sidenav-opening.service";
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import {MatSidenavModule} from "@angular/material/sidenav";
describe('SidenavComponent', () => {
let component: SidenavComponent;
let fixture: ComponentFixture<SidenavComponent>;
let mockService: jasmine.SpyObj<SidenavOpeningService> = jasmine.createSpyObj('SidenavOpeningService', ['isOpen', 'toggle']);
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SidenavComponent,MatSidenavModule, NoopAnimationsModule],
providers: [{ provide: SidenavOpeningService, useValue: mockService }]
})
.compileComponents();
fixture = TestBed.createComponent(SidenavComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should update "opened" based on SidenavOpeningService', () => {
mockService.isOpen.and.returnValue(true);
fixture.detectChanges();
expect(component.opened).toBeTrue();
});
});
I have : Expected undefined to be true. at at UserContext.apply (src/app/core/components/sidenav/sidenav.component.spec.ts:32:30) at _ZoneDelegate.invoke (node_modules/zone.js/fesm2015/zone.js:368:26) at ProxyZoneSpec.onInvoke (node_modules/zone.js/fesm2015/zone-testing.js:273:39) at _ZoneDelegate.invoke (node_modules/zone.js/fesm2015/zone.js:367:52)
Upvotes: 1
Views: 40
Reputation: 81
Calling fixture.detectChanges() in the beforeEach is the problem.
Remove it and call it from the it function after configuring the spy object.
Upvotes: 0
Reputation: 57986
We need to initialize the component, after you setup the jasmine spys this fixes the failure!
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { MatSidenavModule } from '@angular/material/sidenav';
import { SidenavComponent } from './sidenav-responsive-example';
import { SidenavOpeningService } from './sidenav-opening.service';
describe('SidenavComponent', () => {
let component: SidenavComponent;
let fixture: ComponentFixture<SidenavComponent>;
let mockService: jasmine.SpyObj<SidenavOpeningService> = jasmine.createSpyObj(
'SidenavOpeningService',
['isOpen', 'toggle']
);
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SidenavComponent, MatSidenavModule, NoopAnimationsModule],
providers: [{ provide: SidenavOpeningService, useValue: mockService }],
}).compileComponents();
fixture = TestBed.createComponent(SidenavComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should update "opened" based on SidenavOpeningService', () => {
mockService.isOpen.and.returnValue(true);
fixture = TestBed.createComponent(SidenavComponent);
component = fixture.componentInstance;
fixture.detectChanges();
expect(component.opened).toBeTrue();
});
});
stackblitz demo -> ctrl+C
to kill default command in terminal -> npm run test
to start test cases!
Upvotes: 1