Skip to content

Commit 3dbf320

Browse files
authored
Merge branch '9.1.x' into ibarakov/fix-7090-9.1.x
2 parents e927ada + 625b3ef commit 3dbf320

14 files changed

+577
-50
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,18 @@
22

33
All notable changes for each version of this project will be documented in this file.
44

5+
## 9.1.18
6+
7+
### General
8+
- `IgxDatePicker`
9+
- Added `aria-labelledby` property for the input field. This will ensure the users of assistive technologies will also know what component is used for, upon input focus.
10+
11+
## 9.1.16
12+
13+
### General
14+
- `IgxSelect`
15+
- Added `aria-labelledby` property for the items list container(marked as `role="listbox"`). This will ensure the users of assistive technologies will also know what the list items container is used for, upon opening.
16+
517
## 9.1.9
618

719
### New Features

projects/igniteui-angular/src/lib/calendar/calendar-multi-view.component.spec.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { TestBed, async, fakeAsync, tick } from '@angular/core/testing';
33
import { FormsModule } from '@angular/forms';
44
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
55
import { configureTestSuite } from '../test-utils/configure-suite';
6-
import { UIInteractions } from '../test-utils/ui-interactions.spec';
6+
import { UIInteractions, wait } from '../test-utils/ui-interactions.spec';
77
import { IgxCalendarComponent, IgxCalendarModule } from './public_api';
88
import { IgxDatePickerComponent, IgxDatePickerModule } from '../date-picker/date-picker.component';
99
import { DateRangeType } from '../core/dates';
@@ -752,9 +752,9 @@ describe('Multi-View Calendar - ', () => {
752752
expect(document.activeElement).toEqual(monthDates[10]);
753753
}));
754754

