I have an Angular component that takes an NgForm
as an input, it can be modfied and when it becomes valid it will emit an object.
@Input() form!: IQuestionForm; //this type extends NgForm;
@Input() question!: IQuestion;
@Output() questionChange = new EventEmitter<IQuestion>();
ngOnInit(): void {
this.form.form.statusChanges.pipe(filter((s) => s === 'VALID')).subscribe(() => {
this.questionChange.emit(this.question);
});
}
This works, but I am struggling with how to verify this behavior in a unit test.
const mockQuestionForm = new NgForm([], []) as IQuestionForm;
mockQuestionForm.form.addControl('questionText', new FormControl('', Validators.required));
mockQuestionForm.form.addControl('responseType', new FormControl(QuestionTypeEnum.FREE_TEXT, Validators.required));
describe('QuestionFormEditorComponent', () => {
let component: QuestionFormEditorComponent;
let fixture: ComponentFixture<QuestionFormEditorComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [QuestionFormEditorComponent],
});
fixture = TestBed.createComponent(QuestionFormEditorComponent);
component = fixture.componentInstance;
});
it('should emit the updated question object when the form becomes valid', () => {
spyOn(component.questionChange, 'emit');
component.form = { ...mockQuestionForm } as IQuestionForm;
component.question = {
id: '',
text: '',
type: QuestionTypeEnum.FREE_TEXT,
};
fixture.detectChanges(); //triggers ngOnInit()
expect(component.questionChange.emit).not.toHaveBeenCalled();
// ???
expect(component.questionChange.emit).toHaveBeenCalledOnceWith();
});
it('should NOT emit the updated question object when the form becomes invalid', () => {
//similar test here
});
});
Am I on the wrong track here? How should I go about testing this behavior?
This ended up working
it('should NOT emit the updated question object when the form becomes invalid', () => {
spyOn(component.questionChange, 'emit');
fixture.detectChanges(); //triggers ngOnInit()
//Adding an error marks it as invalid
component.form.form.controls['questionText'].setErrors({ required: true });
expect(component.questionChange.emit).not.toHaveBeenCalled();
});
it('should emit the updated question object when the form becomes valid', () => {
spyOn(component.questionChange, 'emit');
fixture.detectChanges(); //triggers ngOnInit()
expect(component.questionChange.emit).not.toHaveBeenCalled();
//Adding an error marks it as invalid
component.form.form.controls['questionText'].setErrors({ required: true });
//remove errors marks it as valid
component.form.form.controls['questionText'].setErrors(null);
expect(component.questionChange.emit).toHaveBeenCalledOnceWith(component.question);
});