Reputation: 3866
I have Component
that has a data member bound by @Input
whose ngOnInit()
doesn't seem to get invoked. The code for this component is as follows:
import { Component, OnInit, Input } from '@angular/core';
import { SelectedStatusConstants } from '../../constants/selected-status.constants';
import { AutoUnsubscribe } from '../../decorator/auto-unsubscribe.decorator';
import { ChartScale } from '../../models/chart-scale.model';
import { SkillsetService } from '../../services/skill-set-service/skill-set.service';
import { NgZone } from '@angular/core';
@Component({
selector: 'app-skillset',
templateUrl: './skillset.component.html',
styleUrls: ['./skillset.component.css']
})
/**
* The skillset component
* @author : Michael Warren
*/
@AutoUnsubscribe
export class SkillsetComponent implements OnInit {
/**
* The selected status
*/
@Input() selectedStatus : string = SelectedStatusConstants.TRAINING;
/**
* Map of selected status to skill id
*/
private static SKILL_INFO : Map<String, any>;
/**
* The id of skill, probably to hit the API with
*/
private skillID : number;
/**
* The flag that tells Angular, and the developer, whether or not ng2_chart dependency is actually being used
*/
USE_NG2_CHART : boolean = true;
/**
* The types of charts
*/
public static readonly chartTypes = {
BAR : 'bar',
PIE : 'pie',
POLAR_AREA : 'polarArea'
}
/**
* The type of chart
*/
chartType = SkillsetComponent.chartTypes.BAR;
/**
* The dummy data to compare against for our tests
*/
readonly DUMMY_DATA = [{data:[1,1,1,1,1], label: 'Mapped'},{data:[1,1,1,1,1],label: 'Unmapped'}];
/**
* The skillset data
*/
skillsetData = this.DUMMY_DATA;
/**
* THe skillset labels
*/
skillsetLabels = [];
/**
* The chart options, as a JavaScript-style object, and pre-initialized so as to DRY up our code...
*/
chartOptions : {[k: string]: any} = {
type : this.chartType,
legend : {
display : false
},
xAxes:[
{
ticks: {
autoSkip:false
}
}
],
scales : new ChartScale()
};
constructor(private skillsetService : SkillsetService, private zone : NgZone) {
// setup SKILL_INFO
if (!SkillsetComponent.SKILL_INFO) {
SkillsetComponent.SKILL_INFO = new Map();
SkillsetComponent.SKILL_INFO.set(SelectedStatusConstants.TRAINING, 6);
SkillsetComponent.SKILL_INFO.set(SelectedStatusConstants.OPEN, 7);
SkillsetComponent.SKILL_INFO.set(SelectedStatusConstants.SELECTED, 8);
SkillsetComponent.SKILL_INFO.set(SelectedStatusConstants.CONFIRMED, 9);
}
}
ngOnInit(): void {
// get skillID
this.skillID = SkillsetComponent.SKILL_INFO.get(this.selectedStatus) || 0;
// get the skillset data here
this.skillsetService.getSkillsetsForStatusID(this.skillID).subscribe((res) => {
// copy in the raw data into local variable
let skillsets : Array<any> = res.data;
// map() that variable into skillsetData,skillsetLabels
this.skillsetData = skillsets.map((obj) => obj.count);
this.skillsetLabels= skillsets.map((obj) => obj.name);
});
}
/**
* Exposing SKILL_INFO in a safe way
*/
public static getSkillInfo() {
return SkillsetComponent.SKILL_INFO;
}
}
This component is not routed in any way, as the use case is to use its tag name, property-binding selectedStatus
. When I wrote my tests on this component, to make sure that its skillsetData
was different from DUMMY_DATA
, it fails. (I made sure to test the service method, and it passed.) The test for the SkillsetComponent
is as follows:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SkillsetComponent } from './skillset.component';
import { SelectedStatusConstants } from '../../constants/selected-status.constants';
import { element, by, browser } from 'protractor';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ChartsModule } from 'ng2-charts';
import { RootComponent } from '../root/root.component';
import { HomeComponent } from '../home/home.component';
import { NavbarComponent } from '../navbar/navbar.component';
import { RouterTestingModule } from '@angular/router/testing';
import { SkillsetService } from '../../services/skill-set-service/skill-set.service';
describe('SkillsetComponent', () => {
let component: SkillsetComponent;
let fixture: ComponentFixture<SkillsetComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SkillsetComponent, RootComponent, HomeComponent, NavbarComponent ],
imports : [
HttpClientTestingModule,
ChartsModule,
RouterTestingModule
],
providers : [
SkillsetService
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SkillsetComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it('should have a non-empty map of skill info', () => {
expect(SkillsetComponent.getSkillInfo()).toBeTruthy();
expect(SkillsetComponent.getSkillInfo().size).toBeGreaterThan(0);
});
it('should have non-zero skillID', () => {
component.selectedStatus = SelectedStatusConstants.CONFIRMED;
expect(component.selectedStatus).toBeTruthy();
})
it('should not be using DUMMY_DATA', () => {
expect(component.skillsetData).not.toEqual(component.DUMMY_DATA);
})
});
How do I ensure that either this ngOnInit()
is getting called, or the test is correctly loading in the data?
Upvotes: 3
Views: 3431
Reputation: 3866
After relaxing from the stressful reality that is this project, for a few, and then coming back to it, I realized that this test:
relied on ngOnInit()
changing data, and passed. Thus, the problem was NOT ngOnInit()
, but my test itself. I found this resource:
it('should have non-zero skillID', () => {
component.selectedStatus = SelectedStatusConstants.CONFIRMED;
expect(component.selectedStatus).toBeTruthy();
})
and refactored my test that failed to:
it('should not be using DUMMY_DATA', () => {
fixture.detectChanges();
fixture.whenStable().then(() => {
expect(component.skillsetData).not.toEqual(component.DUMMY_DATA);
})
});
console.log('Stress makes people do stupid desperate things, especially when said stress comes from super tight deadlines')
Upvotes: 5