I am working on unit-testing with jasmine and karma an angular component. In the template-component a custom dropdown component is used:
<div class="my-modal-body">
<form [formGroup]="form" class="form-horizontal">
<div class="padding-dropdown">
<my-form-wrapper
label="Dateiformat"
labelClass="col-lg-4 two-col-label-size"
inputClass="col-lg-8 two-col-input-size"
>
<my-dropdown
[items]="exportOptionen"
formControlName="dateiTyp"
(selectedChange)="exportFileChange($event)"
>
</my-dropdown>
</my-form-wrapper>
</div>
In my testing I try to test the value change, but can't get it working. However I try to set the value, the exportFileChange is not triggered. And I know that the component is correct, because it's already in production. So it has to be the test that errors.
Here is my test:
it('dateiTyp auswahl excel', waitForAsync(() => {
spyOn(component, 'exportFileChange');
dateiTyp.setValue('Excel');
component.dateiTyp.setValue('Excel', { emitEvent: true });
fixture.detectChanges();
fixture.whenStable().then(
() => {
expect(component.exportFileChange).toHaveBeenCalled();
let exDiv = fixture.debugElement.query(By.css("#excelExportDiv"));
expect(exDiv).not.toBeNull();
}
);
}));
When changing the selection the exportFileChange(event) method should be called and in the template an div appears. The exportFileChange-Method in the component just changes an boolean. I tested changing the boolean in the test and that worked, but the event still wasn't triggered.
Here are the most relevant parts of the setup:
describe('ExportModalComponent', () => {
[...]
let dateiTyp: jasmine.SpyObj<FormControl>;
let dateiTypChange: Subject<string>;
[...]
beforeEach( waitForAsync(() => {
[...]
dateiTyp = jasmine.createSpyObj('dateiTyp', ['value', 'setValue']);
formGroup.get.withArgs('dateiTyp').and.returnValue(dateiTyp);
dateiTypChange = new Subject();
Object.defineProperty(dateiTyp, 'valueChanges', { value: dateiTypChange });
[...]
and my-dropdown.component.d.ts:
export declare class myDropdownComponent implements ControlValueAccessor, OnInit, OnChanges
{ [...] }
I can change the ExportModal-template or the ExportModal-component but I can't change the implementation or use of myDropdownComponent.
I am grateful for every help!
Thanks!
This is not a complete answer but it should help you.
This is a good read. In these kind of situations, I just use triggerEventHandler
on the DebugElement
.
Something like this:
it('should do abc', () => {
// get a handle on the debugElement
const myDropDown = fixture.debugElement.query(By.css('my-dropdown'));
// the first argument is the name of the event you would like to trigger
// and the 2nd argument of type object (or anything) is the $event you want to mock for the calling function
myDropDown.triggerEventHandler('selectedChange', { /* mock $event here */});
// continue with tests
});
I am not entirely sure how your components are wired but that's the best way I have found to raise custom events for custom components.