Search code examples
angularunit-testingprimengprimeng-calendar

Angular unit testing prime ng calendar


Inside a unit test, when I have a regular element I can set its value, trigger a change event and verify the form value matches like so:

const hostElement = fixture.nativeElement;
const userIdSelect: HTMLInputElement = 
hostElement.querySelector('select[formcontrolname="userId"]');
userIdSelect.value = 'myUser';
userIdSelect.dispatchEvent(new Event('change'));  
fixture.detectChanges();
expect(component.form.controls.userId.value).toBe('myUser');

I cant seem to get it to work with the prime ng calendar control.

const myDate= new Date(2019,11,31);
const myDateInput: HTMLInputElement = hostElement.querySelector('p-calendar[formcontrolname="myDate"] input');
myDateInput.value = myDate.toLocaleDateString();
myDateInput.dispatchEvent(new Event('input'));
expect(component.form.controls.myDate.value).toBe(myDate.toLocaleDateString());

I have a feeling this is because the form is bound to the p-calendar element, and not to its child input:

<p-calendar dateFormat="dd/mm/yy" formControlName="myDate"
showIcon="true"
[readonlyInput]="false"></p-calendar>

I've tried dispatching various events on the input (blur, input, etc), but no matter what I cant seem to get the form to get updated. Any ideas? Am I supposed to be setting the value of the p-calendar element instead of its input?


Solution

  • After going though the p-calendar source code, two things are required for this to work. First, date format of input string has to match what the calendar control is expecting, in my case:

    myDateInput.value = moment(myDate).format('DD/MM/YYYY');
    

    Second, because of this: https://github.com/primefaces/primeng/blob/2b632fe200c003eb78e4d3b57d65f7ff27dedcb9/src/app/components/calendar/calendar.ts#L1407

    A keydown event has to be dispatched.

    myDateInput.dispatchEvent(new Event('keydown'));