diff --git a/e2e-app/src/app/app.module.ts b/e2e-app/src/app/app.module.ts index cf0393d92d..a6bf2b9d27 100644 --- a/e2e-app/src/app/app.module.ts +++ b/e2e-app/src/app/app.module.ts @@ -10,6 +10,7 @@ import {NavigationComponent} from './navigation.component'; import {DatepickerAutoCloseComponent} from './datepicker/autoclose/datepicker-autoclose.component'; import {DatepickerFocusComponent} from './datepicker/focus/datepicker-focus.component'; +import {DatepickerMultipleComponent} from './datepicker/multiple/datepicker-multiple.component'; import {DropdownAutoCloseComponent} from './dropdown/autoclose/dropdown-autoclose.component'; import {DropdownFocusComponent} from './dropdown/focus/dropdown-focus.component'; import {DropdownPositionComponent} from './dropdown/position/dropdown-position.component'; @@ -35,6 +36,7 @@ import {TypeaheadValidationComponent} from './typeahead/validation/typeahead-val NavigationComponent, DatepickerAutoCloseComponent, DatepickerFocusComponent, + DatepickerMultipleComponent, DropdownAutoCloseComponent, DropdownFocusComponent, DropdownPositionComponent, diff --git a/e2e-app/src/app/app.routing.ts b/e2e-app/src/app/app.routing.ts index f5546eba64..6d867fc8a3 100644 --- a/e2e-app/src/app/app.routing.ts +++ b/e2e-app/src/app/app.routing.ts @@ -3,6 +3,7 @@ import {RouterModule, Routes} from '@angular/router'; import {DatepickerAutoCloseComponent} from './datepicker/autoclose/datepicker-autoclose.component'; import {DatepickerFocusComponent} from './datepicker/focus/datepicker-focus.component'; +import {DatepickerMultipleComponent} from './datepicker/multiple/datepicker-multiple.component'; import {DropdownAutoCloseComponent} from './dropdown/autoclose/dropdown-autoclose.component'; import {DropdownFocusComponent} from './dropdown/focus/dropdown-focus.component'; import {DropdownPositionComponent} from './dropdown/position/dropdown-position.component'; @@ -27,7 +28,8 @@ export const routes: Routes = [ path: 'datepicker', children: [ {path: 'focus', component: DatepickerFocusComponent}, - {path: 'autoclose', component: DatepickerAutoCloseComponent} + {path: 'autoclose', component: DatepickerAutoCloseComponent}, + {path: 'multiple', component: DatepickerMultipleComponent} ] }, { diff --git a/e2e-app/src/app/datepicker/datepicker.po.ts b/e2e-app/src/app/datepicker/datepicker.po.ts index e9d48b86f8..e9cc35bf5e 100644 --- a/e2e-app/src/app/datepicker/datepicker.po.ts +++ b/e2e-app/src/app/datepicker/datepicker.po.ts @@ -1,4 +1,4 @@ -import {$} from 'protractor'; +import {$, $$} from 'protractor'; export class DatepickerPage { getDatepicker(selector = 'ngb-datepicker') { return $(selector); } @@ -7,9 +7,9 @@ export class DatepickerPage { getToggle() { return $('#toggle'); } - getDayElement(date: Date) { + getDayElement(date: Date, index = 0) { const ariaLabel = date.toLocaleString('en', {weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'}); - return this.getDatepicker().$(`div.ngb-dp-day[aria-label="${ariaLabel}"]`); + return $$('ngb-datepicker').get(index).$(`div.ngb-dp-day[aria-label="${ariaLabel}"]`); } getWeekdayElements() { return this.getDatepicker().$$('div.ngb-dp-weekday'); } diff --git a/e2e-app/src/app/datepicker/multiple/datepicker-multiple.component.html b/e2e-app/src/app/datepicker/multiple/datepicker-multiple.component.html new file mode 100644 index 0000000000..9ec3f7ee7c --- /dev/null +++ b/e2e-app/src/app/datepicker/multiple/datepicker-multiple.component.html @@ -0,0 +1,14 @@ +

