UNPKG

igniteui-angular-sovn

Version:

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

1,132 lines (964 loc) 114 kB
import { DebugElement, QueryList } from '@angular/core'; import { By } from '@angular/platform-browser'; import { ComponentFixture, tick } from '@angular/core/testing'; import { IgxInputDirective } from '../input-group/public_api'; import { IgxGridHeaderComponent } from '../grids/headers/grid-header.component'; import { IgxChipComponent } from '../chips/public_api'; import { IgxGridComponent } from '../grids/grid/grid.component'; import { IgxColumnGroupComponent } from '../grids/columns/column-group.component'; import { IgxGridHeaderGroupComponent } from '../grids/headers/grid-header-group.component'; import { UIInteractions, wait } from './ui-interactions.spec'; import { ControlsFunction } from './controls-functions.spec'; import { IgxGridExpandableCellComponent } from '../grids/grid/expandable-cell.component'; import { IgxColumnHidingDirective } from '../grids/column-actions/column-hiding.directive'; import { IgxColumnPinningDirective } from '../grids/column-actions/column-pinning.directive'; import { parseDate } from '../core/utils'; import { IgxGridHeaderRowComponent } from '../grids/headers/grid-header-row.component'; import { IgxGridRowComponent } from '../grids/grid/grid-row.component'; import { IgxGridCellComponent } from '../grids/cell.component'; import { IgxPivotRowComponent } from '../grids/pivot-grid/pivot-row.component'; import { SortingDirection } from '../data-operations/sorting-strategy'; import { IgxRowDirective } from '../grids/row.directive'; import { CellType, GridType, RowType } from '../grids/common/grid.interface'; import { IgxTreeNodeComponent } from '../tree/tree-node/tree-node.component'; import { IgxColumnComponent } from '../grids/columns/column.component'; import { IgxPivotGridComponent } from '../grids/pivot-grid/pivot-grid.component'; const SUMMARY_LABEL_CLASS = '.igx-grid-summary__label'; const SUMMARY_ROW = 'igx-grid-summary-row'; const SUMMARY_CELL_ACTIVE_CSS_CLASS = 'igx-grid-summary--active'; const FILTER_UI_CELL = 'igx-grid-filtering-cell'; const FILTER_UI_ROW = 'igx-grid-filtering-row'; const FILTER_UI_CONNECTOR = 'igx-filtering-chips__connector'; const FILTER_ROW_BUTTONS_CLASS = '.igx-grid__filtering-row-editing-buttons'; const FILTER_UI_INDICATOR = 'igx-grid__filtering-cell-indicator'; const FILTER_CHIP_CLASS = '.igx-filtering-chips'; const ESF_MENU_CLASS = '.igx-excel-filter__menu'; const ESF_SORT_CLASS = '.igx-excel-filter__sort'; const ESF_MOVE_CLASS = '.igx-excel-filter__move'; const ESF_CUSTOM_FILTER_DIALOG_CLASS = '.igx-excel-filter__secondary'; const ESF_FILTER_ICON = '.igx-excel-filter__icon'; const ESF_FILTER_ICON_FILTERED = '.igx-excel-filter__icon--filtered'; const ESF_ADD_FILTER_CLASS = '.igx-excel-filter__add-filter'; const ESF_DEFAULT_EXPR = 'igx-excel-style-default-expression'; const ESF_DATE_EXPR = 'igx-excel-style-date-expression'; const BANNER_CLASS = '.igx-banner'; const BANNER_TEXT_CLASS = '.igx-banner__text'; const BANNER_ROW_CLASS = '.igx-banner__row'; const EDIT_OVERLAY_CONTENT = '.igx-overlay__content'; const PAGER_BUTTONS = 'igx-page-nav > button'; const ACTIVE_GROUP_ROW_CLASS = 'igx-grid__group-row--active'; const ACTIVE_HEADER_CLASS = 'igx-grid-th--active'; const GROUP_ROW_CLASS = 'igx-grid-groupby-row'; const CELL_SELECTED_CSS_CLASS = 'igx-grid__td--selected'; const CELL_INVALID_CSS_CLASS = 'igx-grid__td--invalid'; const CELL_ACTIVE_CSS_CLASS = 'igx-grid__td--active'; const ROW_DIV_SELECTION_CHECKBOX_CSS_CLASS = 'igx-grid__cbx-selection'; const ROW_SELECTION_CSS_CLASS = 'igx-grid__tr--selected'; const HEADER_ROW_CSS_CLASS = '.igx-grid-thead'; const CHECKBOX_INPUT_CSS_CLASS = '.igx-checkbox__input'; const CHECKBOX_ELEMENT = 'igx-checkbox'; const ICON_CSS_CLASS = 'material-icons igx-icon'; const CHECKBOX_LBL_CSS_CLASS = '.igx-checkbox__composite'; const GROUP_EXPANDER_CLASS = '.igx-grid-th__expander'; const GROUP_HEADER_CLASS = '.igx-grid-th__group-title'; const CELL_CSS_CLASS = '.igx-grid__td'; const ROW_CSS_CLASS = '.igx-grid__tr'; const FOCUSED_CHECKBOX_CLASS = 'igx-checkbox--focused'; const GRID_BODY_CLASS = '.igx-grid__tbody'; const GRID_FOOTER_CLASS = '.igx-grid__tfoot'; const GRID_CONTENT_CLASS = '.igx-grid__tbody-content'; const DISPLAY_CONTAINER = 'igx-display-container'; const SORT_ICON_CLASS = '.sort-icon'; const FILTER_ICON_CLASS = '.igx-excel-filter__icon'; const SELECTED_COLUMN_CLASS = 'igx-grid-th--selected'; const HOVERED_COLUMN_CLASS = 'igx-grid-th--selectable'; const SELECTED_COLUMN_CELL_CLASS = 'igx-grid__td--column-selected'; const FOCUSED_DETAILS_ROW_CLASS = 'igx-grid__tr-container--active'; const DRAG_INDICATOR_CLASS = '.igx-grid__drag-indicator'; const SORTED_COLUMN_CLASS = 'igx-grid-th--sorted'; const SORTING_ICON_ASC_CONTENT = 'arrow_upward'; const SORTING_ICON_DESC_CONTENT = 'arrow_downward'; const SUMMARY_CELL = 'igx-grid-summary-cell'; const COLUMN_ACTIONS_INPUT_CLASS = '.igx-column-actions__header-input'; const COLUMN_ACTIONS_COLUMNS_CLASS = '.igx-column-actions__columns'; const COLUMN_ACTIONS_COLUMNS_LABEL_CLASS = 'igx-checkbox__label'; const GRID_TOOLBAR_TAG = 'igx-grid-toolbar'; const GRID_TOOLBAR_EXPORT_BUTTON_CLASS = '.igx-grid-toolbar__dropdown#btnExport'; const GRID_OUTLET_CLASS = 'div.igx-grid__outlet'; const SORT_INDEX_ATTRIBUTE = 'data-sortIndex'; const RESIZE_LINE_CLASS = '.igx-grid-th__resize-line'; const RESIZE_AREA_CLASS = '.igx-grid-th__resize-handle'; const GRID_COL_THEAD_CLASS = '.igx-grid-th'; const TREE_NODE_TOGGLE = '.igx-tree-node__toggle-button'; export const GRID_SCROLL_CLASS = '.igx-grid__scroll'; export const GRID_MRL_BLOCK = 'igx-grid__mrl-block'; export const CELL_PINNED_CLASS = 'igx-grid__td--pinned'; export const HEADER_PINNED_CLASS = 'igx-grid-th--pinned'; export const GRID_HEADER_CLASS = '.igx-grid-thead__wrapper'; export const PINNED_SUMMARY = 'igx-grid-summary--pinned'; export const PAGER_CLASS = '.igx-page-nav'; export const SAFE_DISPOSE_COMP_ID = 'root'; export class GridFunctions { public static getRows(fix): DebugElement[] { const rows: DebugElement[] = fix.debugElement.queryAll(By.css(ROW_CSS_CLASS)); rows.shift(); return rows; } public static getRowCells(fix, rowIndex: number, row: DebugElement = null): DebugElement[] { const rowElement = row ? row : GridFunctions.getRows(fix)[rowIndex]; return rowElement.queryAll(By.css(CELL_CSS_CLASS)); } public static getGridBody(fix): DebugElement { return fix.debugElement.query(By.css(GRID_BODY_CLASS)); } public static getGridContent(fix): DebugElement { return fix.debugElement.query(By.css(GRID_CONTENT_CLASS)); } public static getGridHeader(grid: GridType): IgxGridHeaderRowComponent { return grid.theadRow; } public static getGridDisplayContainer(fix): DebugElement { const gridBody = this.getGridBody(fix); return gridBody.query(By.css(DISPLAY_CONTAINER)); } public static getGridFooterWrapper(fix): DebugElement { return fix.debugElement.query(By.css(GRID_FOOTER_CLASS)); } public static getGridFooter(fix): DebugElement { return fix.debugElement.query(By.css(GRID_FOOTER_CLASS)).children[0]; } public static getGridScroll(fix): DebugElement { return fix.debugElement.query(By.css(GRID_SCROLL_CLASS)); } public static getRowDisplayContainer(fix, index: number): DebugElement { const row = GridFunctions.getRows(fix)[index]; return row.query(By.css(DISPLAY_CONTAINER)); } public static getColGroup(grid: IgxGridComponent | IgxPivotGridComponent, headerName: string): IgxColumnGroupComponent { const colGroups = grid.columns.filter(c => c.columnGroup && c.header === headerName); if (colGroups.length === 0) { return null; } else if (colGroups.length === 1) { return colGroups[0]; } else { throw new Error('More than one column group found.'); } } public static getPivotRows(fix): DebugElement[] { const rows: DebugElement[] = fix.debugElement.queryAll(By.directive(IgxPivotRowComponent)); return rows; } /** * Focus the grid header */ public static focusHeader(fix: ComponentFixture<any>, grid: GridType) { this.getGridHeader(grid).nativeElement.focus(); fix.detectChanges(); } /** * Focus the first cell in the grid */ public static focusFirstCell(fix: ComponentFixture<any>, grid: GridType) { this.getGridHeader(grid).nativeElement.focus(); fix.detectChanges(); this.getGridContent(fix).triggerEventHandler('focus', null); fix.detectChanges(); } /** * Focus the cell in the grid */ public static focusCell(fix: ComponentFixture<any>, cell: IgxGridCellComponent | CellType) { this.getGridContent(fix).triggerEventHandler('focus', null); fix.detectChanges(); cell.activate(null); fix.detectChanges(); } public static scrollLeft(grid: IgxGridComponent, newLeft: number) { const hScrollbar = grid.headerContainer.getScroll(); hScrollbar.scrollLeft = newLeft; } public static scrollTop(grid: IgxGridComponent, newTop: number) { const vScrollbar = grid.verticalScrollContainer.getScroll(); vScrollbar.scrollTop = newTop; } public static getMasterRowDetail(row) { const nextSibling = row.element.nativeElement.nextElementSibling; if (nextSibling && nextSibling.tagName.toLowerCase() === 'div' && nextSibling.getAttribute('detail') === 'true') { return nextSibling; } return null; } public static verifyMasterDetailRowFocused(row: HTMLElement, focused = true) { expect(row.classList.contains(FOCUSED_DETAILS_ROW_CLASS)).toEqual(focused); } public static setAllExpanded(grid: IgxGridComponent, data: Array<any>) { const allExpanded = new Map<any, boolean>(); data.forEach(item => { allExpanded.set(item['ID'], true); }); grid.expansionStates = allExpanded; } public static elementInGridView(grid: IgxGridComponent, element: HTMLElement): boolean { const gridBottom = grid.tbody.nativeElement.getBoundingClientRect().bottom; const gridTop = grid.tbody.nativeElement.getBoundingClientRect().top; return element.getBoundingClientRect().top >= gridTop && element.getBoundingClientRect().bottom <= gridBottom; } public static toggleMasterRowByClick = (fix, row: IgxGridRowComponent, debounceTime) => new Promise<void>(async (resolve) => { const icon = row.element.nativeElement.querySelector('igx-icon'); UIInteractions.simulateClickAndSelectEvent(icon.parentElement); await wait(debounceTime); fix.detectChanges(); resolve(); }); public static toggleMasterRow(fix: ComponentFixture<any>, row: IgxRowDirective) { const rowDE = fix.debugElement.queryAll(By.directive(IgxRowDirective)).find(el => el.componentInstance === row); const expandCellDE = rowDE.query(By.directive(IgxGridExpandableCellComponent)); expandCellDE.componentInstance.toggle(new MouseEvent('click')); fix.detectChanges(); } public static getMasterRowDetailDebug(fix: ComponentFixture<any>, row: IgxRowDirective) { const rowDE = fix.debugElement.queryAll(By.directive(IgxRowDirective)).find(el => el.componentInstance === row); const detailDE = rowDE.parent.children .find(el => el.attributes['detail'] === 'true' && el.attributes['data-rowindex'] === row.index + 1 + ''); return detailDE; } public static getAllMasterRowDetailDebug(fix: ComponentFixture<any>) { return fix.debugElement.queryAll(By.css('div[detail="true"]')).sort((a, b) => a.context.index - b.context.index); } public static getRowExpandIconName(row: IgxRowDirective) { return row.element.nativeElement.querySelector('igx-icon').textContent; } public static getGroupedRows(fix): DebugElement[] { return fix.debugElement.queryAll(By.css(GROUP_ROW_CLASS)); } public static verifyGroupRowIsFocused(groupRow, focused = true) { expect(groupRow.nativeElement.classList.contains(ACTIVE_GROUP_ROW_CLASS)).toBe(focused); } public static verifyHeaderIsFocused(header, focused = true) { expect(header.nativeElement.classList.contains(ACTIVE_HEADER_CLASS)).toBe(focused); } public static getCurrentCellFromGrid(grid, row, cell) { const gridRow = grid.rowList.toArray()[row]; const gridCell = gridRow.cells.toArray()[cell]; return gridCell; } public static getValueFromCellElement(cell) { return cell.nativeElement.textContent.trim(); } public static verifyColumnIsHidden(column, isHidden: boolean, visibleColumnsCount: number) { expect(column.hidden).toBe(isHidden, 'Hidden is not ' + isHidden); const visibleColumns = column.grid.visibleColumns; expect(visibleColumns.length).toBe(visibleColumnsCount, 'Unexpected visible columns count!'); expect(visibleColumns.findIndex((col) => col === column) > -1).toBe(!isHidden, 'Unexpected result for visibleColumns collection!'); } public static verifyColumnsAreHidden(columns, isHidden: boolean, visibleColumnsCount: number) { const visibleColumns = columns[0].grid.visibleColumns; columns.forEach(column => { expect(column.hidden).toBe(isHidden, 'Hidden is not ' + isHidden); expect(visibleColumns.findIndex((col) => col === column) > -1) .toBe(!isHidden, 'Unexpected result for visibleColumns collection!'); }); expect(visibleColumns.length).toBe(visibleColumnsCount, 'Unexpected visible columns count!'); } public static verifyColumnIsPinned(column, isPinned: boolean, pinnedColumnsCount: number) { expect(column.pinned).toBe(isPinned, 'Pinned is not ' + isPinned); const pinnedColumns = column.grid.pinnedColumns; expect(pinnedColumns.length).toBe(pinnedColumnsCount, 'Unexpected pinned columns count!'); expect(pinnedColumns.findIndex((col) => col === column) > -1).toBe(isPinned, 'Unexpected result for pinnedColumns collection!'); } public static verifyUnpinnedAreaWidth(grid: GridType, expectedWidth: number, includeScrolllWidth = true) { const tolerans = includeScrolllWidth ? Math.abs(expectedWidth - (grid.unpinnedWidth + grid.scrollSize)) : Math.abs(expectedWidth - grid.unpinnedWidth); expect(tolerans).toBeLessThanOrEqual(1); } public static verifyPinnedAreaWidth(grid: GridType, expectedWidth: number) { const tolerans = Math.abs(expectedWidth - grid.pinnedWidth); expect(tolerans).toBeLessThanOrEqual(1); } /* Filtering-related methods */ public static verifyFilterUIPosition(filterUIContainer, grid) { const filterUiRightBorder = filterUIContainer.nativeElement.offsetParent.offsetLeft + filterUIContainer.nativeElement.offsetLeft + filterUIContainer.nativeElement.offsetWidth; expect(filterUiRightBorder).toBeLessThanOrEqual(grid.nativeElement.offsetWidth); } // Generate expected results for 'date' filtering conditions based on the current date public static createDateFilterConditions(grid: IgxGridComponent, today) { const expectedResults = []; // day + 15 const dateItem0 = GridFunctions.generateICalendarDate(grid.data[0].ReleaseDate, today.getFullYear(), today.getMonth()); // month - 1 const dateItem1 = GridFunctions.generateICalendarDate(grid.data[1].ReleaseDate, today.getFullYear(), today.getMonth()); // day - 1 const dateItem3 = GridFunctions.generateICalendarDate(grid.data[3].ReleaseDate, today.getFullYear(), today.getMonth()); // day + 1 const dateItem5 = GridFunctions.generateICalendarDate(grid.data[5].ReleaseDate, today.getFullYear(), today.getMonth()); // month + 1 const dateItem6 = GridFunctions.generateICalendarDate(grid.data[6].ReleaseDate, today.getFullYear(), today.getMonth()); let thisMonthCountItems = 1; let nextMonthCountItems = 1; let lastMonthCountItems = 1; let thisYearCountItems = 6; let nextYearCountItems = 0; let lastYearCountItems = 0; // LastMonth filter if (dateItem3.isPrevMonth) { lastMonthCountItems++; } expectedResults[0] = lastMonthCountItems; // thisMonth filter if (dateItem0.isCurrentMonth) { thisMonthCountItems++; } if (dateItem3.isCurrentMonth) { thisMonthCountItems++; } if (dateItem5.isCurrentMonth) { thisMonthCountItems++; } // NextMonth filter if (dateItem0.isNextMonth) { nextMonthCountItems++; } if (dateItem5.isNextMonth) { nextMonthCountItems++; } expectedResults[1] = nextMonthCountItems; // ThisYear, NextYear, PreviousYear filter // day + 15 if (!dateItem0.isThisYear) { thisYearCountItems--; } if (dateItem0.isNextYear) { nextYearCountItems++; } // month - 1 if (!dateItem1.isThisYear) { thisYearCountItems--; } if (dateItem1.isLastYear) { lastYearCountItems++; } // day - 1 if (!dateItem3.isThisYear) { thisYearCountItems--; } if (dateItem3.isLastYear) { lastYearCountItems++; } // day + 1 if (!dateItem5.isThisYear) { thisYearCountItems--; } if (dateItem5.isNextYear) { nextYearCountItems++; } // month + 1 if (!dateItem6.isThisYear) { thisYearCountItems--; } if (dateItem6.isNextYear) { nextYearCountItems++; } // ThisYear filter result expectedResults[2] = thisYearCountItems; // NextYear filter result expectedResults[3] = nextYearCountItems; // PreviousYear filter result expectedResults[4] = lastYearCountItems; // ThisMonth filter result expectedResults[5] = thisMonthCountItems; return expectedResults; } public static generateICalendarDate(date: Date, year: number, month: number) { date = parseDate(date); return { date, isCurrentMonth: date.getFullYear() === year && date.getMonth() === month, isLastYear: GridFunctions.isLastYear(date, year), isNextMonth: GridFunctions.isNextMonth(date, year, month), isNextYear: GridFunctions.isNextYear(date, year), isPrevMonth: GridFunctions.isPreviousMonth(date, year, month), isThisYear: GridFunctions.isThisYear(date, year) }; } public static isPreviousMonth(date: Date, year: number, month: number): boolean { if (date.getFullYear() === year) { return date.getMonth() < month; } return date.getFullYear() < year; } public static isNextMonth(date: Date, year: number, month: number): boolean { if (date.getFullYear() === year) { return date.getMonth() > month; } return date.getFullYear() > year; } public static isThisYear(date: Date, year: number): boolean { return date.getFullYear() === year; } public static isLastYear(date: Date, year: number): boolean { return date.getFullYear() < year; } public static isNextYear(date: Date, year: number): boolean { return date.getFullYear() > year; } /* Grouping-related members */ public static checkGroups(groupRows, expectedGroupOrder, grExpr?) { // verify group rows are sorted correctly, their indexes in the grid are correct and their group records match the group value. let count = 0; const maxLevel = grExpr ? grExpr.length - 1 : 0; for (const groupRow of groupRows) { const recs = groupRow.groupRow.records; const val = groupRow.groupRow.value; const index = groupRow.index; const field = groupRow.groupRow.expression.fieldName; const level = groupRow.groupRow.level; expect(level).toEqual(grExpr ? grExpr.indexOf(groupRow.groupRow.expression) : 0); expect(index).toEqual(count); count++; expect(val).toEqual(expectedGroupOrder[groupRows.indexOf(groupRow)]); for (const rec of recs) { if (level === maxLevel) { count++; } expect(rec[field]).toEqual(val); } } } public static checkChips(chips, grExpr, sortExpr) { for (let i = 0; i < chips.length; i++) { const chip = chips[i].querySelector('span.igx-chip__label>span').innerText; const chipDirection = chips[i].querySelector('span.igx-chip__label>igx-icon').innerText; const grp = grExpr[i]; const s = sortExpr[i]; expect(chip).toBe(grp.fieldName); expect(chip).toBe(s.fieldName); if (chipDirection === SORTING_ICON_ASC_CONTENT) { expect(grp.dir).toBe(SortingDirection.Asc); expect(s.dir).toBe(SortingDirection.Asc); } else { expect(grp.dir).toBe(SortingDirection.Desc); expect(s.dir).toBe(SortingDirection.Desc); } } } public static getChipText(chipElem) { return chipElem.nativeElement.querySelector('div.igx-chip__content').innerText.trim(); } public static clickChip(debugElement) { UIInteractions.simulateClickAndSelectEvent(debugElement.componentInstance.nativeElement); } public static isInView(index, state): boolean { return index > state.startIndex && index <= state.startIndex + state.chunkSize; } /* Toolbar-related members */ public static getToolbar<T>(fixture: ComponentFixture<T>) { return fixture.debugElement.query(By.css(GRID_TOOLBAR_TAG)); } public static getOverlay(fixture) { const div = fixture.debugElement.query(By.css(GRID_OUTLET_CLASS)); return div.nativeElement; } public static getAdvancedFilteringButton<T>(fix: ComponentFixture<T>) { const button = GridFunctions.getToolbar(fix).query(By.css('igx-grid-toolbar-advanced-filtering > button')); return button ? button.nativeElement : undefined; } public static getColumnHidingButton<T>(fixture: ComponentFixture<T>) { const button = GridFunctions.getToolbar(fixture).query(By.css('igx-grid-toolbar-hiding > button')); return button ? button.nativeElement : undefined; } public static getColumnPinningButton<T>(fixture: ComponentFixture<T>) { const button = GridFunctions.getToolbar(fixture).query(By.css('igx-grid-toolbar-pinning > button')); return button ? button.nativeElement : undefined; } public static getExportButton<T>(fixture: ComponentFixture<T>) { const div = GridFunctions.getToolbar(fixture).query(By.css(GRID_TOOLBAR_EXPORT_BUTTON_CLASS)); return (div) ? div.query(By.css('button')) : null; } public static getExportOptions<T>(fixture: ComponentFixture<T>) { const div = GridFunctions.getOverlay(fixture); return (div) ? div.querySelectorAll('li') : null; } // Filtering public static getFilteringCells(fix) { return fix.debugElement.queryAll(By.css(FILTER_UI_CELL)); } public static getFilteringChips(fix) { return fix.debugElement.queryAll(By.css(FILTER_CHIP_CLASS)); } public static getFilteringChipPerIndex(fix, index) { return this.getFilteringCells(fix)[index].queryAll(By.css(FILTER_CHIP_CLASS)); } public static getFilterRowCloseButton(fix): DebugElement { const filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); const buttonsContainer = filterUIRow.query(By.css(FILTER_ROW_BUTTONS_CLASS)); return buttonsContainer.queryAll(By.css('button'))[1]; } public static removeFilterChipByIndex(index: number, filterUIRow) { const filterChip = filterUIRow.queryAll(By.css('igx-chip'))[index]; ControlsFunction.clickChipRemoveButton(filterChip.nativeElement); } public static verifyFilteringDropDownIsOpened(fix, opened = true) { const dropdownList = fix.debugElement.query(By.css('div.igx-drop-down__list.igx-toggle')); expect(dropdownList !== null).toEqual(opened); } public static selectFilteringCondition(cond: string, ddList) { const ddItems = ddList.nativeElement.children; let i; for (i = 0; i < ddItems.length; i++) { const ddItem = ddItems[i].querySelector('.igx-grid__filtering-dropdown-items span'); if (ddItem.textContent === cond) { ddItem.click(); tick(100); return; } } } public static openFilterDDAndSelectCondition(fix: ComponentFixture<any>, index: number) { GridFunctions.openFilterDD(fix.debugElement); tick(); fix.detectChanges(); const ddList = fix.debugElement.query(By.css('div.igx-drop-down__list-scroll')); const ddItems = ddList.nativeElement.children; ddItems[index].click(); tick(100); fix.detectChanges(); } public static applyFilter(value: string, fix: ComponentFixture<any>) { const filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); const input = filterUIRow.query(By.directive(IgxInputDirective)); UIInteractions.clickAndSendInputElementValue(input.nativeElement, value, fix); // Enter key to submit UIInteractions.triggerEventHandlerKeyDown('Enter', input); fix.detectChanges(); } public static filterBy(condition: string, value: string, fix: ComponentFixture<any>) { // open dropdown this.openFilterDD(fix.debugElement); fix.detectChanges(); const ddList = fix.debugElement.query(By.css('div.igx-drop-down__list-scroll')); this.selectFilteringCondition(condition, ddList); // fix.detectChanges(); tick(100); this.applyFilter(value, fix); tick(100); } public static typeValueInFilterRowInput(value, fix, input = null) { if (!input) { const filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); input = filterUIRow.query(By.directive(IgxInputDirective)); } UIInteractions.clickAndSendInputElementValue(input.nativeElement, value, fix); } public static submitFilterRowInput(fix) { const filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); const input = filterUIRow.query(By.directive(IgxInputDirective)); UIInteractions.triggerEventHandlerKeyDown('Enter', input); fix.detectChanges(); } public static resetFilterRow(fix: ComponentFixture<any>) { fix.componentInstance.grid.filteringRow.onClearClick(); tick(100); fix.detectChanges(); } public static closeFilterRow(fix: ComponentFixture<any>) { fix.componentInstance.grid.filteringRow.close(); fix.detectChanges(); } public static openFilterDD(elem: DebugElement) { const filterUIRow = elem.query(By.css(FILTER_UI_ROW)); const filterIcon = filterUIRow.query(By.css('igx-icon')); filterIcon.nativeElement.click(); } /** * Gets the ESF icon when no filter is applied */ public static getExcelFilterIcon(fix: ComponentFixture<any>, columnField: string) { const columnHeader = GridFunctions.getColumnHeader(columnField, fix).nativeElement; return columnHeader.querySelector(ESF_FILTER_ICON); } /** * Gets the ESF icon when filter is applied */ public static getExcelFilterIconFiltered(fix: ComponentFixture<any>, columnField: string) { const columnHeader = GridFunctions.getColumnHeader(columnField, fix).nativeElement; return columnHeader.querySelector(ESF_FILTER_ICON_FILTERED); } /** * Gets the ESF tree node icon */ public static getExcelFilterTreeNodeIcon(fix: ComponentFixture<any>, index: number) { const treeNodeEl = fix.debugElement.queryAll(By.directive(IgxTreeNodeComponent))[index]?.nativeElement; const expandIcon = treeNodeEl.querySelector(TREE_NODE_TOGGLE); return expandIcon; } public static clickExcelFilterIcon(fix: ComponentFixture<any>, columnField: string) { const filterIcon = GridFunctions.getExcelFilterIcon(fix, columnField); const filterIconFiltered = GridFunctions.getExcelFilterIconFiltered(fix, columnField); const icon = (filterIcon) ? filterIcon : filterIconFiltered; UIInteractions.simulateClickAndSelectEvent(icon); } public static clickExcelTreeNodeExpandIcon(fix: ComponentFixture<any>, index: number) { const expandIcon = GridFunctions.getExcelFilterTreeNodeIcon(fix, index); UIInteractions.simulateClickAndSelectEvent(expandIcon); } public static clickExcelFilterIconFromCode(fix: ComponentFixture<any>, grid: GridType, columnField: string) { const event = { stopPropagation: () => { }, preventDefault: () => { } }; const header = grid.getColumnByName(columnField).headerCell; header.onFilteringIconClick(event); tick(50); fix.detectChanges(); } public static clickExcelFilterIconFromCodeAsync(fix: ComponentFixture<any>, grid: GridType, columnField: string) { const event = { stopPropagation: () => { }, preventDefault: () => { } }; const header = grid.getColumnByName(columnField).headerCell; header.onFilteringIconClick(event); fix.detectChanges(); } public static getApplyButtonExcelStyleFiltering(fix: ComponentFixture<any>, menu = null, grid = 'igx-grid') { const excelMenu = menu ? menu : GridFunctions.getExcelStyleFilteringComponent(fix, grid); const raisedButtons = Array.from(excelMenu.querySelectorAll('.igx-button--raised')); const applyButton: any = raisedButtons.find((rb: any) => rb.innerText === 'apply'); return applyButton; } public static clickApplyExcelStyleFiltering(fix: ComponentFixture<any>, menu = null, grid = 'igx-grid') { const applyButton = GridFunctions.getApplyButtonExcelStyleFiltering(fix, menu, grid); applyButton.click(); } public static clickCancelExcelStyleFiltering(fix: ComponentFixture<any>, menu = null) { const excelMenu = menu ? menu : GridFunctions.getExcelStyleFilteringComponent(fix); const flatButtons = Array.from(excelMenu.querySelectorAll('.igx-button--flat')); const cancelButton: any = flatButtons.find((rb: any) => rb.innerText === 'cancel'); cancelButton.click(); } public static getExcelFilterCascadeButton(fix: ComponentFixture<any>, menu = null): HTMLElement { const excelMenu = menu ? menu : GridFunctions.getExcelStyleFilteringComponent(fix); return excelMenu.querySelector('.igx-excel-filter__actions-filter'); } public static clickExcelFilterCascadeButton(fix: ComponentFixture<any>, menu = null) { const cascadeButton = GridFunctions.getExcelFilterCascadeButton(fix, menu); cascadeButton.click(); } public static clickOperatorFromCascadeMenu(fix: ComponentFixture<any>, operatorIndex: number) { ControlsFunction.clickDropDownItem(fix, operatorIndex); } public static getApplyExcelStyleCustomFiltering(fix: ComponentFixture<any>): HTMLElement { const customFilterMenu = GridFunctions.getExcelStyleCustomFilteringDialog(fix); const raisedButtons = Array.from(customFilterMenu.querySelectorAll('.igx-button--raised')); const applyButton = raisedButtons.find((rb: any) => rb.innerText === 'apply'); return applyButton as HTMLElement; } public static clickApplyExcelStyleCustomFiltering(fix: ComponentFixture<any>) { const applyButton = GridFunctions.getApplyExcelStyleCustomFiltering(fix); applyButton.click(); fix.detectChanges(); } public static clickClearFilterExcelStyleCustomFiltering(fix: ComponentFixture<any>) { const customFilterMenu = GridFunctions.getExcelStyleCustomFilteringDialog(fix); const raisedButtons = Array.from(customFilterMenu.querySelectorAll('.igx-button--flat')); const button: any = raisedButtons.find((rb: any) => rb.innerText === 'Clear filter'); button.click(); fix.detectChanges(); } public static getExcelCustomFilteringExpressionAndButton(fix: ComponentFixture<any>, expressionIndex = 0): HTMLElement { const expr = GridFunctions.getExcelCustomFilteringDefaultExpressions(fix)[expressionIndex]; const andButton = GridFunctions.sortNativeElementsHorizontally(Array.from(expr.querySelectorAll('.igx-button-group__item')))[0]; return andButton; } public static getExcelCustomFilteringExpressionOrButton(fix: ComponentFixture<any>, expressionIndex = 0): HTMLElement { const expr = GridFunctions.getExcelCustomFilteringDefaultExpressions(fix)[expressionIndex]; const orButton = GridFunctions.sortNativeElementsHorizontally(Array.from(expr.querySelectorAll('.igx-button-group__item')))[1]; return orButton; } public static clickCancelExcelStyleCustomFiltering(fix: ComponentFixture<any>) { const customFilterMenu = GridFunctions.getExcelStyleCustomFilteringDialog(fix); const flatButtons = Array.from(customFilterMenu.querySelectorAll('.igx-button--flat')); const cancelButton: any = flatButtons.find((rb: any) => rb.innerText === 'cancel'); cancelButton.click(); } public static getAddFilterExcelStyleCustomFiltering(fix: ComponentFixture<any>): HTMLElement { const customFilterMenu = GridFunctions.getExcelStyleCustomFilteringDialog(fix); const addFilterButton: HTMLElement = customFilterMenu.querySelector(ESF_ADD_FILTER_CLASS); return addFilterButton; } public static clickAddFilterExcelStyleCustomFiltering(fix: ComponentFixture<any>) { const addFilterButton = GridFunctions.getAddFilterExcelStyleCustomFiltering(fix); addFilterButton.click(); } /** * Click the pin/unpin icon in the ESF by specifying whether the icon is in the header * or at its default position (depending on the display density). */ public static clickPinIconInExcelStyleFiltering(fix: ComponentFixture<any>, isIconInHeader = true) { let pinUnpinIcon: any; if (isIconInHeader) { const headerIcons = GridFunctions.getExcelFilteringHeaderIcons(fix); const headerAreaPinIcon = headerIcons.find((buttonIcon: any) => buttonIcon.innerHTML.indexOf('name="pin-left"') !== -1); const headerAreaUnpinIcon = headerIcons.find((buttonIcon: any) => buttonIcon.innerHTML.indexOf('name="unpin-left"') !== -1); pinUnpinIcon = headerAreaPinIcon ? headerAreaPinIcon : headerAreaUnpinIcon; } else { const pinContainer = GridFunctions.getExcelFilteringPinContainer(fix); const unpinContainer = GridFunctions.getExcelFilteringUnpinContainer(fix); pinUnpinIcon = pinContainer ? pinContainer : unpinContainer; } pinUnpinIcon.click(); } /** * Click the hide icon in the ESF by specifying whether the icon is in the header * or at its default position (depending on the display density). */ public static clickHideIconInExcelStyleFiltering(fix: ComponentFixture<any>, isIconInHeader = true) { let hideIcon: any; if (isIconInHeader) { const headerIcons = GridFunctions.getExcelFilteringHeaderIcons(fix); hideIcon = headerIcons.find((buttonIcon: any) => buttonIcon.innerText === 'visibility_off'); } else { hideIcon = GridFunctions.getExcelFilteringHideContainer(fix); } hideIcon.click(); } public static getIconFromButton(iconName: string, component: any) { const icons = component.querySelectorAll('igx-icon'); return Array.from(icons).find((sortIcon: any) => sortIcon.innerText === iconName); } /** * Click the sort ascending button in the ESF. */ public static clickSortAscInExcelStyleFiltering(fix: ComponentFixture<any>) { const sortAscIcon: any = this.getIconFromButton('arrow_upwards', GridFunctions.getExcelFilteringSortComponent(fix)); sortAscIcon.click(); } /** * Click the column selection button in the ESF. */ public static clickColumnSelectionInExcelStyleFiltering(fix: ComponentFixture<any>) { const columnSelectIcon: any = this.getIconFromButton('done', GridFunctions.getExcelFilteringColumnSelectionContainer(fix)); columnSelectIcon.click(); } /** * Click the sort descending button in the ESF. */ public static clickSortDescInExcelStyleFiltering(fix: ComponentFixture<any>) { const sortDescIcon: any = this.getIconFromButton('arrow_downwards', GridFunctions.getExcelFilteringSortComponent(fix)); sortDescIcon.click(); } /** * Click the move left button in the ESF. */ public static clickMoveLeftInExcelStyleFiltering(fix: ComponentFixture<any>) { const moveLeftIcon: any = this.getIconFromButton('arrow_back', GridFunctions.getExcelFilteringMoveComponent(fix)); moveLeftIcon.click(); } /** * Click the move right button in the ESF. */ public static clickMoveRightInExcelStyleFiltering(fix: ComponentFixture<any>) { const moveRightIcon: any = this.getIconFromButton('arrow_forwards', GridFunctions.getExcelFilteringMoveComponent(fix)); moveRightIcon.click(); } public static getExcelFilteringInput(fix: ComponentFixture<any>, expressionIndex = 0): HTMLInputElement { const expr = GridFunctions.getExcelCustomFilteringDefaultExpressions(fix)[expressionIndex]; return expr.querySelectorAll('.igx-input-group__input').item(1) as HTMLInputElement; } public static getExcelFilteringDDInput(fix: ComponentFixture<any>, expressionIndex = 0, isDate = false): HTMLInputElement { const allExpressions = isDate ? GridFunctions.getExcelCustomFilteringDateExpressions(fix) : GridFunctions.getExcelCustomFilteringDefaultExpressions(fix); return allExpressions[expressionIndex].querySelectorAll('.igx-input-group__input').item(0) as HTMLInputElement; } public static setInputValueESF(fix: ComponentFixture<any>, expressionIndex: number, value: any) { const input = GridFunctions.getExcelFilteringInput(fix, expressionIndex); UIInteractions.clickAndSendInputElementValue(input, value, fix); } /** * Gets the clear filter button in the ESF. */ public static getClearFilterInExcelStyleFiltering(fix: ComponentFixture<any>, menu = null): HTMLElement { const excelMenu = menu ? menu : GridFunctions.getExcelStyleFilteringComponent(fix); const clearFilterContainer = excelMenu.querySelector('.igx-excel-filter__actions-clear'); const clearFilterDisabledContainer = excelMenu.querySelector('.igx-excel-filter__actions-clear--disabled'); const clearIcon = clearFilterContainer ? clearFilterContainer : clearFilterDisabledContainer; return clearIcon; } /** * Click the clear filter button in the ESF. */ public static clickClearFilterInExcelStyleFiltering(fix: ComponentFixture<any>, menu = null) { const clearIcon = GridFunctions.getClearFilterInExcelStyleFiltering(fix, menu); clearIcon.click(); } /** * returns the filter row debug element. */ public static getFilterRow(fix: ComponentFixture<any>): DebugElement { return fix.debugElement.query(By.css(FILTER_UI_ROW)); } /** * Open filtering row for a column. */ public static clickFilterCellChip(fix, columnField: string) { const grid = fix.componentInstance.grid; grid.getColumnByName(columnField).filterCell.onChipClicked(); fix.detectChanges(); } /** * Click the filter chip for the provided column in order to open the filter row for it. */ public static clickFilterCellChipUI(fix, columnField: string, forGrid?: GridType) { const headerGroups = fix.debugElement.queryAll(By.directive(IgxGridHeaderGroupComponent)); const headerGroup = headerGroups.find((hg) => { const col: IgxColumnComponent = hg.componentInstance.column; return col.field === columnField && (forGrid ? forGrid.gridAPI.grid === col.grid : true); }); const filterCell = headerGroup.query(By.css(FILTER_UI_CELL)); const chip = filterCell.query(By.css('igx-chip')); chip.nativeElement.click(); fix.detectChanges(); } /** * Presuming filter row is opened, click the filter condition chip based on ascending index (left to right). */ public static clickFilterConditionChip(fix: ComponentFixture<any>, index: number) { const filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); const conditionChips = GridFunctions.sortNativeElementsHorizontally( filterUIRow.queryAll(By.directive(IgxChipComponent)).map((ch) => ch.nativeElement)); conditionChips[index].click(); } /** * Presuming filter row is opened, click the inter-chip operator based on its index. */ public static clickChipOperator(fix: ComponentFixture<any>, index: number) { const filterUIRow = fix.debugElement.query(By.css(FILTER_UI_ROW)); const allIcons = filterUIRow.queryAll(By.css('igx-icon')).map((icon) => icon.nativeElement); const operatorIcons = GridFunctions.sortNativeElementsHorizontally( allIcons.filter((icon) => icon.innerText === 'expand_more')); const operatorIcon = operatorIcons[index]; operatorIcon.click(); } /** * Presuming chip operator dropdown is opened, set the inter-chip operator value. (should be 'And' or 'Or') */ public static clickChipOperatorValue(fix: ComponentFixture<any>, operatorValue: string) { const gridNativeElement = fix.debugElement.query(By.css('igx-grid')).nativeElement; const operators = GridFunctions.sortNativeElementsVertically( Array.from(gridNativeElement.querySelectorAll('.igx-drop-down__item'))); const operator = operators.find((op) => op.innerText.toLowerCase() === operatorValue.toLowerCase()); operator.click(); fix.detectChanges(); } public static getExcelStyleFilteringComponent(fix, grid = 'igx-grid') { const gridNativeElement = fix.debugElement.query(By.css(grid)).nativeElement; let excelMenu = gridNativeElement.querySelector(ESF_MENU_CLASS); if (!excelMenu) { excelMenu = fix.nativeElement.querySelector(ESF_MENU_CLASS); } return excelMenu; } public static getExcelStyleFilteringComponents(fix, grid = 'igx-pivot-grid') { const gridNativeElement = fix.debugElement.query(By.css(grid)).nativeElement; let excelMenus = gridNativeElement.querySelectorAll(ESF_MENU_CLASS); if (!excelMenus) { excelMenus = fix.nativeElement.querySelector(ESF_MENU_CLASS); } return excelMenus; } public static getExcelStyleFilteringCheckboxes(fix, menu = null, grid = 'igx-grid'): HTMLElement[] { const searchComp = GridFunctions.getExcelStyleSearchComponent(fix, menu, grid); return GridFunctions.sortNativeElementsVertically(Array.from(searchComp.querySelectorAll(CHECKBOX_INPUT_CSS_CLASS))); } public static getExcelStyleFilteringSortContainer(fix, menu = null) { const excelMenu = menu ? menu : GridFunctions.getExcelStyleFilteringComponent(fix); return excelMenu.querySelector(ESF_SORT_CLASS); } public static getExcelStyleFilteringSortButtons(fix, menu = null): HTMLElement[] { const sortContainer = GridFunctions.getExcelStyleFilteringSortContainer(fix, menu); return sortContainer.querySelectorAll('.igx-button--flat'); } public static getExcelStyleFilteringMoveContainer(fix, menu = null) { const excelMenu = menu ? menu : GridFunctions.getExcelStyleFilteringComponent(fix); return excelMenu.querySelector(ESF_MOVE_CLASS); } public static getExcelStyleFilteringMoveButtons(fix, menu = null): HTMLElement[] { const moveContainer = GridFunctions.getExcelStyleFilteringMoveContainer(fix, menu); return moveContainer.querySelectorAll('.igx-button--flat'); } public static getExcelStyleSearchComponent(fix, menu = null, grid = 'igx-grid') { const excelMenu = menu ? menu : GridFunctions.getExcelStyleFilteringComponent(fix, grid); const searchComponent = excelMenu.querySelector('.igx-excel-filter__menu-main'); return searchComponent; } public static getExcelStyleSearchComponentScrollbar(fix, menu = null) { const searchComponent = GridFunctions.getExcelStyleSearchComponent(fix, menu); const scrollbar = searchComponent.querySelector('igx-virtual-helper'); return scrollbar; } public static getExcelStyleSearchComponentInput(fix, comp = null, grid = 'igx-grid'): HTMLInputElement { const searchComponent = comp ? comp : GridFunctions.getExcelStyleSearchComponent(fix, null, grid); return searchComponent.querySelector('.igx-input-group__input'); } public static getExcelStyleSearchComponentListItems(fix, comp = null, grid = 'igx-grid'): HTMLElement[] { const searchComponent = comp ? comp : GridFunctions.getExcelStyleSearchComponent(fix, null, grid); return GridFunctions.sortNativeElementsVertically(Array.from(searchComponent.querySelectorAll('igx-list-item'))); } public static getExcelStyleSearchComponentTreeNodes(fix, comp = null, grid = 'igx-tree-grid'): HTMLElement[] { const searchComponent = comp ? comp : GridFunctions.getExcelStyleSearchComponent(fix, null, grid); return GridFunctions.sortNativeElementsVertically(Array.from(searchComponent.querySelectorAll('igx-tree-node'))); } public static getColumnHeaders(fix: ComponentFixture<any>): DebugElement[] { return fix.debugElement.queryAll(By.directive(IgxGridHeaderComponent)); } public static getColumnHeader(columnField: string, fix: ComponentFixture<any>, forGrid?: GridType): DebugElement { return this.getColumnHeaders(fix).find((header) => { const col = header.componentInstance.column; return col.field === columnField && (forGrid ? forGrid === col.grid : true); }); } public static getColumnGroupHeaders(fix: ComponentFixture<any>): DebugElement[] { const allHeaders = fix.debugElement.queryAll(By.directive(IgxGridHeaderGroupComponent)); const groupHeaders = allHeaders.filter(h => h.componentInstance.column.columnGroup); return groupHeaders; } public static getColumnGroupHeader(header: string, fix: ComponentFixture<any>, forGrid?: GridType): DebugElement { const headers = this.getColumnGroupHeaders(fix); const head = headers.find((gr) => { const col = gr.componentInstance.column; return col.header === header && (forGrid ? forGrid === col.grid : true); }); return head; } public static clickColumnHeaderUI(columnField: string, fix: ComponentFixture<any>, ctrlKey = false, shiftKey = false) { const header = this.getColumnHeader(columnField, fix); header.triggerEventHandler('click', new MouseEvent('click', { shiftKey, ctrlKey })); fix.detectChanges(); } public static clickColumnGroupHeaderUI(columnField: string, fix: ComponentFixture<any>, ctrlKey = false, shiftKey = false) { const header = this.getColumnGroupHeaderCell(columnField, fix); header.triggerEventHandler('click', new MouseEvent('click', { shiftKey, ctrlKey })); fix.detectChanges(); } public static getColumnHeaderByIndex(fix: ComponentFixture<any>, index: number) { return fix.debugElement.queryAll(By.css(GRID_COL_THEAD_CLASS))[index]; } public static getColumnHeaderTitleByIndex(fix: ComponentFixture<any>, index: number) { const nativeHeaders = fix.debugElement.queryAll(By.directive(IgxGridHeaderComponent)) .map((header) => header.nativeElement); const sortedNativeHeaders = GridFunctions.sortNativeElementsHorizontally(nativeHeaders); return sortedNativeHeaders[index].querySelector('.igx-grid-th__title'); } public static getFilterChipsForColumn(columnField: string, fix: ComponentFixture<any>) { const columnHeader = this.getColumnHeader(columnField, fix); return columnHeader.parent.queryAll(By.directive(IgxChipComponent)); } public static getFilterOperandsForColumn(columnField: string, fix: ComponentFixture<any>) { const columnHeader = this.getColumnHeader(columnField, fix); return columnHeader.parent.queryAll(By.css('.' + FILTER_UI_CONNECTOR)); } public static getFilterIndicatorForColumn(columnField: string, fix: ComponentFixture<any>): DebugElement[] { const columnHeader = this.getColumnHe