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
text/typescript
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