Skip to content

Commit

Permalink
feat(combo): add svg icon and tests #7282
Browse files Browse the repository at this point in the history
  • Loading branch information
PlamenaMiteva committed Jul 20, 2020
1 parent 6c8a896 commit ed2bd8a
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 33 deletions.
15 changes: 7 additions & 8 deletions projects/igniteui-angular/src/lib/combo/combo.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<ng-content select="igx-hint, [igxHint]"></ng-content>
</ng-container>
<input igxInput #comboInput name="comboInput" type="text" [value]="value" readonly [attr.placeholder]="placeholder"
[disabled]="disabled" (blur)="onBlur()" (focus)="onFocus()"/>
[disabled]="disabled" (blur)="onBlur()" (focus)="onFocus()" />
<ng-container ngProjectAs="igx-suffix">
<ng-content select="igx-suffix"></ng-content>
</ng-container>
Expand Down Expand Up @@ -39,19 +39,18 @@
[(ngModel)]="searchValue" (ngModelChange)="handleInputChange($event)" (keyup)="handleKeyUp($event)"
(keydown)="handleKeyDown($event)" (focus)="dropdown.onBlur($event)" [attr.placeholder]="searchPlaceholder"
aria-autocomplete="both" [attr.aria-owns]="dropdown.id" [attr.aria-labelledby]="ariaLabelledBy" />
<igx-suffix *ngIf="showSearchCaseIcon">
<igx-chip [selectable]="true" (click)="caseSensitive=!this.selected">
<span>Aa</span>
</igx-chip>
</igx-suffix>
<igx-suffix *ngIf="showCaseIcon">
<igx-icon fontSet="case-sensitive" name="case-sensitive" [isActive]="caseSensitive"
(click)="caseSensitive=!caseSensitive">
</igx-icon>
</igx-suffix>
</igx-input-group>
<ng-container *ngTemplateOutlet="headerTemplate">
</ng-container>
<div #dropdownItemContainer class="igx-combo__content" [style.overflow]="'hidden'"
[style.maxHeight.px]="itemsMaxHeight" [igxDropDownItemNavigation]="dropdown" (focus)="dropdown.onFocus()"
[tabindex]="dropdown.collapsed ? -1 : 0" role="listbox" [attr.id]="dropdown.id">
<igx-combo-item role="option" [itemHeight]='itemHeight'
*igxFor="let item of data
<igx-combo-item role="option" [itemHeight]='itemHeight' *igxFor="let item of data
| comboFiltering:searchValue:displayKey:filterable:caseSensitive
| comboGrouping:groupKey:valueKey;
index as rowIndex; containerSize: itemsMaxHeight; scrollOrientation: 'vertical'; itemSize: itemHeight"
Expand Down
95 changes: 75 additions & 20 deletions projects/igniteui-angular/src/lib/combo/combo.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { configureTestSuite } from '../test-utils/configure-suite';
import { DisplayDensity } from '../core/density';
import { AbsoluteScrollStrategy, ConnectedPositioningStrategy } from '../services/public_api';
import { IgxSelectionAPIService } from '../core/selection';
import { IgxIconService } from '../icon/public_api';