755-
it('Verify that months increment/decrement continuously on enter keydown', (fakeAsync(() => {
755+
it('Verify that months increment/decrement continuously on enter keydown', (async() => {
756756
calendar.monthsViewNumber = 2;
757-
tick(100);
757+
await wait(100);
758758
fixture.detectChanges();
759759
const dates = [new Date('2019-10-15'), new Date('2019-11-15'), new Date('2019-12-15'),
760760
new Date('2020-1-15'), new Date('2020-2-15'), new Date('2020-3-15'), new Date('2020-4-15')];
@@ -764,20 +764,21 @@ describe('Multi-View Calendar - ', () => {
764764
for (let i = 1; i < dates.length - 1; i++) {
765765
const arrowRight = HelperTestFunctions.getNexArrowElement(fixture);
766766
UIInteractions.triggerKeyDownEvtUponElem('Enter', arrowRight);
767-
tick(100);
767+
fixture.detectChanges();
768+
await wait(100);
768769
fixture.detectChanges();
769770

770771
HelperTestFunctions.verifyCalendarSubHeaders(fixture, [dates[i], dates[i + 1]]);
771772
}
772-
for (let index = dates.length - 2; index > 0; index--) {
773+
for (let index = dates.length - 2; index > 0; index--) {
773774
const arrowLeft = HelperTestFunctions.getPreviousArrowElement(fixture);
774775
UIInteractions.triggerKeyDownEvtUponElem('Enter', arrowLeft);
775-
tick(100);
776776
fixture.detectChanges();
777-
777+
await wait(200);
778+
fixture.detectChanges();
778779
HelperTestFunctions.verifyCalendarSubHeaders(fixture, [dates[index - 1], dates[index]]);
779780
}
780-
})));
781+
}));
781782

782783
it('Verify that months increment/decrement continuously on mouse down', (fakeAsync(() => {
783784
calendar.monthsViewNumber = 2;

projects/igniteui-angular/src/lib/calendar/calendar.component.spec.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -705,21 +705,24 @@ describe('IgxCalendar - ', () => {
705705
});
706706
});
707707

708-
it('Calendar keyboard navigation - PageUp/PageDown', () => {
708+
it('Calendar keyboard navigation - PageUp/PageDown', fakeAsync(() => {
709709
const component = dom.query(By.css(HelperTestFunctions.CALENDAR_CSSCLASS));
710710

711711
UIInteractions.triggerKeyDownEvtUponElem('PageUp', component.nativeElement);
712712
fixture.detectChanges();
713+
tick(100);
713714
expect(calendar.viewDate.getMonth()).toEqual(4);
714715

715716
calendar.viewDate = new Date(2017, 5, 13);
716717
fixture.detectChanges();
717718
UIInteractions.triggerKeyDownEvtUponElem('PageDown', component.nativeElement);
718719
fixture.detectChanges();
720+
tick(100);
719721

720722
expect(calendar.viewDate.getMonth()).toEqual(6);
721723
UIInteractions.triggerKeyDownEvtUponElem('PageUp', component.nativeElement, true, false, true);
722724
fixture.detectChanges();
725+
tick(100);
723726

724727
expect(calendar.viewDate.getFullYear()).toEqual(2016);
725728

@@ -728,9 +731,10 @@ describe('IgxCalendar - ', () => {
728731

729732
UIInteractions.triggerKeyDownEvtUponElem('PageDown', component.nativeElement, true, false, true);
730733
fixture.detectChanges();
734+
tick(100);
731735

732736
expect(calendar.viewDate.getFullYear()).toEqual(2018);
733-
});
737+
}));
734738

735739
it('Calendar keyboard navigation - Home/End/Enter', () => {
736740
const component = dom.query(By.css(HelperTestFunctions.CALENDAR_CSSCLASS));

projects/igniteui-angular/src/lib/calendar/calendar.component.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ export class IgxCalendarComponent extends IgxMonthPickerBaseDirective implements
466466
* @internal
467467
*/
468468
public previousMonth(isKeydownTrigger = false) {
469+
if (isKeydownTrigger && this.animationAction === ScrollMonth.NEXT) { return; }
469470
this.viewDate = this.calendarModel.getPrevMonth(this.viewDate);
470471
this.animationAction = ScrollMonth.PREV;
471472
this.isKeydownTrigger = isKeydownTrigger;
@@ -478,6 +479,7 @@ export class IgxCalendarComponent extends IgxMonthPickerBaseDirective implements
478479
* @internal
479480
*/
480481
public nextMonth(isKeydownTrigger = false) {
482+
if (isKeydownTrigger && this.animationAction === 'prev') { return; }
481483
this.viewDate = this.calendarModel.getNextMonth(this.viewDate);
482484
this.animationAction = ScrollMonth.NEXT;
483485
this.isKeydownTrigger = isKeydownTrigger;
@@ -491,7 +493,7 @@ export class IgxCalendarComponent extends IgxMonthPickerBaseDirective implements
491493
public startPrevMonthScroll = (isKeydownTrigger = false) => {
492494
this.startMonthScroll$.next();
493495
this.monthScrollDirection = ScrollMonth.PREV;
494-
496+
this.animationAction = ScrollMonth.PREV;
495497
this.previousMonth(isKeydownTrigger);
496498
}
497499

@@ -503,7 +505,7 @@ export class IgxCalendarComponent extends IgxMonthPickerBaseDirective implements
503505
public startNextMonthScroll = (isKeydownTrigger = false) => {
504506
this.startMonthScroll$.next();
505507
this.monthScrollDirection = ScrollMonth.NEXT;
506-
508+
this.animationAction = ScrollMonth.NEXT;
507509
this.nextMonth(isKeydownTrigger);
508510
}
509511

@@ -745,11 +747,11 @@ export class IgxCalendarComponent extends IgxMonthPickerBaseDirective implements
745747
@HostListener('keydown.pageup', ['$event'])
746748
public onKeydownPageDown(event: KeyboardEvent) {
747749
event.preventDefault();
748-
749750
if (this.activeView !== CalendarView.DEFAULT) {
750751
return;
751752
}
752753

754+
753755
const isPageDown = event.key === 'PageDown';
754756
const step = isPageDown ? 1 : -1;
755757
let monthView = this.daysView as IgxDaysViewComponent;
@@ -792,8 +794,10 @@ export class IgxCalendarComponent extends IgxMonthPickerBaseDirective implements
792794
};
793795
}
794796

795-
if (isPageDown) { this.nextMonth(true); } else {
796-
this.previousMonth(true);
797+
if (isPageDown) {
798+
event.repeat ? requestAnimationFrame(() => this.nextMonth(true)) : this.nextMonth(true);
799+
} else {
800+
event.repeat ? requestAnimationFrame(() => this.previousMonth(true)) : this.previousMonth(true);
797801
}
798802
}
799803

projects/igniteui-angular/src/lib/calendar/month-picker/month-picker.component.spec.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Component, ViewChild } from '@angular/core';
2-
import { TestBed } from '@angular/core/testing';
2+
import { TestBed, fakeAsync, tick, flush } from '@angular/core/testing';
33
import { FormsModule } from '@angular/forms';
44
import { By } from '@angular/platform-browser';
55
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
@@ -259,21 +259,35 @@ describe('IgxMonthPicker', () => {
259259

260260
expect(monthPicker.viewDate.getFullYear()).toEqual(2021);
261261
expect(yearBtn.nativeElement.textContent.trim()).toMatch('2021');
262+
});
262263

264+
it('should navigate to the previous/next year via arrowLeft and arrowRight', fakeAsync(() => {
265+
const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent);
266+
fixture.detectChanges();
267+
tick();
268+
flush();
269+
270+
const monthPicker = fixture.componentInstance.monthPicker;
271+
const yearBtn = fixture.debugElement.query(By.css('.igx-calendar-picker__date'));
272+
273+
expect(yearBtn.nativeElement.textContent.trim()).toMatch('2019');
263274
yearBtn.nativeElement.focus();
264275

265-
UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', yearBtn.nativeElement);
276+
UIInteractions.triggerKeyDownEvtUponElem('ArrowLeft', yearBtn.nativeElement);
266277
fixture.detectChanges();
278+
tick(50);
279+
flush();
267280

268-
expect(monthPicker.viewDate.getFullYear()).toEqual(2022);
269-
expect(yearBtn.nativeElement.textContent.trim()).toMatch('2022');
281+
expect(monthPicker.viewDate.getFullYear()).toEqual(2018);
282+
expect(yearBtn.nativeElement.textContent.trim()).toMatch('2018');
270283

271-
UIInteractions.triggerKeyDownEvtUponElem('ArrowLeft', yearBtn.nativeElement);
284+
UIInteractions.triggerKeyDownEvtUponElem('ArrowRight', yearBtn.nativeElement);
272285
fixture.detectChanges();
286+
flush();
273287

274-
expect(monthPicker.viewDate.getFullYear()).toEqual(2021);
275-
expect(yearBtn.nativeElement.textContent.trim()).toMatch('2021');
276-
});
288+
expect(monthPicker.viewDate.getFullYear()).toEqual(2019);
289+
expect(yearBtn.nativeElement.textContent.trim()).toMatch('2019');
290+
}));
277291

278292
it('should not emit onSelection when navigating to the next year', () => {
279293
const fixture = TestBed.createComponent(IgxMonthPickerSampleComponent);

projects/igniteui-angular/src/lib/calendar/month-picker/month-picker.component.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ export class IgxMonthPickerComponent extends IgxMonthPickerBaseDirective {
139139
public changeYearKB(event, next = true) {
140140
if (event.key === KEYS.SPACE || event.key === KEYS.SPACE_IE || event.key === KEYS.ENTER) {
141141
event.stopPropagation();
142-
next ? this.nextYear(event) : this.previousYear(event);
142+
next ? this.nextYear() : this.previousYear();
143143
}
144144
}
145145

@@ -173,8 +173,6 @@ export class IgxMonthPickerComponent extends IgxMonthPickerBaseDirective {
173173
if (!value) {
174174
return new Date();
175175
}
176-
177-
// TO DO: to be refactored after discussion on the desired behavior
178176
super.selectDate(value);
179177
this.viewDate = value;
180178
}
@@ -183,8 +181,6 @@ export class IgxMonthPickerComponent extends IgxMonthPickerBaseDirective {
183181
* @hidden
184182
*/
185183
public writeValue(value: Date) {
186-
187-
// TO DO: to be refactored after discussion on the desired behavior
188184
if (value) {
189185
this.viewDate = this.selectedDates = value;
190186
}
@@ -196,6 +192,7 @@ export class IgxMonthPickerComponent extends IgxMonthPickerBaseDirective {
196192
@HostListener('keydown.pageup', ['$event'])
197193
public previousYear(event?: KeyboardEvent) {
198194
event?.preventDefault();
195+
if (event && this.yearAction === 'next') { return; }
199196
this.yearAction = 'prev';
200197
this.viewDate = this.calendarModel.getPrevYear(this.viewDate);
201198
}
@@ -206,6 +203,7 @@ export class IgxMonthPickerComponent extends IgxMonthPickerBaseDirective {
206203
@HostListener('keydown.pagedown', ['$event'])
207204
public nextYear(event?: KeyboardEvent) {
208205
event?.preventDefault();
206+
if (event && this.yearAction === 'prev') { return; }
209207
this.yearAction = 'next';
210208
this.viewDate = this.calendarModel.getNextYear(this.viewDate);
211209
}

projects/igniteui-angular/src/lib/date-picker/date-picker.component.spec.ts

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { Component, ViewChild, ElementRef, EventEmitter, QueryList } from '@angular/core';
2-
import { async, fakeAsync, TestBed, tick, flush, ComponentFixture } from '@angular/core/testing';
1+
import { Component, ViewChild, ElementRef, EventEmitter, QueryList, Renderer2, DebugElement } from '@angular/core';
2+
import { fakeAsync, TestBed, tick, flush, ComponentFixture, async } from '@angular/core/testing';
33
import { FormsModule, FormGroup, FormBuilder, ReactiveFormsModule, Validators, NgControl } from '@angular/forms';
44
import { By } from '@angular/platform-browser';
55
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
@@ -280,6 +280,43 @@ describe('IgxDatePicker', () => {
280280

281281
});
282282

283+
describe('ARIA Tests', () => {
284+
let labelID: string;
285+
let inputLabelledBy: string;
286+
let dom: DebugElement;
287+
288+
it('ARIA Test for a picker with an input group template', () => {
289+
const fixture = TestBed.createComponent(IgxDatePickerRetemplatedComponent);
290+
fixture.detectChanges();
291+
dom = fixture.debugElement;
292+
293+
labelID = dom.query(By.directive(IgxLabelDirective)).nativeElement.id;
294+
inputLabelledBy = dom.query(By.directive(IgxInputDirective)).nativeElement.getAttribute('aria-labelledby');
295+
expect(inputLabelledBy).toEqual(labelID);
296+
});
297+
298+
it('ARIA Test for picker with a dialog mode', () => {
299+
const fixture = TestBed.createComponent(IgxDatePickerTestComponent);
300+
fixture.detectChanges();
301+
dom = fixture.debugElement;
302+
303+
labelID = dom.query(By.directive(IgxLabelDirective)).nativeElement.id;
304+
inputLabelledBy = dom.query(By.directive(IgxInputDirective)).nativeElement.getAttribute('aria-labelledby');
305+
expect(inputLabelledBy).toEqual(labelID);
306+
});
307+
308+
309+
it('ARIA Test for picker with a dropdown mode', () => {
310+
const fixture = TestBed.createComponent(IgxDatePickerOpeningComponent);
311+
fixture.detectChanges();
312+
dom = fixture.debugElement;
313+
314+
labelID = dom.query(By.directive(IgxLabelDirective)).nativeElement.id;
315+
inputLabelledBy = dom.query(By.directive(IgxInputDirective)).nativeElement.getAttribute('aria-labelledby');
316+
expect(inputLabelledBy).toEqual(labelID);
317+
});
318+
});
319+
283320
describe('DatePicker with passed date', () => {
284321
// configureTestSuite();
285322
let fixture: ComponentFixture<IgxDatePickerWithPassedDateComponent>;
@@ -1416,6 +1453,7 @@ describe('IgxDatePicker', () => {
14161453
let moduleRef;
14171454
let injector;
14181455
let inputGroup: IgxInputGroupComponent;
1456+
let renderer2: Renderer2;
14191457

14201458
beforeEach(() => {
14211459
ngModel = {
@@ -1438,11 +1476,14 @@ describe('IgxDatePicker', () => {
14381476
};
14391477
moduleRef = {};
14401478
injector = { get: () => ngModel };
1479+
14411480
inputGroup = new IgxInputGroupComponent(null, null);
1481+
renderer2 = jasmine.createSpyObj('Renderer2', ['setAttribute'], [{}, 'aria-labelledby', 'test-label-id-1']);
1482+
spyOn(renderer2, 'setAttribute').and.callFake(() => {});
14421483
});
14431484

14441485
it('should initialize date picker with required correctly', () => {
1445-
const datePicker = new IgxDatePickerComponent(overlay, element, cdr, moduleRef, injector);
1486+
const datePicker = new IgxDatePickerComponent(overlay, element, cdr, moduleRef, injector, renderer2);
14461487
datePicker['_inputGroup'] = inputGroup;
14471488
datePicker['_inputDirectiveUserTemplates'] = new QueryList();
14481489
ngModel.control.validator = () => ({ required: true });
@@ -1455,7 +1496,7 @@ describe('IgxDatePicker', () => {
14551496
});
14561497

14571498
it('should initialize date picker with required correctly with user template input-group', () => {
1458-
const datePicker = new IgxDatePickerComponent(overlay, element, cdr, moduleRef, injector);
1499+
const datePicker = new IgxDatePickerComponent(overlay, element, cdr, moduleRef, injector, renderer2);
14591500
datePicker['_inputGroupUserTemplate'] = inputGroup;
14601501
datePicker['_inputDirectiveUserTemplates'] = new QueryList();
14611502
ngModel.control.validator = () => ({ required: true });
@@ -1468,7 +1509,7 @@ describe('IgxDatePicker', () => {
14681509
});
14691510

14701511
it('should update inputGroup isRequired correctly', () => {
1471-
const datePicker = new IgxDatePickerComponent(overlay, element, cdr, moduleRef, injector);
1512+
const datePicker = new IgxDatePickerComponent(overlay, element, cdr, moduleRef, injector, renderer2);
14721513
datePicker['_inputGroup'] = inputGroup;
14731514
datePicker['_inputDirectiveUserTemplates'] = new QueryList();
14741515
datePicker.ngOnInit();
@@ -1565,14 +1606,16 @@ export class IgxDatePickerNgModelComponent {
15651606
<igx-date-picker>
15661607
<ng-template igxDatePickerTemplate let-displayData="displayData">
15671608
<igx-input-group>
1568-
<label igxLabel>Date</label>
1609+
<label igxLabel>Custom Date Label</label>
15691610
<input igxInput [value]="displayData" required />
15701611
</igx-input-group>
15711612
</ng-template>
15721613
</igx-date-picker>
15731614
`
15741615
})
1575-
export class IgxDatePickerRetemplatedComponent { }
1616+
export class IgxDatePickerRetemplatedComponent {
1617+
@ViewChild(IgxDatePickerComponent, { static: true }) public datePicker: IgxDatePickerComponent;
1618+
}
15761619

15771620
@Component({
15781621
template: `

0 commit comments

Comments
 (0)