From 25df51a5834d089192fb40cab5c9160ad3e9e52e Mon Sep 17 00:00:00 2001 From: Basso Date: Fri, 15 Nov 2019 14:29:27 +0100 Subject: [PATCH] feat(timepicker): input filter to accept only numbers (#3247) fixes #2334 --- e2e-app/src/app/app.module.ts | 2 + e2e-app/src/app/app.routing.ts | 2 + .../filter/timepicker-filter.component.html | 4 ++ .../filter/timepicker-filter.component.ts | 8 +++ .../filter/timepicker-filter.e2e-spec.ts | 69 +++++++++++++++++++ .../timepicker/filter/timepicker-filter.po.ts | 8 +++ src/timepicker/timepicker.ts | 16 +++-- 7 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 e2e-app/src/app/timepicker/filter/timepicker-filter.component.html create mode 100644 e2e-app/src/app/timepicker/filter/timepicker-filter.component.ts create mode 100644 e2e-app/src/app/timepicker/filter/timepicker-filter.e2e-spec.ts create mode 100644 e2e-app/src/app/timepicker/filter/timepicker-filter.po.ts diff --git a/e2e-app/src/app/app.module.ts b/e2e-app/src/app/app.module.ts index 2b08dcc290..5a89e1888b 100644 --- a/e2e-app/src/app/app.module.ts +++ b/e2e-app/src/app/app.module.ts @@ -23,6 +23,7 @@ import {TooltipFocusComponent} from './tooltip/focus/tooltip-focus.component'; import {TooltipPositionComponent} from './tooltip/position/tooltip-position.component'; import {TypeaheadAutoCloseComponent} from './typeahead/autoclose/typeahead-autoclose.component'; import {TypeaheadFocusComponent} from './typeahead/focus/typeahead-focus.component'; +import {TimepickerFilterComponent} from './timepicker/filter/timepicker-filter.component'; import {TimepickerNavigationComponent} from './timepicker/navigation/timepicker-navigation.component'; import {TypeaheadValidationComponent} from './typeahead/validation/typeahead-validation.component'; @@ -47,6 +48,7 @@ import {TypeaheadValidationComponent} from './typeahead/validation/typeahead-val TypeaheadFocusComponent, TypeaheadValidationComponent, TypeaheadAutoCloseComponent, + TimepickerFilterComponent, TimepickerNavigationComponent, ], imports: [BrowserModule, FormsModule, ReactiveFormsModule, routing, NgbModule], diff --git a/e2e-app/src/app/app.routing.ts b/e2e-app/src/app/app.routing.ts index 4a2f46f47d..7308166d4f 100644 --- a/e2e-app/src/app/app.routing.ts +++ b/e2e-app/src/app/app.routing.ts @@ -15,6 +15,7 @@ import {TooltipFocusComponent} from './tooltip/focus/tooltip-focus.component'; import {TooltipPositionComponent} from './tooltip/position/tooltip-position.component'; import {TypeaheadAutoCloseComponent} from './typeahead/autoclose/typeahead-autoclose.component'; import {TypeaheadFocusComponent} from './typeahead/focus/typeahead-focus.component'; +import {TimepickerFilterComponent} from './timepicker/filter/timepicker-filter.component'; import {TimepickerNavigationComponent} from './timepicker/navigation/timepicker-navigation.component'; import {TypeaheadValidationComponent} from './typeahead/validation/typeahead-validation.component'; import {DropdownPositionComponent} from './dropdown/position/dropdown-position.component'; @@ -63,6 +64,7 @@ export const routes: Routes = [ path: 'timepicker', children: [ {path: 'navigation', component: TimepickerNavigationComponent}, + {path: 'filter', component: TimepickerFilterComponent}, ] }, ]; diff --git a/e2e-app/src/app/timepicker/filter/timepicker-filter.component.html b/e2e-app/src/app/timepicker/filter/timepicker-filter.component.html new file mode 100644 index 0000000000..b57cf189d4 --- /dev/null +++ b/e2e-app/src/app/timepicker/filter/timepicker-filter.component.html @@ -0,0 +1,4 @@ + diff --git a/e2e-app/src/app/timepicker/filter/timepicker-filter.component.ts b/e2e-app/src/app/timepicker/filter/timepicker-filter.component.ts new file mode 100644 index 0000000000..0801a0fe7e --- /dev/null +++ b/e2e-app/src/app/timepicker/filter/timepicker-filter.component.ts @@ -0,0 +1,8 @@ +import {Component} from '@angular/core'; + +@Component({ + templateUrl: './timepicker-filter.component.html', +}) +export class TimepickerFilterComponent { + time = {hour: null, minute: null, second: null}; +} diff --git a/e2e-app/src/app/timepicker/filter/timepicker-filter.e2e-spec.ts b/e2e-app/src/app/timepicker/filter/timepicker-filter.e2e-spec.ts new file mode 100644 index 0000000000..7a0f8c64d5 --- /dev/null +++ b/e2e-app/src/app/timepicker/filter/timepicker-filter.e2e-spec.ts @@ -0,0 +1,69 @@ +import {protractor} from 'protractor'; + +import {openUrl} from '../../tools.po'; + +import {TimepickerFilterPage} from './timepicker-filter.po'; + +describe('Timepicker', () => { + let page: TimepickerFilterPage; + + beforeAll(() => page = new TimepickerFilterPage()); + beforeEach(async() => await openUrl('timepicker/filter')); + + async function expectValue(expectedValue) { + const inputs = page.getFields(); + + const values = []; + for (let i = 0; i < inputs.length; i++) { + values[i] = await inputs[i].getAttribute('value'); + } + expect(values.join(':')).toBe(expectedValue); + } + + describe('filter', async() => { + it(`should accept numbers`, async() => { + await expectValue('::'); // No starting values + + const inputs = page.getFields(); + await inputs[0].sendKeys('1'); + await inputs[1].sendKeys('2'); + await inputs[2].sendKeys('3'); + + await inputs[0].click(); + await expectValue('01:02:03'); + }); + + it(`shouldn't accept alpha`, async() => { + await expectValue('::'); // No starting values + + const inputs = page.getFields(); + await inputs[0].sendKeys('A'); + await inputs[1].sendKeys('A'); + await inputs[2].sendKeys('A'); + + await inputs[0].click(); + await expectValue('::'); + }); + + it(`shouldn accept special commands`, async() => { + + const inputs = page.getFields(); + + await inputs[0].sendKeys('1'); + await inputs[0].sendKeys(protractor.Key.chord(protractor.Key.CONTROL, 'a')); + await inputs[0].sendKeys(protractor.Key.chord(protractor.Key.CONTROL, 'c')); + + await inputs[1].click(); + await inputs[1].sendKeys(protractor.Key.chord(protractor.Key.CONTROL, 'v')); + + await inputs[2].click(); + await inputs[2].sendKeys(protractor.Key.chord(protractor.Key.CONTROL, 'v')); + + await inputs[0].click(); + await expectValue('01:01:01'); + + }); + + }); + +}); diff --git a/e2e-app/src/app/timepicker/filter/timepicker-filter.po.ts b/e2e-app/src/app/timepicker/filter/timepicker-filter.po.ts new file mode 100644 index 0000000000..fd3012578a --- /dev/null +++ b/e2e-app/src/app/timepicker/filter/timepicker-filter.po.ts @@ -0,0 +1,8 @@ +import {$} from 'protractor'; + +export type Field = 'hour' | 'minute' | 'second'; + +export class TimepickerFilterPage { + getField(field: Field) { return $(`.ngb-tp-${field} > input`); } + getFields() { return ['hour', 'minute', 'second'].map((field: Field) => this.getField(field)); } +} diff --git a/src/timepicker/timepicker.ts b/src/timepicker/timepicker.ts index 2ff2ccddbf..cb16f875b5 100644 --- a/src/timepicker/timepicker.ts +++ b/src/timepicker/timepicker.ts @@ -15,6 +15,8 @@ import {NgbTimepickerConfig} from './timepicker-config'; import {NgbTimeAdapter} from './ngb-time-adapter'; import {NgbTimepickerI18n} from './timepicker-i18n'; +const FILTER_REGEX = /[^0-9]/g; + const NGB_TIMEPICKER_VALUE_ACCESSOR = { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => NgbTimepicker), @@ -38,10 +40,12 @@ const NGB_TIMEPICKER_VALUE_ACCESSOR = { Increment hours -