const CSS_CLASS_COMBO = 'igx-combo';
const CSS_CLASS_COMBO_DROPDOWN = 'igx-combo__drop-down';
Expand Down Expand Up @@ -73,6 +74,7 @@ describe('igxCombo', () => {
{ country: 'Spain', city: 'Madrid' },
{ country: 'Italy', city: 'Rome' }
];
const elementRef = { nativeElement: null };
const mockSelection: {
[key: string]: jasmine.Spy
} = jasmine.createSpyObj('IgxSelectionAPIService', ['get', 'set', 'add_items', 'select_items']);
Expand All @@ -83,8 +85,10 @@ describe('igxCombo', () => {
'get': mockNgControl
});
mockSelection.get.and.returnValue(new Set([]));
const mockIconService = new IgxIconService(null, null);
it('should correctly implement interface methods - ControlValueAccessor ', () => {
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, mockSelection as any, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, mockSelection as any, mockComboService, mockIconService, null, mockInjector);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
expect(mockInjector.get).toHaveBeenCalledWith(NgControl, null);
combo.registerOnChange(mockNgControl.registerOnChangeCb);
Expand Down Expand Up @@ -128,8 +132,9 @@ describe('igxCombo', () => {
pending('Convert existing form test here');
});
it('should properly call dropdown methods on toggle', () => {
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, mockSelection as any, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, mockSelection as any, mockComboService, mockIconService, null, mockInjector);
const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['open', 'close', 'toggle']);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
combo.dropdown = dropdown;
dropdown.collapsed = true;
Expand All @@ -150,9 +155,10 @@ describe('igxCombo', () => {
expect(combo.collapsed).toBe(false);
});
it(`should not focus search input when property autoFocusSearch=false`, () => {
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, mockSelection as any, mockComboService, null, mockInjector);
const dropdownContainer = { nativeElement: { focus: () => {}}};
combo = new IgxComboComponent(elementRef, mockCdr, mockSelection as any, mockComboService, mockIconService, null, mockInjector);
const dropdownContainer = { nativeElement: { focus: () => { } } };
combo['dropdownContainer'] = dropdownContainer;
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
spyOn(combo, 'focusSearchInput');

combo.autoFocusSearch = false;
Expand All @@ -168,8 +174,9 @@ describe('igxCombo', () => {
expect(combo.focusSearchInput).toHaveBeenCalledTimes(1);
});
it('should call dropdown toggle with correct overlaySettings', () => {
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, mockSelection as any, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, mockSelection as any, mockComboService, mockIconService, null, mockInjector);
const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['toggle']);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
combo.dropdown = dropdown;
const defaultSettings = (combo as any)._overlaySettings;
Expand All @@ -185,7 +192,8 @@ describe('igxCombo', () => {
expect(combo.dropdown.toggle).toHaveBeenCalledWith(expectedSettings);
});
it('should properly get/set displayKey', () => {
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, mockSelection as any, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, mockSelection as any, mockComboService, mockIconService, null, mockInjector);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
combo.valueKey = 'field';
expect(combo.displayKey).toEqual(combo.valueKey);
Expand All @@ -194,7 +202,8 @@ describe('igxCombo', () => {
expect(combo.displayKey === combo.valueKey).toBeFalsy();
});
it('should properly call "writeValue" method', () => {
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, mockSelection as any, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, mockSelection as any, mockComboService, mockIconService, null, mockInjector);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
combo.data = data;
spyOn(combo, 'selectItems');
Expand All @@ -211,8 +220,9 @@ describe('igxCombo', () => {
});
it('should select items through setSelctedItem method', () => {
const selectionService = new IgxSelectionAPIService();
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, selectionService, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, selectionService, mockComboService, mockIconService, null, mockInjector);
const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
combo.data = complexData;
combo.valueKey = 'country';
Expand Down Expand Up @@ -245,8 +255,9 @@ describe('igxCombo', () => {
});
it('should set selectedItems correctly on selectItems method call', () => {
const selectionService = new IgxSelectionAPIService();
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, selectionService, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, selectionService, mockComboService, mockIconService, null, mockInjector);
const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
combo.data = data;
combo.dropdown = dropdown;
Expand All @@ -269,8 +280,9 @@ describe('igxCombo', () => {
});
it('should fire onSelectionChange event on item selection', () => {
const selectionService = new IgxSelectionAPIService();
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, selectionService, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, selectionService, mockComboService, mockIconService, null, mockInjector);
const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
combo.data = data;
combo.dropdown = dropdown;
Expand Down Expand Up @@ -339,8 +351,9 @@ describe('igxCombo', () => {
});
it('should properly emit added and removed values in change event on single value selection', () => {
const selectionService = new IgxSelectionAPIService();
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, selectionService, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, selectionService, mockComboService, mockIconService, null, mockInjector);
const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
combo.data = complexData;
combo.valueKey = 'country';
Expand Down Expand Up @@ -370,8 +383,9 @@ describe('igxCombo', () => {
});
it('should properly emit added and removed values in change event on multiple values selection', () => {
const selectionService = new IgxSelectionAPIService();
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, selectionService, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, selectionService, mockComboService, mockIconService, null, mockInjector);
const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
combo.data = complexData;
combo.valueKey = 'country';
Expand Down Expand Up @@ -417,8 +431,9 @@ describe('igxCombo', () => {
});
it('should handle select/deselect ALL items', () => {
const selectionService = new IgxSelectionAPIService();
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, selectionService, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, selectionService, mockComboService, mockIconService, null, mockInjector);
const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
combo.data = data;
combo.dropdown = dropdown;
Expand All @@ -436,8 +451,9 @@ describe('igxCombo', () => {
});
it('should emit onSelectonChange event on select/deselect ALL items method call', () => {
const selectionService = new IgxSelectionAPIService();
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, selectionService, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, selectionService, mockComboService, mockIconService, null, mockInjector);
const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
combo.data = data;
combo.dropdown = dropdown;
Expand Down Expand Up @@ -472,8 +488,9 @@ describe('igxCombo', () => {
});
it('should properly handle selection manipulation through onSelectionChange emit', () => {
const selectionService = new IgxSelectionAPIService();
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, selectionService, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, selectionService, mockComboService, mockIconService, null, mockInjector);
const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
combo.data = data;
combo.dropdown = dropdown;
Expand All @@ -489,7 +506,8 @@ describe('igxCombo', () => {
expect(combo.selectedItems()).toEqual([]);
});
it('should not throw error when setting data to null', () => {
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, mockSelection as any, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, mockSelection as any, mockComboService, mockIconService, null, mockInjector);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
let errorMessage = '';
try {
Expand All @@ -503,7 +521,8 @@ describe('igxCombo', () => {
expect(combo.data.length).toBe(0);
});
it('should not throw error when setting data to undefined', () => {
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, mockSelection as any, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, mockSelection as any, mockComboService, mockIconService, null, mockInjector);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
let errorMessage = '';
try {
Expand All @@ -517,8 +536,9 @@ describe('igxCombo', () => {
expect(combo.data.length).toBe(0);
});
it('should properly handleInputChange', () => {
combo = new IgxComboComponent({ nativeElement: null }, mockCdr, mockSelection as any, mockComboService, null, mockInjector);
combo = new IgxComboComponent(elementRef, mockCdr, mockSelection as any, mockComboService, mockIconService, null, mockInjector);
const dropdown = jasmine.createSpyObj('IgxComboDropDownComponent', ['selectItem']);
spyOn(mockIconService, 'addSvgIconFromText').and.returnValue(null);
combo.ngOnInit();
combo.data = data;
combo.dropdown = dropdown;
Expand Down Expand Up @@ -750,7 +770,7 @@ describe('igxCombo', () => {
scrollIndex += 10;
if (scrollIndex < combo.data.length) {
combo.virtualScrollContainer.scrollTo(scrollIndex);
combo.virtualScrollContainer.onChunkLoad.pipe(take(1)).subscribe(async() => {
combo.virtualScrollContainer.onChunkLoad.pipe(take(1)).subscribe(async () => {
await wait(30);
checkGroupedItemsClass();
});
Expand Down Expand Up @@ -849,6 +869,25 @@ describe('igxCombo', () => {
expect(footerHTMLElement.parentNode).toEqual(dropdownList);
expect(footerHTMLElement.textContent).toEqual('This is a footer');
});
it('should render case-sensitive icon properly', () => {
combo.showCaseIcon = true;
fixture.detectChanges();
combo.toggle();
fixture.detectChanges();

let caseSensitiveIcon = fixture.debugElement.query(By.css('igx-icon[name=\'case-sensitive\']'));
expect(caseSensitiveIcon).toBeDefined();

combo.toggle();
fixture.detectChanges();
combo.showCaseIcon = false;
fixture.detectChanges();
combo.toggle();
fixture.detectChanges();

caseSensitiveIcon = fixture.debugElement.query(By.css('igx-icon[name=\'case-sensitive\']'));
expect(caseSensitiveIcon).toBeNull();
});
});
describe('Positioning tests: ', () => {
let containerElement: any;
Expand Down Expand Up @@ -1753,7 +1792,7 @@ describe('igxCombo', () => {
expect(fixture.debugElement.queryAll(By.css(`.${CSS_CLASS_CLEARBUTTON}`)).length).toEqual(1);

// Clear selected items
const clearButton = fixture.debugElement.query(By.css(`.${CSS_CLASS_CLEARBUTTON}`));
const clearButton = fixture.debugElement.query(By.css(`.${CSS_CLASS_CLEARBUTTON}`));
clearButton.triggerEventHandler('click', UIInteractions.getMouseEvent('click'));
fixture.detectChanges();
fixture.detectChanges();
Expand Down Expand Up @@ -2355,6 +2394,22 @@ describe('igxCombo', () => {
fixture.detectChanges();
expect(combo.isAddButtonVisible()).toEqual(true);
});
it('should be able to toggle search case sensitivity', () => {
combo.showCaseIcon = true;
fixture.detectChanges();
combo.toggle();
fixture.detectChanges();

const caseSensitiveIcon = fixture.debugElement.query(By.css('igx-icon[name=\'case-sensitive\']'));
const searchInput = fixture.debugElement.query(By.css('input[name=\'searchInput\']'));
UIInteractions.triggerInputEvent(searchInput, 'M');
fixture.detectChanges();
expect([...combo.filteredData]).toEqual(combo.data.filter(e => e['field'].toLowerCase().includes('m')));

caseSensitiveIcon.triggerEventHandler('click', UIInteractions.getMouseEvent('click'));
fixture.detectChanges();
expect([...combo.filteredData]).toEqual(combo.data.filter(e => e['field'].includes('M')));
});
});
describe('Form control tests: ', () => {
describe('Reactive form tests: ', () => {
Expand Down
Loading

0 comments on commit ed2bd8a

Please sign in to comment.