I have component which displays Angular Material date inputs. I'm trying to test it using Material Harness CDK and Spectator. I have problems with date formats.
I have custom DateAdapter:
export class IfpDateAdapter extends NativeDateAdapter {
constructor(translateService: TranslateService, platform: Platform) {
super(translateService.currentLang, platform);
translateService.onLangChange
.pipe(untilDestroyed(this))
.subscribe(locale => this.setLocale(locale.lang));
}
createDate(year: number, month: number, date: number): Date {
return new Date(Date.UTC(year, month, date));
}
parse(value: any): Date | null {
if (typeof value === 'string' && value.split('/').length === 3) {
const str = value.split('/');
const year = Number(str[2]);
const month = Number(str[1]) - 1;
const day = Number(str[0]);
return new Date(Date.UTC(year, month, day));
}
super.parse(value);
}
format(date: Date, displayFormat: any): string {
if (displayFormat === 'input') {
return formatDate(date, config.dateFormat, this.locale);
}
return super.format(date, displayFormat);
}
}
and MatDateFormats:
export const IFP_DATE_FORMATS: MatDateFormats = {
parse: {
dateInput: 'DD/MM/YYYY'
},
display: {
dateInput: 'DD/MM/YYYY',
monthYearLabel: { year: 'numeric', month: 'numeric' },
dateA11yLabel: { year: 'numeric', month: 'long', day: 'numeric' },
monthYearA11yLabel: { year: 'numeric', month: 'long' }
}
}
These are provided in createComponentFactory in the same way as in CoreModule:
componentProviders: [
{
provide: DateAdapter,
useClass: IfpDateAdapter,
deps: [TranslateService]
},
{
provide: MAT_DATE_FORMATS,
useValue: IFP_DATE_FORMATS
},
]
For the following test date formats are fine and it passes:
it('should write start date', async () => {
const startDateInput = await loader.getHarness(MatDatepickerInputHarness.with({ancestor: '[data-test=start-date-form-field]'}))
await startDateInput.setValue('11/10/2023')
await startDateInput.blur()
expect(spectator.component.startDateControl.value).toStrictEqual(new Date('2023-10-11'))
})
But another test fails because day and month are swapped:
it('should write value', async () => {
const startDateInput = await loader.getHarness(
MatDatepickerInputHarness.with({ ancestor: '[data-test=start-date-form-field]' })
);
const endDateInput = await loader.getHarness(
MatDatepickerInputHarness.with({ ancestor: '[data-test=end-date-form-field]' })
);
const value: DatePeriodControl = {
startDate: new Date('2023-10-12'),
endDate: new Date('2023-10-15')
};
spectator.component.writeValue(value);
expect(spectator.component.form.value).toStrictEqual(value);
expect(await startDateInput.getValue()).toBe('12/10/2023');
expect(await endDateInput.getValue()).toBe('15/10/2023');
});
Expected: "12/10/2023"
Received: "10/12/2023"
I've tried to set that date as initial value for input and it's displayed in expected format so I have no idea why in test it behaves like this.
The issue you're facing could be related to the order in which your custom IfpDateAdapter and the IFP_DATE_FORMATS are provided to your test environment. In Angular testing, the order of providing services and configurations can sometimes impact how they are used in the component.
To ensure that your custom date adapter and date formats are applied correctly in your tests, make sure that you provide them in the correct order in your test bed configuration. Here's how you can modify your test setup to provide the IFP_DATE_FORMATS before the DateAdapter:
In the above code, the MAT_DATE_FORMATS token is provided with your custom date formats (IFP_DATE_FORMATS) before the DateAdapter token is provided with your custom date adapter (IfpDateAdapter). This order ensures that the date formats are applied correctly by the date adapter when it is instantiated.
Make sure that your IFP_DATE_FORMATS object is defined correctly, and that the display and parse properties are configured as expected for your date format requirements.
If the issue persists, you might want to check if there are any other date-related configurations or providers in your application or test environment that could be conflicting with your custom setup. Also, make sure that there are no global configurations affecting date formats in your Angular testing environment.