From 6ca8ea76c62fddb5d2caca12324273cf1796375e Mon Sep 17 00:00:00 2001 From: Tobias Schweizer Date: Mon, 18 Jun 2018 10:26:43 +0200 Subject: [PATCH 1/4] refactor (mat-calendar): add public method to update today's date --- src/lib/datepicker/calendar.spec.ts | 25 +++++++++++++++++++++++++ src/lib/datepicker/calendar.ts | 8 ++++++++ 2 files changed, 33 insertions(+) diff --git a/src/lib/datepicker/calendar.spec.ts b/src/lib/datepicker/calendar.spec.ts index a5f389c473fc..d6c19113ac44 100644 --- a/src/lib/datepicker/calendar.spec.ts +++ b/src/lib/datepicker/calendar.spec.ts @@ -168,6 +168,31 @@ describe('MatCalendar', () => { expect(activeCell.focus).not.toHaveBeenCalled(); }); + it('should update today\'s date after update of the active date', () => { + + // TODO: How can we actually check that today's date was updated correctly? + // TODO: The test only changes the active date, but not today's date. + // today's date is set by the data adapter's today() method + + const newActiveDate = new Date(); + + // today's date is also the active date + let todaysDay = newActiveDate.getDate(); + + calendarInstance.activeDate = newActiveDate; + fixture.detectChanges(); + + calendarInstance._dateSelected(newActiveDate); + + calendarInstance.updateTodaysDate(); + + let todayCell = calendarBodyEl.querySelector('.mat-calendar-body-today')!; + + expect(todayCell).not.toBeNull(); + expect(todayCell.innerHTML.trim()).toContain(todaysDay.toString()); + + }); + it('should move focus to the active cell when the view changes', () => { const activeCell = calendarBodyEl.querySelector('.mat-calendar-body-active')! as HTMLElement; diff --git a/src/lib/datepicker/calendar.ts b/src/lib/datepicker/calendar.ts index a1215d3ec4d0..a4b95e0531fc 100644 --- a/src/lib/datepicker/calendar.ts +++ b/src/lib/datepicker/calendar.ts @@ -331,6 +331,14 @@ export class MatCalendar implements AfterContentInit, AfterViewChecked, OnDes this._getCurrentViewComponent()._focusActiveCell(); } + /** Updates today's date after an update of the active date */ + updateTodaysDate() { + let view = this.currentView == 'month' ? this.monthView : + (this.currentView == 'year' ? this.yearView : this.multiYearView); + + view.ngAfterContentInit(); + } + /** Handles date selection in the month view. */ _dateSelected(date: D): void { if (!this._dateAdapter.sameDate(date, this.selected)) { From 5e07c6fe2c7b8ee2392d163c6aceed2b69c841e4 Mon Sep 17 00:00:00 2001 From: Tobias Schweizer Date: Tue, 17 Jul 2018 22:17:51 +0200 Subject: [PATCH 2/4] tests (MatCalendar): update today's date --- src/lib/datepicker/calendar.spec.ts | 36 ++++++++++++++------------- src/lib/datepicker/calendar.ts | 3 +++ src/lib/datepicker/datepicker.spec.ts | 14 +++++++++++ src/lib/datepicker/datepicker.ts | 5 ++++ 4 files changed, 41 insertions(+), 17 deletions(-) diff --git a/src/lib/datepicker/calendar.spec.ts b/src/lib/datepicker/calendar.spec.ts index f13225c4f870..b6e4b3208cd7 100644 --- a/src/lib/datepicker/calendar.spec.ts +++ b/src/lib/datepicker/calendar.spec.ts @@ -10,7 +10,9 @@ import { } from '@angular/cdk/testing'; import {Component, NgZone} from '@angular/core'; import {ComponentFixture, TestBed, async, inject} from '@angular/core/testing'; -import {DEC, FEB, JAN, MatNativeDateModule, NOV, JUL} from '@angular/material/core'; +import { + DEC, FEB, JAN, MatNativeDateModule, NOV, JUL, NativeDateAdapter +} from '@angular/material/core'; import {By} from '@angular/platform-browser'; import {Direction, Directionality} from '@angular/cdk/bidi'; import {MatCalendar} from './calendar'; @@ -36,6 +38,7 @@ describe('MatCalendar', () => { ], providers: [ MatDatepickerIntl, + NativeDateAdapter, {provide: NgZone, useFactory: () => zone = new MockNgZone()}, {provide: Directionality, useFactory: () => dir = {value: 'ltr'}} ], @@ -169,30 +172,29 @@ describe('MatCalendar', () => { expect(activeCell.focus).not.toHaveBeenCalled(); }); - it('should update today\'s date after update of the active date', () => { - - // TODO: How can we actually check that today's date was updated correctly? - // TODO: The test only changes the active date, but not today's date. - // today's date is set by the data adapter's today() method + it('should update today\'s date after update of the active date', + inject([NativeDateAdapter], (adapter: NativeDateAdapter) => { - const newActiveDate = new Date(); + spyOn(adapter, 'today').and.callFake(() => { + return new Date(2018, 11, 24, 10, 33, 30, 0); + }); - // today's date is also the active date - let todaysDay = newActiveDate.getDate(); + // fake today: December 24th 2018 + let fakeToday: Date = adapter.today(); - calendarInstance.activeDate = newActiveDate; - fixture.detectChanges(); + calendarInstance.activeDate = fakeToday; + fixture.detectChanges(); - calendarInstance._dateSelected(newActiveDate); + calendarInstance.updateTodaysDate(); - calendarInstance.updateTodaysDate(); + let todayCell = calendarBodyEl.querySelector('.mat-calendar-body-today')!; - let todayCell = calendarBodyEl.querySelector('.mat-calendar-body-today')!; + console.log(todayCell); - expect(todayCell).not.toBeNull(); - expect(todayCell.innerHTML.trim()).toContain(todaysDay.toString()); + expect(todayCell).not.toBeNull(); + expect(todayCell.innerHTML.trim()).toContain(fakeToday.getDate().toString()); - }); + })); it('should move focus to the active cell when the view changes', () => { const activeCell = diff --git a/src/lib/datepicker/calendar.ts b/src/lib/datepicker/calendar.ts index 9eaa9dfe9243..ebcd754aaa8f 100644 --- a/src/lib/datepicker/calendar.ts +++ b/src/lib/datepicker/calendar.ts @@ -340,6 +340,9 @@ export class MatCalendar implements AfterContentInit, AfterViewChecked, OnDes (this.currentView == 'year' ? this.yearView : this.multiYearView); view.ngAfterContentInit(); + + // to be removed once test works + console.log(view._dateAdapter.today()); } /** Handles date selection in the month view. */ diff --git a/src/lib/datepicker/datepicker.spec.ts b/src/lib/datepicker/datepicker.spec.ts index d72646bb1c40..9589f494bba2 100644 --- a/src/lib/datepicker/datepicker.spec.ts +++ b/src/lib/datepicker/datepicker.spec.ts @@ -632,6 +632,20 @@ describe('MatDatepicker', () => { expect(testComponent.datepickerInput.value).toEqual(selected); })); + it('should update model when date is selected using the public method', fakeAsync(() => { + expect(testComponent.selected).toBeNull(); + expect(testComponent.datepickerInput.value).toBeNull(); + + let selected = new Date(2017, JAN, 1); + testComponent.datepicker.select(selected); + fixture.detectChanges(); + flush(); + fixture.detectChanges(); + + expect(testComponent.selected).toEqual(selected); + expect(testComponent.datepickerInput.value).toEqual(selected); + })); + it('should mark input dirty after input event', () => { let inputEl = fixture.debugElement.query(By.css('input')).nativeElement; diff --git a/src/lib/datepicker/datepicker.ts b/src/lib/datepicker/datepicker.ts index 3ea51260165e..59056dec3b4e 100644 --- a/src/lib/datepicker/datepicker.ts +++ b/src/lib/datepicker/datepicker.ts @@ -289,6 +289,11 @@ export class MatDatepicker implements OnDestroy, CanColor { } } + /** Public method to select a date in the Datepicker */ + select(date: D): void { + this._select(date); + } + /** Selects the given date */ _select(date: D): void { let oldValue = this._selected; From 9ecea9693511cdae647697e05d7374b907540141 Mon Sep 17 00:00:00 2001 From: Miles Malerba Date: Tue, 17 Jul 2018 15:47:41 -0700 Subject: [PATCH 3/4] fix test --- src/lib/datepicker/calendar.spec.ts | 59 ++++++++++++----------------- 1 file changed, 25 insertions(+), 34 deletions(-) diff --git a/src/lib/datepicker/calendar.spec.ts b/src/lib/datepicker/calendar.spec.ts index b6e4b3208cd7..cc73039801ae 100644 --- a/src/lib/datepicker/calendar.spec.ts +++ b/src/lib/datepicker/calendar.spec.ts @@ -1,7 +1,5 @@ -import { - ENTER, - RIGHT_ARROW, -} from '@angular/cdk/keycodes'; +import {Direction, Directionality} from '@angular/cdk/bidi'; +import {ENTER, RIGHT_ARROW,} from '@angular/cdk/keycodes'; import { dispatchFakeEvent, dispatchKeyboardEvent, @@ -9,12 +7,9 @@ import { MockNgZone, } from '@angular/cdk/testing'; import {Component, NgZone} from '@angular/core'; -import {ComponentFixture, TestBed, async, inject} from '@angular/core/testing'; -import { - DEC, FEB, JAN, MatNativeDateModule, NOV, JUL, NativeDateAdapter -} from '@angular/material/core'; +import {async, ComponentFixture, inject, TestBed} from '@angular/core/testing'; +import {DateAdapter, DEC, FEB, JAN, JUL, MatNativeDateModule, NOV} from '@angular/material/core'; import {By} from '@angular/platform-browser'; -import {Direction, Directionality} from '@angular/cdk/bidi'; import {MatCalendar} from './calendar'; import {MatDatepickerIntl} from './datepicker-intl'; import {MatDatepickerModule} from './datepicker-module'; @@ -38,7 +33,6 @@ describe('MatCalendar', () => { ], providers: [ MatDatepickerIntl, - NativeDateAdapter, {provide: NgZone, useFactory: () => zone = new MockNgZone()}, {provide: Directionality, useFactory: () => dir = {value: 'ltr'}} ], @@ -66,6 +60,27 @@ describe('MatCalendar', () => { testComponent = fixture.componentInstance; }); + it(`should update today's date`, inject([DateAdapter], (adapter: DateAdapter) => { + let fakeToday = new Date(2018, 0, 1); + spyOn(adapter, 'today').and.callFake(() => fakeToday); + + calendarInstance.activeDate = fakeToday; + calendarInstance.updateTodaysDate(); + fixture.detectChanges(); + + let todayCell = calendarElement.querySelector('.mat-calendar-body-today')!; + expect(todayCell).not.toBeNull(); + expect(todayCell.innerHTML.trim()).toBe('1'); + + fakeToday = new Date(2018, 0, 10); + calendarInstance.updateTodaysDate(); + fixture.detectChanges(); + + todayCell = calendarElement.querySelector('.mat-calendar-body-today')!; + expect(todayCell).not.toBeNull(); + expect(todayCell.innerHTML.trim()).toBe('10'); + })); + it('should be in month view with specified month active', () => { expect(calendarInstance.currentView).toBe('month'); expect(calendarInstance.activeDate).toEqual(new Date(2017, JAN, 31)); @@ -172,30 +187,6 @@ describe('MatCalendar', () => { expect(activeCell.focus).not.toHaveBeenCalled(); }); - it('should update today\'s date after update of the active date', - inject([NativeDateAdapter], (adapter: NativeDateAdapter) => { - - spyOn(adapter, 'today').and.callFake(() => { - return new Date(2018, 11, 24, 10, 33, 30, 0); - }); - - // fake today: December 24th 2018 - let fakeToday: Date = adapter.today(); - - calendarInstance.activeDate = fakeToday; - fixture.detectChanges(); - - calendarInstance.updateTodaysDate(); - - let todayCell = calendarBodyEl.querySelector('.mat-calendar-body-today')!; - - console.log(todayCell); - - expect(todayCell).not.toBeNull(); - expect(todayCell.innerHTML.trim()).toContain(fakeToday.getDate().toString()); - - })); - it('should move focus to the active cell when the view changes', () => { const activeCell = calendarBodyEl.querySelector('.mat-calendar-body-active')! as HTMLElement; From cb84cbe9c2fc5a02da3ba045ec1d91d4afef55e8 Mon Sep 17 00:00:00 2001 From: Tobias Schweizer Date: Wed, 18 Jul 2018 09:15:34 +0200 Subject: [PATCH 4/4] refactor (MatDatepicker): make select a public method --- src/lib/datepicker/calendar.spec.ts | 2 +- src/lib/datepicker/calendar.ts | 3 --- src/lib/datepicker/datepicker-content.html | 2 +- src/lib/datepicker/datepicker.spec.ts | 20 +++----------------- src/lib/datepicker/datepicker.ts | 7 +------ 5 files changed, 6 insertions(+), 28 deletions(-) diff --git a/src/lib/datepicker/calendar.spec.ts b/src/lib/datepicker/calendar.spec.ts index cc73039801ae..927e9159ba46 100644 --- a/src/lib/datepicker/calendar.spec.ts +++ b/src/lib/datepicker/calendar.spec.ts @@ -1,5 +1,5 @@ import {Direction, Directionality} from '@angular/cdk/bidi'; -import {ENTER, RIGHT_ARROW,} from '@angular/cdk/keycodes'; +import {ENTER, RIGHT_ARROW} from '@angular/cdk/keycodes'; import { dispatchFakeEvent, dispatchKeyboardEvent, diff --git a/src/lib/datepicker/calendar.ts b/src/lib/datepicker/calendar.ts index ebcd754aaa8f..9eaa9dfe9243 100644 --- a/src/lib/datepicker/calendar.ts +++ b/src/lib/datepicker/calendar.ts @@ -340,9 +340,6 @@ export class MatCalendar implements AfterContentInit, AfterViewChecked, OnDes (this.currentView == 'year' ? this.yearView : this.multiYearView); view.ngAfterContentInit(); - - // to be removed once test works - console.log(view._dateAdapter.today()); } /** Handles date selection in the month view. */ diff --git a/src/lib/datepicker/datepicker-content.html b/src/lib/datepicker/datepicker-content.html index ea90dbc71087..7284d499d929 100644 --- a/src/lib/datepicker/datepicker-content.html +++ b/src/lib/datepicker/datepicker-content.html @@ -9,7 +9,7 @@ [headerComponent]="datepicker.calendarHeaderComponent" [selected]="datepicker._selected" [@fadeInCalendar]="'enter'" - (selectedChange)="datepicker._select($event)" + (selectedChange)="datepicker.select($event)" (yearSelected)="datepicker._selectYear($event)" (monthSelected)="datepicker._selectMonth($event)" (_userSelection)="datepicker.close()"> diff --git a/src/lib/datepicker/datepicker.spec.ts b/src/lib/datepicker/datepicker.spec.ts index 9589f494bba2..1e8b264b0edf 100644 --- a/src/lib/datepicker/datepicker.spec.ts +++ b/src/lib/datepicker/datepicker.spec.ts @@ -622,20 +622,6 @@ describe('MatDatepicker', () => { expect(testComponent.selected).toBeNull(); expect(testComponent.datepickerInput.value).toBeNull(); - let selected = new Date(2017, JAN, 1); - testComponent.datepicker._select(selected); - fixture.detectChanges(); - flush(); - fixture.detectChanges(); - - expect(testComponent.selected).toEqual(selected); - expect(testComponent.datepickerInput.value).toEqual(selected); - })); - - it('should update model when date is selected using the public method', fakeAsync(() => { - expect(testComponent.selected).toBeNull(); - expect(testComponent.datepickerInput.value).toBeNull(); - let selected = new Date(2017, JAN, 1); testComponent.datepicker.select(selected); fixture.detectChanges(); @@ -663,7 +649,7 @@ describe('MatDatepicker', () => { expect(inputEl.classList).toContain('ng-pristine'); - testComponent.datepicker._select(new Date(2017, JAN, 1)); + testComponent.datepicker.select(new Date(2017, JAN, 1)); fixture.detectChanges(); flush(); fixture.detectChanges(); @@ -737,7 +723,7 @@ describe('MatDatepicker', () => { expect(inputEl.classList).toContain('ng-untouched'); - testComponent.datepicker._select(new Date(2017, JAN, 1)); + testComponent.datepicker.select(new Date(2017, JAN, 1)); fixture.detectChanges(); flush(); fixture.detectChanges(); @@ -779,7 +765,7 @@ describe('MatDatepicker', () => { expect(testComponent.datepickerInput.value).toBeNull(); let selected = new Date(2017, JAN, 1); - testComponent.datepicker._select(selected); + testComponent.datepicker.select(selected); fixture.detectChanges(); expect(testComponent.formControl.value).toEqual(selected); diff --git a/src/lib/datepicker/datepicker.ts b/src/lib/datepicker/datepicker.ts index 59056dec3b4e..563d83295ed3 100644 --- a/src/lib/datepicker/datepicker.ts +++ b/src/lib/datepicker/datepicker.ts @@ -289,13 +289,8 @@ export class MatDatepicker implements OnDestroy, CanColor { } } - /** Public method to select a date in the Datepicker */ - select(date: D): void { - this._select(date); - } - /** Selects the given date */ - _select(date: D): void { + select(date: D): void { let oldValue = this._selected; this._selected = date; if (!this._dateAdapter.sameDate(oldValue, this._selected)) {