Reputation: 1424
I'm attempting to test the values inside of a .subscribe
block within an angular4/typescript jasmine unit test that uses a rxjs auditTime
method. I've read a lot of similar posts to this one that don't seem to get me inside that block.
I have the following example component:
address.component.ts:
export class AddressComponent implements OnInit {
public form: FormGroup;
constructor (
private fb: FormBuilder
) {}
public ngOnInit (): void {
this.createForm();
}
public createForm (): void {
this.form = this.fb.group({
lineOne: [this.address.lineOne],
});
this.form.valueChanges.auditTime(500).subscribe(() => {
this.address.lineOne = this.form.value.lineOne;
});
}
}
address.component.html:
<div class="address">
<form [formGroup]="form">
<div class="row">
<div class="col-12 address-body">
<div class="form-group-main">
<div class="row">
<div class="address-input col-12">
<label for="address-line-one" [class.required]="isMandatory">Address Line 1</label>
<input class="form-control" id="address-line-one" type="text" formControlName="lineOne">
</div>
</div>
</div>
</div>
<div class="col-12 address-body">
<display-address [body]="address.lineOne"></display-address>
</div>
<div class="col-12">
<button class="btn btn-full-width btn-primary btn-sm btn-edit" id="address-edit" type="button" (click)="...">Edit</button>
</div>
</div>
</form>
</div>
address.component.spec.ts:
describe('Address Component', () => {
let component: AddressComponent;
let fixture: ComponentFixture<AddressComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AddressComponent],
imports: [ReactiveFormsModule],
schemas: [NO_ERRORS_SCHEMA],
}).compileComponents().then(() => {
fixture = TestBed.createComponent(AddressComponent);
component = fixture.componentInstance;
});
}));
it('should update address', fakeAsync(() => {
component.address = {lineOne: 'street'};
fixture.detectChanges();
//do something..
}));
});
assuming the above has been setup correctly and i haven't missed something glaringly obvious which is why my tests never provide the correct results, i've tried modifying my test with the following ideas:
spying on auditTime and calling through:
spyOn(component.form.valueChanges, 'auditTime').and.callThrough();
spying on auditTime and calling fake function:
spyOn(component.form.valueChanges,'auditTime').and.callFake(()=> {
return {
subscribe: () => {}
}
});
spying on auditTime and returning a value Observable.of:
spyOn(component.form.valueChanges,'auditTime').and.returnValue(Observable.of('hello'));
calling it directly:
component.form.valueChanges.auditTime().subscribe(result => {
//never get in here
});
trying to wait using: tick()
and trying to flush using: flushMicrotasks()
.
spying on the createForm function:
spyOn(component, 'createForm').and.callFake(() => {
return Observable.of('hello');
});
using debugElement to access and update lineOne always returns errors if i use the following:
const el = fixture.nativeElement.querySelector(By.css('#address-line-one'));
el.value = 'something';
el.dispatchEvent(new Event('input'));
fixture.detectChanges();
as it would appear it can only see the edit button of the html and <display-address></display-address>
, suggesting it's maybe not compiled at the time.
I've also tried wrapping everything in:
fixture.whenStable().then(() => {
// do something..
});
and now i'm out of ideas, if anyone can make sense of the above and point me in the right direction, it would be great..
Thanks to Amir, it would appear that in this particular example i had been massively overthinking the answers required for this, and using the NO_ERRORS_SCHEMA
was hiding the true problem. It turns out i needed to import the component which <display-address>
required:
imports: [ReactiveFormsModule, DisplayAddressComponent],
this allowed the template to compile correctly, meaning that i could see all the form values instead of just <display-address>
. As recommended i used the combination of fakeAsync
and tick(600)
to emit change to the form:
it('should update address', fakeAsync(() => {
component.address = {lineOne: 'street'};
fixture.detectChanges();
expect(component.address.lineOne).toBe('street');
component.form.controls['lineOne'].setValue('test');
tick(600);
expect(component.address.lineOne).toBe('test');
}));
just if anyone had a similar problem.
Upvotes: 1
Views: 1435
Reputation: 3699
Ok i will just post here my assumptions, check if it helps:
Upvotes: 1