UNPKG

igniteui-angular-sovn

Version:

Ignite UI for Angular is a dependency-free Angular toolkit for building modern web apps

1,137 lines (919 loc) 47.9 kB
import { TestBed, waitForAsync, ComponentFixture } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; import { IgxTreeGridComponent } from './public_api'; import { IgxTreeGridSimpleComponent, IgxTreeGridPrimaryForeignKeyComponent } from '../../test-utils/tree-grid-components.spec'; import { TreeGridFunctions } from '../../test-utils/tree-grid-functions.spec'; import { first } from 'rxjs/operators'; import { UIInteractions } from '../../test-utils/ui-interactions.spec'; import { DropPosition } from '../moving/moving.service'; import { configureTestSuite } from '../../test-utils/configure-suite'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { GridFunctions } from '../../test-utils/grid-functions.spec'; import { DebugElement } from '@angular/core'; const CELL_CSS_CLASS = '.igx-grid__td'; describe('IgxTreeGrid - CRUD #tGrid', () => { configureTestSuite(); let treeGrid: IgxTreeGridComponent; let gridContent: DebugElement; beforeAll(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ NoopAnimationsModule, IgxTreeGridSimpleComponent, IgxTreeGridPrimaryForeignKeyComponent ] }).compileComponents(); })); describe('Create', () => { describe('Child Collection', () => { let fix: ComponentFixture<IgxTreeGridSimpleComponent>; beforeEach(() => { fix = TestBed.createComponent(IgxTreeGridSimpleComponent); treeGrid = fix.componentInstance.treeGrid; treeGrid.height = '800px'; fix.detectChanges(); }); it('should support adding root row through treeGrid API', () => { verifyRowsCount(fix, 3, 10); verifyTreeGridRecordsCount(fix, 3, 10); verifyProcessedTreeGridRecordsCount(fix, 3, 10); const newRow = { ID: 777, Name: 'New Employee', HireDate: new Date(2018, 3, 22), Age: 25, Employees: [] }; treeGrid.addRow(newRow); fix.detectChanges(); verifyRowsCount(fix, 4, 11); verifyTreeGridRecordsCount(fix, 4, 11); verifyProcessedTreeGridRecordsCount(fix, 4, 11); }); it('should support adding child rows through treeGrid API', () => { verifyRowsCount(fix, 3, 10); verifyTreeGridRecordsCount(fix, 3, 10); verifyProcessedTreeGridRecordsCount(fix, 3, 10); let newRow = { ID: 777, Name: 'TEST NAME 1', HireDate: new Date(2018, 3, 22), Age: 25, Employees: [] }; treeGrid.addRow(newRow, 847); fix.detectChanges(); verifyRowsCount(fix, 3, 11); verifyTreeGridRecordsCount(fix, 3, 11); verifyProcessedTreeGridRecordsCount(fix, 3, 11); // Add child row on level 3 newRow = { ID: 999, Name: 'TEST NAME 2', HireDate: new Date(2018, 5, 17), Age: 35, Employees: [] }; treeGrid.addRow(newRow, 317); fix.detectChanges(); verifyRowsCount(fix, 3, 12); verifyTreeGridRecordsCount(fix, 3, 12); verifyProcessedTreeGridRecordsCount(fix, 3, 12); }); it('should do nothing when adding child row to a non-existing parent row', () => { verifyRowsCount(fix, 3, 10); verifyTreeGridRecordsCount(fix, 3, 10); verifyProcessedTreeGridRecordsCount(fix, 3, 10); const newRow = { ID: 383, Name: 'TEST NAME 1', HireDate: new Date(2018, 3, 22), Age: 55, Employees: [] }; let error = ''; try { treeGrid.addRow(newRow, 12345); fix.detectChanges(); } catch (ex) { error = (ex as Error).message; } expect(error).toMatch('Invalid parent row ID!'); verifyRowsCount(fix, 3, 10); verifyTreeGridRecordsCount(fix, 3, 10); verifyProcessedTreeGridRecordsCount(fix, 3, 10); }); it('should support adding child row to \'null\' collection through treeGrid API', () => { const newRow = { ID: 888, Name: 'TEST Child', HireDate: new Date(2011, 1, 11), Age: 25, Employees: [] }; treeGrid.addRow(newRow, 475); fix.detectChanges(); verifyRowsCount(fix, 3, 11); verifyTreeGridRecordsCount(fix, 3, 11); verifyProcessedTreeGridRecordsCount(fix, 3, 11); }); it('should support adding child row to \'undefined\' collection through treeGrid API', () => { const newRow = { ID: 888, Name: 'TEST Child', HireDate: new Date(2011, 1, 11), Age: 25, Employees: [] }; treeGrid.addRow(newRow, 957); fix.detectChanges(); verifyRowsCount(fix, 3, 11); verifyTreeGridRecordsCount(fix, 3, 11); verifyProcessedTreeGridRecordsCount(fix, 3, 11); }); it('should support adding child row to \'non-existing\' collection through treeGrid API', () => { const newRow = { ID: 888, Name: 'TEST Child', HireDate: new Date(2011, 1, 11), Age: 25, Employees: [] }; treeGrid.addRow(newRow, 711); fix.detectChanges(); verifyRowsCount(fix, 3, 11); verifyTreeGridRecordsCount(fix, 3, 11); verifyProcessedTreeGridRecordsCount(fix, 3, 11); }); }); describe('Primary/Foreign key', () => { let fix: ComponentFixture<IgxTreeGridPrimaryForeignKeyComponent>; beforeEach(() => { fix = TestBed.createComponent(IgxTreeGridPrimaryForeignKeyComponent); fix.detectChanges(); treeGrid = fix.componentInstance.treeGrid; treeGrid.height = '800px'; }); it('should support adding root row through treeGrid API', () => { verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); verifyProcessedTreeGridRecordsCount(fix, 3, 8); const newRow = { ID: 777, ParentID: -1, Name: 'New Employee', JobTitle: 'Senior Web Developer', Age: 33 }; treeGrid.addRow(newRow); fix.detectChanges(); verifyRowsCount(fix, 9, 9); verifyTreeGridRecordsCount(fix, 4, 9); verifyProcessedTreeGridRecordsCount(fix, 4, 9); }); it('should support adding child rows through treeGrid API', () => { verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); verifyProcessedTreeGridRecordsCount(fix, 3, 8); let newRow = { ID: 777, ParentID: 1, Name: 'New Employee 1', JobTitle: 'Senior Web Developer', Age: 33 }; treeGrid.addRow(newRow, 1); fix.detectChanges(); verifyRowsCount(fix, 9, 9); verifyTreeGridRecordsCount(fix, 3, 9); verifyProcessedTreeGridRecordsCount(fix, 3, 9); // Add child row on level 2 newRow = { ID: 333, ParentID: 4, Name: 'New Employee 2', JobTitle: 'Senior Web Developer', Age: 33 }; treeGrid.addRow(newRow, 4); fix.detectChanges(); verifyRowsCount(fix, 10, 10); verifyTreeGridRecordsCount(fix, 3, 10); verifyProcessedTreeGridRecordsCount(fix, 3, 10); }); it('should do nothing when adding child row to a non-existing parent row', () => { verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); verifyProcessedTreeGridRecordsCount(fix, 3, 8); let error = ''; const newRow = { ID: 777, ParentID: 12345, // there is no row with ID=12345 Name: 'New Employee 1', JobTitle: 'Senior Web Developer', Age: 33 }; try { treeGrid.addRow(newRow, 12345); fix.detectChanges(); } catch (ex) { error = (ex as Error).message; } expect(error).toMatch('Invalid parent row ID!'); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); verifyProcessedTreeGridRecordsCount(fix, 3, 8); }); it('should support adding child rows to a parent with ID=0 through treeGrid API', () => { verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); verifyProcessedTreeGridRecordsCount(fix, 3, 8); let newRow = { ID: 0, Name: 'New Employee 1', JobTitle: 'Senior Web Developer', Age: 33 }; treeGrid.addRow(newRow); fix.detectChanges(); verifyRowsCount(fix, 9, 9); verifyTreeGridRecordsCount(fix, 4, 9); verifyProcessedTreeGridRecordsCount(fix, 4, 9); // Add child row to the parent with ID=0 newRow = { ID: 333, Name: 'New Employee 2', JobTitle: 'Senior Web Developer', Age: 33 }; treeGrid.addRow(newRow, 0); fix.detectChanges(); verifyRowsCount(fix, 10, 10); verifyTreeGridRecordsCount(fix, 4, 10); verifyProcessedTreeGridRecordsCount(fix, 4, 10); }); }); }); describe('Update API', () => { describe('Child Collection', () => { let fix: ComponentFixture<IgxTreeGridSimpleComponent>; beforeEach(() => { fix = TestBed.createComponent(IgxTreeGridSimpleComponent); fix.detectChanges(); treeGrid = fix.componentInstance.treeGrid; }); it('should support updating a root row through the treeGrid API', () => { verifyCellValue(fix, 0, 'Name', 'John Winchester'); verifyRowsCount(fix, 3, 10); const newRow = { ID: 999, Name: 'New Name', HireDate: new Date(2001, 1, 1), Age: 60, Employees: null }; treeGrid.updateRow(newRow, 147); fix.detectChanges(); verifyCellValue(fix, 0, 'Name', 'New Name'); verifyRowsCount(fix, 3, 4); }); it('should support updating a child row through the treeGrid API', () => { verifyCellValue(fix, 6, 'Name', 'Peter Lewis'); verifyRowsCount(fix, 3, 10); const newRow = { ID: 888, Name: 'New Name', HireDate: new Date(2010, 11, 11), Age: 42, Employees: [] }; treeGrid.updateRow(newRow, 299); fix.detectChanges(); verifyCellValue(fix, 6, 'Name', 'New Name'); verifyRowsCount(fix, 3, 10); }); it('should support updating a child row through the rowObject API', () => { verifyCellValue(fix, 6, 'Name', 'Peter Lewis'); verifyRowsCount(fix, 3, 10); const newRow = { ID: 888, Name: 'New Name', HireDate: new Date(2010, 11, 11), Age: 42, Employees: [] }; treeGrid.getRowByKey(299).update(newRow); fix.detectChanges(); verifyCellValue(fix, 6, 'Name', 'New Name'); verifyRowsCount(fix, 3, 10); }); it('should support updating a child tree-cell through the treeGrid API', () => { // Test prerequisites: move 'Age' column so it becomes the tree-column const sourceColumn = treeGrid.columnList.filter(c => c.field === 'Age')[0]; const targetColumn = treeGrid.columnList.filter(c => c.field === 'ID')[0]; treeGrid.moveColumn(sourceColumn, targetColumn, DropPosition.BeforeDropTarget); fix.detectChanges(); verifyCellValue(fix, 6, 'Age', '25'); verifyRowsCount(fix, 3, 10); const newCellValue = 18; treeGrid.updateCell(newCellValue, 299, 'Age'); fix.detectChanges(); verifyCellValue(fix, 6, 'Age', '18'); verifyRowsCount(fix, 3, 10); }); it('should support updating a child tree-cell through the cellObject API', () => { // Test prerequisites: move 'Age' column so it becomes the tree-column const sourceColumn = treeGrid.columnList.filter(c => c.field === 'Age')[0]; const targetColumn = treeGrid.columnList.filter(c => c.field === 'ID')[0]; treeGrid.moveColumn(sourceColumn, targetColumn, DropPosition.BeforeDropTarget); fix.detectChanges(); verifyCellValue(fix, 6, 'Age', '25'); verifyRowsCount(fix, 3, 10); const newCellValue = 18; treeGrid.getCellByKey(299, 'Age').update(newCellValue); fix.detectChanges(); verifyCellValue(fix, 6, 'Age', '18'); verifyRowsCount(fix, 3, 10); }); }); describe('Primary/Foreign key', () => { let fix: ComponentFixture<IgxTreeGridPrimaryForeignKeyComponent>; beforeEach(() => { fix = TestBed.createComponent(IgxTreeGridPrimaryForeignKeyComponent); fix.detectChanges(); treeGrid = fix.componentInstance.treeGrid; }); it('should support updating a root row through the treeGrid API', () => { verifyCellValue(fix, 0, 'Name', 'Casey Houston'); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); // Update row on level 1 const newRow = { ID: 1, ParentID: -1, Name: 'New Name', JobTitle: 'CFO', Age: 40 }; treeGrid.updateRow(newRow, 1); fix.detectChanges(); verifyCellValue(fix, 0, 'Name', 'New Name'); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); }); it('should support updating a root row by changing its ID (its children should become root rows)', () => { verifyCellValue(fix, 0, 'Name', 'Casey Houston'); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); TreeGridFunctions.verifyRowIndentationLevelByIndex(fix, 1, 1); // Second visible row is on level 2 (childrow) const newRow = { ID: 999, // Original ID is 1 and the new one is 999, which will transform its child rows into root rows. ParentID: -1, Name: 'New Name', JobTitle: 'CFO', Age: 40 }; treeGrid.updateRow(newRow, 1); fix.detectChanges(); verifyCellValue(fix, 0, 'Name', 'New Name'); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 5, 8); // Root records increment count with 2 TreeGridFunctions.verifyRowIndentationLevelByIndex(fix, 1, 0); // Second visible row is now on level 1 (rootrow) }); it('should support updating a child row through the treeGrid API', () => { verifyCellValue(fix, 3, 'Name', 'Debra Morton'); verifyRowsCount(fix, 8, 8); const newRow = { ID: 888, ParentID: 2, Name: 'New Name', JobTitle: 'Web Developer', Age: 42 }; treeGrid.updateRow(newRow, 7); fix.detectChanges(); verifyCellValue(fix, 3, 'Name', 'New Name'); verifyRowsCount(fix, 8, 8); }); it('should support updating a child row through the rowObject API', () => { verifyCellValue(fix, 3, 'Name', 'Debra Morton'); verifyRowsCount(fix, 8, 8); const newRow = { ID: 888, ParentID: 2, Name: 'New Name', JobTitle: 'Web Developer', Age: 42 }; treeGrid.getRowByKey(7).update(newRow); fix.detectChanges(); verifyCellValue(fix, 3, 'Name', 'New Name'); verifyRowsCount(fix, 8, 8); }); it('should support updating a child row by changing its original parentID', () => { verifyCellValue(fix, 3, 'Name', 'Debra Morton'); verifyCellValue(fix, 5, 'Name', 'Erma Walsh'); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); const newRow = { ID: 888, ParentID: -1, // Original ID is 2 and the new one is -1, which will make the row a root row. Name: 'New Name', JobTitle: 'Web Developer', Age: 42 }; treeGrid.getRowByKey(7).update(newRow); fix.detectChanges(); verifyCellValue(fix, 3, 'Name', 'Jack Simon'); verifyCellValue(fix, 5, 'Name', 'New Name'); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 4, 8); // Root rows count increment with 1 due to the row update. }); it('should support updating a child tree-cell through the treeGrid API', () => { // Test prerequisites: move 'Name' column so it becomes the tree-column const sourceColumn = treeGrid.columnList.filter(c => c.field === 'Name')[0]; const targetColumn = treeGrid.columnList.filter(c => c.field === 'ID')[0]; treeGrid.moveColumn(sourceColumn, targetColumn, DropPosition.BeforeDropTarget); fix.detectChanges(); verifyCellValue(fix, 3, 'Name', 'Debra Morton'); verifyRowsCount(fix, 8, 8); const newCellValue = 'Michael Myers'; treeGrid.updateCell(newCellValue, 7, 'Name'); fix.detectChanges(); verifyCellValue(fix, 3, 'Name', 'Michael Myers'); verifyRowsCount(fix, 8, 8); }); it('should support updating a child tree-cell through the cellObject API', () => { // Test prerequisites: move 'Name' column so it becomes the tree-column const sourceColumn = treeGrid.columnList.filter(c => c.field === 'Name')[0]; const targetColumn = treeGrid.columnList.filter(c => c.field === 'ID')[0]; treeGrid.moveColumn(sourceColumn, targetColumn, DropPosition.BeforeDropTarget); fix.detectChanges(); verifyCellValue(fix, 3, 'Name', 'Debra Morton'); verifyRowsCount(fix, 8, 8); const newCellValue = 'Michael Myers'; treeGrid.getCellByKey(7, 'Name').update(newCellValue); fix.detectChanges(); verifyCellValue(fix, 3, 'Name', 'Michael Myers'); verifyRowsCount(fix, 8, 8); }); }); }); describe('Update UI', () => { describe('Child Collection', () => { let fix: ComponentFixture<IgxTreeGridSimpleComponent>; beforeEach(() => { fix = TestBed.createComponent(IgxTreeGridSimpleComponent); fix.detectChanges(); treeGrid = fix.componentInstance.treeGrid; for (const col of treeGrid.columnList) { col.editable = true; } gridContent = GridFunctions.getGridContent(fix); }); it('should be able to enter edit mode of a tree-grid column on dblclick, enter and F2', () => { const cell = treeGrid.getCellByColumn(0, 'ID'); UIInteractions.simulateDoubleClickAndSelectEvent(treeGrid.gridAPI.get_cell_by_index(0, 'ID')); fix.detectChanges(); expect(cell.editMode).toBe(true, 'cannot enter edit mode with double click'); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with double click'); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(true, 'cannot enter edit mode with enter'); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with enter'); UIInteractions.triggerEventHandlerKeyDown('f2', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(true, 'cannot enter edit mode with F2'); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with F2'); }); it('should be able to enter edit mode of a non-tree-grid column on dblclick, enter and F2', () => { const cell = treeGrid.getCellByColumn(0, 'Name'); UIInteractions.simulateDoubleClickAndSelectEvent(treeGrid.gridAPI.get_cell_by_index(0, 'Name')); fix.detectChanges(); expect(cell.editMode).toBe(true, 'cannot enter edit mode with double click'); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with double click'); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(true, 'cannot enter edit mode with enter'); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with enter'); UIInteractions.triggerEventHandlerKeyDown('f2', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(true, 'cannot enter edit mode with F2'); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with F2'); }); it('should be able to edit a tree-grid cell through UI', () => { const cell = treeGrid.getCellByColumn(0, 'ID'); const cellDomNumber = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[0]; UIInteractions.simulateDoubleClickAndSelectEvent(treeGrid.gridAPI.get_cell_by_index(0, 'ID')); fix.detectChanges(); expect(cell.editMode).toBe(true); const editTemplate = cellDomNumber.query(By.css('input')); expect(editTemplate).toBeDefined(); UIInteractions.clickAndSendInputElementValue(editTemplate, 146); fix.detectChanges(); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false); expect(parseInt(cell.value, 10)).toBe(146); expect(editTemplate.nativeElement.type).toBe('number'); verifyCellValue(fix, 0, 'ID', '146'); }); it('should be able to edit a non-tree-grid cell through UI', () => { const cell = treeGrid.getCellByColumn(0, 'Name'); const cellDomNumber = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[1]; UIInteractions.simulateDoubleClickAndSelectEvent(treeGrid.gridAPI.get_cell_by_index(0, 'Name')); fix.detectChanges(); expect(cell.editMode).toBe(true); const editTemplate = cellDomNumber.query(By.css('input')); expect(editTemplate).toBeDefined(); UIInteractions.clickAndSendInputElementValue(editTemplate, 'Abc Def'); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false); expect(cell.value).toBe('Abc Def'); expect(editTemplate.nativeElement.type).toBe('text'); verifyCellValue(fix, 0, 'Name', 'Abc Def'); }); it('should emit an event when editing a tree-grid cell through UI', () => { const cellComponent = treeGrid.getCellByColumn(0, 'ID'); const cellDomNumber = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[0]; treeGrid.cellEdit.pipe(first()).subscribe((args) => { expect(args.newValue).toBe(146); }); UIInteractions.simulateDoubleClickAndSelectEvent(treeGrid.gridAPI.get_cell_by_index(0, 'ID')); fix.detectChanges(); expect(cellComponent.editMode).toBe(true); let editTemplate = cellDomNumber.query(By.css('input')); expect(editTemplate).toBeDefined(); UIInteractions.clickAndSendInputElementValue(editTemplate, '146'); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fix.detectChanges(); expect(cellComponent.editMode).toBe(false); expect(cellComponent.value).toBe(146); editTemplate = cellDomNumber.query(By.css('input')); expect(editTemplate).toBeNull(); }); }); describe('Primary/Foreign key', () => { let fix: ComponentFixture<IgxTreeGridPrimaryForeignKeyComponent>; beforeEach(() => { fix = TestBed.createComponent(IgxTreeGridPrimaryForeignKeyComponent); fix.detectChanges(); treeGrid = fix.componentInstance.treeGrid; for (const col of treeGrid.columnList) { col.editable = true; } gridContent = GridFunctions.getGridContent(fix); }); it('should be able to enter edit mode of a tree-grid column on dblclick, enter and F2', () => { const cell = treeGrid.getCellByColumn(0, 'ID'); UIInteractions.simulateDoubleClickAndSelectEvent(treeGrid.gridAPI.get_cell_by_index(0, 'ID')); fix.detectChanges(); expect(cell.editMode).toBe(true, 'cannot enter edit mode with double click'); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with double click'); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(true, 'cannot enter edit mode with enter'); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with enter'); UIInteractions.triggerEventHandlerKeyDown('f2', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(true, 'cannot enter edit mode with F2'); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with F2'); }); it('should be able to enter edit mode of a non-tree-grid column on dblclick, enter and F2', () => { const cell = treeGrid.getCellByColumn(0, 'Name'); UIInteractions.simulateDoubleClickAndSelectEvent(treeGrid.gridAPI.get_cell_by_index(0, 'Name')); fix.detectChanges(); expect(cell.editMode).toBe(true, 'cannot enter edit mode with double click'); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with double click'); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(true, 'cannot enter edit mode with enter'); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with enter'); UIInteractions.triggerEventHandlerKeyDown('f2', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(true, 'cannot enter edit mode with F2'); UIInteractions.triggerEventHandlerKeyDown('escape', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false, 'cannot exit edit mode after entering with F2'); }); it('should be able to edit a tree-grid cell through UI', () => { const cell = treeGrid.getCellByColumn(0, 'ID'); const cellDomNumber = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[0]; UIInteractions.simulateDoubleClickAndSelectEvent(treeGrid.gridAPI.get_cell_by_index(0, 'ID')); fix.detectChanges(); expect(cell.editMode).toBe(true); const editTemplate = cellDomNumber.query(By.css('input')); expect(editTemplate).toBeDefined(); UIInteractions.clickAndSendInputElementValue(editTemplate, 146); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false); expect(parseInt(cell.value, 10)).toBe(146); expect(editTemplate.nativeElement.type).toBe('number'); verifyCellValue(fix, 0, 'ID', '146'); }); it('should be able to edit a non-tree-grid cell through UI', () => { const cell = treeGrid.getCellByColumn(0, 'Name'); const cellDomNumber = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[2]; UIInteractions.simulateDoubleClickAndSelectEvent(treeGrid.gridAPI.get_cell_by_index(0, 'Name')); fix.detectChanges(); expect(cell.editMode).toBe(true); const editTemplate = cellDomNumber.query(By.css('input')); expect(editTemplate).toBeDefined(); UIInteractions.clickAndSendInputElementValue(editTemplate, 'Abc Def'); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fix.detectChanges(); expect(cell.editMode).toBe(false); expect(cell.value).toBe('Abc Def'); expect(editTemplate.nativeElement.type).toBe('text'); verifyCellValue(fix, 0, 'Name', 'Abc Def'); }); it('should emit an event when editing a tree-grid cell through UI', () => { const cellComponent = treeGrid.getCellByColumn(0, 'ID'); const cellDomNumber = fix.debugElement.queryAll(By.css(CELL_CSS_CLASS))[0]; treeGrid.cellEdit.pipe(first()).subscribe((args) => { expect(args.newValue).toBe(146); }); UIInteractions.simulateDoubleClickAndSelectEvent(treeGrid.gridAPI.get_cell_by_index(0, 'ID')); fix.detectChanges(); expect(cellComponent.editMode).toBe(true); let editTemplate = cellDomNumber.query(By.css('input')); expect(editTemplate).toBeDefined(); UIInteractions.clickAndSendInputElementValue(editTemplate, '146'); UIInteractions.triggerEventHandlerKeyDown('enter', gridContent); fix.detectChanges(); expect(cellComponent.editMode).toBe(false); expect(cellComponent.value).toBe(146); editTemplate = cellDomNumber.query(By.css('input')); expect(editTemplate).toBeNull(); }); it('should allow changing the row edit mode runtime.', () => { const cell = treeGrid.getCellByColumn(0, 'Name'); cell.column.editable = true; treeGrid.rowEditable = true; fix.detectChanges(); cell.editMode = true; fix.detectChanges(); expect(cell.row.inEditMode).toBeTrue(); treeGrid.rowEditable = false; fix.detectChanges(); cell.editValue = true; fix.detectChanges(); expect(cell.row.inEditMode).toBeFalse(); }); }); }); describe('Delete', () => { describe('Child Collection', () => { let fix: ComponentFixture<IgxTreeGridSimpleComponent>; beforeEach(() => { fix = TestBed.createComponent(IgxTreeGridSimpleComponent); fix.detectChanges(); treeGrid = fix.componentInstance.treeGrid; }); it('should delete a root level row by ID', () => { let someRow = treeGrid.getRowByIndex(0); expect(someRow.key).toBe(147); verifyRowsCount(fix, 3, 10); verifyTreeGridRecordsCount(fix, 3, 10); verifyProcessedTreeGridRecordsCount(fix, 3, 10); treeGrid.deleteRow(someRow.key); fix.detectChanges(); someRow = treeGrid.getRowByIndex(0); expect(someRow.key).toBe(19); verifyRowsCount(fix, 2, 3); verifyTreeGridRecordsCount(fix, 2, 3); verifyProcessedTreeGridRecordsCount(fix, 2, 3); }); it('should delete a child level row by ID', () => { let someRow = treeGrid.getRowByIndex(3); expect(someRow.key).toBe(317); verifyRowsCount(fix, 3, 10); verifyTreeGridRecordsCount(fix, 3, 10); verifyProcessedTreeGridRecordsCount(fix, 3, 10); treeGrid.deleteRow(someRow.key); fix.detectChanges(); someRow = treeGrid.getRowByIndex(3); expect(someRow.key).toBe(19); verifyRowsCount(fix, 3, 6); verifyTreeGridRecordsCount(fix, 3, 6); verifyProcessedTreeGridRecordsCount(fix, 3, 6); }); it('should delete a root level row through the row object', () => { let someRow = treeGrid.getRowByIndex(0); expect(someRow.key).toBe(147); verifyRowsCount(fix, 3, 10); verifyTreeGridRecordsCount(fix, 3, 10); verifyProcessedTreeGridRecordsCount(fix, 3, 10); someRow.delete(); fix.detectChanges(); someRow = treeGrid.getRowByIndex(0); expect(someRow.key).toBe(19); verifyRowsCount(fix, 2, 3); verifyTreeGridRecordsCount(fix, 2, 3); verifyProcessedTreeGridRecordsCount(fix, 2, 3); }); it('should delete a child level row through the row object', () => { let someRow = treeGrid.getRowByIndex(3); expect(someRow.key).toBe(317); verifyRowsCount(fix, 3, 10); verifyTreeGridRecordsCount(fix, 3, 10); verifyProcessedTreeGridRecordsCount(fix, 3, 10); someRow.delete(); fix.detectChanges(); someRow = treeGrid.getRowByIndex(3); expect(someRow.key).toBe(19); verifyRowsCount(fix, 3, 6); verifyTreeGridRecordsCount(fix, 3, 6); verifyProcessedTreeGridRecordsCount(fix, 3, 6); }); }); describe('Primary/Foreign key', () => { let fix: ComponentFixture<IgxTreeGridPrimaryForeignKeyComponent>; beforeEach(() => { fix = TestBed.createComponent(IgxTreeGridPrimaryForeignKeyComponent); fix.detectChanges(); treeGrid = fix.componentInstance.treeGrid; treeGrid.cascadeOnDelete = false; }); it('should delete a root level row by ID', () => { spyOn(treeGrid.rowDelete, 'emit').and.callThrough(); spyOn(treeGrid.rowDeleted, 'emit').and.callThrough(); let someRow = treeGrid.getRowByIndex(0); expect(someRow.key).toBe(1); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); verifyProcessedTreeGridRecordsCount(fix, 3, 8); const rowDeleteArgs = { rowID: someRow.key, primaryKey: someRow.key, cancel: false, rowData: treeGrid.getRowData(someRow.key), oldValue: null, owner: treeGrid }; const rowDeletedArgs = { data: treeGrid.getRowData(someRow.key), primaryKey: someRow.key, owner: treeGrid }; treeGrid.deleteRow(someRow.key); fix.detectChanges(); expect(treeGrid.rowDelete.emit).toHaveBeenCalledOnceWith(rowDeleteArgs); expect(treeGrid.rowDeleted.emit).toHaveBeenCalledOnceWith(rowDeletedArgs); someRow = treeGrid.getRowByIndex(0); expect(someRow.key).toBe(2); verifyRowsCount(fix, 7, 7); verifyTreeGridRecordsCount(fix, 4, 7); verifyProcessedTreeGridRecordsCount(fix, 4, 7); }); it('should cancel rowDelete event', () => { spyOn(treeGrid.rowDelete, 'emit').and.callThrough(); spyOn(treeGrid.rowDeleted, 'emit').and.callThrough(); let someRow = treeGrid.getRowByIndex(0); expect(someRow.key).toBe(1); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); verifyProcessedTreeGridRecordsCount(fix, 3, 8); treeGrid.rowDelete.subscribe((e: any) => { e.cancel = true; }); const rowDeleteArgs = { rowID: someRow.key, primaryKey: someRow.key, cancel: true, rowData: treeGrid.getRowData(someRow.key), oldValue: null, owner: treeGrid }; treeGrid.deleteRow(someRow.key); fix.detectChanges(); expect(treeGrid.rowDelete.emit).toHaveBeenCalledOnceWith(rowDeleteArgs); expect(treeGrid.rowDeleted.emit).toHaveBeenCalledTimes(0); someRow = treeGrid.getRowByIndex(0); expect(someRow.key).toBe(1); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); verifyProcessedTreeGridRecordsCount(fix, 3, 8); }); it('should delete a child level row by ID', () => { let someRow = treeGrid.getRowByIndex(1); expect(someRow.key).toBe(2); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); verifyProcessedTreeGridRecordsCount(fix, 3, 8); treeGrid.deleteRow(someRow.key); fix.detectChanges(); someRow = treeGrid.getRowByIndex(1); expect(someRow.key).toBe(4); verifyRowsCount(fix, 7, 7); verifyTreeGridRecordsCount(fix, 5, 7); verifyProcessedTreeGridRecordsCount(fix, 5, 7); }); it('should delete a root level row through the row object', () => { let someRow = treeGrid.getRowByIndex(0); expect(someRow.key).toBe(1); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); verifyProcessedTreeGridRecordsCount(fix, 3, 8); someRow.delete(); fix.detectChanges(); someRow = treeGrid.getRowByIndex(0); expect(someRow.key).toBe(2); verifyRowsCount(fix, 7, 7); verifyTreeGridRecordsCount(fix, 4, 7); verifyProcessedTreeGridRecordsCount(fix, 4, 7); }); it('should delete a child level row through the row object', () => { let someRow = treeGrid.getRowByIndex(1); expect(someRow.key).toBe(2); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); verifyProcessedTreeGridRecordsCount(fix, 3, 8); someRow.delete(); fix.detectChanges(); someRow = treeGrid.getRowByIndex(1); expect(someRow.key).toBe(4); verifyRowsCount(fix, 7, 7); verifyTreeGridRecordsCount(fix, 5, 7); verifyProcessedTreeGridRecordsCount(fix, 5, 7); }); it('should delete child rows of a parent row when the "cascadeOnDelete" is set (delete by ID)', () => { treeGrid.cascadeOnDelete = true; let aRow = treeGrid.getRowByIndex(0); expect(aRow.key).toBe(1); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); verifyProcessedTreeGridRecordsCount(fix, 3, 8); treeGrid.deleteRow(aRow.key); fix.detectChanges(); aRow = treeGrid.getRowByIndex(0); expect(aRow.key).toBe(6); verifyRowsCount(fix, 3, 3); verifyTreeGridRecordsCount(fix, 2, 3); verifyProcessedTreeGridRecordsCount(fix, 2, 3); }); it('should delete child rows of a parent row when the "cascadeOnDelete" is set (delete by API)', () => { treeGrid.cascadeOnDelete = true; let aRow = treeGrid.getRowByIndex(0); expect(aRow.key).toBe(1); verifyRowsCount(fix, 8, 8); verifyTreeGridRecordsCount(fix, 3, 8); verifyProcessedTreeGridRecordsCount(fix, 3, 8); aRow.delete(); fix.detectChanges(); aRow = treeGrid.getRowByIndex(0); expect(aRow.key).toBe(6); verifyRowsCount(fix, 3, 3); verifyTreeGridRecordsCount(fix, 2, 3); verifyProcessedTreeGridRecordsCount(fix, 2, 3); }); }); }); }); const verifyRowsCount = (fix, expectedRootRowsCount, expectedVisibleRowsCount) => { const treeGrid = fix.componentInstance.treeGrid; expect(TreeGridFunctions.getAllRows(fix).length).toBe(expectedVisibleRowsCount, 'Incorrect DOM rows length.'); expect(treeGrid.data.length).toBe(expectedRootRowsCount, 'Incorrect data length.'); expect(treeGrid.dataRowList.length).toBe(expectedVisibleRowsCount, 'Incorrect dataRowList length.'); }; const verifyTreeGridRecordsCount = (fix, expectedRootRecordsCount, expectedFlatRecordsCount) => { const treeGrid = fix.componentInstance.treeGrid as IgxTreeGridComponent; expect(treeGrid.rootRecords.length).toBe(expectedRootRecordsCount); expect(treeGrid.records.size).toBe(expectedFlatRecordsCount); }; const verifyProcessedTreeGridRecordsCount = (fix, expectedProcessedRootRecordsCount, expectedProcessedFlatRecordsCount) => { const treeGrid = fix.componentInstance.treeGrid as IgxTreeGridComponent; expect(treeGrid.processedRootRecords.length).toBe(expectedProcessedRootRecordsCount); expect(treeGrid.processedRecords.size).toBe(expectedProcessedFlatRecordsCount); }; const verifyCellValue = (fix, rowIndex, columnKey, expectedCellValue) => { const treeGrid = fix.componentInstance.treeGrid; const actualValue = TreeGridFunctions.getCellValue(fix, rowIndex, columnKey); const actualAPIValue = treeGrid.gridAPI.get_row_by_index(rowIndex).cells.filter((c) => c.column.field === columnKey)[0].value; expect(actualValue.toString()).toBe(expectedCellValue, 'incorrect cell value'); expect(actualAPIValue.toString()).toBe(expectedCellValue, 'incorrect api cell value'); };