I have this setup for a number of components:
@Directive()
export abstract class BaseComponent implements OnInit {
@Select(PortalState.portal) public portalState: Observable<PortalModel>;
public portal: PortalModel;
protected ngUnsubscribe: Subject<void> = new Subject();
constructor(
protected someService: SomeService,
protected route: ActivatedRoute
){
}
public ngOnInit(): void {
this.route.params
.pipe(
filter(res => !!res),
tap(res => this.id = res['id']),
switchMap(() => this.portalState),
takeUntil(this.ngUnsubscribe)
)
.subscribe(res => {
this.portal = res;
this.afterInit();
});
}
public ngOnDestroy(): void {
this.ngUnsubscribe.next();
this.ngUnsubscribe.complete();
}
public abstract afterInit(): void
}
and then in every component which extends this base class:
@Component({...})
export class SomeComponent extends BaseComponent {
public specificVar: any;
constructor(
protected someService: SomeService,
protected route: ActivatedRoute
){
super(someService, route);
}
public afterInit(): void {
/** do component specific stuff */
this.specificVar = 'something';
}
}
Now it works fine, however when testing, the abstract component's ngOnInit seems to be not called at all rendering (in this example) this.specific
variable as undefined.
the spec file looks quite traditional
let store: Store; /** Ngxs store */
const mockPortalModel: PortalModel = {id: 1};
beforeEach(async () => {
TestBed.configureTestingModule(/** providers and usual setup */);
store = TestBed.inject(Store);
store.reset({
portalState: mockPortalModel
});
jest.spyOn(store, 'dispatch');
jest.spyOn(store, 'select');
});
beforeEach(() => {
fixture = TestBed.createComponent(SomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
Any ideas why ngOnInit
and subsequently afterInit
are not being called?
CodePudding user response:
You have to write below function in your SomeComponent
so that it will run your BaseComponent
's ngOnInit
method after SomeComponent
's ngOnInit
method.
ngOnInit() {
super.ngOnInit();
}
CodePudding user response:
The problem was in this.route.params
which had to be mocked, so the subscription could fire. So mocking activated route has solved the issue:
const mockActivatedRoute = {
snapshot: {}, // needs to be there to avoid _lastPathIndex error
params: of({id: 123})
}
/** ... */
providers: [
{provide: ActivatedRoute, useValue: mockActivatedRoute }
]
had ensured that the subscription goes through (see that filter(res => !!res)
- it stopped right there).