I am trying to unit test (Karma/Jasmine Angular 9.15) the disable property of a select going from true to false when an input is filled (not null or empty). Jasmine do not seem to detect de changes becauses I don't pass through the function that processes the boolean 'disabled' when I simulate the value change on the input.
So I am wondering why it doesn't detect the change and since I didn't found a working solution I am questionning my testing strategy about this : Am I doign it right ?
Here is the code :
filter.spec.ts
fdescribe('FilterComponent', () => {
let component: FilterComponent;
let fixture: ComponentFixture<FilterComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ FilterComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FilterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should able the select when input is filled', () => {
let inputFilter = fixture.debugElement.nativeElement.querySelector('#my-filter');
inputFilter.value = "testing";
inputFilter.dispatchEvent(new Event('input'));
fixture.detectChanges();
fixture.whenStable().then(fix=>{
expect(fixture.debugElement.nativeElement.querySelector('#my-
select').disabled).toBeFalse();
});
});
filter.component.html
<!-- Filter -->
<div class="flex-container-h flex-align-center flex-nowrap mlm">
<label class="mt-label txtc-15 mrs" for="my-filter">Contract number</label>
<div class="flex-item-fluid">
<input [(ngModel)]="contractFilter" id="my-filter" type="text"
class="form-control">
</div>
</div>
<!-- Filtre select-->
<div class="flex-container-h flex-align-center flex-nowrap mlm">
<label class="mt-label txtc-15 mrs" for="my-select">Statut</label>
<div class="flex-item-fluid">
<select id="my-select" name="statuts" [disabled]="isSelectDisabled()">
<option value="" selected disabled hidden>Select an option</option>
<option *ngFor="let status of statusesList" [value]="status.code">{{status.libelle}}</option>
</select>
</div>
</div>
filter.component.ts
public isSelectDisabled(): boolean {
return (!this.contractFilter || this.contractFilter === "");
}
Thanks for reading me
Doing it from the HTML
like so might be tricky because there might be asynchronous
tasks with updating values and you might need another fixture.whenStable()
. What I would do is directly change contractFilter
because the Angular team has already tested ngModel
.
import { By } from '@angular/platform-browser';
.....
it('should able the select when input is filled', () => {
component.contractFilter = 'testing';
fixture.detectChanges();
// I like to query the DOM like so
const disableSelect = fixture.debugElement.query(By.css('#my-select[disabled]'));
const enableSelect = fixture.debugElement.query(By.css('#my-select'));
expect(disableSelect).toBeFalsy();
expect(enableSelect).toBeTruthy();
});
We query the DOM for #my-select
with disabled
attribute and expect it to be falsy and we query the DOM for #my-select
without disabled
attribute and expect it to be truthy.