Datepicker focus tests

+ +
+
+ + + + startDate is + {{ startDate | json }} + + +
+ +
diff --git a/e2e-app/src/app/datepicker/multiple/datepicker-multiple.component.ts b/e2e-app/src/app/datepicker/multiple/datepicker-multiple.component.ts new file mode 100644 index 0000000000..4d9a098d6c --- /dev/null +++ b/e2e-app/src/app/datepicker/multiple/datepicker-multiple.component.ts @@ -0,0 +1,6 @@ +import {Component} from '@angular/core'; + +@Component({templateUrl: './datepicker-multiple.component.html'}) +export class DatepickerMultipleComponent { + startDate = {year: 2016, month: 8}; +} diff --git a/e2e-app/src/app/datepicker/multiple/datepicker-multiple.e2e-spec.ts b/e2e-app/src/app/datepicker/multiple/datepicker-multiple.e2e-spec.ts new file mode 100644 index 0000000000..608457c193 --- /dev/null +++ b/e2e-app/src/app/datepicker/multiple/datepicker-multiple.e2e-spec.ts @@ -0,0 +1,20 @@ +import {Key} from 'protractor'; +import {sendKey, openUrl} from '../../tools.po'; +import {DatepickerMultiplePage} from './datepicker-multiple.po'; + +describe('Datepicker', () => { + let page: DatepickerMultiplePage; + + beforeAll(() => page = new DatepickerMultiplePage()); + + beforeEach(async() => await openUrl('datepicker/multiple')); + + it('should lose focus on tapping on a different datepicker instance', async() => { + await page.getDayElement(new Date(2016, 7, 1), 0).click(); + await sendKey(Key.ARROW_DOWN); + await page.expectActive(new Date(2016, 7, 8), 0); + await page.getDayElement(new Date(2016, 7, 1), 1).click(); + await sendKey(Key.ARROW_DOWN); + await page.expectActive(new Date(2016, 7, 8), 1); + }); +}); diff --git a/e2e-app/src/app/datepicker/multiple/datepicker-multiple.po.ts b/e2e-app/src/app/datepicker/multiple/datepicker-multiple.po.ts new file mode 100644 index 0000000000..768402272f --- /dev/null +++ b/e2e-app/src/app/datepicker/multiple/datepicker-multiple.po.ts @@ -0,0 +1,8 @@ +import {DatepickerPage} from './../datepicker.po'; + +export class DatepickerMultiplePage extends DatepickerPage { + async expectActive(date: Date, index: number) { + const dateElement = this.getDayElement(date, index); + expect(await dateElement.$('.active').isPresent()).toBeTruthy(`The date should be active`); + } +} diff --git a/src/datepicker/datepicker.ts b/src/datepicker/datepicker.ts index c3336c7957..116cf9ccfd 100644 --- a/src/datepicker/datepicker.ts +++ b/src/datepicker/datepicker.ts @@ -397,6 +397,7 @@ export class NgbDatepicker implements OnDestroy, this._ngZone.runOutsideAngular(() => { const focusIns$ = fromEvent(this._monthsEl.nativeElement, 'focusin'); const focusOuts$ = fromEvent(this._monthsEl.nativeElement, 'focusout'); + const {nativeElement} = this._elementRef; // we're changing 'focusVisible' only when entering or leaving months view // and ignoring all focus events where both 'target' and 'related' target are day cells @@ -404,7 +405,8 @@ export class NgbDatepicker implements OnDestroy, .pipe( filter( ({target, relatedTarget}) => - !(hasClassName(target, 'ngb-dp-day') && hasClassName(relatedTarget, 'ngb-dp-day'))), + !(hasClassName(target, 'ngb-dp-day') && hasClassName(relatedTarget, 'ngb-dp-day') && + nativeElement.contains(target as Node) && nativeElement.contains(relatedTarget as Node))), takeUntil(this._destroyed$)) .subscribe(({type}) => this._ngZone.run(() => this._service.focusVisible = type === 'focusin')); });