Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ All notable changes for each version of this project will be documented in this

### New Features

- `IgcFormControlDirective`
- Added support for `igc-color-picker` so it can be bound with `ngModel` and `formControlName`, in the same way `igc-rating` is already supported.

- `IgxChipComponent`
- Added the `outlined` property to the component. When set to `true`, the Chip will have an outlined style.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Component, DebugElement, ElementRef, Renderer2, ViewChild, ChangeDetectionStrategy } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { FormsModule } from '@angular/forms';
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { By } from '@angular/platform-browser';
import { defineComponents, IgcRatingComponent } from 'igniteui-webcomponents';
import { defineComponents, IgcColorPickerComponent, IgcRatingComponent } from 'igniteui-webcomponents';

import { IgcFormControlDirective } from './form-control.directive';

Expand All @@ -12,6 +12,7 @@ describe('IgcFormControlDirective - ', () => {
let directive: IgcFormControlDirective;
let input: DebugElement;
let rating: IgcRatingComponent;
let colorPicker: IgcColorPickerComponent;

describe('Unit tests: ', () => {

Expand Down Expand Up @@ -67,6 +68,56 @@ describe('IgcFormControlDirective - ', () => {
});
});

describe('Unit tests - igc-color-picker: ', () => {

beforeEach(waitForAsync(() => {
defineComponents(IgcColorPickerComponent);

TestBed.configureTestingModule({
providers: [
{ provide: ElementRef, useValue: colorPickerElementRef },
{ provide: Renderer2, useValue: renderer2Mock },
IgcFormControlDirective
]
});
}));

const colorPickerElementRef = { nativeElement: document.createElement('igc-color-picker') };

const mockNgControl = jasmine.createSpyObj('NgControl', [
'registerOnChangeCb',
'registerOnTouchedCb'
]);
Comment thread
Copilot marked this conversation as resolved.

const renderer2Mock = jasmine.createSpyObj('renderer2Mock', [
'setProperty'
]);

it('should correctly implement interface methods - ControlValueAccessor ', () => {
directive = TestBed.inject(IgcFormControlDirective);
directive.registerOnChange(mockNgControl.registerOnChangeCb);
directive.registerOnTouched(mockNgControl.registerOnTouchedCb);

// value setter
expect(colorPickerElementRef.nativeElement.value).toBeUndefined();
directive.writeValue('#ff0000');
expect(mockNgControl.registerOnChangeCb).toHaveBeenCalledTimes(0);
expect(colorPickerElementRef.nativeElement.value).toBe('#ff0000');

// listening for value change
directive.listenForValueChange('#00ff00');
expect(mockNgControl.registerOnChangeCb).toHaveBeenCalledWith('#00ff00');

// setDisabledState
directive.setDisabledState(true);
expect(renderer2Mock.setProperty).toHaveBeenCalledWith(colorPickerElementRef.nativeElement, 'disabled', true);

// OnTouched callback
directive.onBlur();
expect(mockNgControl.registerOnTouchedCb).toHaveBeenCalledTimes(1);
});
});

describe('ngModel two-way binding tests: ', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
Expand Down Expand Up @@ -109,6 +160,95 @@ describe('IgcFormControlDirective - ', () => {
expect(input.nativeElement.value).toEqual('8');
});
});

describe('ngModel two-way binding tests - igc-color-picker: ', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
IgxFormsColorPickerControlComponent
]
}).compileComponents();
defineComponents(IgcColorPickerComponent);
}));

beforeEach(fakeAsync(() => {
fixture = TestBed.createComponent(IgxFormsColorPickerControlComponent);
fixture.detectChanges();
input = fixture.debugElement.query(By.css(`#basicModelColor`));
colorPicker = fixture.debugElement.query(By.directive(IgcFormControlDirective)).nativeElement;
tick();
fixture.detectChanges();
}));

it('Should properly init for igc-color-picker.', () => {
directive = fixture.componentInstance.directive;
expect(directive).toBeTruthy();
});

it('Should reflect ngModel change to color-picker', async () => {
input.nativeElement.value = '#ff0000';
input.nativeElement.dispatchEvent(new Event('input'));
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();
expect(colorPicker.value).toEqual('#ff0000');
});

it('Should reflect ngModel change from color-picker', async () => {
colorPicker.setAttribute('value', '#00ff00');
colorPicker.dispatchEvent(new CustomEvent('igcChange', { detail: '#00ff00' }));
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();
expect(input.nativeElement.value).toEqual('#00ff00');
});
});

describe('Reactive forms tests - igc-color-picker: ', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
IgxReactiveFormsColorPickerControlComponent
]
}).compileComponents();
defineComponents(IgcColorPickerComponent);
}));

beforeEach(fakeAsync(() => {
fixture = TestBed.createComponent(IgxReactiveFormsColorPickerControlComponent);
fixture.detectChanges();
colorPicker = fixture.debugElement.query(By.directive(IgcFormControlDirective)).nativeElement;
tick();
fixture.detectChanges();
}));

it('Should write the initial FormControl value to the color-picker', () => {
expect(colorPicker.value).toEqual('#ff0000');
});

it('Should update the FormControl value when the color-picker emits igcChange', async () => {
colorPicker.setAttribute('value', '#0000ff');
colorPicker.dispatchEvent(new CustomEvent('igcChange', { detail: '#0000ff' }));
fixture.detectChanges();
await fixture.whenStable();
fixture.detectChanges();
expect(fixture.componentInstance.form.get('color').value).toEqual('#0000ff');
});

it('Should mark the FormControl as touched on blur', () => {
expect(fixture.componentInstance.form.get('color').touched).toBeFalse();
colorPicker.dispatchEvent(new Event('blur'));
fixture.detectChanges();
expect(fixture.componentInstance.form.get('color').touched).toBeTrue();
});

it('Should reflect FormControl disabled state to the color-picker', () => {
expect(colorPicker.disabled).toBeFalse();
fixture.componentInstance.form.get('color').disable();
fixture.detectChanges();
expect(colorPicker.disabled).toBeTrue();
});
});
});

@Component({
Expand All @@ -132,3 +272,42 @@ class IgxFormsControlComponent {
};
}

@Component({
template: `
<form #form2="ngForm">
<input type="text" id="basicModelColor" name="model color" [(ngModel)]="model.Color">
<igc-color-picker name="modelColor" [(ngModel)]="model.Color" label="Model Color"></igc-color-picker>
</form>
`,
changeDetection: ChangeDetectionStrategy.Eager,
imports: [IgcFormControlDirective, FormsModule]
})
class IgxFormsColorPickerControlComponent {

@ViewChild(IgcFormControlDirective, { static: true })
public directive: IgcFormControlDirective;

public model = {
Color: '#000000'
};
}

@Component({
template: `
<form [formGroup]="form">
<igc-color-picker formControlName="color" label="Reactive Color"></igc-color-picker>
</form>
`,
changeDetection: ChangeDetectionStrategy.Eager,
imports: [IgcFormControlDirective, ReactiveFormsModule]
})
class IgxReactiveFormsColorPickerControlComponent {

@ViewChild(IgcFormControlDirective, { static: true })
public directive: IgcFormControlDirective;

public form = new FormGroup({
color: new FormControl('#ff0000')
});
}

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

@Directive({
// eslint-disable-next-line @angular-eslint/directive-selector
selector: 'igc-rating[ngModel],igc-rating[formControlName]',
selector: 'igc-rating[ngModel],igc-rating[formControlName],igc-color-picker[ngModel],igc-color-picker[formControlName]',
providers: [
{
provide: NG_VALUE_ACCESSOR,
Expand Down
Loading