|
1 | | -import { Component, ViewChild, ElementRef } from '@angular/core'; |
| 1 | +import { Component, ViewChild, ElementRef, EventEmitter } from '@angular/core'; |
2 | 2 | import { async, fakeAsync, TestBed, tick, flush, ComponentFixture } from '@angular/core/testing'; |
3 | | -import { FormsModule, FormGroup, FormBuilder, FormControl, ReactiveFormsModule } from '@angular/forms'; |
| 3 | +import { FormsModule, FormGroup, FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; |
4 | 4 | import { By } from '@angular/platform-browser'; |
5 | 5 | import { NoopAnimationsModule } from '@angular/platform-browser/animations'; |
6 | 6 | import { IgxDatePickerComponent, IgxDatePickerModule } from './date-picker.component'; |
7 | 7 | import { IgxLabelDirective } from '../directives/label/label.directive'; |
8 | | -import { IgxInputDirective } from '../directives/input/input.directive'; |
| 8 | +import { IgxInputDirective, IgxInputState } from '../directives/input/input.directive'; |
9 | 9 | import { UIInteractions, wait } from '../test-utils/ui-interactions.spec'; |
10 | | -import { IgxInputGroupModule } from '../input-group'; |
| 10 | +import { IgxInputGroupModule, IgxInputGroupComponent } from '../input-group'; |
11 | 11 | import { IgxTextSelectionModule } from '../directives/text-selection/text-selection.directive'; |
12 | 12 | import { configureTestSuite } from '../test-utils/configure-suite'; |
13 | 13 | import { IgxButtonModule } from '../directives/button/button.directive'; |
14 | 14 | import { IgxCalendarModule } from '../calendar'; |
15 | 15 | import { InteractionMode } from '../core/enums'; |
16 | 16 | import { DateRangeType } from '../core/dates/dateRange'; |
| 17 | +import { OverlayCancelableEventArgs, OverlayEventArgs, OverlayClosingEventArgs, HorizontalAlignment, VerticalAlignment } from '../services'; |
17 | 18 |
|
18 | 19 | describe('IgxDatePicker', () => { |
19 | 20 | configureTestSuite(); |
@@ -1260,38 +1261,133 @@ describe('IgxDatePicker', () => { |
1260 | 1261 |
|
1261 | 1262 | describe('Reactive form', () => { |
1262 | 1263 | let fixture: ComponentFixture<IgxDatePickerReactiveFormComponent>; |
1263 | | - let datePicker: IgxDatePickerComponent; |
| 1264 | + let datePickerOnChangeComponent: IgxDatePickerComponent; |
| 1265 | + let datePickerOnBlurComponent: IgxDatePickerComponent; |
1264 | 1266 |
|
1265 | 1267 | beforeEach(() => { |
1266 | 1268 | fixture = TestBed.createComponent(IgxDatePickerReactiveFormComponent); |
1267 | | - datePicker = fixture.componentInstance.datePicker; |
| 1269 | + datePickerOnChangeComponent = fixture.componentInstance.datePickerOnChangeComponent; |
| 1270 | + datePickerOnBlurComponent = fixture.componentInstance.datePickerOnBlurComponent; |
1268 | 1271 | fixture.detectChanges(); |
1269 | 1272 | }); |
1270 | 1273 |
|
1271 | | - // Bug #6025 Date picker does not disable in reactive form |
1272 | | - it('Should disable when form is disabled', fakeAsync(() => { |
| 1274 | + it('Should set date picker status to invalid when it is required and has no value', fakeAsync(() => { |
| 1275 | + const inputGroupsElements = fixture.debugElement.queryAll(By.directive(IgxInputDirective)); |
| 1276 | + const inputGroupElement = inputGroupsElements.find(d => d.componentInstance === datePickerOnChangeComponent); |
| 1277 | + const inputDirective = inputGroupElement.injector.get(IgxInputDirective) as IgxInputDirective; |
| 1278 | + |
| 1279 | + expect(inputDirective.valid).toEqual(IgxInputState.INITIAL); |
| 1280 | + |
| 1281 | + datePickerOnChangeComponent.value = null; |
1273 | 1282 | fixture.detectChanges(); |
1274 | | - const formGroup: FormGroup = fixture.componentInstance.reactiveForm; |
1275 | | - const inputGroup = fixture.debugElement.query(By.css('.igx-input-group')); |
1276 | 1283 |
|
1277 | | - inputGroup.nativeElement.click(); |
1278 | | - tick(); |
| 1284 | + expect(inputDirective.valid).toEqual(IgxInputState.INVALID); |
| 1285 | + })); |
| 1286 | + |
| 1287 | + it('Should set date picker status to invalid when it is required and has no value onBlur', fakeAsync(() => { |
| 1288 | + datePickerOnBlurComponent.mode = InteractionMode.DropDown; |
| 1289 | + datePickerOnBlurComponent.mask = 'dd/mm/yyyy'; |
| 1290 | + datePickerOnBlurComponent.inputMask = 'dd/mm/yyyy'; |
1279 | 1291 | fixture.detectChanges(); |
1280 | | - expect(datePicker.collapsed).toBeFalsy(); |
1281 | 1292 |
|
1282 | | - datePicker.closeCalendar(); |
| 1293 | + const inputDirectiveElements = fixture.debugElement.queryAll(By.directive(IgxInputDirective)); |
| 1294 | + const inputDirectiveElement = inputDirectiveElements.find(d => d.componentInstance === datePickerOnBlurComponent); |
| 1295 | + const inputDirective = inputDirectiveElement.injector.get(IgxInputDirective) as IgxInputDirective; |
| 1296 | + |
| 1297 | + expect(inputDirective.valid).toEqual(IgxInputState.INITIAL); |
| 1298 | + |
| 1299 | + inputDirectiveElement.triggerEventHandler('focus', {}); |
1283 | 1300 | fixture.detectChanges(); |
1284 | 1301 |
|
1285 | | - formGroup.disable(); |
1286 | | - tick(); |
| 1302 | + expect(inputDirective.valid).toEqual(IgxInputState.INITIAL); |
| 1303 | + |
| 1304 | + datePickerOnBlurComponent.value = null; |
1287 | 1305 | fixture.detectChanges(); |
| 1306 | + expect(inputDirective.valid).toEqual(IgxInputState.INITIAL); |
1288 | 1307 |
|
1289 | | - inputGroup.nativeElement.click(); |
1290 | | - tick(); |
| 1308 | + inputDirectiveElement.triggerEventHandler('blur', { target: { value: ''}}); |
1291 | 1309 | fixture.detectChanges(); |
1292 | | - const dateDropDown = document.getElementsByClassName('igx-date-picker--dropdown'); |
1293 | | - expect(dateDropDown.length).toEqual(0); |
| 1310 | + |
| 1311 | + expect(inputDirective.valid).toEqual(IgxInputState.INVALID); |
1294 | 1312 | })); |
| 1313 | + |
| 1314 | + // Bug #6025 Date picker does not disable in reactive form |
| 1315 | + it('Should disable when form is disabled', () => { |
| 1316 | + const formGroup: FormGroup = fixture.componentInstance.reactiveForm; |
| 1317 | + const inputGroupsElements = fixture.debugElement.queryAll(By.directive(IgxInputDirective)); |
| 1318 | + const inputGroupElement = inputGroupsElements.find(d => d.componentInstance === datePickerOnBlurComponent); |
| 1319 | + const inputDirective = inputGroupElement.injector.get(IgxInputDirective) as IgxInputDirective; |
| 1320 | + expect(inputDirective.disabled).toBeFalsy(); |
| 1321 | + |
| 1322 | + formGroup.disable(); |
| 1323 | + fixture.detectChanges(); |
| 1324 | + expect(inputDirective.disabled).toBeTruthy(); |
| 1325 | + }); |
| 1326 | + }); |
| 1327 | + |
| 1328 | + describe('Control value accessor unit tests', () => { |
| 1329 | + let ngModel; |
| 1330 | + let overlay; |
| 1331 | + let element; |
| 1332 | + let cdr; |
| 1333 | + let moduleRef; |
| 1334 | + let injector; |
| 1335 | + let inputGroup: IgxInputGroupComponent; |
| 1336 | + |
| 1337 | + beforeEach(() => { |
| 1338 | + ngModel = { |
| 1339 | + control: { touched: false, dirty: false, validator: null }, |
| 1340 | + valid: false, |
| 1341 | + statusChanges: new EventEmitter(), |
| 1342 | + }; |
| 1343 | + overlay = { |
| 1344 | + onOpening: new EventEmitter<OverlayCancelableEventArgs>(), |
| 1345 | + onOpened: new EventEmitter<OverlayEventArgs>(), |
| 1346 | + onClosed: new EventEmitter<OverlayEventArgs>(), |
| 1347 | + onClosing: new EventEmitter<OverlayClosingEventArgs>() |
| 1348 | + }; |
| 1349 | + element = {}; |
| 1350 | + cdr = { |
| 1351 | + markForCheck: () => {}, |
| 1352 | + detectChanges: () => {}, |
| 1353 | + detach: () => {}, |
| 1354 | + reattach: () => {} |
| 1355 | + }; |
| 1356 | + moduleRef = {}; |
| 1357 | + injector = { get: () => ngModel }; |
| 1358 | + inputGroup = new IgxInputGroupComponent(null, null); |
| 1359 | + }); |
| 1360 | + |
| 1361 | + it('should initialize date picker with required correctly', () => { |
| 1362 | + const datePicker = new IgxDatePickerComponent(overlay, element, cdr, moduleRef, injector); |
| 1363 | + datePicker['inputGroup'] = inputGroup; |
| 1364 | + ngModel.control.validator = () => ({ required: true}); |
| 1365 | + datePicker.ngOnInit(); |
| 1366 | + datePicker.ngAfterViewInit(); |
| 1367 | + datePicker.ngAfterViewChecked(); |
| 1368 | + |
| 1369 | + expect(datePicker).toBeDefined(); |
| 1370 | + expect(inputGroup.isRequired).toBeTruthy(); |
| 1371 | + }); |
| 1372 | + |
| 1373 | + it('should update inputGroup isRequired correctly', () => { |
| 1374 | + const datePicker = new IgxDatePickerComponent(overlay, element, cdr, moduleRef, injector); |
| 1375 | + datePicker['inputGroup'] = inputGroup; |
| 1376 | + datePicker.ngOnInit(); |
| 1377 | + datePicker.ngAfterViewInit(); |
| 1378 | + datePicker.ngAfterViewChecked(); |
| 1379 | + |
| 1380 | + expect(datePicker).toBeDefined(); |
| 1381 | + expect(inputGroup.isRequired).toBeFalsy(); |
| 1382 | + |
| 1383 | + ngModel.control.validator = () => ({ required: true}); |
| 1384 | + ngModel.statusChanges.emit(); |
| 1385 | + expect(inputGroup.isRequired).toBeTruthy(); |
| 1386 | + |
| 1387 | + ngModel.control.validator = () => ({ required: false}); |
| 1388 | + ngModel.statusChanges.emit(); |
| 1389 | + expect(inputGroup.isRequired).toBeFalsy(); |
| 1390 | + }); |
1295 | 1391 | }); |
1296 | 1392 | }); |
1297 | 1393 |
|
@@ -1442,23 +1538,27 @@ export class IgxDatePickerOpeningComponent { |
1442 | 1538 | @Component({ |
1443 | 1539 | template: ` |
1444 | 1540 | <form [formGroup]="reactiveForm"> |
1445 | | - <p> |
1446 | | - <igx-date-picker formControlName="datePickerReactive" #datePickerReactive></igx-date-picker> |
1447 | | - </p> |
1448 | | -</form> |
| 1541 | + <igx-date-picker formControlName="datePickerOnChange" #datePickerOnChangeComponent></igx-date-picker> |
| 1542 | + <igx-date-picker formControlName="datePickerOnBlur" #datePickerOnBlurComponent></igx-date-picker> |
| 1543 | + </form> |
1449 | 1544 | ` |
1450 | 1545 | }) |
1451 | 1546 | class IgxDatePickerReactiveFormComponent { |
1452 | | - @ViewChild('datePickerReactive', { read: IgxDatePickerComponent, static: true }) |
1453 | | - public datePicker: IgxDatePickerComponent; |
| 1547 | + @ViewChild('datePickerOnChangeComponent', { read: IgxDatePickerComponent, static: true }) |
| 1548 | + public datePickerOnChangeComponent: IgxDatePickerComponent; |
| 1549 | + |
| 1550 | + @ViewChild('datePickerOnBlurComponent', { read: IgxDatePickerComponent, static: true }) |
| 1551 | + public datePickerOnBlurComponent: IgxDatePickerComponent; |
| 1552 | + |
1454 | 1553 | reactiveForm: FormGroup; |
1455 | 1554 |
|
1456 | 1555 | constructor(fb: FormBuilder) { |
| 1556 | + const date = new Date(2000, 10, 15); |
1457 | 1557 | this.reactiveForm = fb.group({ |
1458 | | - datePickerReactive: new FormControl(''), |
| 1558 | + datePickerOnChange: [date, Validators.required], |
| 1559 | + datePickerOnBlur: [date, { updateOn: 'blur', validators: Validators.required}] |
1459 | 1560 | }); |
1460 | 1561 | } |
1461 | | - onSubmitReactive() { } |
1462 | 1562 | } |
1463 | 1563 |
|
1464 | 1564 | @Component({ |
|
0 commit comments