From 66b1ba9d2fd8ca1a44c9677aec0f244ff3d8517e Mon Sep 17 00:00:00 2001 From: ddaribo Date: Thu, 11 Nov 2021 13:56:26 +0200 Subject: [PATCH] feat(tree-grid): add cascade selection PF/FK tests --- .../tree-grid/tree-grid-selection.spec.ts | 188 +++++++++++++++++- .../lib/test-utils/sample-test-data.spec.ts | 74 ++++++- .../test-utils/tree-grid-components.spec.ts | 20 ++ 3 files changed, 277 insertions(+), 5 deletions(-) diff --git a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-selection.spec.ts b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-selection.spec.ts index 5473eec5c3b..81211d05868 100644 --- a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-selection.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid-selection.spec.ts @@ -2,7 +2,6 @@ import { TestBed, fakeAsync, tick, waitForAsync } from '@angular/core/testing'; import { SortingDirection } from '../../data-operations/sorting-expression.interface'; import { IgxTreeGridComponent } from './tree-grid.component'; import { IgxGridCell, IgxTreeGridModule } from './public_api'; -import { IgxTreeGridCellComponent } from './tree-cell.component'; import { IgxTreeGridSimpleComponent, IgxTreeGridCellSelectionComponent, @@ -11,7 +10,8 @@ import { IgxTreeGridRowEditingTransactionComponent, IgxTreeGridCustomRowSelectorsComponent, IgxTreeGridCascadingSelectionComponent, - IgxTreeGridCascadingSelectionTransactionComponent + IgxTreeGridCascadingSelectionTransactionComponent, + IgxTreeGridPrimaryForeignKeyCascadeSelectionComponent } from '../../test-utils/tree-grid-components.spec'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { @@ -53,7 +53,8 @@ describe('IgxTreeGrid - Selection #tGrid', () => { IgxTreeGridRowEditingTransactionComponent, IgxTreeGridCustomRowSelectorsComponent, IgxTreeGridCascadingSelectionComponent, - IgxTreeGridCascadingSelectionTransactionComponent + IgxTreeGridCascadingSelectionTransactionComponent, + IgxTreeGridPrimaryForeignKeyCascadeSelectionComponent ], imports: [IgxTreeGridModule, NoopAnimationsModule, IgxGridSelectionModule, IgxActionStripModule] }) @@ -1040,7 +1041,7 @@ describe('IgxTreeGrid - Selection #tGrid', () => { })); }); - describe('Cascading Row Selection', () => { + describe('Cascading Row Selection - Child collection data', () => { beforeEach(fakeAsync(() => { fix = TestBed.createComponent(IgxTreeGridCascadingSelectionComponent); fix.detectChanges(); @@ -1755,6 +1756,185 @@ describe('IgxTreeGrid - Selection #tGrid', () => { }); }); + describe('Cascading Row Selection - Primary/Foreign key data', () => { + beforeEach(fakeAsync(() => { + fix = TestBed.createComponent(IgxTreeGridPrimaryForeignKeyCascadeSelectionComponent); + fix.detectChanges(); + treeGrid = fix.componentInstance.treeGrid; + actionStrip = fix.componentInstance.actionStrip; + })); + + it(`Filter out all children for a certain parent, except for one. Select it. + Parent should also become selected. Clear filters. Parent should become in + indeterminate state as there are non-selected children.`, async () => { + treeGrid.filter('ID', 475, IgxNumberFilteringOperand.instance().condition('equals')); + await wait(100); + fix.detectChanges(); + + treeGrid.selectRows([475], true); + await wait(100); + fix.detectChanges(); + + expect(getVisibleSelectedRows(fix).length).toBe(2); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 0, true, true); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 1, true, true); + + treeGrid.clearFilter(); + await wait(100); + fix.detectChanges(); + + expect(getVisibleSelectedRows(fix).length).toBe(1); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 0, false, null); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 1, true, true); + }); + + it(`If there is only one selected leaf row for a particular parent and we filter it out parent's checkbox state -> non-selected. + All non-direct parents’ checkbox states should be set correctly as well`, async () => { + treeGrid.selectRows([711], true); + fix.detectChanges(); + + expect(getVisibleSelectedRows(fix).length).toBe(1); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 0, false, null); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 3, false, null); + + treeGrid.filter('ID', 711, IgxNumberFilteringOperand.instance().condition('doesNotEqual')); + fix.detectChanges(); + + await wait(100); + fix.detectChanges(); + + expect(getVisibleSelectedRows(fix).length).toBe(0); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 0, false, false); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 3, false, false); + }); + + it(`If there is only one non-selected row for a particular parent and we filter it out parent's checkbox state -> selected. + All non-direct parents’ checkbox states should be set correctly as well`, async () => { + treeGrid.selectRows([711, 998], true); + fix.detectChanges(); + + expect(getVisibleSelectedRows(fix).length).toBe(2); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 0, false, null); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 3, false, null); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 4, true, true); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 5, true, true); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 6, false, false); + + treeGrid.filter('ID', 299, IgxNumberFilteringOperand.instance().condition('doesNotEqual')); + fix.detectChanges(); + + await wait(200); + fix.detectChanges(); + + expect(getVisibleSelectedRows(fix).length).toBe(3); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 0, false, null); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 3, true, true); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 4, true, true); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 5, true, true); + }); + + it('After adding a new child row to a selected parent its checkbox state SHOULD be indeterminate.', async () => { + treeGrid.selectRows([847], true); + fix.detectChanges(); + expect(getVisibleSelectedRows(fix).length).toBe(2); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 8, true, true); + TreeGridFunctions.verifyHeaderCheckboxSelection(fix, null); + + const row = treeGrid.gridAPI.get_row_by_index(8); + actionStrip.show(row); + fix.detectChanges(); + + // add new child through the UI + const editActions = fix.debugElement.queryAll(By.css(`igx-grid-action-button`)); + const addChildBtn = editActions[2].componentInstance; + addChildBtn.actionClick.emit(); + fix.detectChanges(); + endTransition(); + + const addRow = treeGrid.gridAPI.get_row_by_index(9); + expect(addRow.addRowUI).toBeTrue(); + + treeGrid.gridAPI.crudService.endEdit(true); + await wait(100); + fix.detectChanges(); + const addedRow = treeGrid.gridAPI.get_row_by_index(10); + expect(addedRow.rowData.Name).toBe(undefined); + + TreeGridFunctions.verifyDataRowsSelection(fix, [9], true); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 8, false, null); + TreeGridFunctions.verifyHeaderCheckboxSelection(fix, null); + }); + + it('If parent and its children are selected and we delete a child, parent SHOULD be still selected.', async () => { + treeGrid.selectRows([147], true); + fix.detectChanges(); + expect(getVisibleSelectedRows(fix).length).toBe(7); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 0, true, true); + TreeGridFunctions.verifyHeaderCheckboxSelection(fix, null); + + expect(treeGrid.dataRowList.length).toBe(10); + + const childRow = treeGrid.gridAPI.get_row_by_index(5); + actionStrip.show(childRow); + fix.detectChanges(); + + // delete the child through the UI + const editActions = fix.debugElement.queryAll(By.css(`igx-grid-action-button`)); + const deleteBtn = editActions[2].componentInstance; + deleteBtn.actionClick.emit(); + fix.detectChanges(); + + await wait(100); + fix.detectChanges(); + + expect(treeGrid.dataRowList.length).toBe(9); + expect(getVisibleSelectedRows(fix).length).toBe(6); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 3, true, true); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 0, true, true); + TreeGridFunctions.verifyHeaderCheckboxSelection(fix, null); + }); + + it('If we delete the only selected child of a parent row, the parent checkbox state SHOULD be deselected', async () => { + treeGrid.selectRows([711], true); + fix.detectChanges(); + expect(getVisibleSelectedRows(fix).length).toBe(1); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 3, false, null); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 0, false, null); + TreeGridFunctions.verifyHeaderCheckboxSelection(fix, null); + + expect(treeGrid.dataRowList.length).toBe(10); + + // delete the child through the API + const childRow = treeGrid.gridAPI.get_row_by_index(4); + childRow.delete(); + fix.detectChanges(); + + await wait(100); + fix.detectChanges(); + + expect(treeGrid.dataRowList.length).toBe(9); + expect(getVisibleSelectedRows(fix).length).toBe(0); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 3, false, false); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 0, false, false); + TreeGridFunctions.verifyHeaderCheckboxSelection(fix, false); + }); + + it(`Set nested child row, that has its own children, as initially selected and verify + that both direct and indirect parent's checkboxes are set in the correct state.`, fakeAsync(() => { + treeGrid.selectedRows = [317]; + fix.detectChanges(); + tick(100); + fix.detectChanges(); + + expect(getVisibleSelectedRows(fix).length).toBe(4); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 0, false, null); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 3, true, true); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 4, true, true); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 5, true, true); + TreeGridFunctions.verifyRowByIndexSelectionAndCheckboxState(fix, 6, true, true); + })); + }); + describe('Cascading Row Selection with Transaction', () => { beforeEach(fakeAsync(() => { fix = TestBed.createComponent(IgxTreeGridCascadingSelectionTransactionComponent); diff --git a/projects/igniteui-angular/src/lib/test-utils/sample-test-data.spec.ts b/projects/igniteui-angular/src/lib/test-utils/sample-test-data.spec.ts index e716a120db8..863341bcf05 100644 --- a/projects/igniteui-angular/src/lib/test-utils/sample-test-data.spec.ts +++ b/projects/igniteui-angular/src/lib/test-utils/sample-test-data.spec.ts @@ -1142,6 +1142,79 @@ export class SampleTestData { } ]); + public static employeeSmallPrimaryForeignKeyTreeData = () => ([ + { + ID: 147, + ParentID: -1, + Name: 'John Winchester', + HireDate: new Date(2008, 3, 20), + Age: 55, + }, + { + ID: 475, + ParentID: 147, + Name: 'Michael Langdon', + HireDate: new Date(2011, 6, 3), + Age: 30, + }, + { + ID: 957, + ParentID: 147, + Name: 'Thomas Hardy', + HireDate: new Date(2009, 6, 19), + Age: 29, + }, + { + ID: 317, + ParentID: 147, + Name: 'Monica Reyes', + HireDate: new Date(2014, 8, 18), + Age: 31, + }, + { + ID: 711, + ParentID: 317, + Name: 'Roland Mendel', + HireDate: new Date(2015, 9, 17), + Age: 35 + }, + { + ID: 998, + ParentID: 317, + Name: 'Sven Ottlieb', + HireDate: new Date(2009, 10, 11), + Age: 44 + }, + { + ID: 299, + ParentID: 317, + Name: 'Peter Lewis', + HireDate: new Date(2018, 3, 18), + Age: 25 + }, + { + ID: 19, + ParentID: -1, + Name: 'Yang Wang', + HireDate: new Date(2010, 1, 1), + Age: 61, + }, + { + ID: 847, + ParentID: -1, + Name: 'Ana Sanders', + HireDate: new Date(2014, 1, 22), + Age: 42, + }, + { + ID: 663, + ParentID: 847, + Name: 'Elizabeth Richards', + HireDate: new Date(2017, 11, 9), + Age: 25 + } + ]); + /* Search tree data: Every employee node has ID, Name, HireDate, Age, JobTitle and Employees */ public static employeeSearchTreeData = () => ([ { @@ -1399,7 +1472,6 @@ export class SampleTestData { Age: 25, OnPTO: false }, - { ID: 141, ParentID: 663, diff --git a/projects/igniteui-angular/src/lib/test-utils/tree-grid-components.spec.ts b/projects/igniteui-angular/src/lib/test-utils/tree-grid-components.spec.ts index d6a8147474c..92e12160ec7 100644 --- a/projects/igniteui-angular/src/lib/test-utils/tree-grid-components.spec.ts +++ b/projects/igniteui-angular/src/lib/test-utils/tree-grid-components.spec.ts @@ -973,3 +973,23 @@ export class IgxTreeGridGroupByAreaTestComponent { @ViewChild(IgxTreeGridGroupByAreaComponent, { static: true }) public groupByArea: IgxTreeGridGroupByAreaComponent; } +@Component({ + template: ` + + + + + + + + + + ` +}) +export class IgxTreeGridPrimaryForeignKeyCascadeSelectionComponent { + @ViewChild(IgxTreeGridComponent, { static: true }) public treeGrid: IgxTreeGridComponent; + @ViewChild('actionStrip', { read: IgxActionStripComponent, static: true }) + public actionStrip: IgxActionStripComponent; + public data = SampleTestData.employeeSmallPrimaryForeignKeyTreeData(); +}