|
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, AbstractControlOptions } 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 | 8 | import { IgxInputDirective } 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 |
| -import { DateRangeType } from 'igniteui-angular'; |
14 | 13 | import { IgxButtonModule } from '../directives/button/button.directive';
|
15 | 14 | import { IgxCalendarModule } from '../calendar';
|
16 | 15 | import { InteractionMode } from '../core/enums';
|
| 16 | +import { DateRangeType } from '../core/dates/dateRange'; |
| 17 | +import { OverlayCancelableEventArgs, OverlayEventArgs, OverlayClosingEventArgs } from '../services'; |
17 | 18 |
|
18 |
| -describe('IgxDatePicker', () => { |
| 19 | +fdescribe('IgxDatePicker', () => { |
19 | 20 | configureTestSuite();
|
20 | 21 | beforeEach(async(() => {
|
21 | 22 | TestBed.configureTestingModule({
|
@@ -1262,49 +1263,161 @@ describe('IgxDatePicker', () => {
|
1262 | 1263 |
|
1263 | 1264 | describe('Reactive form', () => {
|
1264 | 1265 | let fixture: ComponentFixture<IgxDatePickerReactiveFormComponent>;
|
1265 |
| - let datePicker: IgxDatePickerComponent; |
| 1266 | + let datePickerOnChange: IgxDatePickerComponent; |
| 1267 | + let datePickerOnBlur: IgxDatePickerComponent; |
1266 | 1268 |
|
1267 | 1269 | beforeEach(() => {
|
1268 | 1270 | fixture = TestBed.createComponent(IgxDatePickerReactiveFormComponent);
|
1269 |
| - datePicker = fixture.componentInstance.datePicker; |
| 1271 | + datePickerOnChange = fixture.componentInstance.datePickerOnChange; |
| 1272 | + datePickerOnBlur = fixture.componentInstance.datePickerOnBlur; |
1270 | 1273 | fixture.detectChanges();
|
1271 | 1274 | });
|
1272 | 1275 |
|
1273 |
| - it('Should properly initialize when used as a form control in reactive form', fakeAsync(() => { |
1274 |
| - expect(datePicker).toBeDefined(); |
1275 |
| - expect(datePicker.value).toEqual(new Date(2000, 10, 15)); |
| 1276 | + it('Should properly initialize when used as a form control in reactive form', () => { |
| 1277 | + expect(datePickerOnChange).toBeDefined(); |
| 1278 | + expect(datePickerOnChange.value).toEqual(new Date(2000, 10, 15)); |
1276 | 1279 |
|
1277 |
| - const datePickerFormReference = fixture.componentInstance.reactiveForm.controls.datePickerReactive; |
| 1280 | + const datePickerFormReference = fixture.componentInstance.reactiveFormOnChange.controls.datePickerReactiveOnChange; |
1278 | 1281 | expect(datePickerFormReference).toBeDefined();
|
1279 | 1282 | expect(datePickerFormReference.status).toEqual('VALID');
|
| 1283 | + }); |
| 1284 | + |
| 1285 | + it('Should set date picker status to invalid when it is required and has no value', fakeAsync(() => { |
| 1286 | + const inputGroup = (datePickerOnChange as any).inputGroup as IgxInputGroupComponent; |
| 1287 | + const datePickerFormReference = fixture.componentInstance.reactiveFormOnChange.controls.datePickerReactiveOnChange; |
| 1288 | + expect(datePickerFormReference.status).toEqual('VALID'); |
| 1289 | + expect(inputGroup.isRequired).toBeFalsy(); |
| 1290 | + expect(inputGroup.validClass).toBeFalsy(); |
| 1291 | + |
| 1292 | + const form = fixture.componentInstance.reactiveFormOnChange; |
| 1293 | + form.controls.datePickerReactiveOnChange.setValidators(Validators.required); |
| 1294 | + datePickerOnChange.value = null; |
| 1295 | + fixture.detectChanges(); |
| 1296 | + expect(inputGroup.isRequired).toBeTruthy(); |
| 1297 | + expect(inputGroup.validClass).toBeFalsy(); |
| 1298 | + expect(datePickerFormReference.status).toEqual('INVALID'); |
| 1299 | + })); |
| 1300 | + |
| 1301 | + it('Should set date picker status to invalid when it is required and has no value onBlur', fakeAsync(() => { |
| 1302 | + const formGroup = fixture.componentInstance.reactiveFormOnBlur; |
| 1303 | + datePickerOnBlur.mode = InteractionMode.DropDown; |
| 1304 | + datePickerOnBlur.mask = 'dd/mm/yyyy'; |
| 1305 | + datePickerOnBlur.inputMask = 'dd/mm/yyyy'; |
| 1306 | + fixture.detectChanges(); |
| 1307 | + |
| 1308 | + const inputElement = (datePickerOnBlur as any).inputGroup.input.element.nativeElement; |
| 1309 | + inputElement.click(); |
| 1310 | + inputElement.focus(); |
| 1311 | + tick(); |
| 1312 | + fixture.detectChanges(); |
| 1313 | + |
| 1314 | + const inputGroup = (datePickerOnBlur as any).inputGroup as IgxInputGroupComponent; |
| 1315 | + expect(formGroup.controls.datePickerReactiveOnBlur.status).toEqual('VALID'); |
| 1316 | + expect(inputGroup.isRequired).toBeFalsy(); |
| 1317 | + expect(inputGroup.validClass).toBeFalsy(); |
| 1318 | + |
| 1319 | + formGroup.controls.datePickerReactiveOnBlur.setValidators(Validators.required); |
| 1320 | + fixture.detectChanges(); |
| 1321 | + |
| 1322 | + datePickerOnBlur.value = null; |
| 1323 | + fixture.detectChanges(); |
| 1324 | + expect(inputGroup.isRequired).toBeFalsy(); |
| 1325 | + expect(inputGroup.validClass).toBeFalsy(); |
| 1326 | + expect(formGroup.controls.datePickerReactiveOnBlur.status).toEqual('VALID'); |
| 1327 | + |
| 1328 | + inputElement.blur(); |
| 1329 | + fixture.detectChanges(); |
| 1330 | + expect(inputGroup.isRequired).toBeTruthy(); |
| 1331 | + expect(inputGroup.validClass).toBeFalsy(); |
| 1332 | + expect(formGroup.controls.datePickerReactiveOnBlur.status).toEqual('INVALID'); |
1280 | 1333 | }));
|
1281 | 1334 |
|
1282 | 1335 | // Bug #6025 Date picker does not disable in reactive form
|
1283 | 1336 | it('Should disable when form is disabled', fakeAsync(() => {
|
1284 | 1337 | fixture.detectChanges();
|
1285 |
| - const formGroup: FormGroup = fixture.componentInstance.reactiveForm; |
1286 |
| - const inputGroup = fixture.debugElement.query(By.css('.igx-input-group')); |
| 1338 | + const formGroup: FormGroup = fixture.componentInstance.reactiveFormOnChange; |
| 1339 | + const inputGroup = (datePickerOnChange as any).inputGroup as IgxInputGroupComponent; |
1287 | 1340 |
|
1288 |
| - inputGroup.nativeElement.click(); |
1289 |
| - tick(); |
| 1341 | + inputGroup.element.nativeElement.click(); |
1290 | 1342 | fixture.detectChanges();
|
1291 |
| - expect(datePicker.collapsed).toBeFalsy(); |
| 1343 | + tick(500); |
| 1344 | + expect(datePickerOnChange.collapsed).toBeFalsy(); |
1292 | 1345 |
|
1293 |
| - datePicker.closeCalendar(); |
1294 |
| - tick(); |
| 1346 | + datePickerOnChange.closeCalendar(); |
1295 | 1347 | fixture.detectChanges();
|
| 1348 | + tick(); |
| 1349 | + expect(datePickerOnChange.collapsed).toBeTruthy(); |
1296 | 1350 |
|
1297 | 1351 | formGroup.disable();
|
1298 |
| - tick(); |
1299 | 1352 | fixture.detectChanges();
|
1300 |
| - |
1301 |
| - inputGroup.nativeElement.click(); |
1302 | 1353 | tick();
|
| 1354 | + |
| 1355 | + inputGroup.element.nativeElement.parentElement.click(); |
1303 | 1356 | fixture.detectChanges();
|
| 1357 | + tick(); |
1304 | 1358 | const dateDropDown = document.getElementsByClassName('igx-date-picker--dropdown');
|
1305 | 1359 | expect(dateDropDown.length).toEqual(0);
|
1306 | 1360 | }));
|
1307 | 1361 | });
|
| 1362 | + |
| 1363 | + describe('Control value accessor unit tests', () => { |
| 1364 | + let ngModel; |
| 1365 | + let overlay; |
| 1366 | + let element; |
| 1367 | + let cdr; |
| 1368 | + let moduleRef; |
| 1369 | + let injector; |
| 1370 | + let inputGroup: IgxInputGroupComponent; |
| 1371 | + |
| 1372 | + beforeEach(() => { |
| 1373 | + ngModel = { |
| 1374 | + control: { touched: false, dirty: false, validator: null }, |
| 1375 | + valid: false, |
| 1376 | + statusChanges: new EventEmitter(), |
| 1377 | + }; |
| 1378 | + overlay = { |
| 1379 | + onOpening: new EventEmitter<OverlayCancelableEventArgs>(), |
| 1380 | + onOpened: new EventEmitter<OverlayEventArgs>(), |
| 1381 | + onClosed: new EventEmitter<OverlayEventArgs>(), |
| 1382 | + onClosing: new EventEmitter<OverlayClosingEventArgs>() |
| 1383 | + }; |
| 1384 | + element = {}; |
| 1385 | + cdr = { markForCheck: () => {}}; |
| 1386 | + moduleRef = {}; |
| 1387 | + injector = { get: () => ngModel }; |
| 1388 | + inputGroup = new IgxInputGroupComponent(null, null); |
| 1389 | + }); |
| 1390 | + |
| 1391 | + it('should initialize date picker with required correctly', () => { |
| 1392 | + const datePicker = new IgxDatePickerComponent(overlay, element, cdr, moduleRef, injector); |
| 1393 | + datePicker['inputGroup'] = inputGroup; |
| 1394 | + ngModel.control.validator = () => ({ required: true}); |
| 1395 | + datePicker.ngOnInit(); |
| 1396 | + datePicker.ngAfterViewInit(); |
| 1397 | + |
| 1398 | + expect(datePicker).toBeDefined(); |
| 1399 | + expect(inputGroup.isRequired).toBeTruthy(); |
| 1400 | + }); |
| 1401 | + |
| 1402 | + it('should update inputGroup isRequired correctly', () => { |
| 1403 | + const datePicker = new IgxDatePickerComponent(overlay, element, cdr, moduleRef, injector); |
| 1404 | + datePicker['inputGroup'] = inputGroup; |
| 1405 | + datePicker.ngOnInit(); |
| 1406 | + datePicker.ngAfterViewInit(); |
| 1407 | + expect(datePicker).toBeDefined(); |
| 1408 | + |
| 1409 | + ngModel.statusChanges.emit(); |
| 1410 | + expect(inputGroup.isRequired).toBeFalsy(); |
| 1411 | + |
| 1412 | + ngModel.control.validator = () => ({ required: true}); |
| 1413 | + ngModel.statusChanges.emit(); |
| 1414 | + expect(inputGroup.isRequired).toBeTruthy(); |
| 1415 | + |
| 1416 | + ngModel.control.validator = () => ({ required: false}); |
| 1417 | + ngModel.statusChanges.emit(); |
| 1418 | + expect(inputGroup.isRequired).toBeFalsy(); |
| 1419 | + }); |
| 1420 | + }); |
1308 | 1421 | });
|
1309 | 1422 |
|
1310 | 1423 | @Component({
|
@@ -1453,20 +1566,46 @@ export class IgxDatePickerOpeningComponent {
|
1453 | 1566 |
|
1454 | 1567 | @Component({
|
1455 | 1568 | template: `
|
1456 |
| - <form [formGroup]="reactiveForm" (ngSubmit)="onSubmitReactive()"> |
1457 |
| - <igx-date-picker formControlName="datePickerReactive" #datePickerReactive></igx-date-picker> |
1458 |
| - <button type="submit" [disabled]="!reactiveForm.valid">Submit</button> |
| 1569 | + <form [formGroup]="reactiveFormOnChange" (ngSubmit)="onSubmitReactive()"> |
| 1570 | + <igx-date-picker formControlName="datePickerReactiveOnChange" #datePickerReactiveOnChange></igx-date-picker> |
| 1571 | + <button #submitButtonOnChange type="submit" [disabled]="!reactiveFormOnChange.valid">Submit</button> |
| 1572 | + </form> |
| 1573 | + <form [formGroup]="reactiveFormOnBlur" (ngSubmit)="onSubmitReactive()"> |
| 1574 | + <igx-date-picker formControlName="datePickerReactiveOnBlur" #datePickerReactiveOnBlur></igx-date-picker> |
| 1575 | + <button #submitButtonOnBlur type="submit" [disabled]="!reactiveFormOnBlur.valid">Submit</button> |
1459 | 1576 | </form>
|
1460 | 1577 | `
|
1461 | 1578 | })
|
1462 | 1579 | class IgxDatePickerReactiveFormComponent {
|
1463 |
| - @ViewChild('datePickerReactive', { read: IgxDatePickerComponent, static: true }) |
1464 |
| - public datePicker: IgxDatePickerComponent; |
1465 |
| - reactiveForm: FormGroup; |
| 1580 | + @ViewChild('datePickerReactiveOnChange', { read: IgxDatePickerComponent, static: true }) |
| 1581 | + public datePickerOnChange: IgxDatePickerComponent; |
| 1582 | + |
| 1583 | + @ViewChild('datePickerReactiveOnBlur', { read: IgxDatePickerComponent, static: true }) |
| 1584 | + public datePickerOnBlur: IgxDatePickerComponent; |
| 1585 | + |
| 1586 | + @ViewChild('submitButtonOnChange', { static: true }) |
| 1587 | + public submitButtonOnChange: ElementRef; |
| 1588 | + |
| 1589 | + @ViewChild('submitButtonOnBlur', { static: true }) |
| 1590 | + public submitButtonOnBlur: ElementRef; |
| 1591 | + |
| 1592 | + reactiveFormOnChange: FormGroup; |
| 1593 | + reactiveFormOnBlur: FormGroup; |
| 1594 | + |
| 1595 | + public validatorOptions: AbstractControlOptions = { |
| 1596 | + validators: [], |
| 1597 | + asyncValidators: [], |
| 1598 | + updateOn: 'change' |
| 1599 | + }; |
1466 | 1600 |
|
1467 | 1601 | constructor(fb: FormBuilder) {
|
1468 |
| - this.reactiveForm = fb.group({ |
1469 |
| - datePickerReactive: [new Date(2000, 10, 15)], |
| 1602 | + this.reactiveFormOnChange = fb.group({ |
| 1603 | + datePickerReactiveOnChange: [new Date(2000, 10, 15), this.validatorOptions], |
| 1604 | + }); |
| 1605 | + |
| 1606 | + this.validatorOptions.updateOn = 'blur'; |
| 1607 | + this.reactiveFormOnBlur = fb.group({ |
| 1608 | + datePickerReactiveOnBlur: [new Date(2000, 10, 15), this.validatorOptions], |
1470 | 1609 | });
|
1471 | 1610 | }
|
1472 | 1611 | onSubmitReactive() { }
|
|
0 commit comments