I understand the root of the error, the component I'm testing requires a FormGroup
to be passed into it's @Input() form: FormGroup
. I just can't figure out how to pass one in when testing this component.
There error occurs in my before each function when I call fixture.detectChanges()
so the form must be passed in before that point
my current code get's the error group is not defined:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import {
ReactiveFormsModule,
FormsModule,
Validators,
FormBuilder
} from '@angular/forms';
import { StaticComponent } from '../../firewall/static/static.component';
describe('StaticComponent', () => {
let component: StaticComponent;
let fixture: ComponentFixture<StaticComponent>;
beforeEach(
async(() => {
TestBed.configureTestingModule({
declarations: [
StaticComponent
],
imports: [
CommonModule,
ReactiveFormsModule,
FormsModule
],
providers: [
NetworkService,
NetworkValidator,
HostNameValidator,
NotificationsService
]
}).compileComponents();
})
);
beforeEach(() => {
fixture = TestBed.createComponent(StaticComponent);
component = fixture.componentInstance;
component.ruleForm = FormBuilder.group({
chain: ['chain', Validators.required],
ip: [
'',
Validators.required,
this.networkValidator.validateNetwork('ip')
],
action: ['action', Validators.required]
});
fixture.detectChanges();
});
fit('should be created', () => {
expect(component).toBeTruthy();
});
});
How do I pass in a pre-fab form to my @Input of the component during the test? I cant seem to provide FormBuilder correctly
This is a test component spec that I came up with for you. Notice the mocked FormBuilder
that I have added and the way that I have provided it in the spec.
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TestingComponent } from './testing.component';
import { FormBuilder, Validators } from '@angular/forms';
describe('TestingComponent', () => {
let component: TestingComponent;
let fixture: ComponentFixture<TestingComponent>;
const formBuilder: FormBuilder = new FormBuilder();
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TestingComponent ],
providers: [ { provide: FormBuilder, useValue: formBuilder } ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TestingComponent);
component = fixture.componentInstance;
component.ruleForm = formBuilder.group({
chain: ['chain', Validators.required],
ip: [
'',
Validators.required
],
action: ['action', Validators.required]
});
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
This is my test component in case you need to refer to that.
import { Component, OnInit } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'app-testing',
templateUrl: './testing.component.html',
styleUrls: ['./testing.component.css']
})
export class TestingComponent implements OnInit {
ruleForm: FormGroup = new FormGroup({});
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
this.ruleForm = this.formBuilder.group({
chain: ['chain', Validators.required],
ip: [
'',
Validators.required
],
action: ['action', Validators.required]
});
}
}
I ran into the same error after running detectChanges
. My component's FormGroup, however, was initiated in ngOnInit, not passed as an input.
The solution for my case was wrapping the component under test
in a wrapper component. This process will force Angular to put the component under test
through the lifecycle events e.g. ngOnInit that you would otherwise have to invoke yourself. It also feels like the right way to test a component with inputs. It's a little more boilerplate, but this method mimics angular's natural behavior more closely.
Here is a reproduction of code from this Medium article
describe('ComponentUnderTestComponent', () => {
let testHostComponent: TestHostComponent;
let testHostFixture: ComponentFixture<TestHostComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ComponentUnderTestComponent, TestHostComponent]
}).compileComponents();
}));
beforeEach(() => {
testHostFixture = TestBed.createComponent(TestHostComponent);
testHostComponent = testHostFixture.componentInstance;
testHostFixture.detectChanges();
});
it('should show TEST INPUT', () => {
expect(testHostFixture.nativeElement.querySelector('div').innerText)
.toEqual('TEST INPUT');
});
@Component({
selector: `host-component`,
template: `<component-under-test input="test input"></component-under-test>`
})
class TestHostComponent {
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With