From 2dfb42733ee480003e63eb26927b766f0707ba0a Mon Sep 17 00:00:00 2001 From: Plamen Dobrev Date: Mon, 8 Apr 2024 11:13:02 +0300 Subject: [PATCH] fix(buttonGroup): issue with MutationObserver wrongly deselecting buttons --- .../lib/buttonGroup/buttonGroup.component.ts | 39 ++--- .../buttonGroup/buttongroup.component.spec.ts | 146 ++++++++++++++++-- .../excel-style-sorting.component.html | 4 +- .../excel-style-sorting.component.ts | 2 +- .../grid/grid-filtering-advanced.spec.ts | 10 +- .../lib/grids/grid/grid-filtering-ui.spec.ts | 66 ++++---- 6 files changed, 201 insertions(+), 66 deletions(-) diff --git a/projects/igniteui-angular/src/lib/buttonGroup/buttonGroup.component.ts b/projects/igniteui-angular/src/lib/buttonGroup/buttonGroup.component.ts index 9d4614a64ca..eec1169f2bc 100644 --- a/projects/igniteui-angular/src/lib/buttonGroup/buttonGroup.component.ts +++ b/projects/igniteui-angular/src/lib/buttonGroup/buttonGroup.component.ts @@ -357,8 +357,6 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After return; } - this.updateSelected(index); - const button = this.buttons[index]; button.select(); } @@ -387,12 +385,28 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After this.buttons.forEach((_, i) => { if (i !== index && this.selectedIndexes.indexOf(i) !== -1) { this.deselectButton(i); + this.updateDeselected(i); } }); } } + public updateDeselected(index: number) { + const button = this.buttons[index]; + if (this.selectedIndexes.indexOf(index) !== -1) { + this.selectedIndexes.splice(this.selectedIndexes.indexOf(index), 1); + } + + this._renderer.setAttribute(button.nativeElement, 'aria-pressed', 'false'); + this._renderer.removeClass(button.nativeElement, 'igx-button-group__item--selected'); + + const indexInViewButtons = this.viewButtons.toArray().indexOf(button); + if (indexInViewButtons !== -1) { + this.values[indexInViewButtons].selected = false; + } + } + /** * Deselects a button by its index. * ```typescript @@ -412,16 +426,7 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After } const button = this.buttons[index]; - this.selectedIndexes.splice(this.selectedIndexes.indexOf(index), 1); - - this._renderer.setAttribute(button.nativeElement, 'aria-pressed', 'false'); - this._renderer.removeClass(button.nativeElement, 'igx-button-group__item--selected'); button.deselect(); - - const indexInViewButtons = this.viewButtons.toArray().indexOf(button); - if (indexInViewButtons !== -1) { - this.values[indexInViewButtons].selected = false; - } } /** @@ -497,8 +502,6 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After * @hidden */ public _clickHandler(index: number) { - this.mutationObserver.disconnect(); - const button = this.buttons[index]; const args: IButtonGroupEventArgs = { owner: this, button, index }; @@ -519,8 +522,6 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After this.deselected.emit(args); } } - - this.mutationObserver?.observe(this._el.nativeElement, this.observerConfig); } private setMutationsObserver() { @@ -544,7 +545,7 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After observer.observe(this._el.nativeElement, this.observerConfig); // Cleanup function - this._renderer.listen(this._el.nativeElement, 'DOMNodeRemoved', () => { + this._renderer.listen(this._el.nativeElement, 'DOMAttrModified', () => { observer.disconnect(); }); }); @@ -567,11 +568,11 @@ export class IgxButtonGroupComponent extends DisplayDensityBase implements After } private updateButtonSelectionState(index: number, args: IButtonGroupEventArgs) { - if (this.selectedIndexes.indexOf(index) === -1) { - this.selectButton(index); + if (this.buttons[index].selected) { + this.updateSelected(index); this.selected.emit(args); } else { - this.deselectButton(index); + this.updateDeselected(index); this.deselected.emit(args); } } diff --git a/projects/igniteui-angular/src/lib/buttonGroup/buttongroup.component.spec.ts b/projects/igniteui-angular/src/lib/buttonGroup/buttongroup.component.spec.ts index 0d4708873b2..58e02e20246 100644 --- a/projects/igniteui-angular/src/lib/buttonGroup/buttongroup.component.spec.ts +++ b/projects/igniteui-angular/src/lib/buttonGroup/buttongroup.component.spec.ts @@ -3,10 +3,12 @@ import { TestBed, fakeAsync, flushMicrotasks, waitForAsync } from '@angular/core import { ButtonGroupAlignment, IgxButtonGroupComponent } from './buttonGroup.component'; import { configureTestSuite } from '../test-utils/configure-suite'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; -import { UIInteractions } from '../test-utils/ui-interactions.spec'; +import { UIInteractions, wait } from '../test-utils/ui-interactions.spec'; import { IgxButtonDirective } from '../directives/button/button.directive'; import { getComponentSize } from '../core/utils'; import { NgFor } from '@angular/common'; +import { IgxRadioGroupDirective } from '../directives/radio/radio-group.directive'; +import { IgxRadioComponent } from '../radio/radio.component'; interface IButton { type?: string; @@ -148,148 +150,198 @@ describe('IgxButtonGroup', () => { expect(btnGroupInstance.deselected.emit).toHaveBeenCalled(); }); - it('should should reset its current selection state on selectionMode runtime change', () => { + it('should should reset its current selection state on selectionMode runtime change', async () => { const fixture = TestBed.createComponent(ButtonGroupWithSelectedButtonComponent); + + await wait(); fixture.detectChanges(); const buttonGroup = fixture.componentInstance.buttonGroup; buttonGroup.selectionMode = 'multi'; + + await wait(); fixture.detectChanges(); buttonGroup.selectButton(0); buttonGroup.selectButton(1); buttonGroup.selectButton(2); + + await wait(); fixture.detectChanges(); expect(buttonGroup.selectedButtons.length).toBe(3); + buttonGroup.selectionMode = 'single'; + + await wait(); fixture.detectChanges(); expect(buttonGroup.selectedButtons.length).toBe(0); }); - it('Button Group single selection', () => { + it('Button Group single selection', async () => { const fixture = TestBed.createComponent(InitButtonGroupComponent); + + await wait(); fixture.detectChanges(); const buttongroup = fixture.componentInstance.buttonGroup; buttongroup.selectButton(0); + await wait(); expect(buttongroup.selectedButtons.length).toBe(1); expect(buttongroup.buttons.indexOf(buttongroup.selectedButtons[0])).toBe(0); buttongroup.selectButton(2); + await wait(); expect(buttongroup.selectedButtons.length).toBe(1); expect(buttongroup.buttons.indexOf(buttongroup.selectedButtons[0])).toBe(2); }); - it('Button Group single required selection', () => { + it('Button Group single required selection', async () => { const fixture = TestBed.createComponent(InitButtonGroupComponent); + await wait(); fixture.detectChanges(); - + const buttongroup = fixture.componentInstance.buttonGroup; buttongroup.selectionMode = 'singleRequired'; + await wait(); spyOn(buttongroup.deselected, 'emit'); - + buttongroup.selectButton(0); + await wait(); expect(buttongroup.selectedButtons.length).toBe(1); expect(buttongroup.buttons.indexOf(buttongroup.selectedButtons[0])).toBe(0); - + const button = fixture.debugElement.nativeElement.querySelector('button'); button.click(); + await wait(); expect(buttongroup.selectedButtons.length).toBe(1); expect(buttongroup.buttons.indexOf(buttongroup.selectedButtons[0])).toBe(0); expect(buttongroup.deselected.emit).not.toHaveBeenCalled(); }); - it('Button Group multiple selection', () => { + it('Button Group multiple selection', async () => { const fixture = TestBed.createComponent(InitButtonGroupWithValuesComponent); + await wait(); fixture.detectChanges(); const buttongroup = fixture.componentInstance.buttonGroup; expect(buttongroup.selectionMode).toBe('multi'); + buttongroup.selectButton(1); + await wait(); expect(buttongroup.selectedButtons.length).toBe(1); + buttongroup.selectButton(2); + await wait(); expect(buttongroup.selectedButtons.length).toBe(2); + buttongroup.deselectButton(2); buttongroup.deselectButton(1); + await wait(); expect(buttongroup.selectedButtons.length).toBe(0); + buttongroup.selectButton(0); buttongroup.selectButton(3); + await wait(); // Button 3 is disabled, but it can be selected expect(buttongroup.selectedButtons.length).toBe(2); }); - it('Button Group multiple selection with mouse click', () => { + it('Button Group multiple selection with mouse click', async () => { const fixture = TestBed.createComponent(InitButtonGroupWithValuesComponent); + await wait(); fixture.detectChanges(); const buttongroup = fixture.componentInstance.buttonGroup; expect(buttongroup.selectionMode).toBe('multi'); UIInteractions.simulateClickEvent(buttongroup.buttons[0].nativeElement); + await wait(); expect(buttongroup.selectedButtons.length).toBe(1); + UIInteractions.simulateClickEvent(buttongroup.buttons[1].nativeElement); + await wait(); expect(buttongroup.selectedButtons.length).toBe(2); + UIInteractions.simulateClickEvent(buttongroup.buttons[0].nativeElement); UIInteractions.simulateClickEvent(buttongroup.buttons[1].nativeElement); + await wait(); expect(buttongroup.selectedButtons.length).toBe(0); + buttongroup.buttons[0].nativeElement.click(); buttongroup.buttons[3].nativeElement.click(); + await wait(); // Button 3 is disabled, and it should not be selected with mouse click expect(buttongroup.selectedButtons.length).toBe(1); }); - it('Button Group - templated buttons with multiple selection', () => { + it('Button Group - templated buttons with multiple selection', async () => { const fixture = TestBed.createComponent(TemplatedButtonGroupComponent); + await wait(); fixture.detectChanges(); const buttongroup = fixture.componentInstance.buttonGroup; expect(buttongroup.buttons.length).toBe(4); - expect(buttongroup.selectionMode).toBe('multi'); + buttongroup.selectButton(1); + await wait(); expect(buttongroup.selectedButtons.length).toBe(1); + buttongroup.selectButton(2); + await wait(); expect(buttongroup.selectedButtons.length).toBe(2); + buttongroup.deselectButton(1); buttongroup.deselectButton(2); + await wait(); expect(buttongroup.selectedButtons.length).toBe(0); + buttongroup.selectButton(0); buttongroup.selectButton(3); + await wait(); // It should be possible to select disabled buttons expect(buttongroup.selectedButtons.length).toBe(2); + buttongroup.deselectButton(3); + await wait(); expect(buttongroup.selectedButtons.length).toBe(1); }); - it('Button Group - templated buttons with single selection', () => { + it('Button Group - templated buttons with single selection', async () => { const fixture = TestBed.createComponent(TemplatedButtonGroupComponent); + await wait(); fixture.detectChanges(); const buttongroup = fixture.componentInstance.buttonGroup; buttongroup.selectionMode = 'single'; + await wait(); expect(buttongroup.buttons.length).toBe(4); expect(buttongroup.selectionMode).toBe('single'); buttongroup.selectButton(1); + await wait(); expect(buttongroup.selectedButtons.length).toBe(1); expect(buttongroup.buttons.indexOf(buttongroup.selectedButtons[0])).toBe(1); buttongroup.selectButton(2); + await wait(); expect(buttongroup.selectedButtons.length).toBe(1); expect(buttongroup.buttons.indexOf(buttongroup.selectedButtons[0])).toBe(2); buttongroup.deselectButton(2); + await wait(); expect(buttongroup.selectedButtons.length).toBe(0); buttongroup.selectButton(0); buttongroup.selectButton(2); buttongroup.selectButton(3); + await wait(); expect(buttongroup.selectedButtons.length).toBe(1); // Button 3 is disabled, but it can be selected expect(buttongroup.buttons.indexOf(buttongroup.selectedButtons[0])).toBe(3); @@ -382,6 +434,37 @@ describe('IgxButtonGroup', () => { }); })); + it('should correctly change the selection state of a button group and styling of its buttons when bound to another component\'s selection', async () => { + const fixture = TestBed.createComponent(ButtonGroupSelectionBoundToAnotherComponent); + fixture.detectChanges(); + + const radioGroup = fixture.componentInstance.radioGroup; + const buttonGroup = fixture.componentInstance.buttonGroup; + expect(radioGroup.radioButtons.last.checked).toBe(true); + expect(buttonGroup.buttons[1].selected).toBe(true); + expect(buttonGroup.buttons[1].nativeElement.classList.contains('igx-button-group__item--selected')).toBe(true); + + radioGroup.radioButtons.first.select(); + fixture.detectChanges(); + await wait(); + + expect(radioGroup.radioButtons.first.checked).toBe(true); + expect(buttonGroup.buttons[0].selected).toBe(true); + expect(buttonGroup.buttons[0].nativeElement.classList.contains('igx-button-group__item--selected')).toBe(true); + expect(buttonGroup.buttons[1].selected).toBe(false); + expect(buttonGroup.buttons[1].nativeElement.classList.contains('igx-button-group__item--selected')).toBe(false); + + radioGroup.radioButtons.last.select(); + fixture.detectChanges(); + await wait(); + + expect(radioGroup.radioButtons.last.checked).toBe(true); + expect(buttonGroup.buttons[1].selected).toBe(true); + expect(buttonGroup.buttons[1].nativeElement.classList.contains('igx-button-group__item--selected')).toBe(true); + expect(buttonGroup.buttons[0].selected).toBe(false); + expect(buttonGroup.buttons[0].nativeElement.classList.contains('igx-button-group__item--selected')).toBe(false); + }); + }); @Component({ @@ -529,3 +612,42 @@ class ButtonGroupButtonWithBoundSelectedOutputComponent { public selectedValue = 1; } + +@Component({ + template: ` + + + {{ item }} + + + + + + + + `, + standalone: true, + imports: [ IgxButtonGroupComponent, IgxButtonDirective, NgFor, IgxRadioGroupDirective, IgxRadioComponent ] +}) +class ButtonGroupSelectionBoundToAnotherComponent { + @ViewChild('radioGroup', { read: IgxRadioGroupDirective, static: true }) public radioGroup: IgxRadioGroupDirective; + @ViewChild('buttonGroup', { static: true }) public buttonGroup: IgxButtonGroupComponent; + + public selectedValue = 'Bar'; + + public onRadioChange(event: { value: string; }) { + this.selectedValue = event.value; + } + + public get isFirstRadioButtonSelected() { + return this.selectedValue === 'Foo'; + } +} diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.html b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.html index f83660e22cd..bd9b7750437 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.html @@ -7,7 +7,7 @@ igxButton [displayDensity]="esf.displayDensity" [attr.data-togglable]="true" - (click)="onSortButtonClicked(1)" + (buttonSelected)="onSortButtonClicked(1)" > arrow_upwards @@ -21,7 +21,7 @@ igxButton [displayDensity]="esf.displayDensity" [attr.data-togglable]="true" - (click)="onSortButtonClicked(2)" + (buttonSelected)="onSortButtonClicked(2)" > arrow_downwards diff --git a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.ts b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.ts index 1ad0df6e7cb..cf88d737722 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.ts +++ b/projects/igniteui-angular/src/lib/grids/filtering/excel-style/excel-style-sorting.component.ts @@ -52,7 +52,7 @@ export class IgxExcelStyleSortingComponent implements OnDestroy { * @hidden @internal */ public onSortButtonClicked(sortDirection) { - if (this.sortButtonGroup.selectedIndexes.length === 0) { + if (this.sortButtonGroup.buttons.filter(b => b.selected).length === 0) { if (this.esf.grid.isColumnGrouped(this.esf.column.field)) { this.sortButtonGroup.selectButton(sortDirection - 1); } else { diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-advanced.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-advanced.spec.ts index 52fce57cbad..9fdce7ab66f 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-advanced.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-advanced.spec.ts @@ -1,7 +1,7 @@ import { fakeAsync, TestBed, tick, flush, ComponentFixture } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { IgxGridComponent } from './grid.component'; -import { UIInteractions } from '../../test-utils/ui-interactions.spec'; +import { UIInteractions, wait } from '../../test-utils/ui-interactions.spec'; import { configureTestSuite } from '../../test-utils/configure-suite'; import { IgxNumberFilteringOperand, @@ -2286,7 +2286,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { verifyContextMenuVisibility(fix, false); })); - it('Should change the group\'s operator when using its context menu buttons.', fakeAsync(() => { + it('Should change the group\'s operator when using its context menu buttons.', async () => { // Apply advanced filter through API. const tree = new FilteringExpressionsTree(FilteringLogic.And); tree.filteringOperands.push({ @@ -2315,7 +2315,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { // Click the innner group's operator line. operatorLine.click(); - tick(400); + await wait(400); fix.detectChanges(); // Click the 'and' button of the button group in the context menu. @@ -2323,6 +2323,7 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { const andOperatorButton: any = Array.from(buttonGroup.querySelectorAll('.igx-button-group__item')) .find((b: any) => b.textContent.toLowerCase() === 'and'); andOperatorButton.click(); + await wait(); fix.detectChanges(); // Verify new operator of inner group. @@ -2333,12 +2334,13 @@ describe('IgxGrid - Advanced Filtering #grid - ', () => { const orOperatorButton: any = Array.from(buttonGroup.querySelectorAll('.igx-button-group__item')) .find((b: any) => b.textContent.toLowerCase() === 'or'); orOperatorButton.click(); + await wait(); fix.detectChanges(); // Verify new operator of inner group. operatorLine = GridFunctions.getAdvancedFilteringTreeGroupOperatorLine(fix, [1]); verifyOperatorLine(operatorLine, 'or'); - })); + }); it('Should apply changes in the group\'s operator made via its context menu buttons.', fakeAsync(() => { // Apply advanced filter through API. diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-ui.spec.ts b/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-ui.spec.ts index 53358f57fff..22332126b8f 100644 --- a/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-ui.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/grid/grid-filtering-ui.spec.ts @@ -3081,94 +3081,102 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { fix.detectChanges(); })); - it('Should sort the grid properly, when clicking Ascending button.', fakeAsync(() => { + it('Should sort the grid properly, when clicking Ascending button.', async () => { grid.columnList.get(2).sortable = true; fix.detectChanges(); - GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'Downloads'); + GridFunctions.clickExcelFilterIconFromCodeAsync(fix, grid, 'Downloads'); + fix.detectChanges(); + await wait(100); const sortAsc = GridFunctions.getExcelStyleFilteringSortButtons(fix)[0]; - UIInteractions.simulateClickEvent(sortAsc); - tick(DEBOUNCETIME); + sortAsc.click(); + await wait(); fix.detectChanges(); expect(grid.sortingExpressions[0].fieldName).toEqual('Downloads'); expect(grid.sortingExpressions[0].dir).toEqual(SortingDirection.Asc); ControlsFunction.verifyButtonIsSelected(sortAsc); - UIInteractions.simulateClickEvent(sortAsc); - tick(DEBOUNCETIME); + sortAsc.click(); + await wait(); fix.detectChanges(); expect(grid.sortingExpressions.length).toEqual(0); ControlsFunction.verifyButtonIsSelected(sortAsc, false); - })); + }); - it('Should sort the grid properly, when clicking Descending button.', fakeAsync(() => { + it('Should sort the grid properly, when clicking Descending button.', async () => { grid.columnList.get(2).sortable = true; fix.detectChanges(); - GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'Downloads'); + GridFunctions.clickExcelFilterIconFromCodeAsync(fix, grid, 'Downloads'); + await wait(100); + fix.detectChanges(); const sortDesc = GridFunctions.getExcelStyleFilteringSortButtons(fix)[1]; - UIInteractions.simulateClickEvent(sortDesc); - tick(DEBOUNCETIME); + sortDesc.click(); + await wait(); fix.detectChanges(); expect(grid.sortingExpressions[0].fieldName).toEqual('Downloads'); expect(grid.sortingExpressions[0].dir).toEqual(SortingDirection.Desc); ControlsFunction.verifyButtonIsSelected(sortDesc); - UIInteractions.simulateClickEvent(sortDesc); - tick(DEBOUNCETIME); + sortDesc.click(); + await wait(); fix.detectChanges(); expect(grid.sortingExpressions.length).toEqual(0); ControlsFunction.verifyButtonIsSelected(sortDesc, false); - })); + }); - it('Should (sort ASC)/(sort DESC) when clicking the respective sort button.', fakeAsync(() => { + it('Should (sort ASC)/(sort DESC) when clicking the respective sort button.', async () => { grid.columnList.get(2).sortable = true; fix.detectChanges(); - GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'Downloads'); + GridFunctions.clickExcelFilterIconFromCodeAsync(fix, grid, 'Downloads'); + await wait(100); + fix.detectChanges(); const sortAsc = GridFunctions.getExcelStyleFilteringSortButtons(fix)[0]; const sortDesc = GridFunctions.getExcelStyleFilteringSortButtons(fix)[1]; - UIInteractions.simulateClickEvent(sortDesc); - tick(DEBOUNCETIME); + sortDesc.click(); + await wait(); fix.detectChanges(); expect(grid.sortingExpressions[0].fieldName).toEqual('Downloads'); expect(grid.sortingExpressions[0].dir).toEqual(SortingDirection.Desc); ControlsFunction.verifyButtonIsSelected(sortDesc); - UIInteractions.simulateClickEvent(sortAsc); - tick(DEBOUNCETIME); + sortAsc.click(); + await wait(); fix.detectChanges(); expect(grid.sortingExpressions[0].fieldName).toEqual('Downloads'); expect(grid.sortingExpressions[0].dir).toEqual(SortingDirection.Asc); ControlsFunction.verifyButtonIsSelected(sortAsc); ControlsFunction.verifyButtonIsSelected(sortDesc, false); - })); + }); - it('Should toggle correct Ascending/Descending button on opening when sorting is applied.', fakeAsync(() => { + it('Should toggle correct Ascending/Descending button on opening when sorting is applied.', async () => { grid.columnList.get(2).sortable = true; grid.sortingExpressions.push({ dir: SortingDirection.Asc, fieldName: 'Downloads' }); fix.detectChanges(); - GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'Downloads'); + GridFunctions.clickExcelFilterIconFromCodeAsync(fix, grid, 'Downloads'); + await wait(100); + fix.detectChanges(); const sortAsc = GridFunctions.getExcelStyleFilteringSortButtons(fix)[0]; const sortDesc = GridFunctions.getExcelStyleFilteringSortButtons(fix)[1]; ControlsFunction.verifyButtonIsSelected(sortAsc); ControlsFunction.verifyButtonIsSelected(sortDesc, false); - })); + }); it('Should move column left/right when clicking buttons.', fakeAsync(() => { grid.moving = true; @@ -4682,14 +4690,14 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { ControlsFunction.verifyButtonIsSelected(orButton, false); })); - it('Should select the button operator in custom expression when pressing \'Enter\' on it.', fakeAsync(() => { + it('Should select the button operator in custom expression when pressing \'Enter\' on it.', async () => { // Open excel style custom filtering dialog. - GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'ProductName'); + GridFunctions.clickExcelFilterIconFromCodeAsync(fix, grid, 'ProductName'); GridFunctions.clickExcelFilterCascadeButton(fix); fix.detectChanges(); GridFunctions.clickOperatorFromCascadeMenu(fix, 0); - tick(200); + await wait(200); const andButton = GridFunctions.getExcelCustomFilteringExpressionAndButton(fix); const orButton = GridFunctions.getExcelCustomFilteringExpressionOrButton(fix); @@ -4700,6 +4708,7 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Press 'Enter' on 'or' button and verify it gets selected. UIInteractions.triggerKeyDownEvtUponElem('Enter', orButton, true); + await wait(); fix.detectChanges(); ControlsFunction.verifyButtonIsSelected(andButton, false); @@ -4707,11 +4716,12 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => { // Press 'Enter' on 'and' button and verify it gets selected. UIInteractions.triggerKeyDownEvtUponElem('Enter', andButton, true); + await wait(); fix.detectChanges(); ControlsFunction.verifyButtonIsSelected(andButton); ControlsFunction.verifyButtonIsSelected(orButton, false); - })); + }); it('Should open conditions dropdown of custom expression with \'Alt + Arrow Down\'.', fakeAsync(() => { // Open excel style custom filtering dialog.